朋友帮忙:300高分求对WORD,EXCEL的控制: ( 积分: 300 )

  • 主题发起人 主题发起人 wei0916
  • 开始时间 开始时间
W

wei0916

Unregistered / Unconfirmed
GUEST, unregistred user!
问题如下:
1:如果一个WORD文档有多页,要求用程序得出最大页数并循环选中每一页.
2:如果一个EXCEL有多行,要求用程序选中任意多行多列.
3:将WORD文档的底色变成黑色.
工作急需.可以QQ交流:503588783
最好请针对上面的功能给出实现过程或源码,不要给一些链接或者别人的贴子,我找过大富翁的资料,看过一些贴子,但还是没有发现能实现上面功能的贴子.
 
每一项实现网上都有例子, 很简单, 自己动手录制宏代码, 翻译成delphi就可以了。
 
楼下说的很对,我每次就是这样搞的.
并且是非常的行之有效啊.
 
帮你顶,接点小分!
 
冷涯:你好.你能告诉我上面的问题吗.
 
使用COM对象,本论坛中就有,
在离线库里一下就找到了,给你铁一下

蚯蚓 (2000-05-21 22:54:00)
关于使用COM对象的方法,以Microsoft Word为例,作简要说明:


Step0: 从Word的类型库(Type Library)文件生成声明文件(xxx_TLB.pas),

要使用自动对象,必须先读取相应的类型库文件(*.TLB),从其中得到自动对象的类型信息,

方法:在Delphi IDE中打开....../Microsoft Office/Office/M$Word8.olb

Delphi将根据类型库中的信息生成声明单元Word_TLB.pas,

注意,Delphi在转换过程中将以下符号(symbol)进行了重命名(rename):
--------------------------------------------------------
类型库中的符号 重命名为
--------------------------------------------------------
Application WordApplication
Document WordDocument
Font WordFont
ParagraphFormat WordParagraphFormat
OLEControl WordOLEControl
LetterContent WordLetterContent
--------------------------------------------------------
这个问题后面会详细讨论



Word_TLB.pas中包含的如下信息:
...
...
const
...
//coClass "Application" 的ClassID
CLASS_WordApplication: TGUID = '{000209FF-0000-0000-C000-000000000046}';
...
...
...
我们也将在后面用到

蚯蚓 (2000-05-21 22:56:00)
Step1: 创建WordApplication对象,如下:

函数CreateCOMObject将根据指定的ClassID创建对应的COM自动对象,声明如下:

//unit COMObj
function CreateCOMObject(const ClassID: TGUID): IUnknown;

在本例中,我们创建WordApplication对象的代码如下:


// 引用COMObj单元和Word_TLB单元
uses
..., ..., ..., COMObj, Word_TLB;

type
TfmMain = class(TForm)
...
...
private
// 声明一个变量,保存WordApplication的引用
// WordApplication在Word_TLB单元中声明
WordApp: WordApplication;
protected
procedure StartWordApp;
procedure TerminateWordApp;
end;

其中StartWordApp方法将分别创建一个WordApplication对象,
实现如下:

procedure TfmMain.StartWordApp;
begin
if not Assigned(WordApp) then
try
// 创建WordApplication对象
WordApp:=CreateCOMObject(CLASS_WordApplication) as WordApplication;
with WordApp do
begin
// 指定COM对象的属性
Caption:='This copy of WinWord is launched by '+Forms.Application.ExeName;
Visible:=True;
end;
ShowMsg('启动 Word Application 成功');
except
ShowError('启动 Word Application 失败');
end;
end;

procedure TfmMain.btStartWordAppClick(Sender: TObject);
begin
StartWordApp;
end;

soul (2000-05-21 22:58:00)
????????什么意思??????

蚯蚓 (2000-05-21 23:00:00)
Step2: 创建WordApplication对象后就可以使用其属性和方法了,如下:

// 创建新文档
procedure TfmMain.btNewDocClick(Sender: TObject);
var
DocTemplate,
NewTemplate : OleVariant;
begin
StartWordApp;
DocTemplate := UnAssigned; // 打开新文档时使用的模板
NewTemplate := False; // 是否将文档作为模板打开
WordApp.Documents.Add(DocTemplate,NewTemplate);
end;

