⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 07.txt

📁 VB文章集(含API、窗口、数据库、多媒体、系统、文件、等等)
💻 TXT
📖 第 1 页 / 共 2 页
字号:
Office 95 API 的企业开发者指南


摘要

这篇技术文章探讨如何编写Microsoft Office解决方案代码,以便使用16位和32位版本的Office产品顺利进行应用编程接口(API)调用。特别是,本文适用于Microsoft Access 、Visual Basic 、Microsoft Word 、Microsoft Excel 和Microsoft Project 。实现这种API调用的方法有三类:使用REGISTER、使用Declare语句和使用一个类型库。本文分别对这三种API调用方法进行了探讨和举例。在本文中,假设读者已对我先前的一篇技术文章“将你基于16位Office的解决方案移植到32位Office ”较为熟悉,并且假设读者是一位经验丰富的Office 开发者,他需要移植或编写解决方案,以满足16位到32位互操作性的新要求。

引言

对于编写一个面向多个平台多个版本Microsoft Office 产品的解决方案问题,它是大多数编译语言开发者所不熟悉的。编译语言应用程序开发者喜欢在编辑程序开发中选择一个时间段,将解决方案加到一个执行文件中,而很少需要解决由产品开发引起的问题。一个Office 解决方案应具有一个可在所有Office 产品和所有操作系统中正确执行的解决方案文件(一个.XLS、.MDB、.MPP或.DOT文件)。Office 开发者必须编写具有对前五年内发布的版本的向后兼容性和对将发布的下一版本的向前兼容性。例如,一个在Microsoft Excel 4.0和Microsoft Excel 5.0上运行的费用报告应能在Microsoft Excel NT、Microsoft Excel 95和Microsoft Excel 2001(假定存在)上运行。

Office 95将32位Office 产品引入到主流企业环境中,它们将与16位Office 产品共存许多年。在我以前的一篇技术文章“将你基于16位Office的解决方案移植到32位Office ”中,对不能从一个32位应用程序调用16位API的问题以及不能从一个16位应用程序调用32位API的问题进行了阐述,在那篇文章中列出的16位/32位互操作性解决方案将在本文中作进一步的探讨。

注:根据经验,我把Windows 3.1中的API调用转换为Win32 应用编程接口(API)调用称之为32A规则,即:“如果在任何调用参数中使用了名称字符串,给DLL名添加一个32,给函数名添加一个A(对于ANSI)”。这个经验对于绝大多数API调用是可行的,但对于某些函数,这个经验可能行不通,因此它并不是绝对正确的解决方案。

16位/32位互操作性解决方案比16位API调用移植到相当的32位API调用(换句话说,使用32A规则)的要求更多;它需要解决方案在16位或32位Office 产品中执行时能选择适当的API。

术语

为了避免用语使用的混淆,下列表中定义了在本技术文章中使用的术语:

术语 定义 
Office 产品 不将代码编译为一个可执行程序的产品。下列产品之一:Microsoft Project 、Microsoft Access、Word 和Microsoft Excel 。 
编译语言 将代码编译为一个可执行程序的产品,例如Visual Basic 、FORTRAN、PowerStation 、Visual FoxPro 和Visual C++。 
解决方案 由第三方或开发者使用某个Office 产品及其格式(如Microsoft Excel (.XLS)、Word (.DOT)、Microsoft Project (.MPP)或者Microsoft Access(.MDB))开发的应用程序。 
解决方案代码 编写有解决方案的代码(XLM或Basic或者结合使用) 
平台 Microsoft Windows和Apple Macintosh 操作系统。一些Office 产品适用于所有Windows和Macintosh操作系统。通过将解决方案从一个操作系统复制到另一操作系统, Microsoft Excel 可在Macintosh和Windows PC中执行同一应用程序(在一定的限制条件下)。 

 

API调用方法

解决方案代码可采用下列三种方法之一进行编写--使用Microsoft Excel 宏(XLM)、Basic(Access Basic、Visual Basic 、VBA和WordBasic)或者混合使用XLM和Basic。XLM使用REGISTER和CALL命令来进行API调用,Basic使用Declare语句、类型库或者这两者的结合使用来进行API调用。经一个开发者传给另一开发者的Microsoft Excel 解决方案可以使用所有这些方法进行API调用。这三种方法对于最新版本的Microsoft Excel 都适用。

表1 API调用方法描述

方法 语言 进行API调用的方法 
REGISTER XLM宏 从宏中使用REGISTER和CALL函数 
Declare Access Basic、
Visual Basic 、

VBA、WordBasic
 使用Declare语句 
类型库 仅VBA 从对象浏览器上选择类型库方法 

这些方法不会产生某个特定版本的解决方案,它取决于开发者编写代码的引用或解决方案所必须运行的产品范围。例如,为了使解决方案在Microsoft Excel 4.0中也有效,开发者可以在Microsoft Excel 95的XLM中编写一个解决方案。表2中列出了各种API调用可在哪些Microsoft 产品中使用。

表2 Microsoft 产品的API调用方法

