《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')代码讲解:我们先看看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系统):ReturnValue = Shell('C:\Microsoft Office\Office\Word.exe',1)u特别注意点,对于AppActivate的用法,我在修订代码的时候进行了完善,对于64位的OFFICE系统和32位的OFFICE系统,下面的代码:Set ws = CreateObject('wscript.shell')Private Sub CommandButton2_Click()AppActivate 'Microsoft Excel'
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比较。Private Declare PtrSafe Function BringWindowToTop Lib 'user32' (ByVal HWnd As LongPtr) As LongPrivate Declare PtrSafe Function FindWindow Lib 'user32' Alias 'FindWindowA' ( _ByVal lpClassName As String, _ByVal lpWindowName As String) As LongPrivate Declare PtrSafe Function SetFocus Lib 'user32' (ByVal HWnd As LongPtr) As LongPrivate Declare Function BringWindowToTop Lib 'user32' (ByVal HWnd As Long) As LongPrivate Declare Function FindWindow Lib 'user32' Alias 'FindWindowA' ( _ByVal lpClassName As String, _ByVal lpWindowName As String) As LongPrivate Declare Function SetFocus Lib 'user32' (ByVal HWnd As Long) As LongPrivate Sub CommandButton1_Click()'假如有多个EXCEL运行,程序是无法判断是要激活哪一个EXCEL的;'同时必须使用vbNullString调用,而不是''的空字符串的调用在FindWindow函数中两者有不同XLHWnd = FindWindow(lpClassName:=MyCLASS, lpWindowName:=vbNullString)Res = BringWindowToTop(HWnd:=XLHWnd)MsgBox '置顶激活错误,错误代码: ' & CStr(Err.LastDllError)代码讲解:上述代码在头部建立了引用API函数的声明,在代码中首先会查找excel程序,如果找到会将EXCEL置顶。此程序将激活主EXCEL程序,并获得焦点,注意:如果打开VBA编辑器,此操作将无法正常工作。如果打开VBA编辑器窗口,系统将设置焦点到那个窗口,而不是XLMAIN窗口。此代码可以激活任何应用程序,只需更改myCLASS到应用程序主窗口的类,这里我给大家一些常见的OFFICE应用程序常见的类:Excel 97、2000、2002、2003、2007、2013 为 XlMainWord 97、2000、2002、2003、2007、2013 为OpusAppAccess 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序的顶部。如果窗口为顶层窗口,则该窗口被激活;如果窗口为子窗口,则相应的顶级父窗口被激活。返回值:如果函数成功,返回值为非零;如果函数失败,返回值为零。若想获得更多错误信息,可以调用GetLastError函数。函数功能:该函数获得一个顶层窗口的句柄,该窗口的类名和窗口名与给定的字符串相匹配。这个函数不查找子窗口。在查找时不区分大小写。函数语法:HWND FindWindow(LPCTSTR IpClassName,LPCTSTR IpWindowName);参数:IpClassName :指向一个指定了类名的空结束字符串,或一个标识类名字符串的成员的指针。如果该参数为一个成员,则它必须为前次调用theGlobafAddAtom函数产生的全局成员。该成员为16位,必须位于IpClassName的低 16位,高位必须为 0。IpWindowName:指向一个指定了窗口名(窗口标题)的空结束字符串。如果该参数为空,则为所有窗口全匹配。返回值:如果函数成功,返回值为具有指定类名和窗口名的窗口句柄;如果函数失败,返回值为NULL。这个函数有两个参数,第一个是要找的窗口的类,第二个是要找的窗口的标题。在搜索的时候不一定两者都知道,但至少要知道其中的一个。有的窗口的标题是比较容易得到的,如'计算器',所以搜索时应使用标题进行搜索。但有的软件的标题不是固定的,如'记事本',如果打开的文件不同,窗口标题也不同,这时使用窗口类搜索就比较方便。如果找到了满足条件的窗口,这个函数返回该窗口的句柄,否则返回0。⑤关于句柄,句柄是整个Windows编程的基础。一个句柄是指使用的一个唯一的整数值,即一个4字节(64位程序中为8字节)长的数值,来标识应用程序中的不同对象和同类中的不同的实例,诸如,一个窗口,按钮,图标,滚动条,输出设备,控件或者文件等。应用程序能够通过句柄访问相应的对象的信息,但是句柄不是指针,程序不能利用句柄来直接阅读文件中的信息。如果句柄不在I/O文件中,它是毫无用处的。 句柄是Windows用来标志应用程序中建立的或是使用的唯一整数,Windows大量使用了句柄来标识对象。本节知识点回向:在本节中我们讲了如何做到在不同的应用程序间切换,主要利用了两种方案,一种是利用API函数,要查找到程序的局部然后置顶,一种是利用了AppActivate,这两种方法在应用上要注意测试,对于前者要注意所用的office是否合适于这种应用,后者要注意应用的稳定性。本讲的知识点:② FindWindow 和 SetFocus 如何应用。本节代码参考文件“001 在WORD中激活EXCEL.docm”l学习是自我提高的过程,也是自我修行的过程。学,总会有收获。生命向前,没有达到不了的远方。我20多年的VBA实践经验,全部浓缩在下面的各个教程中,教程学习顺序:① 7→1→3→2→6→5或者7→4→3→2→6→5。第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系统测试。
_______________________________