// 关闭当前文档
procedure TfmMain.btCloseDocClick(Sender: TObject);
var
SaveChanges,
OriginalFormat,
RouteDocument : OleVariant;
begin
SaveChanges := WdDoNotSaveChanges; // 不保存修改
OriginalFormat := UnAssigned; // 未赋值
RouteDocument := UnAssigned; // 未赋值
WordApp.ActiveDocument.Close(SaveChanges,OriginalFormat,RouteDocument);
end;

蚯蚓 (2000-05-21 23:04:00)
Step3:COM对象使用完毕后,注意释放

TerminateWordApp方法将释放WordApp指向的COM对象,
实现如下:

procedure TfmMain.TerminateWordApp;
var
SaveChanges,
OriginalFormat,
RouteDocument : OleVariant;
begin
if Assigned(WordApp) then
begin
SaveChanges := WdDoNotSaveChanges; // 不保存修改
OriginalFormat := UnAssigned; // 未赋值
RouteDocument := UnAssigned; // 未赋值
try
// 调用COM对象方法
WordApp.Quit(SaveChanges,OriginalFormat,RouteDocument);
ShowMsg('关闭 Word Application 成功');
except
ErrorMsg('关闭 Word Application 失败');
end;
// 将WordApp赋值为Nil,则原来指向的COM对象的引用记数减1
// 当引用记数为0时,COM对象将被释放
WordApp := Nil;
end;
end;

procedure TfmMain.FormDestroy(Sender: TObject);
begin
TerminateWordApp;
end;

soul (2000-05-21 23:05:00)
sorry!

soul (2000-05-21 23:06:00)
可惜没有收藏夹。

soul (2000-05-21 23:08:00)
估计很快会被hubdog收藏到葵花宝典里

蚯蚓 (2000-05-21 23:08:00)
后记:
1、以上所述方法是完全通过编程直接调用COM实现的,
所有使用COM的地方都可以通过上面的方法实现,
步骤为:
(0)根据类型库文件生成声明单元
(1)得到需要的ClassID后使用CreateCOMObject函数创建COM对象
(2)使用COM对象的属性和方法完成操作
(3)释放COM对象

2、我们的目的不仅仅是为了控制Word,而是为了说明使用COM的根本方法,
选择Word作为例子,是因为大家都比较熟悉,
对Word的控制,Delphi已经提供了一些支持,包括:
....../Delphi5/Ocx/Servers/Word97.pas
等于前面所说的Word_TLB.pas,

....../Delphi5/Demos/Activex/Oleauto/Word8/autoimpl.pas
将以上对COM对象的操作封装成了一个Delphi类

还可以参考两个示例:
....../Delphi5/Demos/Activex/Oleauto/Word8/word8auto.dpr

....../Delphi5/Demos/Activex/Oleauto/SrvCOMp/Word/pwordCOMp.dpr


3、一般情况下会同时提供很多COM Server,
应该使用什么对象、使用什么方法、使用什么属性
需要参考帮助文件,上面的例子中M$Word8.olb的帮助文件为:
..../Microsoft Office/Office/VBAWRD8.HLP
在没有帮助文件的情况下就需要研究类型库中的信息了


4、关于类型库本身
类型库包含非常丰富的信息,包括:

Interface、DispInterface、CoClass、Enumeration、
Alias、Record、Union、Module等等

这些是类型库的基本信息,此外还包括:
指定的帮助文件、所依赖的其它类型库等等

类型库一般以单独的类型库文件(*.TLB)提供,或包含在Server程序中(*.EXE、*.DLL)
类型库信息包含在EXE中的例子有:
..../Delphi5/Demos/Activex/Oleauto/Autoserv/memoedit.dpr
在DLL中的例子有:
..../Delphi5/Bin/StdVcl40.DLL
这两种情况下,实际上类型库信息都包含在EXE/DLL中的名为"TypeLib"的资源中

查看M$Word8.OLB可以看到,它实际上是一个DLL格式文件

5、关于类型库的Register和Unregister
Windows下有注册类型库的程序RegSvr32.exe,Borland自己也有TRegSvr.exe
除此之外,在Delphi IDE中打开类型库后,可以使用菜单Run|Register ActiveX Server
或Run|Unregister ActiveX Server
那么类型库的Register和Unregister具体是怎么实现的呢,

