因有些功能不支持,所以新增了某些功能,以防后期变动不好变更,手动做个记录
- 将公式替换成指定的符号,读取到 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('/<m:oMath>[\s|\S]*?<\/m:oMath>/', '<w:r><w:t>$Math$</w:t></w:r>', $content);
// 后续在将$Math$标记替换为对应的处理过的mathml公式(或latex表达式、公式图片)
}
return $this->getDomFromString($content);
}
- 表格的单元格宽度的单位
文件名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);
}
}
}
}
}
//...
}
- 内容的对齐样式
文件名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
}
// ........
}
- 新增首行缩进功能
文件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);
}
- 读取单元格的边框和颜色
文件名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);
}
- 解析图片宽度
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);
}
}
}
}