在Windows系统下使用PHP生成Word文档的教程
准备工作
首先,请确保在你的windows系统中已经安装并配置好了一个典型的wamp环境。由于interop纯粹是一个windows的特性,我们将在windows平台下搭建apache和php。在这个实例中,我使用了easyphp 14.1,这款软件安装和配置都十分容易。
接下来,我们要安装microsoft office。版本不是严格要求的。我正在使用的是office2013专业版,但是任何2007之后的office版本都应该可以使用。
我们然后需要去确保开发interop应用(又被称作pia,优先交互组件)的库是安装好的。为了确保这个,我们可以打开资源管理器,然后找到<windows目录>\assembly,我们将会看到下面安装好的pias分支:
我们可以看到一个 microsoft.office.interop.word 条目(在这个截图中有下划线)。 这就是我们在这个示例中将要使用的 pia。请特别注意它的“名称”,“版本”和“公钥标记”。我们将要在php脚本中用到它们。
在这个目录中,我们还可以看到其它用于编程(不仅是php,还有vb.net, c#等)的pias(包括整个office家族)。
如果这个列表没有包含 microsoft.office.interop 的整个包,我们可以重新安装office并且在安装中包含pia;我们也可以手动下载安装这个包。安装的详细步骤可以查阅这个msdn页面。
注意:只有microsoft office 2010 pia redistributable 可以被单独下载安装。这个包中的 pia 版本是14.0.0。版本15只能通过安装office获得。
最后,我们需要在文件 php.ini 中启用 php 扩展 php_com_dotnet.dll,并且重启服务器。
现在我们可以开始编程了。
html表单
由于该demo主要关注与后台的处理,所以我们这里就用一个简单的html表单做前台的展示,看起来应该是这样的:
我们有一个文本框用于输入“name”,一个“gender”的单选按钮组,一个“age”的域值控制还有一个文本域来写“message”,最后,还需要一个“submit”按钮。
将该文件命名为“index.html”,保存在虚拟主机的根目录下,这样我们可以直接通过url访问该文件,例如:http://test/test/interop
后台
后台的php文件是我们所要讨论的核心部分。我先将代码贴到下面,接下来在一步一步的进行解释
<?php $inputs = $_post; $inputs['printdate']=''; // a dummy value to avoid a php notice as we don't have "printdate" in the post variables. $assembly = 'microsoft.office.interop.word, version=15.0.0.0, culture=neutral, publickeytoken=71e9bce111e9429c'; $class = 'microsoft.office.interop.word.applicationclass'; $w = new dotnet($assembly, $class); $w->visible = true; $fn = __dir__ . '\\template.docx'; $d = $w->documents->open($fn); echo "document opened.<br><hr>"; $flds = $d->fields; $count = $flds->count; echo "there are $count fields in this document.<br>"; echo "<ul>"; $mapping = setupfields(); foreach ($flds as $index => $f) { $f->select(); $key = $mapping[$index]; $value = $inputs[$key]; if ($key == 'gender') { if ($value == 'm') $value = 'mr.'; else $value = 'ms.'; } if($key=='printdate') $value= date ('y-m-d h:i:s'); $w->selection->typetext($value); echo "<li>mappig field $index: $key with value $value</li>"; } echo "</ul>"; echo "mapping done!<br><hr>"; echo "printing. please wait...<br>"; $d->printout(); sleep(3); echo "done!"; $w->quit(false); $w=null; function setupfields() { $mapping = array(); $mapping[0] = 'gender'; $mapping[1] = 'name'; $mapping[2] = 'age'; $mapping[3] = 'msg'; $mapping[4] = 'printdate'; return $mapping; }
在设置完用来获取表单中传过来的值的变量$inputs之后,我们要创建一个虚拟值用来存放printdate——我们稍后会讨论为何需要这个变量——现在,我们看到这4行比较关键的代码:
$assembly = 'microsoft.office.interop.word, version=15.0.0.0, culture=neutral, publickeytoken=71e9bce111e9429c'; $class = 'microsoft.office.interop.word.applicationclass'; $w = new dotnet($assembly, $class); $w->visible = true;
在php中的com操纵需要在一个assembly里请求一个class的实例。在我们的案例中,我见将要操作word。如果考虑到我们上一个截图中展示的代码,我们将能够构造出一个完整签名的word pia:
- “name”,“version”,“public key token”是在当我们浏览“c:\windows\assembly”时所展示的信息
- “cultrue”总是neutrual的。
调用类编译后的文件后缀名为通常为applicationclass.
通过设置下面两个步骤,我们可以初始化一个word对象:
首先,word对象可以保存在后台或者通过将visible属性设置为true,使它在前台展示出来。
然后,我们打开将要处理的文档,把它实例化为一个$d变量。
在文档对象中,基于html表单的文本来添加文档的内容,这里可以设置一些参数。
最不好的方式是对php页面上所有内容进行硬编码,然后将它们添加到word对象中。我强烈建议不采用此种方式,原因有:
1 代码没有灵活性,php内容的任何变化都需要重新修改脚本;
2 违反了控制层、展示层的分离;
3 如果需要设置word内容的格式(对齐,字体,样式,等),这种方式大大增加了代码行数,并且以编程的方式来修改样式是非常麻烦的。
另一种方式是使用“搜索-替换”。php内置的这种功能非常强大。我们可以创建一个word文档,在那些需要被替换的占位内容周围放置一些分隔符。比如,我们创建一个文档包含如下内容:
{{name}}
在php中,我们只需使用从表单提交中获取的“name”值来替换。这种方式避免了第一选项中的那些缺点。我们只需要找到正确的分隔符,在这个例子中,除了使用的模板是word文档,我们更像是做一个模板渲染。
第三个选项是我的建议,并是word中的高级主题。我们将用域来表示占位符,在我们的php代码中,我们会直接更新了相应的表单值的字段。
这种方法灵活,快速,符合word的最佳实践。这也避免了文件的全文搜索,这有助于提高性能。请注意,此选项有它的缺点了。
总之,自从首次亮相,word从来没有支持命名索引的字段。尽管我们对于我们在word文档中创建的字段提供了一个名字,我们还是要用数字下标来访问每个字段。这也解释了为什么我们要使用专用的功能(setupfields)做表单字段的字段索引和名之间的映射手册
学习如何在word文档中插入字段(点击查看一个定制好的版本),请参阅相关 word 帮助主题和手册。对于这个demo,我们有一个具备5个mergefield字段的文档。此外,我们将文档和php脚本放在一个目录下,以方便获取。
请注意,printdate字段并没有一个相应的窗体字段。这就是为什么我们要在$inputs数组中添加一个假的printdate作为key。没有这个key,脚本依然可以执行,但是会有提示说明$inputs数组中不存在索引printdate。
在使用表单数据更新完字段的值之后,我们将会使用下面的命令打印文档:
$d->printout();
printout方法有几个可选参数,这里,我们使用最简单的格式。这将会给链接到我们windows机器的默认打印机打印一份副本。
我们可以通过使用printpreview进行打印预览。在纯自动化的情景下,当然,我们直接使用printout进行打印。
在退出word应用程序之前,我们还需要稍作等待,因为打印工作需要时间来完全退出后台。如果没有delay(3),$w->quit将会立刻得到执行,并且打印工作立刻被终止。
最终,我们调用 $w->quit(false) 来选择通过我们的php脚本调用关闭word应用程序。这里提供的唯一参数是用来指明我们是否希望在退出前保存更改。我们确实对文档进行了更改,但是我们不希望保存它们,因为我们希望能为其他用户的输入提供一份干净的模板。
当我们完成编码之后,我们可以加载表单页面,输入一些内容并提交表单。下面的截图展示了php脚本的输出,同时更新了word文档:
提高编码速度并更好的理解pia
php是一种弱类型的语言。一个com对象是一种object类型。在我们的php编码过程中,在一个对象中我们无法使用代码自动提示和完成功能,在一个word应用,一个文档甚至一个字段中同样如此。我们不知道它有哪些特性,或者它支持哪些方法。
这将大幅度的降低我们开发的速度。为了使开发更快,首先,我建议我们在c#中开发功能应当迁移至我们的php编码。我推荐一款免费的c# ide 叫做"#develop",你可以在这里下载。相比vs,我更喜欢这一款软件,因为#develop体积更小,更简洁,响应更快。
c#代码迁移至php一点也不吓人。先让我展示一些c#的代码:
w.visible=true;
string path=application.startuppath+"\\template.docx";
word.document d=w.documents.open(path) as word.document;
word.fields flds=d.fields;
int len=flds.count;
foreach (word.field f in flds)
{
f.select();
int i=f.index;
w.selection.typetext("...");
}
我们可以看到,c#的代码和我们之前展示的php的代码基础一模一样。由于c#是一种强类型语言,所以我们可以看到有些类型转换的语句,我们不得不显性的给我们的变量赋一种类型。
有了代码的类型,我们可以尽情的享受代码的自动提示和代码自动完成功能,这样我们开发的速度将有大幅度提高。
另一种可以给予我们更快速度进行php开发的方式是使用word的宏命令。我们先操作一遍我们需要重复的动作,然后用一个宏将其录制下来。一个宏其实是visual basic,同样也可以非常容易的翻译成php。
最重要的是,office pia微软官方文档,特别是文档中对于每个office应用的命名空间,总会是我们所需要的最想进的参考。比较常用的3个应用如下:
- excel 2013:http://msdn.microsoft.com/en-us/library/microsoft.office.interop.excel(v=office.15).aspx
- word 2013:http://msdn.microsoft.com/en-us/library/microsoft.office.interop.word(v=office.15).aspx
- powerpoint2013:http://msdn.microsoft.com/en-us/library/microsoft.office.interop.powerpoint(v=office.15).aspx
结语
在这篇文章中,我们演示了如何使用php com库和microsoft office interop功能来倩影一个word文档。
windows和office在我们的日常生活中可以说是被广泛的使用。能够知道和了解office或者windows的强大之处还有php,对于任何一个在windows平台上进行php开发的程序员都是十分必要的。
使用php的com扩展,掌握这一组合的大门就被打开了。
如果你对于这部分的编程比较感兴趣,请留下你的评论,我们将会考虑在这个话题上写更多的文章。我十分期待更多现实生活的应用开发能使用这种方式。
上一篇: 使用AD对Linux客户端进行身份验证
下一篇: IT业和管理业
推荐阅读
-
在Windows系统下使用PHP生成Word文档的教程
-
在Windows系统下使用PHP生成Word文档的教程
-
php在程序中将网页生成word文档并提供下载的代码_PHP教程
-
在Windows系统下使用PHP生成Word文档的教程
-
为什么在WINDOWS下使用PHP4的SESSION功能老是报路_PHP教程
-
在Windows系统下使用PHP生成Word文档的教程
-
为什么在WINDOWS下使用PHP4的SESSION功能老是报路_PHP教程
-
PHPUnit 在 Windows 下的配置及使用教程_PHP教程
-
在Windows系统下使用PHP生成Word文档的教程_PHP
-
PHPUnit 在 Windows 下的配置及使用教程_PHP教程