8

以前に PowerPoint プレゼンテーションに埋め込まれた XML ドキュメントまたは Word ドキュメントを開いて読み取るアプリケーションを開発しています。このオブジェクト ( xmlFile as Object) を読み取るには、次のことを行う必要があります。

xmlFile.OLEFormat.DoVerb 1

これによりパッケージ オブジェクトが開かれ、Notepad.exe の開いているインスタンスを取得し、その内容を ADODB ストリームに読み込む別のサブルーチンがあります。

この手順の例は、Google ドキュメントで入手できます。

XML_Test.pptm

このプロセス中に、Notepad.exe がフォーカスを得る数秒のウィンドウがあり、不注意でキーストロークを行うと、望ましくない結果や XML データの読み取りエラーが発生する可能性があります。

次の 2 つのいずれかを探しています。

  1. この操作の実行中にユーザーが(キーボード/マウスなどを介して)誤って入力するのを防ぐ方法。MouseKeyboardTest以下のサブルーチンのように、ユーザーのマシンを制御しないものが望ましいです。または、
  2. XML データを文字列変数に抽出するより優れた方法。

#1の場合:これは私が見つけた関数であり、使用するのが苦手です。私は、ユーザーシステムをこのように制御することに慎重です。##他に使用できる方法はありますか?##

Private Declare Function BlockInput Lib "USER32.dll" (ByVal fBlockIt As Long) As Long
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

Sub MouseKeyboardTest() 'both keyboard and mouse blocked

    BlockInput True ' Turns off Keyboard and Mouse
'   Routine goes here
    Sleep 5000 ' Optional coding
    BlockInput False ' Turns on Keyboard and Mouse

End Sub

#2の場合:いくつかの背景がありますが、.NET以外の方法を使用して埋め込みオブジェクトを確実に抽出できないことが問題のようですDoVerb 1。VBAスキルの影響を受けないアプリケーション(メモ帳)で保存されていないドキュメントを扱っているので、これが唯一の方法のようです。その完全な背景は、ここにあります:

PowerPoint VBA から OLEObject (XML ドキュメント) を抽出する

4

4 に答える 4

2

上記のコメントで正しく推測したように、メモ帳からフォーカスを外すと問題が解決します。以下のコードはまさにそれを行います。

ロジック:

A. _ シェイプをループして名前を取得します。あなたのシナリオでは、次のようになりますChart Meta XML_fbc9775a-19ea-.txt

ここに画像の説明を入力

B. _ 、などFindWindowのAPI を使用して、部分的なキャプションを使用してメモ帳ウィンドウのハンドルを取得します。GetWindowTextLengthGetWindow

C. _ ShowWindowAPI を使用してウィンドウを最小化する

コード (VBA-Powerpoint でテスト済み)

このコードを上記の PPTM のモジュールに貼り付けます

Private Declare Function FindWindow Lib "User32" Alias "FindWindowA" _
(ByVal lpClassName As String, ByVal lpWindowName As String) As Long

Private Declare Function GetWindowText Lib "User32" Alias "GetWindowTextA" _
(ByVal hWnd As Long, ByVal lpString As String, ByVal cch As Long) As Long

Private Declare Function GetWindowTextLength Lib "User32" Alias _
"GetWindowTextLengthA" (ByVal hWnd As Long) As Long

Private Declare Function GetWindow Lib "User32" (ByVal hWnd As Long, _
ByVal wCmd As Long) As Long

Private Declare Function ShowWindow Lib "User32" (ByVal hWnd As Long, _
ByVal nCmdShow As Long) As Long

Private Const GW_HWNDNEXT = 2
Private Const SW_SHOWMINIMIZED = 2

