聊聊通过phpword生成复杂格式word文档的历程

方滴云WEB2022-04-09 23:49

最近玩那个mPdf有点上隐了,当然很多东西是通过看作者的源码理解的。看了人家的源码后,也越来越感觉到差距了,代码这个东西,唉,真的认真不得。

首先,PDF优势很明显,格式保持的好,易传播,对于小白,它的内容编辑也是不那么容易的,这也是对我们的保护吧,当然遇到流氓,另当别论了。

PDF对于我们办公而言,最大的问题就是要编辑它,不太方便。最近在做的一个系统,有大量的文档要在服务端生成,然后让用户下载填写上传。这个过程考虑到,人都是懒的,所以PDF自然不合适了。

好的,那我们就来玩WORD吧,首先看到的就是phpword,是的,这个后端我们用的php。看了百度上的相关文章,以抄为主吧,不过没有关系,我们在官方与github上找到了文档与示例。

文档:https://phpword.readthedocs.io/en/latest/intro.html

github:https://github.com/PHPOffice/PHPWord

中文文档:https://segmentfault.com/a/1190000019479817(应该是这位大神理解编写的)

中文文档:https://phpword-zh.readthedocs.io/_/downloads/zh_CN/latest/pdf/(强烈推荐)

后面两个资料是搭梯子找到的。这里又要吐槽百度了,要用户做内容呀,不能老是养亲儿子、干儿子什么的,这么玩下去。。。没说了,保重吧。

上手后,首先看的是那个英文文档,当然本人,英文不怎么的,翻译后结合多年的word排版经验理解的,基本都还OK,最让我兴奋的就是那个模版。

模版完全实现了甲方说了算,不管甲方的那个文档排版的美不美丽,只要把要替换的字段用变量代替,然后在生成的时候把它传入就OK了,当然传变量的方式,如果可以直接传对象就更完美了。当然,这里作者有自己的考量,完全能理。

模版这块的测试,对着文档实现还是非常顺利的,当然也发现了两个小问题,就是replaceBlock与deleteBlock这两个函数好像不走,用了后会提示文件损坏。因为可以通过别的方案解决,所以这里就没有纠结了。

接着研究了它的,HTML转WORD, 这里要特别注意两点:

第一,所有的标签都要闭合,这里主要说的就是img等单标签,以定要 以"/>"结尾;

第二,CSS只有在标签上才有效,因为我们大多数都没有这么做,最后放弃了它,用粗暴的方法将HTML转WORD也一样。

最后,想另外一个项目,也需要转WROD,于是一起研究了下。这个项目有点特殊,它是个发货单。核心内容如下

这里有很多产品,每个产品有多种规格,客户会对不同的规格下单,我们在单据中要体现每一项的明细,同时还要对每一项目进行统计,最后再汇总统计。

毫无疑问,模版那么香,我首先想到的,当然是使用模版替换了。但是这里有个比较搞人的地方,就是单据要求明细要分栏打印,这个在模版里,我折腾了下,感觉不是很实现,当然也可能是文档研究的不透彻吧。

最后无奈,只能重新篇通读开发文档了。整个WORD,我们就用代码一个字一个字的写进来吧。在基本掌握了基础知识后,我们就开始折腾它了。

首先,数据库里查出来的是一条一条的记录,这里我们需要把记录按产品的ID进行分成 一个一个的对象,因为这每一个对象就对象表格的一块儿吧,然后再将统计信息加在后面,先看下生成的效果吧。

这部分其实是很容易搞定的,不过也有个小麻烦,就是分栏的时候,一定要把最后一项列完后,再让它分列,这里要现实也不难,就是先看一共有多少列(这里每个后面都有合计,如果统计记录一定要加上)。

然后算了平均值,再去找平均值那列是第几个对象,这个对象列完,左边有多少列,把它乘以2,在右边用空列补上就可以了,这里要把平均值所在的位置与要补的列数记录好,后面要用。

到这里,如果我们表格生成部分,特别是样式与合并单元格理解的还行的吧,这部分的表格生成,应该是比较顺利的。当然,这里也有个小问题,就是如果跨页的话,还是会错位,这个只有手动调整下了。

最后做页眉页脚,因为我的页眉的图片,比较奇怪,这里的图片那些对齐方式在这里失败了,所以只能用相对定位了,然后文字缩进与它拉开距离。

再就是两端对齐的问题,这个可以参考下github中“TabStops”这个示例。

另外,页眉的下划线,最开始我一直在找配置,后来想想,确实应该也是没有的,因为有不同的线型、线宽、颜色、长度等,确实不好弄。这里我想的方案有两个,第一个有表格,第二画线

我用了粗暴的方法二,直接画上一条线,不过啊,这个线的长度,我真不知道那个单位是如何转换的。最后无奈,按比例试着算出来的。

最后一个问题,页边距与页眉、页脚的高度问题,找了很久,最后是在那个推荐的中文文档中找到的,这个文档 是官方出的,个人觉得比那个英文的写的好,唯一就是字太小、颜色太浅,太难看了。

最后,收工了。是的,没有一句代码,只是记录下解决问题的思路,有了思路,其实问题都是很好解决的。

关于学习,看源码与手册,确实很重要,网上有些作者感觉有些不负责任,到处抄,或者有些有点老了。