我正在开发一个应用程序,它打开并读取以前嵌入PowerPoint演示文稿或Word文档中的XML文档。为了阅读这个对象(xmlFile as Object
),我必须这样做:
xmlFile.OLEFormat.DoVerb 1
这会打开包对象,我有另一个子例程来获取Notepad.exe的打开实例,并将其内容读入ADODB流。
Google文档中提供了此过程的示例:
在此过程中,Notepad.exe会在几秒钟内获得焦点,无意中击键可能会导致意外结果或读取XML数据时出错。
我正在寻找两件事之一:
MouseKeyboardTest
子程序。或者,对于#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:有些背景,但问题似乎是无法使用DoVerb 1
以外的任何方法可靠地提取嵌入对象。由于我正在处理一个不受我的VBA技能影响的应用程序(记事本)中未保存的文档,这似乎是唯一的方法。完整的背景,在这里:
答案 0 :(得分:2)
正如您在上面的评论中正确猜到的那样,将焦点从记事本上移开将解决您的问题。下面的代码确实如此。
<强> LOGIC 强>:
<强> A 即可。循环通过形状并获取它的名称。在您的方案中,它将类似于Chart Meta XML_fbc9775a-19ea-.txt
<强>乙即可。使用FindWindow
,GetWindowTextLength
,GetWindow
等API来使用部分字幕来获取记事本窗口的句柄。
<强> C 即可。使用ShowWindow
API最小化窗口
代码(在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
答案 1 :(得分:1)
我的理解是,您可以控制XML文件如何嵌入到PowerPoint演示文稿中。在这里,我不太明白为什么你选择将所需的数据保存为嵌入对象的内容。
可以肯定的是,获取这些内容的任务不是小菜一碟。实际上,只要没有(简单甚至是中等难度)方式从VBA调用QueryInterface
和使用IPersist*
接口,只有一种方法可以获取嵌入对象的内容。方法包括以下步骤:
OLEFormat.DoVerb 1
。更好的方法是拨打OLEFormat.Activate
,但这与您的特定问题无关。Notepad.exe
没有公开这样的编程模型,你使用了WinAPI
这是最好的选择。不幸的是,您当前的方法至少有两个缺陷:
notepad.exe
的激活导致用户干扰的可能性)。.txt
以外的notepad.exe
个文件的默认程序,则您的方法注定失败。如果您确实可以控制嵌入对象的创建方式,那么更好的方法是将XML数据存储在Shape
对象的某个属性中。我会使用Shape.AlternativeText
(非常简单易用;如果您将.pptm
导出为HTML,或者有AlternativeText
重要的不同情况)或Shape.Tags
,则不应使用对于那个问题,这个问题可能是最具语义正确性的。
答案 2 :(得分:0)
我认为阻止用户是正确的方法,
如果您必须使用记事本窗口的内容,我建议使用SendKeys方法,以便发送此组合:
SendKeys("^A^C")
相当于“全选”和“复制”,
然后你可以继续在剪贴板上“脱机”工作,而不用担心按键干扰。
答案 3 :(得分: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