PHPWord 实现合并多个word文件

这篇具有很好参考价值的文章主要介绍了PHPWord 实现合并多个word文件。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

PHPWord

本来想着当调包侠呢,结果翻了一遍文档,没有这种操作支持,阿这😂

GPT

不出意外的一顿胡扯,给👨‍🦳气的要中风啦

思路

word 也就是docx结尾的文件本质上就是xml字符串,
两个word文件合并其实就是把两个字符串拼接起来,你真是小天才呢👨‍🎤

具体步骤

原地址 【能打开的直接抄就完啦】

打不开的也别急,我给你搬运一份奥🤟

首先要拓展一下官方的类,为啥涅?里面的属性咱拿不到

class OpenTemplateProcessor extends \PhpOffice\PhpWord\TemplateProcessor {
    public function __construct($instance) {
        return parent::__construct($instance);
    }
    public function __get($key) {
        return $this->$key;
    }
    public function __set($key, $val) {
        return $this->$key = $val;
    }
}

然后就可以愉快的拼接xml字符串啦,有一些xml的固定格式需要注意👍

$mainTemplateProcessor = new \common\helpers\OpenTemplateProcessor($filename);

$innerTemplateProcessor = new \common\helpers\OpenTemplateProcessor($filename);
            
// 拓展类就是为了拿到他的xml
$innerXml = $innerTemplateProcessor->tempDocumentMainPart;
$innerXml = preg_replace('/^[\s\S]*<w:body>(.*)<\/w:body>.*/ ', '$1 ', $innerXml);

// remove tag containing header, footer, images
$innerXml = preg_replace('/<w:sectPr>.*<\/w:sectPr>/ ', ' ', $innerXml);

// 把取出来的内容放进</w:body> 结束符之前
$mainXml = $mainTemplateProcessor->tempDocumentMainPart;
$mainXml = preg_replace('/<\/w:body>/', '<w:p><w:r><w:br w:type = "page" /><w:lastRenderedPageBreak/></w:r></w:p>' . $innerXml . ' </w:body> ', $mainXml);
$mainTemplateProcessor->tempDocumentMainPart = $mainXml;
$mainTemplateProcessor->saveAs($folder . "1.docx");

关于文件合并后图片显示重复的问题

因为之前拿相同的文件测试的并没有发现😅

word文件转成xml后的内容(以OpenTemplateProcessor这个类为例)

$this->tempDocumentRelations
<Relationships
    <Relationship Id="rId4" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/image1.png"/>
</Relationships>


$this->tempDocumentMainPart
<w:document
    xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
		........
    xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape"
    xmlns:wpsCustomData="http://www.wps.cn/officeDocument/2013/wpsCustomData" mc:Ignorable="w14 w15 wp14">
    <w:body>
    	....太多了省略下
    	           <w:drawing>
                    <wp:inline distT="0" distB="0" distL="114300" distR="114300">
                        <wp:extent cx="5273040" cy="3495675"/>
                        <wp:effectExtent l="0" t="0" r="3810" b="9525"/>
                        <wp:docPr id="1" name="图片 1" descr="B1E79294E5A79B%BE-14023560415"/>
                        <wp:cNvGraphicFramePr>
                            <a:graphicFrameLocks
                                xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" noChangeAspect="1"/>
                        </wp:cNvGraphicFramePr>
                        <a:graphic
                            xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">
                            <a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture">
                                <pic:pic
                                    xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture">
                                    <pic:nvPicPr>
                                        <pic:cNvPr id="1" name="图片 1" descr="B1E79294E5A79B%BE-14023560415"/> // 这个name
                                        <pic:cNvPicPr>
                                            <a:picLocks noChangeAspect="1"/>
                                        </pic:cNvPicPr>
                                    </pic:nvPicPr>
                                    <pic:blipFill>
                                        <a:blip r:embed="rId4"/> // 还有这个r:embed
                                        <a:stretch>
                                            <a:fillRect/>
                                        </a:stretch>
                                    </pic:blipFill>
                                    <pic:spPr>
                                        <a:xfrm>
                                            <a:off x="0" y="0"/>
                                            <a:ext cx="5273040" cy="3495675"/>
                                        </a:xfrm>
                                        <a:prstGeom prst="rect">
                                            <a:avLst/>
                                        </a:prstGeom>
                                    </pic:spPr>
                                </pic:pic>
                            </a:graphicData>
                        </a:graphic>
                    </wp:inline>
                </w:drawing>

根据结构可以看出图片是怎么构成的 namer:embed 其中r:embed的值就在 Relationships中,这样就标识了一个图片

看到这大概明白怎么回事了,因为不同word文件中的r:embed值可能是相同(大概率是),百度了一下word里的图片默认是按1,2这样递增的数
值标识。

按我们上面的操作,只拼接了w:body 里的字符 并忽略了文件2的 Relationships,所以文件2的图片指向了文件1的Relationships

思路弄明白就简单了,就是把Relationships 的图片也合并过来,然后r:embed的标识符要改,还有一点比较重要是图片资源也要写入到第一个word中去,光修改标识符是不够的,毕竟字符串合并图片都不存在

简单的示例:文章来源地址https://www.toymoban.com/news/detail-610225.html

        $files = File::files(public_path("storage/we")); // 获取目录下的所有文件
        $mainXml = "";
        $mainTemplateProcessor = null;
        foreach ($files as $key=> $file) {
            if ($key != 0) {
                $innerTemplateProcessor = new Template($file->getRealPath());
                $innerXml = $innerTemplateProcessor->tempDocumentMainPart;
                // 正则出所有的图片
                preg_match_all('/<Relationship\s+Id="([^"]+)"\s+Type="http:\/\/schemas\.openxmlformats\.org\/officeDocument\/2006\/relationships\/image"\s+Target="([^"]+)"\/>/',$innerTemplateProcessor->tempDocumentRelations['word/document.xml'],$res);
                // 把图片索引更改下,追加并写入
                foreach ($res[0] as $k => $v) {
                    $rid = "rId{$key}{$k}";
                    $innerXml = str_replace($res[1][$k],$rid,$innerXml);
                    $extension = pathinfo($res[2][$k], PATHINFO_EXTENSION);
                    $mediaName = "media/image{$rid}.{$extension}";
                    $relations = str_replace(
                        [$res[1][$k],$res[2][$k]],
                        [$rid,$mediaName],
                        $v);
                    if (!$mainTemplateProcessor->zipClass->addFromString('word/'.$mediaName,$innerTemplateProcessor->zipClass->getFromName('word/'.$res[2][$k]))){
                        throw new \Exception("add media fail");
                    }
                    $tempData = $mainTemplateProcessor->tempDocumentRelations;
                    $tempData['word/document.xml'] = str_replace('</Relationships>',$relations,$mainTemplateProcessor->tempDocumentRelations['word/document.xml']).'</Relationships>';
                    $mainTemplateProcessor->tempDocumentRelations =  $tempData;
                }

                $innerXml = preg_replace('/^[\s\S]*<w:body>(.*)<\/w:body>.*/ ', '$1 ', $innerXml);

                $innerXml = preg_replace('/<w:sectPr>.*<\/w:sectPr>/ ', ' ', $innerXml);

                $mainXml= preg_replace('/<\/w:body>/', '<w:p><w:r><w:br w:type = "page" /><w:lastRenderedPageBreak/></w:r></w:p>' . $innerXml . ' </w:body> ', $mainXml);
            } else {
                $mainTemplateProcessor = new Template($file->getRealPath());
                $mainXml = $mainTemplateProcessor->tempDocumentMainPart;
            }

        }
        $mainTemplateProcessor->tempDocumentMainPart = $mainXml;
        $mainTemplateProcessor->saveAs(public_path("storage/3.docx"));

