您的当前位置:首页>全部文章>文章详情

phpword 使用TemplateProcessor方式实现在word模板中动态插入表格

发表于:2025-02-19 00:38:07浏览:51次TAG: #ThinkPHP #PHP #PhpWord #TemplateProcessor #WORD

为了使用PHPWordTemplateProcessor类读取一个 Word 模板,并在模板中指定的 ${TABLE} 标记位置插入一个新的表格,我们可以按照以下步骤操作。这个过程包括加载模板、创建表格,然后通过 setComplexBlock 方法将表格插入到指定标记位置。下面是一个具体的示例代码,展示了如何实现这一点:

首先,请确保你已经通过 Composer 安装了 PHPWord 库。

composer require phpoffice/phpword

php代码如下:

use PhpOffice\PhpWord\TemplateProcessor;
use PhpOffice\PhpWord\Element\Table;
use PhpOffice\PhpWord\Style\Cell;

public function contract_word($id)
    {    
        $detail = Db::name('Contract')->where('id', $id)->find();
        $detail['subject_title'] = Db::name('Enterprise')->where(['id' => $detail['subject_id']])->value('title');
        $detail['yi_address'] = Db::name('Enterprise')->where(['id' => $detail['subject_id']])->value('tax_address');
        $detail['yi_bank'] = Db::name('Enterprise')->where(['id' => $detail['subject_id']])->value('tax_bank');
        $detail['yi_banksn'] = Db::name('Enterprise')->where(['id' => $detail['subject_id']])->value('tax_banksn');

        $detail['jia_address'] = Db::name('Customer')->where(['id' => $detail['customer_id']])->value('tax_address');
        $detail['jia_bank'] = Db::name('Customer')->where(['id' => $detail['customer_id']])->value('tax_bank');
        $detail['jia_banksn'] = Db::name('Customer')->where(['id' => $detail['customer_id']])->value('tax_banksn');

        $filename = $detail['name']."_简版_销售合同.docx";
        // 导出word文件路径+文件名
        $path = CMS_ROOT . "public/storage/word/".$filename;
        // 模板文件路径+文件名
        $templatePath = CMS_ROOT . "public/static/home/file/contract1.docx";
        $tmp = new TemplateProcessor($templatePath);

        // 准备要插入表格的数据
        $rows = [
            ['产品名称', '规格', '单位', '数量', '含税单(元/KG)', '不含税总金额(元)', '含税总金额(元)'],
        ];
        $list = unserialize($detail['content']);
        $product_num=0;
        foreach ($list as $key => $value) {
            $rows[]=[$value['product_title'],$value['product_specs'],$value['product_unit'],$value['product_num'],$value['product_price'],$value['product_subnotax'],$value['product_subtotal']];
            $product_num+=$value['product_num'];
        }
        $rows[]=['合计','','','','','',$detail['cost']];

        // 获取页面宽度(以 twips 为单位),假设使用 A4 纸张大小和默认页边距
        $pageWidthTwips = 8500; 

        $columnWidthTwips = [1300,1000,800,1100,1300,1500,1500];

        // 创建表格
        $table = new Table(['unit' => \PhpOffice\PhpWord\SimpleType\TblWidth::TWIP, 'width' => $pageWidthTwips]);

        //单元格属性
        $borderSize = 6; // 边框粗细
        $borderColor = '000000'; // 黑色边框颜色

        $cellStyle = [
            'borderTopSize' => $borderSize, 'borderTopColor' => $borderColor,
            'borderBottomSize' => $borderSize, 'borderBottomColor' => $borderColor,
            'borderLeftSize' => $borderSize, 'borderLeftColor' => $borderColor,
            'borderRightSize' => $borderSize, 'borderRightColor' => $borderColor,
            'valign' => 'center', // 垂直居中
            'unit' => \PhpOffice\PhpWord\SimpleType\TblWidth::TWIP,
        ];
        $textStyle = ['name' => '黑体', 'size' => 10.5]; // 设置字体为黑体

        foreach ($rows as $index => $rowData) {
            $tableRow = $table->addRow();
            foreach ($rowData as $key => $cellData) {            
                $cellStyle['gridSpan'] = 1;
                $cellStyle['width'] = $columnWidthTwips[$key];

                // 创建带有样式的单元格并添加文本
                $tableCell = $tableRow->addCell(null, $cellStyle); // 使用上面定义的宽度
                $tableCell->addText($cellData, $textStyle, ['alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]);
            }
        }

        $cny = cny($detail['cost']);
        $tableRow = $table->addRow();    
        $cellStyle['gridSpan'] = 1;
        $cellStyle['width'] = 1300;
        $mergedCell = $tableRow->addCell(null, $cellStyle);
        $mergedCell->addText('大写合计', $textStyle, ['alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]);

        $cellStyle['gridSpan'] = 6;
        $cellStyle['width'] = 7200;
        $mergedCell = $tableRow->addCell(null, $cellStyle);
        $mergedCell->addText($cny, $textStyle, ['alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]);

        // 使用 setComplexBlock 方法替换 ${TABLE} 标签为生成的表格
        $tmp->setComplexBlock('${TABLE}', $table);

        $tmp->setValue('START', date('Y年m月d日', $detail['start_time']));
        $tmp->setValue('END', date('Y年m月d日', $detail['end_time']));
        $tmp->setValue('SIGN', date('Y年m月d日', $detail['sign_time']));
        $tmp->setValue('TAX', $detail['tax']);
        $tmp->setValue('JIA', $detail['customer']);
        $tmp->setValue('JIA_ADDRESS', $detail['jia_address']);
        $tmp->setValue('JIA_BANK', $detail['jia_bank']);
        $tmp->setValue('JIA_BANKSN', $detail['jia_banksn']);
        $tmp->setValue('YI', $detail['subject_title']);
        $tmp->setValue('YI_ADDRESS', $detail['yi_address']);
        $tmp->setValue('YI_BANK', $detail['yi_bank']);
        $tmp->setValue('YI_BANKSN', $detail['yi_banksn']);
        $tmp->setValue('CODE', $detail['code']);

        $tmp->saveAs($path);
        //下载文件
        if (is_file($path)){
            $file  =  fopen($path, "rb");
            Header( "Content-type:  application/octet-stream ");
            Header( "Accept-Ranges:  bytes ");
            Header( "Content-Disposition:  attachment;  filename= $filename");
            while (!feof($file)) {
                echo fread($file, 8192);
                ob_flush();
                flush();
            }
            fclose($file);
        } else {
            return to_assign(1,"文件生成失败");
        }
    }

关键点解释:

  • TemplateProcessor: 用于处理Word文档模板,允许你用动态内容替换占位符。
  • Table: 创建一个新的表格对象,并根据需要填充数据。
  • setComplexBlock: 这个方法用于替换模板中的复杂块(如表格)。你需要提供占位符名称(如${TABLE})和要插入的对象(如新创建的表格)。