产品版本 REGISTER方法 Declare方法 类型库方法 
Microsoft Excel 3.0,4.0 X     
Microsoft Excel 5.0,5.0NT,95 X X X 
Word 2.0,6.0,95   X   
Visual Basic 1.0,2.0,3.0   X   
Visual Basic 4.0   X X 
Project 4.0,95   X   
Microsoft Access1.0,1.1,2.0   X   
Microsoft Access95   X X 
FoxPro 2.5   X   
FoxPro 3.0   X X 

我们在讨论16位和32位API调用时,都将使用同一个简单的API调用示例--GetTickCount来进行论述。

REGISTER方法

对于在编写Office 解决方案前先在Visual Basic 中编写过代码的开发者,他们并不熟悉使用REGISTER方法的API调用。旧版本Microsoft Excel 的开发者从XLM中进行API调用,并避免使用VBA。我们不能把XLM看作是过时的技术--虽然从Microsoft Excel 4.0开始未对其更改。如果性能问题变得很重要时,XLM仍是最好的选择。Microsoft Excel 5.0开发者工具包中陈述了直接从XLM中进行API调用的优点。

由于C API最易于在Microsoft Excel 宏和工作表上使用,因此对于Visual Basic 所用的外部函数的编写,它并不是非常好(虽然VB 和C API可被融入混合解决方案中)。

为了从XLM进行API调用,要求使用REGISTER函数来引用动态连接库(DLL)以及使用CALL函数来执行它。REGISTER函数与VBA中的Declare语句的作用是一样的。推荐的REGISTER句法如下:

REGISTER(module_text,procedure,type_text,function_text,argument_text,macro_type,category,shortcut_text)

要返回到所给出的API调用示例,我们可以在XLM的一些代码行中采用GetTickCount。

这个代码在16位Microsoft Excel 中产生下列输出:

如果我们在32位的Microsoft Excel 中运行这个代码,结果是失败的。API调用返回#VALUE!,表明传递给DLL或从DLL中传递变量是失败的:

我们必须将这个代码转换为一个32位的API调用,因此,我们使用32A规则,在DLL名上添加一个32,如果是字符串,在其上添加一个A。采用32A规则的代码如下所示。

在调用TestGetTickCount32A时,我们会遇到另一种错误。返回#NAME?变量,这意味着在DLL中不存在这个函数。它可能是错误的DLL或错误的函数名(记住,函数名是区分大小写的)。这必定是32A规则的一个例外(我承认,我是有意选用这个函数的)。

在MSDN库中,使用关键字索引在PlatformSDK(平台软件开发包)中查找GetTickCount。在主题的顶端弹出的快速信息(Quick Info)会告诉你该函数在KERNEL32库中(在Window 3.x中,该函数在USER库中)。下列代码列出修改后的32位Microsoft Excel 宏。

在32位Microsoft Excel 中运行此代码,我们得到正确的结果:

为说明在16位和32位Microsoft Excel 中的API调用方式,参阅表3,表中显示了这些宏的结果。使用32A规则的宏(“32A位”)在16位和32位解决方案中产生的结果相同。它说明了REGISTER函数从16位或者32位解决方案中定位(或定位失败)16位和32位DLL中的函数名的能力。返回#VALUE!表明在传递或接收参数中出现了问题。

表3:从16位和32位Microsoft Excel 进行调用的结果

Microsoft Excel 4.0(16位版) Microsoft Excel 95(32位版)

我们能够编写宏以进行16位API调用或32位API调用,但是,我们必须编写可进行16位API调用和32位API调用的宏,这取决于Office 产品的版本。解决方案代码必须在16位Microsoft Excel 和32位Microsoft Excel 上均能运行。在我以前的文章(“将你基于16位Office的解决方案移植到32位Office ”)中描述的VBA函数Engine32不能在Microsoft Excel 4.0(Microsoft Excel 4.0不包含VBA)中正常工作。Engine32可在Microsoft Excel 5.0及更高版本上正常工作。一个与Microsoft Excel 4.0兼容的Engine32函数必须使用宏代码。

XLM的Engine32函数

对于XLM,解决方案与VBA解决方案类似。如果Microsoft Excel 是一个32位版,函数信息(“osversion(操作系统版本)”)将包含32。如果Microsoft Excel 是一个32位版,下列所示的Engine32宏返回TRUE;如果Microsoft Excel 是16位版,该宏返回FALSE。

REGISTER方法解决方案的示例

由于Enging32已定义,GetTickCount的宏代码很简单:

Engine32将在所有版本的Microsoft Excel 中运行正常。GetTickCount函数与在Windows3.1中的API调用是一样的。

注:如果对性能关心,你应在装载这个解决方案时注册所有API调用。

REGISTER方法解决方案的步骤

如果你正将Microsoft Excel 解决方案转换为能在16位和32位产品上运行的解决方案,我建议你采用下列步骤:

创建一个名为APICALLS的新宏;

在APICALLS宏中创建Engine32函数;

定位解决方案中的所有REGISTER函数,并将它们移到APICALLS中,一个一栏;

使用上面的REGISTER解决方案示例中的宏代码作为一个模板,在你的宏表中为每个API创建函数;

添加所需的ARGUMENT行;

添加所需的RESULT行;

