提示:不支持.doc文件的读取

有一个客户有这样的需求,需要在ThinkPHP里使用PHPWord组件,把一个文档(DOC1)的内容,插入另一个文档(DOC2)的指定页内。由于两个文档的内容都不是固定的,所以不能使用PHPWord的Template功能。

以前从来没有使用过PHPWord,所以前后也折腾了几天。从熟悉PHPWord的功能开始,看示例代码,还有源码,最终还是摸索出来解决方案,下面说下解决思路:

首先读取DOC1的内容,PHPWord把内容分成不同的节点和容器,最顶级的是Section,里面有TextRun(文本块),Table(表格)等容器。这些容器里又有Text(文本),Row(表格行),Cell(单元格)等,还有一些其他的TextBreak,PageBreak(分页符)等制表符。

逐级读取内容后,然后把读取出的内容插入到一个新的文档内。当读取到指定的分页符之后,再读取DOC2的内容,跟着前面的内容插入,最后保存新的文档。

贴一部分代码:

namespace Home\Logic;

Vendor('PhpOffice.autoload');

use PhpOffice\PhpWord\PhpWord;

use PhpOffice\PhpWord\IOFactory;

use PhpOffice\PhpWord\Style\Font;

use PhpOffice\PhpWord\Shared\ZipArchive;

use PhpOffice\PhpWord\Settings;

class MergeFile {

private $currentPage = 0; // 当前分页

private $page = 0; // 插入页数

private $args = null; // 文本段样式

private $tmpFiles = []; // 临时文件

/**

* 合并文件

*

* @param URI

* 文件1地址

* @param URI

* 文件2地址

* @param Numeric

* 指定插入的页数

*

* @return String

* 新文件的URI

*/

public function joinFile($file1, $file2, $page)

{

$S1 = IOFactory::load($file1)->getSections();

$S2 = IOFactory::load($file2)->getSections();

$this->page = $page > 0 ? $page - 1 : $page;

$phpWord = new PhpWord();

foreach ($S1 as $S) {

$section = $phpWord->addSection($S->getStyle());

$elements = $S->getElements();

# 逐级读取/写入节点

$this->copyElement($elements, $section, $S2);

}

$F1 = IOFactory::createWriter($phpWord);

$path = $_SERVER['DOCUMENT_ROOT'] . __ROOT__ . '/Public/Write/';

if(!is_dir($path)) mkdir($path);

$filePath = $path . time() . '.docx';

$F1->save($filePath);

# 清除临时文件

foreach($this->tmpFiles as $P) {

unlink($P);

}

return $filePath;

}

/**

* 逐级读取/写入节点

*

* @param Array

* 需要读取的节点

* @param PhpOffice\PhpWord\Element\Section

* 节点的容器

* @param Array

* 文档2的所有节点

*/

private function copyElement($elements, &$container, $S2 = null)

{

$inEls = [];

foreach ($elements as $i => $E) {

# 检查当前页数

if ($this->currentPage == $this->page && !is_null($S2)) {

# 开始插入

foreach ($S2 as $k => $v) {

$ELS = $v->getElements();

$this->copyElement($ELS, $container);

}

# 清空防止重复插入

$S2 = null;

}

$ns = get_class($E);

$elName = end(explode('\\', $ns));

$fun = 'add' . $elName;

# 统计页数

if ($elName == 'PageBreak') {

$this->currentPage ++;

}

# 合并文本段

if($elName == 'TextRun'

#&& !is_null($S2)

) {

$tmpEls = $this->getTextElement($E);

if(!is_null($tmpEls)) {

$inEls = array_merge($inEls, $tmpEls);

}

$nextElName = '';

if($i + 1 < count($elements)) {

$nextE = $elements[$i + 1];

$nextClass = get_class($nextE);

$nextElName = end(explode('\\', $nextClass));

}

if($nextElName == 'TextRun') {

# 对比当前和下一个节点的样式

if(is_object(end($inEls))) {

$currentStyle = end($inEls)->getFontStyle();

} else {

continue;

}

$nextEls = $this->getTextElement($nextE);

if(is_null($nextEls)) {

$nextStyle = new Font();

} else {

$nextStyle = current($nextEls)->getFontStyle();

}

}

}

# 设置参数

$a = $b = $c = $d = $e = null;

@list($a, $b, $c, $d, $e) = $args;

$newEl = $container->$fun($a, $b, $c, $d, $e);

$this->setAttr($elName, $newEl, $E);

#$inEls = [];

if(method_exists($E, 'getElements')

&& $elName != 'TextRun'

) {

$inEls = $E->getElements();

}

if(method_exists($E, 'getRows'))

$inEls = $E->getRows();

if(method_exists($E, 'getCells'))

$inEls = $E->getCells();

if (count($inEls) > 0) {

$this->copyElement($inEls, $newEl);

$inEls = [];

$this->args = null;

}

}

return $pageIndex;

}

/**

* 获取Text节点

*/

private function getTextElement($E) {

$elements = $E->getElements();

$result = [];

foreach($elements as $inE) {

$ns = get_class($inE);

$elName = end(explode('\\', $ns));

if($elName == 'Text') {

$inE->setPhpWord(null);

$result[] = $inE;

} elseif (method_exists($inE, 'getElements')) {

$inResult = $this->getTextElement($inE);

}

if(!is_null($inResult))

$result = array_merge($result, $inResult);

}

return count($result) > 0 ? $result : null;

}

private function setAttr($elName, &$newEl, $E)

{

switch (strtolower($elName)) {

case 'footnote':

$newEl->setReferenceId($E->getReferenceId());

break;

case 'formfield':

$newEl->setName($E->getName());

$newEl->setDefault($E->getDefault());

$newEl->setValue($E->getValue());

$newEl->setEntries($E->getEntries());

break;

case 'object':

$newEl->setImageRelationId($E->getImageRelationId());

$newEl->setObjectId($E->getObjectId());

break;

case 'sdt':

$newEl->setValue($E->getValue());

$newEl->setListItems($E->getListItems());

break;

case 'table':

$newEl->setWidth($E->getWidth());

break;

}

}

}

程序员客栈,汇集各路码农,找到你的靠谱技术小伙伴 http://t.cn/RXz4ONT

word合并文档php,使用PHPWord合并Word文档,在文档指定页插入另一个文档的内容相关推荐

  1. word指定页插入页码

    word指定页插入页码 (这里使用office2019),我们要把项目概述页作为页码的第一页, 1.首先目录和项目概述之间选择布局->分隔符->下一页.此时会多出一个空白页,先不要删除这个 ...

  2. 如何用word 2007在指定页插入页码和页眉页脚?

    哎,如何在word 2007中在指定页插入页眉页脚呢?这是我在写论文时遇到的一个大麻烦.翻看网络上的资料,基本上都是说03版的.利用03版的资料研究了半天(可能03版资料讲的都不好,小小自恋一下,呵呵 ...

  3. php打开word文档_PHP使用phpword生成word文档

    写在前边的话 使用phpword生成文档有两种方式 直接使用代码编写word文档,用代码生成word,但是设置样式,格式,图片非常麻烦,不建议使用.如果客户或产品提供一份word的样式,我们也难以完全 ...

  4. php生成格式 word文档,php使用phpword生成word文档

    require_once '../libs/PHPWord/PHPWord.php'; require_once '../libs/PHPWord/PHPWord/IOFactory.php'; re ...

  5. 在Word从指定页插入页眉 页眉内容自动填充为章节标题

    1.打开Word--在想插入页眉的开始页的首位点击 布局选项卡--点开分隔符--找到分节符:点下一页 2.找到插入选项卡--找到页眉--点击--空白页眉插入--单击取消链接到前一节 4.使用域批量修改 ...

  6. 在Word指定页插入页码

    1.如图示例,新建了四个页面 2.来到"前言页",将光标回车定位至最后一行 3.然后在[布局]选项卡的[分隔符]找到[分节符]下的[下一页],点击. 4.点击之后,"第一 ...

  7. 使用phpoffice/phpword读取word内容

    一:phpoffice/phpword安装 composer require phpoffice/phpword phpword的GitHub地址:https://github.com/PHPOffi ...

  8. 如何将pdf多页插入word且保持插入内容的清晰度

    举例说明小编使用的两种插入方法区别,方便有需要的小伙伴选择. 假如需要将所有的证明材料以目录的方式整理出来,最终导出pdf版本.材料证明包括如下条目: 技术评价证明(复印件) 学术论文 应用证明 专利 ...

  9. Word从指定页开始插入页码

    前言   写文档很容易出现一个令人头疼的问题,那就是无法从指定页开始插入页码.例如:写一份课程设计报告,报告封面和目录应该是不占页码的,真正的页码应该开始于第三页甚至更往后.本文的目的就是记录(或者说 ...

最新文章

  1. mysql 程序迁移_如何从MySQL数据库程序中迁移数据库文件
  2. ASP.NET开发常用代码
  3. 命令回复mysql数据库_用命令行恢复MySQL数据库
  4. mysql 5.6.11 error 1059_mysql5.6.15问题如何解决
  5. 张一春教授计算机辅助教学,我校特邀评审专家张一春教授来校做专题讲座
  6. 微软的.NET Core开始支持Raspberry Pi 3
  7. oracle块空间的使用,Oracle管理存储架构(二)--Oracle管理数据块空间
  8. md5 java 工具类_Java实现一个MD5工具类
  9. python骗局-1.python真的是万恶之源么?(初识python)
  10. Word转PDF方法(jacob插件)
  11. oracle 分析函数之分组求和、连续求和
  12. Python自动化办公之操作Excel文件
  13. Java中 … 三个点是什么意思?
  14. 聪明人为何无法征服世界?
  15. 辐射强度和辐射亮度_如何在“辐射4”中隐藏“创意俱乐部新闻”垃圾邮件
  16. 互联神州---AK爆头战报
  17. 回溯算法(回溯搜索法)
  18. Redis的三种启动方式
  19. RHCSA认证考试---5.配置 crontab
  20. 《赢在中国》精彩评语

热门文章

  1. exiftool 删除和添加图片旋转信息
  2. CTFSHOW web入门 命令执行+文件包含+PHP特性
  3. 第六章微型计算机,微型计算机原理及应用 第六章微型计算机的接口技术
  4. Rviz中控制机器人模型运动(arbotix)
  5. 单源最短路径-分支限界法-优先队列式分支限界法-Dijkstra
  6. 哈,我终于成功量产:因写保护无法格式化的U盘。
  7. 推荐1个视频播放画中画工具!
  8. SpringMVC框架从入门到精通
  9. awesome-adb
  10. 计算机组成原理-第三章-存储系统