打开..../Delphi5/Demos/Activex/TRegSvr/TRegSvr.dpr,查看源代码,我们可以看到:
(1)对于*.tlb:
调用OleAut32.DLL中的LoadLibrary函数,得到一个ITypeLib接口,
调用ITypeLib的GetLibAttr方法,得到tagTLibAttr结构,其中包括
GUID、LCID、Major Version、Minor Version、SysKind信息
Register的方法是:
调用OleAut32.DLL中RegisterTypeLib函数
Unregister的方法是:
调用OleAut32.DLL中UnregisterTypeLib函数,参数由前面的tagTLibAttr结构中各域指定

详见TRegSvr.dpr中的RegisterTLB过程

(2)对于*.dll:
调用LoadLibrary函数载入dll
Register的方法是:
调用DLL中的DllRegisterServer函数
Unregister的方法是:
调用DLL中的DllUnregisterServer函数
(3)对于*.exe
Register的方法是:
调用EXE,命令行参数为"/RegServer"
Unregister的方法是:
调用EXE,命令行参数为"/UnregServer"
也就是说,对于DLL和EXE,应该实现自注册(Self Register),
即ActiveX Server本身完成Register和Unregister动作。

对于Delphi编写的ActiveX Server,这些工作都在COMServ.pas完成,
详细的过程比较罗嗦,有兴趣可以去看看,
主要的代码在RegisterTypeLibrary和UnregisterTypeLibrary过程中
和上面的TRegSvr.dpr中对TLB的注册过程大致一样

经过上面的分析可以看到,最终都是通过OleAut32.DLL中的
RegisterTypeLib和UnregisterTypeLib完成的,

我们注意到一点奇怪的现象:
上面提到的源代码在调用RegisterTypeLib时都是直接调用,
该函数的声明在ActiveX.pas中,指定到OleAut32.DLL中的RegisterTypeLib函数
就在相同的地方,我们也看到了UnregisterTypeLib的声明,
但是,上面提到的源代码在调用UnregisterTypeLib时都没有直接调用,
而是先GetModuleHandle('OLEAut32.DLL'),然后用GetProcAddress查找UnregisterTypeLib,
再根据查找的结果进行调用
而且所有相关的地方都是这样进行,估计不是失误,这样看来,
似乎Borland在写这段程序时考虑到了OLEAut32.DLL中不包括UnregisterTypeLib函数的情况,
难道OLEAut32.DLL的早期版本中的确不包括UnregisterTypeLib函数??
但M$DN对UnregisterTypeLib的说明没有提到

6、关于打开类型库时符号重命名(symbol rename)
类型库中某些符号在生成声明单元时被重命名,
大部分是因为符号名与Pascal关键字重名,因此Delphi必须重命名

但前面说到的几个符号的重命名显然不是这个原因,我们注意到:
(1)这几个符号都是CoClass,而且是类型库中几乎全部的CoClass,
只有一个CoClass:"Global"不在其中
(2)这几个符号被重命名后都加上了"Word"前缀,
而这个类型库的名称正好就是"Word"
其中是否存在联系??

7、对于任意的一个CoClass,从类型库中可以得到其中的interface信息,
因此创建和释放COM对象的代码可以自动生成,
对于所有的interface,也可以从类型库中得到其属性、方法信息,
因此访问这些属性、方法的代码也可以自动生成

由此,Delphi 5 将在声明单元中为所有的CoClass
创建相应的代理类(OLE Server Proxy class),
这些代理类以Delphi类的形式提供封装,而内部实现了对COM对象的全部操作,
包括创建、释放以及访问各种属性和方法
另外,Delphi 5还会将这些代理类作为组件注册到组件板的'Server'页面上
详情请在xxx_TLB.pas中查找"OLE Server Proxy class"

通过这些代理类,我们可以很方便地使用COM对象,
而不必向上面所说的那样一切都通过自己实现,
当然,前面所说的是一切的基础,应该作为原理了解


soul (2000-05-21 23:12:00)
所以,象这样的帖子是否可以让出题人选出关键贴,然后在加一个显示并发送此贴精华呢?

沈前卫 (2000-05-21 23:28:00)
不错,不错,就是这类文章太少了。 :)

白马小将 (2000-05-22 0:07:00)
听君一席话,胜读十年书。


蚯蚓 (2000-05-23 23:00:00)
<font color=darkgreen><b>版权没有
欢迎转载
</b></font>

adminis (2000-05-23 23:20:00)
哈哈,这个死蚯蚓,化成灰我也认得你。
在网上水平又高,又不贪财的有几个?
你是不是名望太高怕惹人耳目?
所以改做幕后工作?
佩服佩服。

蚯蚓 (2000-05-23 23:25:00)
这篇是我自己写的,
起因是几个月前有个家伙问我COM对象该怎么调用,
于是我就打开类型库看啊看啊。。。。。


最近还看到几篇好文章,很适合入门者,可惜是E文的,
打算熬几夜翻译出来,再贴给大家看。。。

amo (2000-05-24 0:07:00)
钦佩,
本来上次参与sonie的题目对COM也有了一点了解,
也想写点心得,
不过总是瞎忙这瞎忙那,
最后没写

到底是earthworm,
在地下勤勤恳恳

向你学习,
不过我就不钻到地下去的;-)

avant (2000-05-24 19:40:00)
太好了,谢谢,还有吗?
继续关注!

小虎 (2000-05-25 12:03:00)
终于忍不住贴上来了。
不过,我最后还是用别的方法搞定的。
等哪天有空,写出来给你看

蚯蚓 (2000-05-25 23:22:00)
>> 终于忍不住贴上来了

实在是闲的无聊啊, 没办法

再说了,人都是有表现欲的嘛,
你难道没写过 'xxx到此一游' ?
乾隆老爷子不也写了一万多首"诗"??

cheka (2000-05-25 23:54:00)
大富翁真应该有个精华区的,放一些非FAQ的专题文章.
网易广州社区的C版精华区就狠酷.

沈前卫 (2000-05-26 2:04:00)
精华区没多大必要,还是学习学习ex-ex,限制人的发言权,注册为专家才分发言,
答错以红色显示,专家分不能用来提问。 :)

蚯蚓 (2000-06-07 13:48:00)
接受答案了.


沈前卫的回答最终被接受。
 
delphi有自带的ole控件可以操作!
2ccc有例子!
 
学习一下。
 
http://www.star-reg.com/dl/ExcelRead&WriteOCX.rar
这项技术可较好地解决你的问题
QQ:292044357
 
正在研究该类问题,可以交流一下.qq:154711636
 
顶分喔!
 
首先创建 Excel 对象,使用ComObj:
var ExcelApp: Variant;
ExcelApp := CreateOleObject( 'Excel.Application' );

1) 显示当前窗口:
ExcelApp.Visible := True;

2) 更改 Excel 标题栏:
ExcelApp.Caption := '应用程序调用 Microsoft Excel';

3) 添加新工作簿:
ExcelApp.WorkBooks.Add;

4) 打开已存在的工作簿:
ExcelApp.WorkBooks.Open( 'C:/Excel/Demo.xls' );

5) 设置第2个工作表为活动工作表:
ExcelApp.WorkSheets[2].Activate;

ExcelApp.WorksSheets[ 'Sheet2' ].Activate;

6) 给单元格赋值:
ExcelApp.Cells[1,4].Value := '第一行第四列';

7) 设置指定列的宽度(单位:字符个数),以第一列为例:
ExcelApp.ActiveSheet.Columns[1].ColumnsWidth := 5;

8) 设置指定行的高度(单位:磅)(1磅=0.035厘米),以第二行为例:
ExcelApp.ActiveSheet.Rows[2].RowHeight := 1/0.035; // 1厘米

9) 在第8行之前插入分页符:
ExcelApp.WorkSheets[1].Rows[8].PageBreak := 1;

10) 在第8列之前删除分页符:
ExcelApp.ActiveSheet.Columns[4].PageBreak := 0;

11) 指定边框线宽度:
ExcelApp.ActiveSheet.Range[ 'B3:D4' ].Borders[2].Weight := 3;
1-左 2-右 3-顶 4-底 5-斜( / ) 6-斜( / )

12) 清除第一行第四列单元格公式:
ExcelApp.ActiveSheet.Cells[1,4].ClearContents;

