phpword打开_解决 PHPWord 中的 ProofErr 问题

原文:解决 PHPWord 中的 ProofErr 问题

一、PHPWord 简介

PHPWord 是 PHPOffice 中的一部分(另有 PhpSpreadsheet 用于处理 Excel),主要用于 PHP 项目中对 OOXML/OpenXML(Microsoft Office Open XML), OpenDocument/ODF(OASIS Open Document Format for Office Applications), RTF(Rich Text Format), HTML, PDF 等格式的文件进行读写操作。PHPOffice 的所有项目已经在 GitHub 上开源。


二、遇到的问题

PHPWord 作为处理文档的第三方扩展,在 OA 项目中被广泛使用。最近,公司内部使用的后台系统就遇到了这么一个问题。 起因是财务想要修改原有的发票模版,将落款单位由原先的固定值改为“我开户行”对应的公司名称(就是因为老板又注册了几家公司)。原有模版:

f6f2fca120bf92fae1ec684326f77c67.png
原有模板

翻出模版以后,第一想法当然就是把模版里的{{companyName}}复制一份替换掉原先的苹果母公司。替换、保存、上传后,手动生成了文档,打开一看,居然变成了:

207996b9c02125730b860a92f197e23f.png
生成的文件

在经过多次替换后发现,只有 {{bank}} 这个占位符可以被正确识别进行替换,其他占位符均替换失败。那么,会不会是变量长度导致的异常呢?于是我取 {{candidateName}} 的前几个字母 {{can}} 进行了尝试,果然成功了

……吗?

事实证明,在每个占位符只取前 3~4 个字母的情况下,仍然出现了大批量的翻车事故。除了 {{bank}} 这个占位符,一如既往的坚挺。无奈之下,只能使用最低级的方法——打印内容。


三、查看输出

首先,看一下 PHPWord 在项目中的用法:

$templateProcessor = new TemplateProcessor($file_path);
$templateProcessor->setValue('{{invoiceTitle}}', $invoiceTitle);
$templateProcessor->saveAs($save_path);

其实很容易理解,读取一个模版,把对应的占位符用想输出的变量使用 setValue() 方法替换,然后保存,所以直接把 setValue() 后的 $templateProcessor 打印出来看看就可以了。通过比较替换成功/失败的两种情况:

#  正常情况
<w:r w:rsidR="00B06CB3">
  <w:rPr>
    <w:rFonts w:ascii="宋体" w:hAnsi="宋体"/>
    <w:b/>
    <w:bCs/>
    <w:sz w:val="28"/>
    <w:szCs w:val="28"/>
  </w:rPr>
  <w:t>{{bank}}</w:t>
</w:r>
#  错误情况
<w:r>
  <w:rPr>
    <w:rFonts w:ascii="宋体" w:hAnsi="宋体"/>
    <w:b/>
    <w:bCs/>
    <w:sz w:val="28"/>
    <w:szCs w:val="28"/>
  </w:rPr>
  <w:t>
    {{
  </w:t>
</w:r>
<w:proofErr w:type="spellStart"/>
<w:r>
  <w:rPr>
    <w:rFonts w:ascii="宋体" w:hAnsi="宋体"/>
    <w:b/>
    <w:bCs/>
    <w:sz w:val="28"/>
    <w:szCs w:val="28"/>
  </w:rPr>
  <w:t>
    invoiceTitle
  </w:t>
</w:r>
<w:bookmarkStart w:id="0" w:name="OLE_LINK3"/>
<w:bookmarkStart w:id="1" w:name="OLE_LINK4"/>
<w:proofErr w:type="spellEnd"/>
<w:r>
  <w:rPr>
    <w:rFonts w:ascii="宋体" w:hAnsi="宋体"/>
    <w:b/>
    <w:bCs/>
    <w:sz w:val="28"/>
    <w:szCs w:val="28"/>
  </w:rPr>
  <w:t>
    }}
  </w:t>
</w:r>
<w:bookmarkEnd w:id="0"/>
<w:bookmarkEnd w:id="1"/>

发现:正常情况下,{{bank}}这个占位符作为一个整体,被一堆标签封闭起来,这些标签应该表示了字体、字号等信息。而{{invoiceTitle}}这个标签,"{{", "invoiceTitle" 和 "}}" 则被分隔成三个部分,所以不能被正确识别进行替换。所以问题就变成了为什么这个占位符会被分隔开呢?


四、面向谷歌 debug

既然已经找到大括号和英文之间被prroofErr这个标签给隔开了,那么就来看看这个到底是什么吧。在进行各个文本格式的简单科普之后,我了解了目前主流的几种文本格式,并且在一个 博客 中看到了相关解释:

If you are using Word to make your template, you may have problems periodically with TBS tags not merging due to being broken up by extra blocks of code inserted by Word. This extra code is not noticeable in Word, but sometimes it seems to mangle the TBS tag too much to be recognized. When this happens, you can do two things that will clean up your document.
1. Select any tags ([onshow;data;noerr;], e.g.) in your document and go to the review tab (I am using Word 2010 here, but 2007 is very similar). Click 'Language' > 'Set Proofing Language' (2010) or 'Set Language' in the 'Proofing' division (2007). Then check the box 'Do not check spelling or grammar'. This will prevent Word from adding those extra proofErr tags (and breaking up your TBS tags). It will also remove any that already exist in your document. (Or you can run spell check and ignore everything)
2. The w:rsID tags are a little trickier. There is a hidden option you can access through the macro editor (Alt + F11 will bring it up). Once you are in the macro editor, Ctrl + G will open the 'Immediate Window'. If you paste the following code into the Immediate Window: Application.Options.StoreRSIDOnSave = False
And then save your document (you do not need to save the macro with the document, it just applies to your Word session), it will remove all of the extra w:rsid tags breaking up your TBS tags.
Notes on editing: You will want to apply these changes at the end of editing, before you save. If you come back later and edit your document, it will forget that you don’t want spell checking and grammar. You can remind it by setting the language again, or by running Spell Check and telling it to ignore all of the problems it encounters. I edited my document more after running the macro I mentioned (in a new Word session, when my Immediate Window was clear again) and my w:rsid tags did not come back, but I suspect they would return if I edited enough.
There is one more potentially problematic tag: <w:bookmarkStart w:id="0" w:name="_GoBack"/> <w:bookmarkEnd w:id="0"/>
which will insert itself wherever it pleases (from what I understand, it has something to do with moving your screen back to your previous edit if you hit undo, so it attaches itself to the edit before last?). I haven’t done much experimenting with this yet, it may not interfere with TBS tags, and I’m not totally sure where it shows up.
Hope this helps.

其中第一点指出问题可能出在拼写检查,第二点指出问题可能出在宏编辑器。当然如果我当时再细心一点,思维再发散一点,应该不难看出除了{{bank}}以外其他的占位符全都出现了红色波浪线,唯一能被正确替换的就是通过了拼写检查的占位符。


五、修复 bug

找出问题后修改就变得非常简单。只需要把这些个小驼峰命名法的单词换成下划线分隔,甚至于更偷懒的方法,直接打开模版文件,关闭拼写检查后保存上传。


六、个人感想

  1. 一些离奇的问题往往排查起来十分困难,但是了解以后修改起来十分简单
  2. 并不是说用谷歌的就比用百度的有逼格,但是在编程这一块,毕竟发源地在国外,早起步了十几二十年,沉淀下来的有帮助的东西总归是多一些
  3. 即使现在的翻译功能十分好用,良好的英文阅读能力在提升编程水平的路上会有重要帮助

七、一些题外话

看似洋洋洒洒写了一篇短文章,其实这个问题用几句话就可以简单概括。写这么多字,一来是重新锻炼一下自己的归纳总结能力,二来是最近部门里合作的几个后端同事水平不尽如人意,希望写下的这么一个对小问题的排查解决过程能对正在学习 PHP 的人一些帮助。 程序员真的是一个神奇的职业,既有毕业两年已经精通算法和 C 甚至单片机、FPGA 等软硬件通吃的大佬,也有拿着 13k 月薪的三年工作经验只会用 PHP 写写业务碰到问题只会两手一摊说“我不会” 的部分同事。“用代码改变世界”,共勉。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值