添加16位API REGISTER行,在函数名后加上16;

添加32位API REGISTER行,在函数名后加上32;

进行任何数据处理以进行API调用;

添加一个IF行以调用相应的API;

RETURE返回变量(如果有);

测试函数;

为Microsoft Excel 定义函数。

这个过程可使宏表中现有的API调用保持原样。一旦你创建了宏表APICALLS(并进行了测试),你可以把它加到其他解决方案中,重复使用这个宏,这样可节省转换时间。该宏表的内容独立于解决方案(它仅包含Windows API调用)并可在其他解决方案中重复使用。这个宏表APICALLS成为将来开发16位/32位解决方案的罗塞达石碑。

Declare方法

VBA的引入给Microsoft Excel 开发者提供了XLM的替代方法。Visual Basic 、WordBasic和Microsoft Access开发者也能毫无困难地编写Microsoft Excel 和Microsoft Project解决方案。Basic代码可在广泛的产品中进行交换。年轻一代的Office 开发者将在VBA中编写代码,而很少使用XLM。

从VBA中调用API需要使用API Declare语句。一个经声明的API可在Basic代码(或在一个宏中)的任何地方被调用。编写Declare语句有两种方法,如下所示:

Word Declare语句

'Word是首选的编写Declare 语句的方法

'它的格式是固定的,具有向后兼容性。

Declare Sub SubName Lib LibName$ [(ArgumentList)] [ Alias Routine$]

Declare Function FunctionName[$] Lib LibName$ [( ArgumentList)] [Alias Routine$] As Type

VBA、Basic和Microsoft Access Declare语句

Declare Sub globalname Lib "libname" [Alias "aliasname" ][([ argumentlist])]

Declare Function globalname Lib libname [Alias aliasname ] [([ argumentlist])] [As type]

因为我已在“将你基于16位Office的解决方案移植到32位Office ”中进行了这方面的一些讨论,并得出了上面的分类,我将简要地利用一个函数示例来说明Declare解决方案。

Basic Engine32函数

如果32位API调用是正常的(16位API调用失败),Engine32函数返回True;如果16位API调用是正常的(32位API调用失败),该函数返回False。在“将你基于16位Office的解决方案移植到32位Office ”一文中给出的Engine32函数被设计成可说明它们在每个Office 产品中的差异的示例。下面给出的是经修改后的函数,它具有更好的性能并能在更多的版本上运行。

利用在第一个函数中初始化静态变量可改善性能。随后的所有调用使用这些静态变量,而不是重复进行额外的函数调用。改善性能的另一方法是初始化一个全局或公有变量;然而,它存在一个缺陷,在一些产品中发生Reset(重置)时,在全局变量得到重新初始化前,随后的所有API调用可能失败。

Microsoft Excel 5或更高版本和Project 4或更高版本

如果Microsoft Excel 和Microsoft Project 是32位的产品,它们中的Application.OperatingSystem属性通常包含32。由于Microsoft Excel 5.0既有16位产品又有32位产品,因此产品版本号是不充分的。

Function Engine32%()

Static sEngine32%,SEval% 'Statics用于性能的改善。

If SEval% Then Engine32%=sEngine32%: Exit Function

If instr(Application.OperatingSystem,"32") then sEngine32%=True

Seval%=True

Engine32%=sEngine32%

End Function

Microsoft Access 1.1或更高版

Microsoft Access不具有既有16位又有32位产品的版本。通过调用SysCmd检查版本号,确定正在使用的Microsoft Access的版本。Microsoft Access 1.1在构造时没有加入一个版本号常量,因此,我们通常使用7,以确保代码可在Microsoft Access中正常工作。这种方法可用来查看你的解决方案代码进行的是一个16位还是一个32位API调用。

Function Engine32% ()

Static sEngine32%,SEval%

If SEval% Then Engine32%=sEngine32%: Exit Function

If SysCmd(7) > 2 Then sEngine32% = True

Seval%=True

End Function

Word for Wndows 2.0或更高版

由于Word不支持静态变量,Word 必须每次对Engine32函数赋值。首先,我们检查产品版本号是否表明其是一个32位版本,然后我们检查操作系统的版本,查看它是否是一个32位的操作系统。这两个步骤是需要的,因为Word 6.0以前的版本不能使用GetSystemInfo,并且Word 6.0既具有16位版又具有32位版。

Function Engine32

Engine32 = 0

If Val(AppInfo$(2)) > 5 Then

OS$ = GetSystemInfo$(23)

If Val(OS$) > 6.3 Or Len(OS$) = 0 Then Engine32 = - 1

End If

End Function

Visual Basic

虽然Visual Basic 不使用解决方案代码,但Basic代码通常要与包含上述的产品之间进行交换。Visual Basic 4.0没有 Application.OperatingSystem 属性(它不是VBA所专有的一部分),而是使用条件编译#IF和 #ELSE。如果你打算将你的代码与其他Microsoft 产品共享,你应创建下列函数(不要在别处使用条件编译):

Function Engine32%()

'这仅针对 VB4。

#IF WIN16

Engine32% = False

#ELSE

Engine32% = True

#ENDIF

End Function

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -