PHPword解析内容支撑

因有些功能不支持,所以新增了某些功能,以防后期变动不好变更,手动做个记录

  1. 将公式替换成指定的符号,读取到 html 后读取 xml 解析公式,根据标记符号进行替换
    文件名PhpOffice\PhpWord\Shared\XMLReader.php

    public function getDomFromZip($zipFile, $xmlFile)
    {
        if (file_exists($zipFile) === false) {
            throw new \Exception('Cannot find archive file.');
        }

        $zip = new \ZipArchive();
        $zip->open($zipFile);
        $content = $zip->getFromName($xmlFile);
        $zip->close();

        if ($content === false) {
            return false;
        }
        if($xmlFile === 'word/document.xml'){
            // 字符串替换,将公式替换成$Math$
            $content = preg_replace('/[\s|\S]*?<\/m:oMath>/', '$Math$', $content);
            // 后续在将$Math$标记替换为对应的处理过的mathml公式(或latex表达式、公式图片)
            
        }

        return $this->getDomFromString($content);
    }

公式转换传送大飞机来咯!

  1. 表格的单元格宽度的单位
    文件名PhpOffice\PhpWord\Reader\Word2007\AbstractPart.php
protected function readTable(){
  //...
                foreach ($rowNodes as $rowNode) {
                    if ('w:trPr' == $rowNode->nodeName) { // Row style
                        // @todo Do something with row style
                    } elseif ('w:tc' == $rowNode->nodeName) { // Cell
                        $cellWidth = $xmlReader->getAttribute('w:w', $rowNode, 'w:tcPr/w:tcW');
                        $cellStyle = null;
                        $cellStyleNode = $xmlReader->getElement('w:tcPr', $rowNode);
                        if (!is_null($cellStyleNode)) {
                            $cellStyle = $this->readCellStyle($xmlReader, $cellStyleNode);
                        }
                        $cell = $row->addCell($cellWidth, $cellStyle);

                        // ----------以下为新增部分
                        // 设置单位
                        $cellUnit = $xmlReader->getAttribute('w:type', $rowNode, 'w:tcPr/w:tcW');
                        $cell->setUnit($cellUnit);
                        // ----------以上为新增部分

                        $cellNodes = $xmlReader->getElements('*', $rowNode);
                        foreach ($cellNodes as $cellNode) {
                            if ('w:p' == $cellNode->nodeName) { // Paragraph
                                $this->readParagraph($xmlReader, $cellNode, $cell, $docPart);
                            }
                        }
                    }
                }
            }

  //...
}
  1. 内容的对齐样式
    文件名Element\AbstractContainer.php
    protected function addElement($elementName)
    {
        $elementClass = __NAMESPACE__ . '\\' . $elementName;
        $this->checkValidity($elementName);

        // Get arguments
        $args = func_get_args();
        $withoutP = in_array($this->container, array('TextRun', 'Footnote', 'Endnote', 'ListItemRun', 'Field'));
        if ($withoutP && ($elementName == 'Text' || $elementName == 'PreserveText')) {
            // 此处不知道为何要把样式移除,移除后的段落无alignment样式了,故把此代码注释了,不知会有何遗留问题,待发现。
            // $args[3] = null; // Remove paragraph style for texts in textrun
        }
        // ........
    }

  1. 新增首行缩进功能
    文件Style\Paragraph.php
    /**
     * 缩进字符
     *
     * @var integer
     * @Author 
     * @DateTime 2022-11-03
     */
    private $firstLineChars = 0; //新增属性

    // 修改方法
    public function getStyleValues()
    {
        $styles = array(
            // ...
            'indentation'         => $this->getIndentation(),
            // ------新增内容开始
            'firstLineChars'      => $this->getFirstLineChars(),
            // ------新增内容结束
            'spacing'             => $this->getSpace(),
            'pagination'          => array(
                'widowControl'    => $this->hasWidowControl(),
                'keepNext'        => $this->isKeepNext(),
                'keepLines'       => $this->isKeepLines(),
                'pageBreak'       => $this->hasPageBreakBefore(),
            ),
           // ...
        );
        return $styles;
    }

    新增方法
    /**
     * Get getFirstLineChars
     *
     * 
     */
    public function getFirstLineChars()
    {
        return $this->firstLineChars;
    }
    /**
     * Set getFirstLineChars
     *
     * 
     */
    public function setFirstLineChars($num = 0)
    {
        $this->firstLineChars = $num;
    }

文件Reader\Word2007\AbstractPart.php

    protected function readParagraphStyle(XMLReader $xmlReader, \DOMElement $domNode)
    {
        if (!$xmlReader->elementExists('w:pPr', $domNode)) {
            return null;
        }

        $styleNode = $xmlReader->getElement('w:pPr', $domNode);
        $styleDefs = array(
            'styleName'           => array(self::READ_VALUE, array('w:pStyle', 'w:name')),
            'alignment'           => array(self::READ_VALUE, 'w:jc'),
            'basedOn'             => array(self::READ_VALUE, 'w:basedOn'),
            'next'                => array(self::READ_VALUE, 'w:next'),
            'indent'              => array(self::READ_VALUE, 'w:ind', 'w:left'),
            'hanging'             => array(self::READ_VALUE, 'w:ind', 'w:hanging'),
            'firstLineChars'      => array(self::READ_VALUE, 'w:ind', 'w:firstLineChars'), //新增首行缩进
            'spaceAfter'          => array(self::READ_VALUE, 'w:spacing', 'w:after'),
            'spaceBefore'         => array(self::READ_VALUE, 'w:spacing', 'w:before'),
            'widowControl'        => array(self::READ_FALSE, 'w:widowControl'),
            'keepNext'            => array(self::READ_TRUE,  'w:keepNext'),
            'keepLines'           => array(self::READ_TRUE,  'w:keepLines'),
            'pageBreakBefore'     => array(self::READ_TRUE,  'w:pageBreakBefore'),
            'contextualSpacing'   => array(self::READ_TRUE,  'w:contextualSpacing'),
            'bidi'                => array(self::READ_TRUE,  'w:bidi'),
            'suppressAutoHyphens' => array(self::READ_TRUE,  'w:suppressAutoHyphens'),
        );
        return $this->readStyleDefs($xmlReader, $styleNode, $styleDefs);
    }

  1. 读取单元格的边框和颜色

文件名PhpOffice\PhpWord\Reader\Word2007\AbstractPart.php

    /**
     * Read w:tcPr
     *
     * @param \PhpOffice\PhpWord\Shared\XMLReader $xmlReader
     * @param \DOMElement $domNode
     * @return array
     */
    private function readCellStyle(XMLReader $xmlReader, \DOMElement $domNode)
    {
        $styleDefs = array(
            'vlign'        => array(self::READ_VALUE, 'w:vAlign'),
            'textDirection' => array(self::READ_VALUE, 'w:textDirection'),
            'gridSpan'      => array(self::READ_VALUE, 'w:gridSpan'),
            'vMerge'        => array(self::READ_VALUE, 'w:vMerge'),
            'bgColor'       => array(self::READ_VALUE, 'w:shd', 'w:fill'),
        );

        // ------新增内容开始
        $borders = array('top', 'left', 'bottom', 'right');
        if ($xmlReader->elementExists('w:tcBorders', $domNode)) {
            foreach ($borders as $side) {
                $ucfSide = ucfirst($side);
                $styleDefs["border{$ucfSide}Size"] = array(self::READ_VALUE, "w:tcBorders/w:$side", 'w:sz');
                $styleDefs["border{$ucfSide}Color"] = array(self::READ_VALUE, "w:tcBorders/w:$side", 'w:color');
                $styleDefs["border{$ucfSide}Style"] = array(self::READ_VALUE, "w:tcBorders/w:$side", 'w:val');
            }
        }
        // ------新增内容结束

        return $this->readStyleDefs($xmlReader, $domNode, $styleDefs);
    }


  1. 解析图片宽度
    namespace PhpOffice\PhpWord\Reader\Word2007\AbstractPart.php;
    protected function readRunChild(XMLReader $xmlReader, \DOMElement $node, AbstractContainer $parent, $docPart, $paragraphStyle = null, $fontStyle = null)
    {
        if ($node->nodeName == 'w:drawing') {
            if (!is_null($target)) {
                if(strpos($target,'wmf') === false){
                    // 2022/12/28 日新增读取图片宽度
                    $imgShowWidth = $xmlReader->getAttribute('cx', $node, 'wp:inline/wp:extent');
                    if($imgShowWidth == null){
                        $imgShowWidth = $xmlReader->getAttribute('cx', $node, 'wp:anchor/wp:extent');
                    }

                    $imageSource = "zip://{$this->docFile}#{$target}";
                    $parent->addImage($imageSource, null, false, $name,$imgShowWidth);
                }else{
                    $textContent = "{error:不支持mathtype}";
                    $parent->addText($textContent, $fontStyle, $paragraphStyle);
                }
                
            }
        }
    }

你可能感兴趣的:(PHP,Laravel,phpword,laravel)