Word与Excel应用程序间的切换

《VBA信息获取与处理》教程是我推出第六套教程,目前已经是第一版修订了。这套教程定位于最高级,是学完初级,中级后的教程。
信息,含义非常之广泛,是我们日常生活不可或缺的一部分。从天气情况和预报,到人际关系,宇宙洪荒,都是信息的组成部分。信息在某种程度上就是数据,或者可以用数据来体现,获得信息也就是数据的获得。这部教程给大家讲解的内容有:跨应用程序信息获得、随机信息的利用、电子邮件的发送、VBA互联网数据抓取、VBA延时操作,剪切板应用、Split函数扩展、工作表信息与其他应用交互,FSO对象的利用、工作表及文件夹信息的获取、图形信息的获取以及定制工作表信息函数等等内容。程序文件通过32位和64位两种OFFICE系统测试。是非常抽象的,更具研究的价值。
这套教程共两册,八十四讲,今后一段时间会给大家陆续推出修订后的教程内容。今日的内容是第2讲:word与excel应用程序间的切换。

第二节  在word和excel两个应用程序间的激活操作

如我们的报告界面,当我们的界面继续往下进行,在第二个以及第三个按钮处我们要激活刚才打开的excel,这个按钮的代码该如何写呢?

1  用AppActivate语句

利用AppActivate语句激活EXCEL是非简单的,我们看下面的按钮代码:
Private Sub CommandButton2_Click()
Set ws = CreateObject('wscript.shell')
ws.AppActivate '001 工作表'
End Sub
代码的截图:
代码讲解:我们先看看AppActivate语句的语法:
语法:AppActivate title [, wait]
参数title;是必须的,这是应用程序的名称,正如它显示在应用程序窗口的标题栏那样,或者它也可以是Shell函数返回的任务ID号码。注意,参数title要跟每个正运行的应用程序的标题字符串进行对比,如果没有精确的匹配,那么任何标题字符串里前面的字符和参数title一致的应用程序就会被激活。(例如,你要激活Excel,那么title参数应该是“Microsoft Excel”,如果你写的是“Microsoft”,那么激活的就也可能是Word,PowerPoint……)。
第二个参数wait是可选的,它是个布尔值(True或False),明确VB什么时候激活应用程序。如果在这里是False的话,该应用程序就立即会被激活,甚至被调应用程序并没有焦点。如果在wait参数处放置True的话,那么被调的应用程序就会等到它有了焦点,然后才会激活该应用程序。
例如,要激活Word,你就得输入下列语句:AppActivate “Microsoft Word”注意,应用程序名称用双引号引用起来。
也可以使用Shell函数返回的数值作为语句AppActivate的参数,例如(仅适合于32位OFFICE系统):
Sub mynz()
ReturnValue = Shell('C:\Microsoft Office\Office\Word.exe',1)
AppActivate ReturnValue
End sub
u特别注意点,对于AppActivate的用法,我在修订代码的时候进行了完善,对于64位的OFFICE系统和32位的OFFICE系统,下面的代码:
Set ws = CreateObject('wscript.shell')
ws.AppActivate '001 工作表'
是都是可以利用的。
u对于教程最初给出的代码:
Private Sub CommandButton2_Click()
AppActivate 'Microsoft Excel'
End Sub
只适合于32位系统。大家要注意。

2  利用API函数

