内置于php4里的com函数对于我们在win32环境下开发程序是相当有吸引力的,但是至今仍没有多少相关的技术文档。本文将以三个例子分别处理 ms office 2000 word 、 excel 、 adobe distiller 来说明如何在php中使用com函数。
com技术是由microsoft在几年前提出并开发的,本文中提到的相关名词有ole, ole automation,activex, com ,这些词的意思都基本一样,都表示用一段封装的代码(对象)来完成一个windows 应用程序的一些功能。 php4 com 函数可以连接一个对象实例,并使用它的方法与属性。
如果你想使用下面的例子源码,请参考一下我的配置。
windows 98 - ms office 2000
apache 1.3.9 windows
php4.02 dev (08-20-00) running as cgi
php4中的com标记
现在让我们开始吧,用php4的com来实例化一个组件,需要 new 操作符和对象的 "ole 程序标识":
$instance = new com("$identifier");
?>
因为com是一个php4的保留字,它传送这个对象的标识给一个构造函数,现在得到了这个组件的一个实例,根据oop类的性质,我们可以很容易地访问它的方法与属性。
例如:
$instance->[object]->[method1]->[method2]->..->[property];
?>
就是这么简单!
oop的结构在php下不能工作,(由于php语法的问题,属性的名字.值是非法字符,如点和圆括号等),所以php4提供了两个相应的函数:
bool com_set(class com_object, string property name, string property_value);
mixed com_get(class com_object, string property_name);
?>
最后,php4也支持dcom技术,可以在远程计算机创建一个对象实例。
$instance = new com(string "component name", string "remote_server_address");
?>
注意:这是用dcom指令来设置php。在将来,php开发者提供unix下对dcom的支持。
标识、方法和属性
标识是一个如下的字串:
ms word: "word.application" or "word.application.9"
ms excel: "excel.application" or "excel.sheet"
adobe acrobat: "exch.application" or "pdfdistiller.pdfdistiller"
对于最后一个标识,我要指明的是,获得正确的对象标识名不是一件容易的事。如果你不能访问vba文档,你可以查找一下windows的注册表,在 hkey_classes_root 中寻找一下,你就可以得到一些应用程序的名字。在你的机器上有效的对象标识放在 clsid 子文件夹下。
应用程序一般会提供文档说明它的com方法和属性。在office2000中,你可以运行程序,打开vba编辑器 ,选择对象编辑器。输入应用程序库中的一个方法名或属性名,然后,在下面的窗口中用鼠标右键选择一个类或成员名称,点帮助,你就会得到关于这个类或成员的描述。你也可以参考 msdn。一个 excel 的例子如下: http://msdn.microsoft.com/library/officedev/off2000/xltocobjectmodelapplication.htm
用com函数操作 ms word
现在,我们开始第一个例子吧:
#*********************************************************
# 本例来自zend站点,略有改动
# 打开一个word实例,并新建一个文档useless test.doc
# 输入一行文字 "this is a test2..."
#*********************************************************
#实例化一个对象
$word = new com("word.application") or die("unable to instantiate word");
#取得并显示版本
print "loaded word, version {$word->version}
";
#另一种方法去取得版本
$testversion = com_get($word->application,version);
print "version using com_get(): $testversion
";
#使其可见
$word->visible = 1;
#创建新文件
$word->documents->add();
#写字符
$word->selection->typetext("this is a test...");
#保存
$word->documents[1]->saveas("useless test.doc");
#关闭
$word->quit();
?>
你只要花几分钟来读这个程序,并参考word的ole 技术文档,你将学到几乎是你在自己程序中所需的全部的操作。
ms excel在使用php的com函数
如同上面的word的例子一样,你应学习这个例子的同时参考excel的visual basic 编辑器中的对象浏览器的帮助文档。
#打开workbook和它的sheet,
#本例使用一个电子表格是excel安装时自带的solvsamp.xls
$workbook = "c:program filesmicrosoft officeofficesamplessolvsamp.xls";
$sheet = "quick tour";
#实例化一个组件的对象
$ex = new com("excel.sheet") or die ("did not connect");
#取程序名称和版本
print "application name:{$ex->application->value}
" ;
print "loaded version: {$ex->application->version}
";
#打开工作本使我们可使用它
$wkb = $ex->application->workbooks->open($workbook) or die ("did not open");
#预保存原来的工作本,创建一个工作本的复本
$ex->application->activeworkbook->saveas("ourtest");
#$ex->application->visible = 1; #本句去注释让excel可见
# 读写一个单元格在一个新的工作表中
# 我们可以读到这个单元格 e11 (advertising in the 4th. quarter)
$sheets = $wkb->worksheets($sheet); #select the sheet
$sheets->activate; #activate it
$cell = $sheets->cells(11,5) ; #select the cell (row column number)
$cell->activate; #activate the cell
print "old value = {$cell->value}
"; #print the value of the cell:10000
$cell->value = 15000; #change it to 15000
print "new value = {$cell->value}
";#print the new value=15000
#最后,用新值重新计算这个单元格
$sheets->calculate;
#必须的如果要计算,手动则是可选的
#可看到效果总价值(e13单元格)
$cell = $sheets->cells(13,5) ; #select the cell (row column number)
$number = number_format($cell->value);
print "new total cost =$$number - was $47,732 before.
";
#根据计算公式,广告影响了公司的开销,这里将显示 $57,809
#使用excel内建的函数
# pmt(percent/12 months,number of payments,loan amount)
$pay = $ex->application->pmt(0.08/12,10,10000);
$pay = sprintf("%.2f",$pay);
print "monthly payment for $10,000 loan @8% interest /10 months: $ $pay
";
#should print monthly payment = $ -1,037.03
#可选,保存
$ex->application->activeworkbook->saveas("ourtest");
#关闭,不提问
$ex->application->activeworkbook->close("false");
unset ($ex);
?>
这个例子让你的php与excel一同工作了,当然,也有更多的对象可以使用,访问一个自已写的oop封装类也与访问excel一样容易。
用php的com访问 adobe distiller
这最后一个例子不是ms程序了,如果你的程序有一个postscript文件,你会对这个有兴趣的,改写(蒸馏)它成为一个pdf文档. adobe 有一个程序叫 distiller ,它可以生成一个实例。代码如下:
$pdf = new com("pdfdistiller.pdfdistiller.1");
?>
有一点要注意的,是在distiller 的文档中给出的这个ole标识名 "pdfdistiller" 是无效的。
蒸馏一个文件的最基本的方法是:
$pdf->filetopdf ($psfile, stroutputpdf '', strjoboptions "");
?>
这 $psfile 是这个postscript的文件名, stroutputpdf 是输出文件pdf的文件名。 strjoboptions 是distiller的参数文件名,最后两个参数是可选的,默认是同一名字。 这ps文件名与pdf文件名,使用这个默认的job options 文件。例如:
$pdf->filetopdf ($psfile, "", "");
#这儿$psfile 可以是 myfile.ps 将返回 myfile.pdf 文件。
?>
在distiller中有更多的方法和属性能被用。如果你感兴趣,请参考一下adobe的技术文档。
中止/可能的问题
如果你的代码中发生了什么错误,你可能会创建了一个实例,但没有正常地关闭它。最糟的是,这个应用程序可能被这个实例所保持,结果,在你的程序列表中就存在多份这个程序的副本,即使你更正了这个错误也会干扰你的结果。解决方法是:修正一个bug以来要及时清除它们在你重新开始运行之前,用 并结束任务。同样的原因,在你的代码最后,也要及时关闭这个程序并删除这个实例。
你有一些技巧在处理 com_get 和 com_set的异常时。例如:
$version = com_get($instance->application,"version");
将会在word中工作但在excel中会产生一个错误。
有一些对象在php4中是不能实例化的,这是因为这个程序要一个自定义的接口,但php4不支持。
为什么我们要用它?
我希望这三个例子可以给你一些思考的线索,php的com允许你在php的脚本中访问windows4的程序。这个代码比asp简单并且能集成其它的php对数据库强大的支持功能。microsoft 在各个方面都大力销售这个com 技术,在不同的名称和结构下,如 com+(combine com with microsoft transaction server mts), ado, ole db, owc, windows dna, 等等。 php 和 apache的结合,提供了一个开放源码的解决方案。
新闻热点
疑难解答