到了这里,关于PHPWord 实现合并多个word文件的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【方法】如何合并多个PDF文件?

    多个PDF文件,想合并成一个文件,要怎么操作呢? 如果PDF文件的数量少,并且页数也不多,可以试试将内容复制黏贴到Word文档,再转为PDF格式;如果文件数量多,页数也多,就不太合适了,容易出错,也十分耗费时间。 想要快速合并多个PDF文件,又不容易出错,不妨借助

    2024年01月24日
    浏览(41)
  • 合并多个大语言模型文件的方法

    运行下面命令, (示例)Linux and macOS: (示例)Windows command line: refer: https://huggingface.co/TheBloke/Swallow-70B-instruct-GGUF 完结!

    2024年01月17日
    浏览(49)
  • 使用Python合并多个Excel文件

    合并Excel可以将多个文件中的数据合并到一个文件中,这样可以帮助我们更好地汇总和管理数据。日常工作中,合并Excel主要有以下两种需求: 将多个Excel文件合并为一个文件 将多个Excel工作表合并为一个工作表 这篇文章将介绍如何使用第三方Python库 Spire.XLS for Python 实现以上

    2024年02月05日
    浏览(42)
  • lammps教程:多个dump文件合并为一个文件

    大家好,我是小马老师。 本文介绍多个dump文件合并为一个dump文件的方法。 在前面的文章中,介绍过python ovito可以把一个dump文件按帧拆分为多个dump文件。 同理,多个dump文件也可以合并为一个dump文件。 基本原理是先读入多个dump文件,然后再合并输出为一个单独的文件。

    2023年04月09日
    浏览(162)
  • 多个excel文件合并为一个excel

    Python openpyxl库实现将同一目录下的excel文件合并为一个excel功能(包含格式,不含宏),运行程序后,输入要生成的excel文件名称即可

    2024年02月16日
    浏览(44)
  • 【工程实践】python 合并多个csv文件

            处理数据时,有多个csv文件需要合并。有两个方法可以实现,第一个是可以通过python提供的pandas模块,借助 pd.concat()实现多个csv文件的合并。第二个是通过linux命令实现。 1-1 获得全部csv文件路径 1-2  查看数据 1-3 合并数据 2-1 合并数据         将所有的csv文件

    2024年02月11日
    浏览(75)
  • Python自动办公之合并多个PDF文件

    本文基于使用pycharm平台,使用glob库和PyPDF2库实现 首先将需要合并的文件放于一个文件中 如下图 addpdf文件夹为需要合并的文件位置 good.py为代码块  代码如下 代码并没有对输入内容进行限制,可能会出现很大问题,但是正常使用是可以的.

    2024年02月11日
    浏览(45)
  • 合并PDF(将多个pdf文件整合成一个pdf文件)

    推荐使用下面这个 免费在线 的PDF文件合并工具,简单且易操作。 合并PDF - 在线上免费合并PDF文件 (smallpdf.com) 还有其他功能,不过现在我尚未使用其他功能:  关于费用:  

    2024年02月04日
    浏览(36)
  • ESP32 bin文件生成及多个bin文件合并指南

    在ESP32开发过程中,对于我们实际的开发人员来说,将程序烧录进入ESP32内不是什么复杂的事情,直接输入 idf.py flash 指令即可实现,但是当我们开发完成之后,如何将对应的bin文件提供给测试人员进行相应的测试,以及如何提供bin文件给到产线进行生产呢? 通常将工程文件直

    2024年02月09日
    浏览(60)
  • Python 合并多个 PDF 文件并建立书签目录

    今天在用 WPS 的 PDF 工具合并多个文件的时候,非常不给力,居然卡死了好几次,什么毛病?! 心里想,就这么点儿功能,居然收了我会员费都实现不了?不是吧…… 只能自己来了,主要用了 pypdf 库,因为 PyPDF2 版本更新原因,一些类和函数已经过时,截止发文时以下是最新

    2024年02月11日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包