Sub Sample()
    Dim shp As Shape
    Dim winName As String
    Dim Ret As Long

    For Each shp In ActivePresentation.Slides(1).Shapes
        If shp.Type = msoEmbeddedOLEObject Then
            winName = shp.Name
            shp.OLEFormat.Activate
            Exit For
        End If
    Next

    If winName <> "" Then
        Wait 1

        If GetHwndFromCaption(Ret, Replace(winName, ".txt", "")) = True Then
           Call ShowWindow(Ret, SW_SHOWMINIMIZED)
        Else
            MsgBox "Window not found!", vbOKOnly + vbExclamation
        End If
    End If
End Sub

Private Function GetHwndFromCaption(ByRef lWnd As Long, ByVal sCaption As String) As Boolean
    Dim Ret As Long
    Dim sStr As String

    GetHwndFromCaption = False

    Ret = FindWindow(vbNullString, vbNullString)

    Do While Ret <> 0

        sStr = String(GetWindowTextLength(Ret) + 1, Chr$(0))
        GetWindowText Ret, sStr, Len(sStr)
        sStr = Left$(sStr, Len(sStr) - 1)
        If InStr(1, sStr, sCaption) > 0 Then
            GetHwndFromCaption = True
            lWnd = Ret
            Exit Do
        End If
        Ret = GetWindow(Ret, GW_HWNDNEXT)
    Loop
End Function

Private Sub Wait(ByVal nSec As Long)
    nSec = nSec + Timer
    While nSec > Timer
        DoEvents
    Wend
End Sub
于 2013-05-07T21:59:06.473 に答える
1

私が理解しているのは、そもそも XML ファイルを PowerPoint プレゼンテーションに埋め込む方法を制御できるということです。ここで、必要なデータを埋め込みオブジェクトのコンテンツとして保持することを選択した理由がよくわかりません。

確かに、それらのコンテンツを取り戻すのは簡単なことではありません。QueryInterface実際には、VBA からインターフェイスを呼び出して使用する(単純な、またはやや難しい) 方法がない限りIPersist*、埋め込みオブジェクトのコンテンツにアクセスする方法は 1 つしかありません。この方法には、次の手順が含まれます。

  1. 埋め込みオブジェクトをアクティブにします。あなたはそのために使用OLEFormat.DoVerb 1しました。より良い方法は を呼び出すことOLEFormat.Activateですが、これは特定の問題には関係ありません。
  2. 埋め込みオブジェクトのプログラミング モデルを使用して、コンテンツの取得、保存、公開されているものなどの便利な操作を実行します。はそのようなプログラミング モデルを公開していないため、利用可能な最良の選択肢であるNotepad.exeことに頼りました。WinAPI

残念ながら、現在のアプローチには少なくとも 2 つの欠陥があります。

  1. notepad.exe質問で特定したもの(ユーザーの干渉の可能性につながるアクティベーション)。
  2. .txtユーザーが以外のファイルを開くための既定のプログラムを持っている場合notepad.exe、あなたのアプローチは失敗に終わります。

埋め込みオブジェクトの作成方法を制御できる場合は、Shapeオブジェクトのプロパティに XML データを格納することをお勧めします。私は(非常に簡単に使用できます。HTMLShape.AlternativeTextにエクスポートする場合、または重要な別のシナリオがある場合は使用しないでください)または(これはおそらくタスクにとって最も意味的に正しいです)を使用します。.pptmAlternativeTextShape.Tags

于 2013-05-07T22:29:09.450 に答える
0

Sid の提案によると、私のアプローチは、Notepad.exe を最小化する方法を見つけることでした。そのオブジェクトを取得して閉じる方法を既に見つけたので、これはそれほど難しくないと思いました。

これらを追加します:

Public Declare Function _
     ShowWindow& Lib "user32" (ByVal hwnd As Long, _
                        ByVal ncmdshow As Long)
Public Const SW_MINIMIZE = 6

そして、FindNotepad関数の直前Exit Function(つまり、メモ帳が見つかった後) でウィンドウを最小化します。

ShowWindow TopWnd, SW_MINIMIZE
于 2013-05-07T22:00:21.197 に答える