如本讲的内容,在Word中使用代码自动化激活Excel,其实,在我们写程序的时候,会发现,当运行某个活动应用程序时(如word),从这个运行程序的代码激活另外一个应用程序作为主窗口(如在word运行时激活Excel窗口)对于用户来说是非常有用的。这时我们可以尝试使用上面的AppActivate语句,但这要求事先知道要激活的窗口的标题。而且,从实际的表现看,AppActivate有点给人不靠谱的感觉,有时工作,有时不工作(会提示:引发错误5,无效的过程调用)。所以,我给大家讲解下面的第二种方案就是调用API函数的方案。
我们可以使用几个简单的Windows API函数完成同样的任务。API是直接调用组成Windows的DLL库文件的过程。可以使用API函数完成VBA本身无法执行的操作。但是有一点值得注意。就是API没有VBA代码的错误处理功能,如果使用无效参数调用API函数,可能会导致Excel崩溃并丢失所有工作。API函数的使用应该非常谨慎。
以下代码将激活主Excel窗口并将键盘焦点设置为Excel中的活动工作表。我这里给出的代码在13版32位office中已经实测,在16版及64位ofiice或许不能完全得到你需要的效果,这一点要注意。当然为了保证代码应适用于其他的场合我给出的是通用的版本,可以将MyCLASS的值从xlmain更改为其他应用程序的WINDOW类从而完成实际的需要。
Option Compare Text  '声明比较字符串数据时要使用的默认比较方法按TEXT比较。
' Window API 引用声明
#If VBA7 Then
Private Declare PtrSafe Function BringWindowToTop Lib 'user32' (ByVal HWnd As LongPtr) As Long
Private Declare PtrSafe Function FindWindow Lib 'user32' Alias 'FindWindowA' ( _
ByVal lpClassName As String, _
ByVal lpWindowName As String) As Long
Private Declare PtrSafe Function SetFocus Lib 'user32' (ByVal HWnd As LongPtr) As Long
#Else
Private Declare Function BringWindowToTop Lib 'user32' (ByVal HWnd As Long) As Long
Private Declare Function FindWindow Lib 'user32' Alias 'FindWindowA' ( _
ByVal lpClassName As String, _
ByVal lpWindowName As String) As Long
Private Declare Function SetFocus Lib 'user32' (ByVal HWnd As Long) As Long
#End If
Private Sub CommandButton1_Click()
Dim Res As Long
Dim XLHWnd As Long
Const MyCLASS = 'XLMAIN'
'假如有多个EXCEL运行,程序是无法判断是要激活哪一个EXCEL的;
'同时必须使用vbNullString调用,而不是''的空字符串的调用在FindWindow函数中两者有不同
XLHWnd = FindWindow(lpClassName:=MyCLASS, lpWindowName:=vbNullString)
If XLHWnd > 0 Then
'设置活动窗口
Res = BringWindowToTop(HWnd:=XLHWnd)
If Res = 0 Then
MsgBox '置顶激活错误,错误代码:  ' & CStr(Err.LastDllError)
Else
SetFocus HWnd:=XLHWnd
End If
Else
MsgBox '没有发现 Excel被打开'
End If
End Sub
代码截图:
代码讲解:上述代码在头部建立了引用API函数的声明,在代码中首先会查找excel程序,如果找到会将EXCEL置顶。此程序将激活主EXCEL程序,并获得焦点,注意:如果打开VBA编辑器,此操作将无法正常工作。如果打开VBA编辑器窗口,系统将设置焦点到那个窗口,而不是XLMAIN窗口。此代码可以激活任何应用程序,只需更改myCLASS到应用程序主窗口的类,这里我给大家一些常见的OFFICE应用程序常见的类:
Excel 97、2000、2002、2003、2007、2013  为 XlMain
Word 97、2000、2002、2003、2007、2013   为OpusApp
Access 2000、2002、2003、2007、2013   为OMain
下面我们看看上述代码的详细讲解:
①  Const MYCLASS = 'XLMAIN'
获取主'Excel应用程序窗口的窗口句柄('XLMAIN')。如果“正在运行Excel的多个实例”,您无法控制将检索哪个实例的HWnd。
② XLHWnd = FindWindow(lpClassName:=MyCLASS, lpWindowName:=vbNullString)
在调用' FindWindow时,你必须使用vbNullString不是一个空字符串'',当调用API函数时,vbNullString和空字符串“”之间有区别。
③ BringWindowToTop(HWnd:=XLHWnd) 将应用程序置顶
函数语法: BringWindowToTop(HWND hWnd);
函数功能:该函数将指定的窗口设置到Z序的顶部。如果窗口为顶层窗口,则该窗口被激活;如果窗口为子窗口,则相应的顶级父窗口被激活。
参数:hWnd: 设置到Z序的顶部的窗口句柄。
返回值:如果函数成功,返回值为非零;如果函数失败,返回值为零。若想获得更多错误信息,可以调用GetLastError函数。
④ FindWindow用法
函数功能:该函数获得一个顶层窗口的句柄,该窗口的类名和窗口名与给定的字符串相匹配。这个函数不查找子窗口。在查找时不区分大小写。
函数语法:HWND FindWindow(LPCTSTR IpClassName,LPCTSTR IpWindowName);
参数:IpClassName :指向一个指定了类名的空结束字符串,或一个标识类名字符串的成员的指针。如果该参数为一个成员,则它必须为前次调用theGlobafAddAtom函数产生的全局成员。该成员为16位,必须位于IpClassName的低 16位,高位必须为 0。
IpWindowName:指向一个指定了窗口名(窗口标题)的空结束字符串。如果该参数为空,则为所有窗口全匹配。
返回值:如果函数成功,返回值为具有指定类名和窗口名的窗口句柄;如果函数失败,返回值为NULL。
这个函数有两个参数,第一个是要找的窗口的类,第二个是要找的窗口的标题。在搜索的时候不一定两者都知道,但至少要知道其中的一个。有的窗口的标题是比较容易得到的,如'计算器',所以搜索时应使用标题进行搜索。但有的软件的标题不是固定的,如'记事本',如果打开的文件不同,窗口标题也不同,这时使用窗口类搜索就比较方便。如果找到了满足条件的窗口,这个函数返回该窗口的句柄,否则返回0。
⑤关于句柄,句柄是整个Windows编程的基础。一个句柄是指使用的一个唯一的整数值,即一个4字节(64位程序中为8字节)长的数值,来标识应用程序中的不同对象和同类中的不同的实例,诸如,一个窗口,按钮,图标,滚动条,输出设备,控件或者文件等。应用程序能够通过句柄访问相应的对象的信息,但是句柄不是指针,程序不能利用句柄来直接阅读文件中的信息。如果句柄不在I/O文件中,它是毫无用处的。 句柄是Windows用来标志应用程序中建立的或是使用的唯一整数,Windows大量使用了句柄来标识对象。
⑥ SetFocus HWnd:=XLHWnd
设置焦点。
本节知识点回向:在本节中我们讲了如何做到在不同的应用程序间切换,主要利用了两种方案,一种是利用API函数,要查找到程序的局部然后置顶,一种是利用了AppActivate,这两种方法在应用上要注意测试,对于前者要注意所用的office是否合适于这种应用,后者要注意应用的稳定性。本讲的知识点:
①   AppActivate 如何应用。
②   FindWindow 和 SetFocus 如何应用。
③  上述两种应用的优缺点分析。
④   理解API函数声明与OFFICE版本的关系。
本节代码参考文件“001 在WORD中激活EXCEL.docm”
l学习是自我提高的过程,也是自我修行的过程。学,总会有收获。生命向前,没有达到不了的远方。
我20多年的VBA实践经验,全部浓缩在下面的各个教程中,教程学习顺序:
① 7→1→3→2→6→5或者7→4→3→2→6→5。
② 7→8
各套教程内容简介:
第7套教程(共三册):《VBA之EXCEL应用》:是对VBA基本的讲解
第1套教程(共三册):《VBA代码解决方案》:是入门后的提高教程
第4套教程(16G):VBA代码解决方案之视频(第一套的视频讲解)
第3套教程(共两册):《VBA数组与字典解决方案》:是对数组和字典的专题讲解
第2套教程(共两册):《VBA数据库解决方案》:是对数据库的专题讲解
第6套教程(共两册):《VBA信息获取与处理》:讲解VBA的网络及跨程序应用
第5套教程(共两册):VBA中类的解读和利用:类及接口技术的讲解
第8套教程(共三册):VBA之Word应用(最新教程):word中VBA的利用
l第六套教程:VBA信息获取与处理,这是一部高级教程,涉及范围更广,实用性更强,面向中高级人员。教程共二十个专题,包括:跨应用程序信息获得、随机信息的利用、电子邮件的发送、VBA互联网数据抓取、VBA延时操作,剪切板应用、Split函数扩展、工作表信息与其他应用交互,FSO对象的利用、工作表及文件夹信息的获取、图形信息的获取以及定制工作表信息函数等等内容。程序文件通过32位和64位两种OFFICE系统测试。

_______________________________


(0)

相关推荐