13) 设置第一行字体属性:
ExcelApp.ActiveSheet.Rows[1].Font.Name := '隶书';
ExcelApp.ActiveSheet.Rows[1].Font.Color := clBlue;
ExcelApp.ActiveSheet.Rows[1].Font.Bold := True;
ExcelApp.ActiveSheet.Rows[1].Font.UnderLine := True;

14) 进行页面设置:

a.页眉:
ExcelApp.ActiveSheet.PageSetup.CenterHeader := '报表演示';
b.页脚:
ExcelApp.ActiveSheet.PageSetup.CenterFooter := '第&P页';
c.页眉到顶端边距2cm:
ExcelApp.ActiveSheet.PageSetup.HeaderMargin := 2/0.035;
d.页脚到底端边距3cm:
ExcelApp.ActiveSheet.PageSetup.HeaderMargin := 3/0.035;
e.顶边距2cm:
ExcelApp.ActiveSheet.PageSetup.TopMargin := 2/0.035;
f.底边距2cm:
ExcelApp.ActiveSheet.PageSetup.BottomMargin := 2/0.035;
g.左边距2cm:
ExcelApp.ActiveSheet.PageSetup.LeftMargin := 2/0.035;
h.右边距2cm:
ExcelApp.ActiveSheet.PageSetup.RightMargin := 2/0.035;
i.页面水平居中:
ExcelApp.ActiveSheet.PageSetup.CenterHorizontally := 2/0.035;
j.页面垂直居中:
ExcelApp.ActiveSheet.PageSetup.CenterVertically := 2/0.035;
k.打印单元格网线:
ExcelApp.ActiveSheet.PageSetup.PrintGridLines := True;

15) 拷贝操作:

a.拷贝整个工作表:
ExcelApp.ActiveSheet.Used.Range.Copy;
b.拷贝指定区域:
ExcelApp.ActiveSheet.Range[ 'A1:E2' ].Copy;
c.从A1位置开始粘贴:
ExcelApp.ActiveSheet.Range.[ 'A1' ].PasteSpecial;
d.从文件尾部开始粘贴:
ExcelApp.ActiveSheet.Range.PasteSpecial;

16) 插入一行或一列:
a. ExcelApp.ActiveSheet.Rows[2].Insert;
b. ExcelApp.ActiveSheet.Columns[1].Insert;

17) 删除一行或一列:
a. ExcelApp.ActiveSheet.Rows[2].Delete;
b. ExcelApp.ActiveSheet.Columns[1].Delete;

18) 打印预览工作表:
ExcelApp.ActiveSheet.PrintPreview;

19) 打印输出工作表:
ExcelApp.ActiveSheet.PrintOut;

20) 工作表保存:
if not ExcelApp.ActiveWorkBook.Saved then
ExcelApp.ActiveSheet.PrintPreview;

21) 工作表另存为:
ExcelApp.SaveAs( 'C:/Excel/Demo1.xls' );

22) 放弃存盘:
ExcelApp.ActiveWorkBook.Saved := True;

23) 关闭工作簿:
ExcelApp.WorkBooks.Close;

24) 退出 Excel:
ExcelApp.Quit;

(二) 使用Delphi 控件方法
在Form中分别放入ExcelApplication, ExcelWorkbook和ExcelWorksheet。

1) 打开Excel
ExcelApplication1.Connect;

2) 显示当前窗口:
ExcelApplication1.Visible[0]:=True;

3) 更改 Excel 标题栏:
ExcelApplication1.Caption := '应用程序调用 Microsoft Excel';

4) 添加新工作簿:
ExcelWorkbook1.ConnectTo(ExcelApplication1.Workbooks.Add(EmptyParam,0));

5) 添加新工作表:
var Temp_Worksheet: _WorkSheet;
begin
Temp_Worksheet:=ExcelWorkbook1.
WorkSheets.Add(EmptyParam,EmptyParam,EmptyParam,EmptyParam,0) as _WorkSheet;
ExcelWorkSheet1.ConnectTo(Temp_WorkSheet);
End;

6) 打开已存在的工作簿:
ExcelApplication1.Workbooks.Open (c:/a.xls
EmptyParam,EmptyParam,EmptyParam,EmptyParam,
EmptyParam,EmptyP
 
后退
顶部