在VBA shell命令中使用AppActivate和Sendkeys

6
我希望能够通过VBA的shell命令在应用程序之间来回切换。我正在使用SendKeys在进程A中执行操作,然后移动到进程B,再回到进程A和进程B。第一次迭代运行良好。当我使用AppActivate返回到进程B时,它实际上确实将焦点切换回了进程B。但是,它忽略了来自SendKeys的后续命令。
示例代码:
Sub pastePDF2TXT_v3(pdfName As String, txtName As String)


Dim acrobatID
Dim acrobatInvokeCmd As String
Dim acrobatLocation As String

Dim notepadID

Dim acrobatID2
Dim notepadID2

Debug.Print "here"


acrobatLocation = "C:\Program Files\Adobe\Acrobat 9.0\Acrobat\Acrobat.exe"

acrobatInvokeCmd = acrobatLocation & " " & pdfName

acrobatID = Shell(acrobatInvokeCmd, 1)
AppActivate acrobatID
SendKeys "^a", True  '^A selects everything already in the pdf file.
SendKeys "^c", True  '^C copies the selection to the clipboard.



notepadID = Shell("NOTEPAD.EXE " & txtName, 1)  ' invoke notepad on the text file.
AppActivate notepadID                           ' set the new app as teh active task.

SendKeys "^a", True  '^A selects everything already in the text file.
SendKeys "^v", True  '^V pastes the new stuff over the top of the old text file (deleting the old stuff)
SendKeys "%{END}", True ' makre sure last line of text file 
SendKeys "{ENTER}", True



AppActivate acrobatID  ' NOTE: APPEARS TO WORK UP TO THIS POINT.

SendKeys "{ENTER}", True  ' NOTE: SECOND APP IGNORES SUBSEQUENT COMMANDS FROM HERE DOWN.
SendKeys "^a", True  '^A selects everything already in the pdf file.
SendKeys "^c", True  '^C copies the selection to the clipboard.
SendKeys "%f", True  'alt f, x to exit Notepad.exe
SendKeys "x", True
'acrobatID.Quit


Debug.Print "start second"

AppActivate notepadID                           ' set the new app as teh active task.


SendKeys "%{END}", True 'Go to end of text file.
SendKeys "^v", True  '^V pastes the new stuff at end of file.
SendKeys "{ENTER}", True

SendKeys "^s", True   

SendKeys "%f", True   'alt f, x to exit Notepad.exe
SendKeys "x", True

notepadID.Quit
acrobatID.Quit

End Sub
6个回答

4

我知道这个问题很老,但我也遇到了同样的问题,但我认为所选择的答案并不正确。

当您调用AppActivate时,脚本会停止运行,等待目标应用程序终止。应用程序终止后,脚本才会继续执行。我没有看到解决此问题的方法。

编辑:

我使用批处理文件调用CSCRIPT的AppActivate命令,并且注意到您严格使用VBS文件。尝试调用CMD作为新窗口,并将CSCRIPT //NoLogo //B WScript.CreateObject("WSCript.shell").AppActivate("Window Name")作为参数传递,看看是否能够绕过此问题。


我已经完成了那个项目,不再处理这个问题;然而,这种情况每隔几年就会出现一次,所以我会记住这件事情,等到下一次再来处理。谢谢,tff。 - elbillaf

2
同样地,我试图在使用shell命令打开的pdf文档上使用AppActivate,以便我可以在其上使用SendKeys。它总是会生成“运行时错误5”。我的解决方案最终是根本不使用AppActivate,实际上打开文档会将其置于前台。问题在于,SendKeys语句会在shell命令之后立即执行,但pdf需要一两秒钟才能打开。我的解决方案是在执行sendkeys语句之前暂停代码几秒钟。
我使用了pootle flump提供的时间延迟。在这里查看讨论线程: http://www.dbforums.com/microsoft-access/1219379-time-delay-vba.html

那对我有用。我使用了一个时间延迟,例如:Application.Wait Now + TimeValue("00:00:2")。 - Selrac

2
经过在各种论坛上数小时的研究,我发现无法使用Adobe Reader的库对象和函数。唯一可行的选择是使用Shell命令来使用Adobe Reader文件菜单中提供的“另存为文本”选项。快捷键是Alt+f+a+x+s。我在下面的代码中实现了这些功能,虽然有些步骤需要插入延迟,但效果完美。
Sub SavePDFasText()
Dim AdobeReaderPath As String
Dim PdfFilePath As String
Dim PDFid, NotepdId As Double

AdobeReaderPath = "C:\Program Files\Adobe\Reader 10.0\Reader\AcroRd32.exe"
PdfFilePath = "D:\PowerGenMacro\opm_11.pdf"
PDFid = Shell(AdobeReaderPath & " " & PdfFilePath, vbNormalFocus)
Application.Wait TimeSerial(Hour(Now()), Minute(Now()), Second(Now()) + 5)
'Alt+f+a+x is required to save the pdf as text in the adobe reader
SendKeys "%(FAX)", True
Application.Wait TimeSerial(Hour(Now()), Minute(Now()), Second(Now()) + 2)
SendKeys "%S", True
SendKeys "^q", True

End Sub

0

这可能更像是一条评论而不是答案,但我似乎不能“评论”,所以...

你已经做得很好了。但很有可能,你永远无法可靠地使其正常工作 - 毫无疑问。一旦你让它工作,未来的Acrobat UI行为或Windows对哪些事物可以向其他事物发送事件的规则进行更改,然后你又会遇到问题。

在这种情况下,你可能遇到的是Windows试图防止应用程序从正在与用户交互的第一个应用程序中窃取焦点。尝试执行类似于在一个应用程序中放置一个按钮以将数据写入临时文件并打开MS Word进行编辑的操作时,你会遇到相同类型的问题。Windows会阻止焦点从当前应用程序转移到MS Word,因为你刚刚点击了当前应用程序中的按钮。

因此,与其试图解决这个不可能的技术问题,让我们退一步并问一下你最初希望通过所有这些做什么。也许,通过这种方式,我们可以帮助你实现目标 :)


我手头有一堆(超过1000个)PDF文件,其中包含我想要解析的文本。其中一些文本是自由格式的,无法使用。文本的其他部分几乎都是格式一致的,我可以获取这些信息并将其放入数据库(Excel电子表格)以供后续分析。在将数据放入文本文件后,我使用Perl脚本解析所需内容并创建CSV文件。这种方法很糟糕 - 原因如你所说,而且它在美学上很丑陋,并且似乎在所有情况下都不能保持一致。 - elbillaf
通用方法适用于PDF只有一页的情况,但对于多页文档,Acrobat在^A(从sendkeys)中只选择一页,因此我必须来回切换 - 这似乎不起作用。我已经解决了当前任务的问题,但我希望有一种通用方法来解决这种问题,以便未来的方法不会那么烦人。 - elbillaf
1
你能使用像http://www.pdf2txt.com/这样的工具,而不是尝试自动化Acrobat GUI吗? - Steve Jorgensen

0

尝试使用 sendkeys "%{tab}" 切换窗口,但保持仅有 2 个活动窗口。

或者尝试在 sendkeys {Tab} 后仅使用 appactivate,以便在切换窗口命令之前不会选择文本输入框。

或者尝试使用 try appactivate window name, 1,然后 sleep 2000,以允许时间将该窗口置于焦点。


0

你忘记在每个SendKeys之间加上"DoEvents"以及一些延迟/等待时间,给它一些执行的时间。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接