使用Microsoft自动化组件
作者:
摘自:网络
在Servers页面上的组件是TOleServer的子类。类型库(.TLB)被引入到Delphi中。一个类型库是一种描述一个自动化服务器接口的特殊文件。当一个TLB被引入到Delphi的时候,Delphi将这个类型库封装到一个组件类中;这个组件可以被安装到VCL中。在组件面板中Servers属性页上的组件是自动化服务器,每个自动化服务器代表Microsoft Office中一个特定的应用程序部分。
注意:本章包括一个摘自Evil Empire详细材料的讨论。建议你学习这门技术。如果您是一个反Microsoft的成员,您可以跳过本章,但是要记住Inprise为我们提供代表这些应用程序服务器的组件有它足够的理由。如果要使用Delphi控制Microsoft Office可以帮助您的话,考虑使用这些组件。
自动化是COM协议的一部分。自动化描述了服务器应用程序怎样将接口提供给客户应用程序以及客户端怎样通过编程控制服务器。客户应用程序被叫做自动化控制器。自动化控制器可以是使用任何支持自动化的语言编写的应用程序或者动态链接库。您可以很容易地在Delphi中创建客户端控制器和自动化服务器。
本章介绍了怎样使用当今世界上一些最具有特色的对象——Microsoft Office应用程序。绝大多数,可能是全部的Office都可以用作自动化服务器。这意味着它们可以被用作独立的应用程序或者应用程序服务器。使用这些功能强大的应用程序服务器可以使开发者能够提供功能强大的文字处理、数据库、数字处理和关系管理的能力,这取代了许多用户已经购买的一些现有的代码。
12.1 TOleServer
TOleServer是TComponent的子类。OleServer对象具有TComponent的所有特性和方法,并且这些特性和方法都在TOleServer类中被定义了。Servers属性页上的组件是Microsoft Offiec自动化服务器,TOleServer是这些组件的直接祖先类,所以很好的理解ToleServer可以使您有一个更高的起点。表12.1列出了OleServer中所有的特性,表12.2列出了OleServer中所有的方法。除了OleServer特性,TOleServer的每一个子类将引入在类型库中定义的行为和数据。我们将在本章的后面部分作详细的介绍。
表12.1 TOleServer特性,其中AutoConnect,ConnectKind和
RemoteMachineName是由TOleServer引入的公开特性
特性 |
说明 |
AutoConnect |
如果这个特性为True,服务器在运行时连接。如果在运行时将其特性改为False将不会在运行时产生影响 |
ConnectKind |
由TConnectKind枚举定义,描述服务器怎样被连接。比如说,ckRunningOrNew将连接到服务器的一个运行实例或者开始一个新的实例。可以选择的项为:ckRunningOrNew,ckNewInstance, ckRunningInstance, ckRemote,ckAttach ToInterface |
EventDispatch |
保护特性,可以被为COM事件特性服务的子孙类所使用 |
RemoteMachineName |
指定运行服务器的机器名,将ConnectKind特性设置为ckRemote,您将连接到其他独立计算机的服务器上 |
ServerData |
保护的记录特性,它保存了有关连接到的自动化服务器的信息 |
下面用表12.1的特性作一个示范,遵循下面所列的步骤,将连接到您的网络中其他计算机上的一个Microsoft Word实例(需要远程计算机的名称,并且远程计算机必须有一个Microsoft Word的一个拷贝。在“控制面板”中的“网络”小应用程序中的“标识”属性页中的“计算机名”域中可以找到计算机名称)。
1.创建一个新的Delphi应用程序。
2.在窗体上的任何位置放置一个TButton组件。
3.在窗体上放置一个TWordDocument组件。
4.在Object Inspector中(可以按F11打开),将WordDocument组件的Remote MachineName特性设置为安装有Microsoft Word的计算机名称(在“控制面板”中的“网络”小应用程序中的“标识”属性页中的“计算机名”域中可以找到计算机名称或者你也可以使用机器中相应于RemoteMachineName的IP地址)。
5.第4步将ConnectKind特性改变为ckRemote。
6.双击第2步中窗体上的按钮,为按钮添加Click事件处理程序。
7.将下面的代码添加到第6步创建的事件处理程序中。
procedure TForm1.Button1Click(Sender: TObject);
var
FileName : OleVariant;
begin
WordDocument1.Connect;
try
WordDocument1.Content.Text := 'Viva Las Vegas!';
FileName := 'c:\temp\vegas.doc';
WordDocument1.SaveAs(FileName);
finally
WordDocument1.Disconnect;
end;
end;
注意:您不能够使远程计算机上的Word服务器实例在远程计算机上可视。但您可以使Word 服务器实例在运行客户端控制器的计算机上可视。
WordDocument已经被连接了。如果您和远程的计算机很近,当加载Word实例的时候您将看到硬盘指示灯会短暂地亮一下。WordDocument的Content特性代表了所有文档的内容;text特性是显示在文档体上的实际文本。SaveAs方法必须有一个OleVariant类型的变量。确保正确的路径。最后断开与Word文档的连接。TWordDocument是TOleServer的子孙类。在上面的程序段中,只从TOleServer继承了Connect和Disconnect两个方法。Content特性和SaveAs方法是由TWordDocument组件引入的方法。请参考表12.2所示TOleServer的方法。
提示:leading_in接口方法(如_AddRef方法)被自动加入,以使它们与其他的方法区别开。在一般情况下没有必要调用这些方法。
每一个继承TOleServer的类都具有表12.1和表12.2中列出的特性和方法。所有在组件面板的Server属性页上的自动化服务器在它们的直接祖先中有TComponent和TOleServer。
表12.2 TOleServer的方法:MSOffice自动化服务器继承了这些方法
方法 |
说明 |
_AddRef |
保护方法,用于增加引用服务器对象的引用计数 |
_Release |
减少引用计数的保护方法,如果引用计数等于0,那么对象将从内存中被释放 |
Connect |
虚抽象方法,子孙类使用这个方法连接到服务器,如果ConnectKind设置为ckAttachToInterface,那么子孙类将使用ConnectTo方法实现 |
ConnectEvents |
保护方法,用于在内部实现COM事件处理程序 |
Create |
构造一服务器类的实例 |
Destroy |
解除一服务器类的实例 |
Disconnnect |
虚抽象方法,子孙类用于终止与服务器的连接 |
DisconnectEvents |
终止由ConnectEvents方法创建的连接 |
GetAutoConnect |
保护方法,用于读取AutoConnect特性 |
GetConnectKind |
保护方法,用于读取ConnectKind特性 |
GetServer |
保护方法,返回与服务器的一个接口 |
InitServerData |
保护方法,用于初始化ServerData特性 |
InvokeEvent |
为COM对象发送一个事件到正确的事件处理程序 |
Loaded |
当从DFM文件中读取stream-published特性的时候调用Loaded;如果AutoConnect设置为True,Loaded被重载并连接到服务器 |
QueryInterface |
返回与指定接口的引用(如果服务器支持这个接口) |
SetAutoConnect |
保护方法,用于设置AutoConnect特性 |
SetConnectKind |
保护方法,用于设置ConnectKind特性 |
12.2 Microsoft 自动化服务器
代码再使用是在COM和DCOM(分布式COM)的后台被激活的,动态链接库是COM的祖先。想想,COM的创造者——Microsoft,会在它的一些应用程序中包含COM接口,这一点也不奇怪。对于Microsoft和我们来说,COM是一种获取应用程序间相互操作的手段。许多Microsoft的应用程序是自动化服务器,包括Access, Schedule+,Word,Excel,PowerPoint,PhotoDraw,Outlook,FrontPage,MS-Project和 Visual Source Safe。这意味着您可以再使用这些特色丰富的应用程序作为您的应用程序的服务器。
有许多不同的方法用于自动化服务器,本节将介绍其中一些服务器。
12.2.1 自动化服务器组件概览
从Delphi应用程序中使用自动化服务器最简单的方法是在专业版和企业版的Servers属性页中选择你所感兴趣的组件。因为这些服务器的库被引入到Delphi中,并被组件化了,所以它们都具有TOleObject类接口。它们同样具有在特定的服务器的COM接口中暴露的方法、特性和事件,这里的特定的服务器根据服务器的需要来指定。表12.3列出了所有当前可用的服务器组件。
注意:Delphi类的结构(被指定为一个接口)和在.TLB(类型库)文件中描述的COM接口在语义上很相似,但语法不同。本章我们将全部使用Delphi代码访问自动化服务器,因此现在很有必要首先讨论COM接口。
表12.3 Microsoft自动化服务器在VCL库中集成为组件
组件 |
服务器说明 |
TWordDocument |
Microsoft Word的文档接口。包含了Content接口,Content接口包含在文档中实际显示的文本 |
TWordFont |
Font接口使您可以操纵字体 |
TWordParagraphFormat |
Paragraph接口简化了控制段落缩进、段落终止和段落级别上的文本控制 |
TWordLetterContent |
LetterContent接口支持控制容器、主题、拷贝和其他文字创建任务 |
TWordApplication |
这个Application接口为Word自动化服务器自身 |
TExcelQueryTable |
QueryTable接口允许从外部的Recordset中重新获取数据(Recordset是一个ADO对象,类似于Delphi中的TDataSet) |
TExcelApplication |
这个Application接口表示Excel自动化服务器 |
TExcelChart |
Chart接口支持绘图 |
TExcelWorksheet |
Worksheet接口表示一个基于单元的电子表格 |
TExcelWorkbook |
Workbook接口表示包含文件所有工作表的视图 |
TExcelOleObject |
OleObject为在工作表中与一个嵌入的Ole对象的接口 |
TPowerPointSlide |
Slide接口表示在演示中的单幻灯片 |
TPowerPointPresentation |
与Powerpoint演示的一个接口;接口是Presentation |
(续表)
组件 |
服务器说明 |
TPowerPointApplication |
Power Point 自动化服务器 |
TMaster |
Master接口表示PowerPoint幻灯片控制器,它控制演示时如背景、颜色布局和文本风格的特性 |
TBinder |
Binder接口(只在Office 97上可用)支持从完全不同的Office应用程序中添加文档到统一的文档中 |
TFormatCondition |
有条件地格式化Access中组合框和文本框中的文本 |
TAccessHyperlink |
在Access中的超链接接口 |
TAccessForm |
Access具有设计图形用户接口的能力;这个类表示Form接口 |
TAccessReport |
Access Report接口 |
TAccessApplication |
Access应用程序自动化服务器接口 |
TAccessReferences |
在Access引用中,TAccessReferences引用Access应用程序所引用的外部库。这个引用集合包括了所有使用中的库引用的列表。比如说,Access中的Visual Basic Editor就有msado15.dll(支持ADO对象)的引用 |
TDataAccessPage |
数据激活网页接口,DataAccessPage引用Access创建的外部网页 |
TAllForms |
AllForms集合接口包括所有在Access数据库中的窗体 |
TAllReports |
AllReports集合接口包括了所有Access数据库中的报表 |
TAllMacros |
AllMacros接口包括了所有数据库中的宏 |
TAllModules |
AllModules返回所有Access数据库中的Visual Basic模块(.BAS)和(.CLS)文件 |
TAllDataAccessPages |
所有在Access数据库中的数据访问页 |
TAllTables |
所有在Access数据库中的表 |
TAllQueries |
AllQueries是与每个数据库所有查询的集合的一个接口 |
TAllViews |
Access 2000工程支持视图和存储过程,AllViews是与Access 2000工程中的所有视图的一个接口,并使用SQL Server数据库 |
TAllStoredProcedures |
在Access工程中的所有存储过程 |
TAllDatabaseDiagrams |
Access 2000工程使用SQL Server数据库,并支持ERDs(实体关系图表)的创建。这个集合是Access 2000工程中与所有ERDs的接口 |
TCurrentProject |
CurrentProject接口引用Access自身的运行实例 |
TCurrentData |
此接口包含与Access 2000工程中所有集合的一个引用(比如说,AllDatabaseDiagrams,AllStoredProcedures等) |
TCodeProject |
此接口引用在Access数据库(.MDB)和工程(.ADP)中包含代码的对象 |
TWizHook |
紧随Answer Wizard |
TDefaultWebOptions |
与包含超级链接颜色编码的DefaultWebOptions(默认Web选项)的一个接口 |
TAccessWebOptions |
Access的Web选项,覆盖DefaultWebOptions |
TClass_ |
实现Visual Basic类模块的基本接口,包括初始化和终止的事件处理程序 |
提示:服务器组件的源代码可以在您所安装Delphi的OCX\Server目录中找到。
Servers属性页上的VCL组件的使用要比使用CreateOleObject(请参考下一节)创建自动化服务器简单得多。首先,它们的类型库已经被导入了,并且已经在TOleServer子类中创建了Delphi接口。这使您可以更一致地使用Object Pascal,而不必涉及到用Windows使用这些服务器。再者,当您使用一个特定类型的服务器对象的时候,完整代码特性将自动为您显示特性、方法和事件。如果您使用变体数据类型创建这个COM服务器,则需要有服务器特性的一个备用引用。
本章示范了一些使用自动化服务器组件的例子。但是,如果组件不存在,您仍然可以使用自动化服务器;不过您需要使用一个更低级的提取。比如说,Visual SourceSafe不出现在VCL面板上,但是它是一个自动化服务器,您可以给这个服务器定义一个客户端控制器。
12.2.2 导入类型库
如果一个自动化服务器已经存在,但是没有为这个服务器定义组件,那么您可以通过导入这个类型库创建这个组件。一个比较好的例子是Visual SourceSafe。SourceSafe是一个来自Microsoft的源控制应用程序,它同Visual Studio和Microsoft Office Development工具一起出售。您可以使用SourceSafe自动化服务器自动存档数据,将数据保护能力加入到您的应用程序中。
导入类型库
当您为一个自动化服务器导入类型库的时候,Delphi将这个类型库封装进子孙组件包装器(TOleServer的子类,在本章的前面部分已经作了介绍)中。这个组件包装器自动包含所必须的Register过程,将组件安装到VCL中。要导入一个类型库,选择Project菜单中的Import Type Library。在Import Type Library对话框中显示了有效的类型库列表,如图12.1所示。
Import Type Library对话框上面的列表框列出了所有已经注册的类型库(图12.1显示出SourceSafe服务器已经在PC机上注册了,我们将用这个类型库作示范)。单击Create Unit(创建单元)按钮创建类型库单元。如果这个单元已经存在,那么对话框提示是否覆盖这个已经存在的类型库单元。如果您选择了“Yes”,那么将创建新的单元,选择了“No”则打开这个已经存在的单元。
查看SourceSafe单元;Register过程列在单元的后面部分,如下所示。
procedure Register;
begin
RegisterComponents(‘ActiveX’,[TVSSDatabase]);
end;
您可以注册组件(参考下一部分)或者通过编程动态创建服务器的实例。在下一部分介绍安装组件,在此之后的CreateOleObject部分示范了在组件没有安装的情况下使用这个组件的例子。
图12.1 Import Type Library为从已经注册的COM对象创建类型库
提供了方便,(本图示出了被选择的Visual SourceSafe类型库)
注册自动化服务器
当一个类型库被导入时,它被包装进一个TOleServer组件包装器中。这时,您可以使用Component菜单像安装其他组件一样安装类型库。假设您已经为Visual SourceSafe组件创建了一个类型库,或者已经打开了已经存在的类型库,则完成下面的步骤来安装这个组件。
注意:您需要在您的PC机上有一份Visual SourceSafe 6.0的拷贝,以执行下面的步骤来安装 SourceSafe组件。
1.将SourceSafe的类型库调到Delphi的前台,选择Component,然后选择Install Component。
2.选择New Package属性页,将组件安装到一个新的包中。
3.确保单元文件名指向SourceSafe类型库;文件名应该类似于SourceSafeTypeLib _TLB.pas。
4.选择一个包文件名(如果您选择了Into new package属性页,如图12.2所示,那么请输入新的包名和路径)。
5.输入简短的有关包的说明,如图12.2所示。
6.单击OK按钮,组件单元将被编译;包库将被链接并且安装到VCL组件面板中。
图12.2 Install Component对话框,包含安装一个SourceSafe组件的信息
回想一下前面部分所列的Register过程,输入一个类型库,TVSSDatabase组件将被安装到组件面板上的ActiveX属性页中。要改变目标属性页,将文本“ActiveX”改为“Servers”,这将安装这个服务器到Servers属性页中。
您已经创建了组件,您可以像使用其他自动化服务器组件一样使用这个组件。它具有与任何TOleServer一样的基本接口,以及SourceSafe所特有的附加特性。
例子程序有一个菜单(有File,Import File菜单项)、一个列表框和一个Memo,例子程序用SourceSafe数据库的文件填充列表框。当您在列表框中选择一个文件,然后单击File,Import File的时候,处理Import File的OnClick事件方法从SourceSafe获得一个文件的拷贝,然后将这个文件加载到Memo控件中。下面的程序说明了上面步骤1~6中已经创建的TVSSDatabase组件的使用。
unit USourceSafeDemo;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls,
Forms, Dialogs,
StdCtrls, comobj, OleServer, access2000, SourceSafeTypeLib_TLB,
Menus;
type
TForm1 = class(TForm)
Memo1: TMemo;
MainMenu1: TMainMenu;
File1: TMenuItem;
ImportFile1: TMenuItem;
ListBox1: TListBox;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure ImportFile1Click(Sender: TObject);
private
{ Private declarations }
procedure PopulateList;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.FormCreate(Sender: TObject);
const
DatabaseName = 'xxxxxxxxxxxxxxx\srcsafe.ini';
UserName = 'xxxxxxx';
Password = 'xxxxxxxx';
begin
VSSDatabase1.Connect;
VSSDatabase1.Open( DatabaseName, UserName, Password );
PopulateList;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
VSSDatabase1.Disconnect;
end;
procedure TForm1.PopulateList;
const
ProjectPath = '/xxxxxxxx xxx/xxxxxx';
var
I : Integer;
begin
VSSDatabase1.CurrentProject := ProjectPath;
with VSSDatabase1.VSSItem[VSSDatabase1.CurrentProject,
False].Items[False] do
for I := 1 to Count do
ListBox1.Items.Add( Item[I].Name );
end;
procedure TForm1.ImportFile1Click(Sender: TObject);
const
Path = 'c:\temp\';
var
FileName, Target, Source: WideString;
begin
try
FileName := ListBox1.Items[ListBox1.ItemIndex];
Target := Path + FileName;
Source := VSSDatabase1.CurrentProject + '/' + FileName;
VSSDatabase1.VSSItem[ Source, False ].Get( Target,
VSSFLAG_USERROYES );
Memo1.Lines.LoadFromFile( Output );
except
on E : EListError do
ShowException( E, Addr(E));
end;
end;
end.
警告:这个应用程序的例子需要有Visual SourceSafe 6.0、一个实际的SourceSafe数据库(数据库里包含文件),并且c:\temp目录必须存在,否则这个程序将不能工作。
FormCreate事件处理程序连接到服务器,并以特定的用户和密码打开SourceSafe数据库(现有的路径、用户名和密码被注销,因为例子测试时与现有使用中的数据库冲突)。记住在DatabaseName的后面添加srcsafe.ini文件,调用PopulateList函数用工程中的文件名填充列表框(如图12.3所示)。析构函数断开与自动化服务器的连接。
图12.3 存储在SourceSafe中的文件列表
在Items集合中的所有条款中都重复使用了PopulateList方法。with子句在PopulateList中,其后面的VSSData-base1.VSSItem[VSSDatabase1.CurrentProject, False].Items[False]分解如下。VSSDatabase1是引用自动化服务器的组件。VSSItem数组由工程名字(一个工程在SourceSafe中看起来就像一个目录结构)索引,第二个参数为True或者False,False表示被删除的文件也被包括进来。Items特性引用工程和包含在VSSDatabase1.CurrentProject中的文件,并且False值表示被删除的项不被包括进来(这有点冗长)。
当ImportFile OnClick事件处理程序被调用的时候,被选择的文件用于索引VSSItem,并且调用VSSItem的Get方法使这个文件只读——VSSFLAG_USERROYES设置文件的只读特性。这个文件从SourceSafe被写到一个外部文件,由Memo1的Lines特性描述的TString对象从外部文件加载源代码。
使用这个代码,如本部分开始的时候所介绍的,您可以很容易地在您所能创建的任何软件中加入版本控制,最好复习一下这部分内容,以更好地理解。作如下思考,将TVSSDatabase组件包装到一个类中,以整理为获取一个文件列表或者执行检查所带来的繁琐的步骤。
下面部分示范在没有类型库或者合适的组件包装器的时候怎样创建自动化实例。
12.2.3 CreateOleObject
CreateOleObject在comobj.pas中作了定义。这是通过调用ole32.dll库中的CoCreateInstance过程实现的。当您使用CreateOleObject创建自动化服务器的时候,需要类的名称并且需要指定一个变体数据类型的返回值,虽然您还可以使用在服务器中定义的接口,但是您需要知道什么接口。Delphi的代码完整性不能辅助您有关接口的信息。所以在任何可能的情况下使用组件包装器。
procedure TForm1.PopulateList;
var
I : Integer;
VSS : Variant;
Begin
VSS := CreateOleObject('SourceSafe');
try
VSS.Open( 'xxxxxxxxxxx xxx\srcsafe.ini', 'xxxxxxx',
'xxxxxxxx');
VSS.CurrentProject := '/xxxxxxxx xxx/xxxxxx';
for I := 1 to VSS.VSSItem[VSS.CurrentProject].Items.Count do
ListBox1.Items.Add(
VSS.VSSItem[VSS.CurrentProject].Items.Item[I].Name );
finally
VSS := varNull;
end;
end;
前面所列的程序中再次使用了PopulateList,该例子示范了怎样创建SourceSafe自动化服务器的实例,PopulateList打开了数据库、设置当前的工程、并填充列表框,全部都在一个函数中完成。相对而言,代码看起来不像本章早些时候的组件化版本那么复杂。可能最大的不同之处是,前面的版本允许代码完整,在需要正确地获得特性和方法的时候可以提供更多帮助。
12.2.4 CreateRemoteComObject
CreateRemoteComObject在comobj.pas中作了定义。这通过调用ole32.dll中定义的CoCreateInstanceEx函数实现。如果您想查看这个函数,您可以看到许多附加的工作隐藏在CreateRemoteComObject中。
这个函数创建一个自动化服务器的实例,如果服务器组件可用的话使用一个服务器组件会更加容易,但是这不免是另外一种方法。下一个例子同本章开始的时候举的例子一样,惟一的不同之处是本例使用CreateRemoteComObject函数运行Word实例,而不是使用TWordDocument服务器组件。
var
Document : OleVariant;
begin
Document := CreateRemoteComObject('PTK300',
StringToGuid('Word.Document'))
As WordDocument;
Document.Content.Text := 'Viva Las Vegas!';
Document.SaveAs('c:\temp\viva_vegas.doc');
end;
CreateRemoteComObject返回一个IUnknown接口类型;As WordDocument子句,看起来像一个动态抛掷,实际上在这个上下文中是引导编译器调用IUnknown的QueryInterface方法以确定这个COM对象是否支持这个接口文档。在这个例子里,COM对象支持接口文档。Word应用程序运行在远程计算机上,其Content.Text特性指定为“Viva Las Vegas!”,文档被保存到文件中。
本章的剩下部分介绍怎样使用已经存在的组件。我们将在附录C中再次讨论怎样创建自动化服务器。
12.3 Access
作为一个Delphi开发者,通常您可能反对使用Microsoft工具。很明显,尽管如此Microsoft的 Access可以用来创建桌面数据库应用程序,它担任了数据库的角色。同时应该注意Access是一个完整的开发工具,包括一个基于对象的语言和Visual Basic for Applications。并且Access是一个自动化服务器。
可能会出现这种情况,在Access中已经实现了全部代码,或者在Access中有一些方便的工具,但却可能在Delphi中重新使用会很耗时并且不方便,其中一个例子就是Get External Data特性。Access有一个内建的解析引擎用于读取和解析固定的或者是定界的文本文件,并将它们导入到数据库中。如果有一个处理过程需要读取文本文件到数据库中,为什么不使用Access作为服务器来为您完成这个处理呢?其结果将会是更有力地和更方便地实现这个过程,而没有必要从头开始凑合代码。
12.3.1 用Access解析固定长度的数据
看起来似乎在身边就有很巨大数目的定长数据。比如说,NSCC(国家证券交易所)保存了大约8500个美国的证券代理商的商业数据。NSCC是一个票据交换所,从事两种主要的股票交易和OTC(over-the-counter)证券市场。每天会有成千上万的商业认证在NSCC处理。代理商必须使用NSCC商业认证数据为他们已经注册的代表处理委托。NSCC是一个很好的例子,大银行、保险公司、代理商以及许多其他组织也是在规定的原则基础上处理固定格式的数据。
注意:类似IBM和 Microsoft这样的公司从事交易协议,这将使这些数据直接跨渡客户端服务器应用程序。您将发现您必须处理固定格式的文本数据,除非这些协议在主干流中。
任何开发者可能都有过编写一个解析算法的想法,解析固定格式数据,将其转换为更可用的格式。即便这样说,像类似于在第3章中介绍的TParser类的类,都只使解析固定格式数据的工作变得更简单一些(只是相对于从头开始编写程序来说),但实际上并不简单。要实现最少数目的步骤必须考虑使用完整的解决方案。请进入Microsoft Access。
定义导入规范
Microsoft Access有一个功能强大的解析引擎,这使您可以可视地解析样本数据文件。任何您所定义的可视解析规则可以被保存为导入规范。以后固定格式的文件可以快速地被导入,重复使用任何已经保存的导入规范。因为Access通过Application.DoCmd接口暴露这个特性,您可以控制递归解析任务的导入。
注意:本部分的例子是用Access 2000实现的,这需要Access 2000的一个拷贝来完成这个例子。
导入规范可以根据需要变得很简单或者很复杂。Access的使用没有限制,由于本书的篇幅原因和为讲解更清楚的原因,这个例子文件很简单。为了介绍,假设您有一个固定长度文件(包含一个日期,格式为yyyymmdd)、一个基于9位数社会保险账号号码和一个没有小数的不定长度的交易数量。下面是一个文件的例子,例子中显示了列标题值(标题不包括在实际的数据文件中)。
日期 账号 交易
2000021255512456713056
20000301555236789145607
2000041766656123456
逻辑字段和值的界限如表12.4所示。
表12.4 包含日期、账号号码和交易数量的固定长度文件
日期 |
账号 |
交易 |
20000212 |
555124567 |
13056 |
20000301 |
555236789 |
145607 |
20000417 |
666561234 |
56 |
第一行包含了列标题,第四行包含值56,代表交易的数量是56分。要在Access中定义一个导入规范,请完成下面所示的步骤。
1.使用前面表12.4创建固定长度文件,不要使用列标题。文件命名为anydata.txt,并保存到c:\temp目录中。
2.运行Microsoft Access 2000。
3.当Access打开的时候,提示您打开一个已经存在的数据库。在上面标有“Create a new database using”的组合框中,选择“Blank Access Database”(如图12.4所示)左边的单选按钮。选择一个数据库名称并定位。记住选择的数据库名称和位置。在本例中,用c:\temp\anydata.mdb。
图12.4 创建新的空Access数据库
4.在Access中,依次单击File | Get External Data | Import。在导入对话框中,改变文件的类型字段为文本文件。选择c:\temp\anydata.txt文件,单击Import按钮。将弹出Import Text(导入文本)向导对话框,如图12.5所示。
5.单击Next按钮。在列表框的上面,在标记下面,从左边数起,在8和17的位置处单击创建垂直线断点(如图12.5所示)。
6.单击Advanced按钮。此按钮将打开Import Specification(导入规范)对话框,如图12.6所示。
7.在打开的对话框中,改变File Format(文件格式)为Fixed Width(固定长度)。改变日期顺序为YDM,选择Dates复选框中的Four Digit Years和Leading Zeros(图12.6为完成导入规范的示意图)。
图12.5 Access Import Text向导
图12.6 使用Import Specification对话框定义和保存一个导入
规范,该导入规范被Access和自动化控制器重新使用
8.单击Save As 按钮保存导入规范为“Any-Data Import Specification”。您必须记住这个导入规范的名称,因为这将被自动化控制器用以运行导入。
9.单击OK按钮关闭Import Specification对话框。
10.单击Finish按钮接受后面的默认值。
使用三行测试数据,完成上面所示的步骤。Access将创建一个名为AnyData的表(为被导入文件的文件名部分),添加一个主键字段。Access将自动为主键字段提供一个惟一的关键字,在默认情况下命名为ID。
测试导入规范
在任何时候您所获得四位数据只要和已经存在的导入规范匹配,您就可以重新使用这个匹配的规范导入并很快解析添加的数据。使用导入规范,您可以编写一个自动化控制器,它可以自动运行这个处理过程。
下面的代码使用这个导入规范和前面部分所用的样本文本文件,示范了用Access应用程序作为自动化服务器来导入数据。
const
DatabaseName = 'c:\temp\anydata.mdb';
SpecificationName = 'AnyData Import Specification';
FileName = 'c:\temp\anydata.txt';
TableName = 'AnyData';
procedure TForm1.ImportTextData1Click(Sender: TObject);
begin
AccessApplication1.Connect;
try
AccessApplication1.OpenCurrentDatabase( DatabaseName, False );
AccessApplication1.DoCmd.TransferText( acImportFixed,
SpecificationName, TableName, FileName, False, '', 0);
AccessApplication1.CloseCurrentDatabase;
finally
AccessApplication1.Disconnect;
end;
end;
TAccessApplication组件从组件面板的Servers属性页中添加进来。将ConnectKindr修改为ckNewInstance。如果您使用默认值ckRunningOrNew,那么如果数据库已经被打开的话AccessApplication1.OpenCurrentDatabase将引发一个异常。常量acImportFixed已经在Access2000.pas中作了定义;当您添加TAccessApplication Server组件的时候,Access2000.pas将被添加进来。SpecificationName是在导入规范中定义的名称。TableName可以是一个新的或者已经存在的表名称。DatabaseName参数是Access MDB数据库文件,文本文件是您所想导入的任何文件。
查看数据
您可以在Delphi中添加一个ODBC别名简化对表的使用。在Windows 控制面板中使用ODBC小应用程序来创建一个别名。Data Access和Data Control组件可以被用来创建浏览器,用于查看被导入的数据(参考第13章开始的一个例子,这个例子示范了怎样创建一个数据表浏览器)。
12.4 小 结
自动化控制器所发挥的作用可以和被使用的自动化服务器所发挥的作用一样。可以控制Access和Word以用于数据库和Word处理任务,以及在您的应用程序中并入版本控制能力。您可以直接从Outlook中读取相关的数据、控制PowerPoint演示或者更多。使用自动化服务器可能完成的事务是巨大的。这些应用程序的复杂程度是难以想象的,可以这么说,要详细地介绍与使用自动化服务器有关的任何一个应用程序都需要几百页的篇幅。安装一个自动化服务器、运行这个服务器和获取服务器对象是第一步,接下来需要做的就是学习使用那些接口了。
在本章中,您体验到了COM自动化的重要部分。您学习了怎样创建一个自动化服务器的实例、怎样导入类型库和怎样编写自动化控制器。还学习了在组件类(TOleServer的子类)中使用Delphi包装COM对象。首先,创建组件简化了使用自动化服务器,这是最直接的方法。请参考附录C,那里有创建自身的自动化服务器应用程序的例子。
使用Microsoft自动化组件相关推荐
- VS2008下, Microsoft AJAX 组件开发单独js智能提示
VS2008下,在使用单独JS文件开发 Microsoft AJAX 组件时,在js的第一行加上引用标记即可实现js智能提示. ASP.NET 2.0 /// <reference name & ...
- SQL Server2019安装步骤及脱机安装Microsoft机器学习组件下一步不能继续的问题
目录 1.下载 2.安装 (1)脱机安装Microsoft机器学习服务器组件无法出现下一步的解决方案 1.下载 首先下载好SQL Server 2014 安装包,下面也给大家提供了SQL Server ...
- DevOps自动化组件-RUNDECK介绍、开发、部署、使用
前言碎语 RunDeck 是用 Java开发的自动化部署持续集成的工具应用,项目已开源.runDeck的产品属性和jenkis类似.提供web界面和restapi来给用户使用,Web界面主要提供给非开 ...
- Aspose.Word企业案例:Acumen Fuse 使用 Aspose 组件将项目分析数据导出到 Microsoft Word 和 Excel
关于 Acumen Fuse Acumen Fuse™ 是一种指标分析和可视化工具,不仅可以评估进度,还可以评估成本.风险.挣值和项目绩效.使用度量库,Fuse™ 分析提供了一种强大的方法来查明项目中 ...
- 检索COM 类工厂中CLSID 为{00024500-0000-0000-C000-000000000046}组件时失败
检索 COM 类工厂中 CLSID 为{00024500-0000-0000-C000-000000000046} 的组件时失败,原因是出现以下错误: 80070005 当在ASP.NET应用程序中引 ...
- 深入了解Blazor组件
目录 介绍 什么是组件? 渲染器和渲染树 客户端应用程序 Blazor服务器 Blazor Web Assembly App.razor 组件 HelloWorld组件 一个简单的IComponent ...
- [转载]在ASP.NET中使用Microsoft Word文档
[介绍] 本文是应在ASP.NET里创建Microsoft Word文档之需而写的.这篇文章演示了在ASP.NET里怎么创建和修改Microsoft Word文档. [背景] 自动化是一种能让各种语言 ...
- Microsoft 365管理和报告工具
在管理 Microsoft 365 设置的过程中,本机Microsoft 365 功能可能无法满足你的需求.M365 Manager Plus 具有复杂的功能,使 Microsoft 365 管理毫不 ...
- COM 组件设计与应用(十一)—— IDispatch 及双接口的调用
原文:http://www.vckbase.com/index.php/wv/1236 一.前言 前段时间,由于工作比较忙,没有能及时地写作.其间收到了很多网友的来信询问和鼓励,在此一并表示感谢.咳. ...
最新文章
- 段页式存储管理方式的定义
- 从电影死亡笔记看商业智能在治安领域的应用
- NYOJ 891 找点
- 什么是 ABAP Field Symbol
- ListView上移 和下移
- HTML+CSS+JS实现燃烧的火焰火花动画特效
- 解决矩池云使用中ssh链接的时候日志丢失
- 简单高精度模板(bzoj 1089: [SCOI2003]严格n元树)
- Android API中文文档(111) —— MailTo
- VMware系统运维(十一)部署虚拟化桌面 Horizon View 5.2 HTML ACCESS安装
- 计算机科学与技术的学习路线
- NUC970 SD卡驱动(SDIO)
- 沃谈小知识| 断网不下岗的“断点续传”功能
- 正方教务管理系统后台敏感日志查看漏洞
- Creating and Configuring a CDB
- DIY钢铁侠电动开合
- 『TensorFlow』模型载入方法汇总
- opc服务器不稳定的原因,OPC Client和OPC Server容易出现通讯故障,原因是什么?
- Android版简历(四)
- ghost android x86,系统之家GHOST WIN7x86 纯净版v2019.11
热门文章
- 【币圈心得】套单、交易框架
- 用shell脚本自动监测Kafka积压
- json过滤某些属性之@JsonIgnore
- 微信小程序 LBS 能力全面解析
- iOS支付宝支付(Alipay)详细接入流程以及项目中遇到的问题分析
- SpringBoot-Binder的使用
- Vuex的核心概念 Action
- linux克隆后修改网卡名称,vmware虚拟机克隆后网卡修改
- 甘肃省计算机科学技术专业好的大学,甘肃省普通高等学校计算机科学与技术专业综合评价通用指标体系(普通本科)...
- 利用大数据 构建用户画像 为电商平台 提供精准营销