博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用PHPWord对Word文件做模板替换
阅读量:6163 次
发布时间:2019-06-21

本文共 5293 字,大约阅读时间需要 17 分钟。

因工作需要,使用了版本比较旧的项目

官方已不见维护更新,上次版本更新是在Fri Jul 8, 2011 at 8:00 AM
如果PHP版本>=5.3.3,强烈推荐使用这个开源项目
本篇针对的为旧版本的

基本安装

问题总结

Autoloader自动加载部分情况下失败

在使用Yii 1配置自动加载时无法正常加载类库,需对其PHPWord/Autoloader.php做部分调整,这儿借鉴了PHPExcelAutoloader:

/** * PHPWord_Autoloader */class PHPWord_Autoloader{    /**     * Register the Autoloader with SPL     *     */    public static function Register() {        $functions = spl_autoload_functions();          foreach ( $functions as  $function)              spl_autoload_unregister($function);          $functions = array_merge(array(array('PHPWord_Autoloader','Load')),$functions);          foreach ( $functions as $function)              $x = spl_autoload_register($function);          return $x;     }   //    function Register()    /**     * Autoload a class identified by name     *     * @param    string    $pClassName        Name of the object to load     */    public static function Load($pClassName){        if ((class_exists($pClassName,FALSE)) || (strpos($pClassName, 'PHPWord') !== 0)) {            //    Either already loaded, or not a PHPWord class request            return FALSE;        }        $pClassFilePath = PHPWORD_BASE_PATH .                          str_replace('_',DIRECTORY_SEPARATOR,$pClassName) .                          '.php';        if ((file_exists($pClassFilePath) === FALSE) || (is_readable($pClassFilePath) === FALSE)) {            //    Can't load            return FALSE;        }        require($pClassFilePath);    }   //    function Load()}

模板替换时无法识别模板标签

表现

  1. 使用/复制官方样例的模板文件替换正常

  2. 自己手动敲出模板标签替换异常

原因

  1. PHPWord的替换规则是将Word文件解析成XML进行替换处理,当Word解析成XML时字符分离了,导致匹配不上模板标签;

  2. 具体分析可参考一下资料:

解决办法

参考

改进Template类:

可参考对Template类进行改造。
因为下面仍需要修改Template类,这儿暂时就不贴代码了,下面一并贴出改造后的代码。

中文乱码

参考

编辑PHPWord/Template.php,找到代码$replace = utf8_encode($replace);,删除或者注释掉这行代码,添加$replace = iconv( 'gbk','utf-8', $replace);,比如代码改为如下:

/** * Set a Template value *  * @param mixed $search * @param mixed $replace */public function setValue($search, $replace) {    if(substr($search, 0, 2) !== '${' && substr($search, -1) !== '}') {        $search = '${'.$search.'}';    }     if(!is_array($replace)) {        //$replace = utf8_encode($replace);        $replace =iconv('gbk', 'utf-8', $replace); // 注释掉上面行后添加这行    }     $this->_documentXML = str_replace($search, $replace, $this->_documentXML);}

空格输出

参考

在想要输出换行的地方用<w:br />代替即可.

标记符号输出

参考

仅以输出为例,其它符号与之类似。
注:PHP文件需要使用UTF-8编码

  1. Word文件中按照参考文件方式插入

  2. 复制符号到PHP文件;

  3. 正常的输出替换。

    具体代码见如下的项目代码

Template类代码

// code/*** Set a Template value** @param mixed $search* @param mixed $replace*/public function setValue($search, $replace, $limit=-1) {    if(substr($search, 0, 1) !== '{' && substr($search, -1) !== '}') {        $search = '{'.$search.'}';    }        if(!is_array($replace)) {        // $replace = utf8_encode($replace);        // $replace = iconv( 'gbk','utf-8', $replace);        $replace = str_replace("\n","
",$replace); } preg_match_all('/\{[^}]+\}/', $this->_documentXML, $matches); foreach ($matches[0] as $k => $match) { $no_tag = strip_tags($match); if ($no_tag == $search) { $match = '{'.$match.'}'; $this->_documentXML = preg_replace($match, $replace, $this->_documentXML, $limit); if ($limit == 1) { break; } } }}// code

项目代码

// @author Heier xheier@outlook.compublic function actionExportPersonTable() {    // 获取数据部分代码    // ...    $PHPWord = new PHPWord();        // Word模板目录    $personBasePath = Yii::app()->basePath.'/person/';        // 删除目录下临时文件-十分钟以前    $this->delfile( $personBasePath, 10 );        // 模板文件名    $tempName = $personBasePath . '/moban.docx';        $word = $PHPWord->loadTemplate( $tempName );        // 项目使用的是GBK编码,需要做转换    $username = iconv('gbk', 'utf-8', getUserNameById($personData[0]['user_id']) );    $personal_type = $personData[0]['personal_type'];        // 模板替换开始    // 可以输出打勾的方框    $deptA=$deptBP=$deptB=$deptC=$deptD = '□';    if( $DirectorLevel == 'A' ) {        $deptA = '☑';    } elseif( $DirectorLevel == 'B+' ) {        $deptBP = '☑';    } elseif( $DirectorLevel == 'B' ) {        $deptB = '☑';    } elseif( $DirectorLevel == 'C' ) {        $deptC = '☑';    } elseif( $DirectorLevel == 'D' ) {        $deptD = '☑';    }    $word->setValue('deptA', $deptA);    $word->setValue('deptBP', $deptBP);    $word->setValue('deptB', $deptB);    $word->setValue('deptC', $deptC);    $word->setValue('deptD', $deptD);    // 设置其它替换    // ...        // 生成临时文件以供下载    $tmpFileName = md5( time().'Heier' );        $word->save($personBasePath . '/' . $tmpFileName .'.docx');    $file = $personBasePath . '/' . $tmpFileName .'.docx';        // 下载Word文件    ob_start(); //打开缓冲区    $fp = fopen($file,"r");    $file_size = filesize($file);    $downFileName = 'XXX.docx';        header("Cache-Control: public");    header("Content-type: application/octet-stream");    header("Accept-Ranges: bytes");    header("Content-Disposition: attachment; filename={$downFileName}");    header("Pragma:no-cache");    header("Expires:0");    $buffer = 1024;    $file_count = 0;    //向浏览输出回数据    while(!feof($fp) && $file_count < $file_size){        $file_con = fread($fp,$buffer);        $file_count += $buffer;        echo $file_con;    }    ob_end_flush();//输出全部内容到浏览器}

参考文档汇总

  1. ;

  2. ;

  3. ;

  4. ;

  5. ;

  6. ;

关于我

文章转载自我的博客:

你可能感兴趣的文章
Quartz
查看>>
正则表达式的语法规则
查看>>
C#一个关于委托和事件通俗易懂的例子
查看>>
类似于SVN的文档内容差异对比工具winmerge
查看>>
Cause: java.sql.SQLException: The user specified as a definer ('root'@'%') does not exist
查看>>
quratz线程
查看>>
execnet: rapid multi-Python deployment
查看>>
windows修改3389端口
查看>>
关于JavaScript词法
查看>>
FreeSwitch中的会议功能(4)
查看>>
MySQL中创建用户分配权限(到指定数据库或者指定数据库表中)
查看>>
AutoReleasePool 和 ARC 以及Garbage Collection
查看>>
重新想象 Windows 8 Store Apps (9) - 控件之 ScrollViewer 基础
查看>>
乐在其中设计模式(C#) - 提供者模式(Provider Pattern)
查看>>
MVP Community Camp 社区大课堂
查看>>
GWT用frame调用JSP
查看>>
大型高性能ASP.NET系统架构设计
查看>>
insert select带来的问题
查看>>
EasyUI 添加tab页(iframe方式)
查看>>
mysqldump主要参数探究
查看>>