如何在PHP中合并docx文档?

如何在PHP中合并docx文档?,php,ms-word,docx,Php,Ms Word,Docx,有人知道如何将docx文档与PHP(如果在PHP中不可能的话,还可以使用Python)合并(连接)吗 澄清一下,我的服务器是基于Linux的。我有两个现有的docx文档,我需要使用PHP或Python将它们放在一个新的docx文档中。合并两个不同的docx文件可能非常复杂,因为每个docx中的标题、样式、图表、注释、用户修改跟踪和其他特殊内容都保存在单独的内部XML子文件中。因此,两个Docx可能具有具有相同id的不同对象。因此,在这两个文档中列出所有可能的对象,给它们新的内部ID,并在一个文档

有人知道如何将docx文档与PHP(如果在PHP中不可能的话,还可以使用Python)合并(连接)吗


澄清一下,我的服务器是基于Linux的。我有两个现有的docx文档,我需要使用PHP或Python将它们放在一个新的docx文档中。

合并两个不同的docx文件可能非常复杂,因为每个docx中的标题、样式、图表、注释、用户修改跟踪和其他特殊内容都保存在单独的内部XML子文件中。因此,两个Docx可能具有具有相同id的不同对象。因此,在这两个文档中列出所有可能的对象,给它们新的内部ID,并在一个文档中重新影响它们,这将是一项非常艰巨的工作。目前可能只有Ms Office可以这样做

但是,如果您知道要合并的两个文档具有相同的样式,并且没有图表、标题和其他特殊对象,那么合并将变得非常容易

在这种情况下,您只需要使用Zip读取器,例如打开第一个Docx文件(从技术上讲,它是包含XML子文件的Zip存档);然后读取子文件“word/document.xml”,并提取标签之间的部分。 在第二个Docx文件中,打开“word/content.xml”并在标签前面插入上一个内容。将结果保存在新的Docx文件中

这可以使用TbsZip完成,如下所示:

<?php

include_once('tbszip.php');

$zip = new clsTbsZip();

// Open the first document
$zip->Open('doc1.docx');
$content1 = $zip->FileRead('word/document.xml');
$zip->Close();

// Extract the content of the first document
$p = strpos($content1, '<w:body');
if ($p===false) exit("Tag <w:body> not found in document 1.");
$p = strpos($content1, '>', $p);
$content1 = substr($content1, $p+1);
$p = strpos($content1, '</w:body>');
if ($p===false) exit("Tag </w:body> not found in document 1.");
$content1 = substr($content1, 0, $p);

// Insert into the second document
$zip->Open('doc2.docx');
$content2 = $zip->FileRead('word/document.xml');
$p = strpos($content2, '</w:body>');
if ($p===false) exit("Tag </w:body> not found in document 2.");
$content2 = substr_replace($content2, $content1, $p, 0);
$zip->FileReplace('word/document.xml', $content2, TBSZIP_STRING);

// Save the merge into a third file
$zip->Flush(TBSZIP_FILE, 'merge.docx');
Close();
//提取第一个文档的内容
$p=strpos($content1,,$p);
$content1=substr($content1,$p+1);
$p=strpos($content1,”);
如果($p==false)退出(“在文档1中找不到标记”);
$content1=substr($content1,0,$p);
//插入到第二个文档中
$zip->Open('doc2.docx');
$content2=$zip->FileRead('word/document.xml');
$p=strpos($content2',);
如果($p==false)退出(“在文档2中找不到标记”);
$content2=substr\u replace($content2,$content1,$p,0);
$zip->FileReplace('word/document.xml',$content2,TBSZIP_字符串);
//将合并保存到第三个文件中
$zip->Flush(TBSZIP_文件'merge.docx');

您可以用一行代码将两个Word文档与PHPDocX合并:(来源:)

通过这种合并,您可以保留所有的节结构(纸张大小、页边距、相关页脚和页眉等),包括所有必需的样式,管理所有列表(这看起来很简单,但在OOXML标准中并非如此),保留图像和图表以及脚注、尾注和注释

此外,还可以选择保留原始编号(默认情况下,页面编号将继续)

还可以通过mergeType选项放弃合并文档的节结构,并将其添加到第一个文档的末尾,作为其最后一个节的一部分。当然,在这种情况下,不会导入页眉和页脚,但所有其他元素仍会保留。

可以将多个Word文档合并/连接到一个Word文档中,同时根据ImportFormatMode参数值保留附加文档或目标文档的格式。第二,它是一种商业API,但免费定价计划允许每月150次免费API调用

<?php

require_once('D:\xampp\htdocs\aspose-words-cloud-php-master\vendor\autoload.php');

//TODO: Get your ClientId and ClientSecret at https://dashboard.aspose.cloud (free registration is required).

$ClientSecret="xxxxxxxxxxxxxxxxxxxxxxxxxxxx";
$ClientId="xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx";

$wordsApi = new Aspose\Words\WordsApi($ClientId,$ClientSecret);


try {

    $remoteDataFolder = "Temp";
    $localFile = "C:/Temp/02_pages_adobe.docx";
    $remoteFileName = "02_pages_adobe.docx";
    $localFile1 = "C:/Temp/Sections.docx";
    $remoteFileName1 = "Sections.docx";
    $outputFileName = "TestAppendDocument.docx";

        
    $uploadRequest = new Aspose\Words\Model\Requests\UploadFileRequest($localFile,$remoteDataFolder."/".$remoteFileName,null);
    $wordsApi->uploadFile($uploadRequest);
    $uploadRequest1 = new Aspose\Words\Model\Requests\UploadFileRequest($localFile1,$remoteDataFolder."/".$remoteFileName1,null);
    $wordsApi->uploadFile($uploadRequest1);

    $requestDocumentListDocumentEntries0 = new Aspose\Words\Model\DocumentEntry(array(
            "href" => $remoteDataFolder . "/" . $remoteFileName1,
            "import_format_mode" => "KeepSourceFormatting",
        ));
    $requestDocumentListDocumentEntries = [
            $requestDocumentListDocumentEntries0,
        ];
    $requestDocumentList = new Aspose\Words\Model\DocumentEntryList(array(
            "document_entries" => $requestDocumentListDocumentEntries,
        ));
    $request = new Aspose\Words\Model\Requests\AppendDocumentRequest(
            $remoteFileName,
            $requestDocumentList,
            $remoteDataFolder,
            NULL,
            NULL,
            NULL,
            $remoteDataFolder . "/" . $outputFileName,
            NULL,
            NULL
        );

    $result = $wordsApi->appendDocument($request);
        
    ##Download file 
    $request = new Aspose\Words\Model\Requests\DownloadFileRequest($remoteDataFolder."/".$outputFileName,NULL,NULL);
    $result = $wordsApi->downloadFile($request);
    copy($result->getPathName(),"AppendOutput.docx");

    
} catch (Exception $e) {
    echo  "Something went wrong: ",  $e->getMessage(), "\n";
    PHP_EOL;
}

?>


附言:我是Aspose的开发者宣传员。

由于.docx理论上是XML,您应该能够解析它并从中构造新的XML文档。不过,我对Microsoft universe的了解还不够,无法向您提供更多详细信息。@deceze、.docx实际上是一个包含XML和大量其他资源(图像等)的zip文件。不幸的是,合并它们似乎有点棘手。@Yongke,有没有办法在Windows服务器上通过COM调用MS Word?通过这种方式,使用Word来完成实际工作,您将获得更大的进步。也许你可以启动一个虚拟实例?@Brad很高兴知道。“Office Open XML”毕竟不容易使用,我为什么不感到惊讶呢o) @deceze,'嗯,我将取代原始文档格式。您只需记住所有支持的内容。如何处理不同的纸张尺寸?图像的放置?格式化?等。让Word做这项工作要容易得多。即使您可以自动化OpenOffice来实现这一点,除了基本文档之外,兼容性也不是100%。PHPDocX中的功能不是免费的,实际上并不便宜。很好!这太完美了!帮助很多:-)要在每个文档后添加分页符,请将$content1提取中的最后一行代码替换为:
$content1=''.substr($content1,0,$p)
为了让分页符与最新版本的Word一起工作,我不得不使用
'
这是一篇非常古老的文章,但即使是在最后一个PHP7.3上,它也确实有效!是的,对于分页符,您需要应用TimL行,而不是旧行,因为它不起作用!。。。。所以它变成了$content1=''.substr($content1,0,$p);
<?php

require_once('D:\xampp\htdocs\aspose-words-cloud-php-master\vendor\autoload.php');

//TODO: Get your ClientId and ClientSecret at https://dashboard.aspose.cloud (free registration is required).

$ClientSecret="xxxxxxxxxxxxxxxxxxxxxxxxxxxx";
$ClientId="xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx";

$wordsApi = new Aspose\Words\WordsApi($ClientId,$ClientSecret);


try {

    $remoteDataFolder = "Temp";
    $localFile = "C:/Temp/02_pages_adobe.docx";
    $remoteFileName = "02_pages_adobe.docx";
    $localFile1 = "C:/Temp/Sections.docx";
    $remoteFileName1 = "Sections.docx";
    $outputFileName = "TestAppendDocument.docx";

        
    $uploadRequest = new Aspose\Words\Model\Requests\UploadFileRequest($localFile,$remoteDataFolder."/".$remoteFileName,null);
    $wordsApi->uploadFile($uploadRequest);
    $uploadRequest1 = new Aspose\Words\Model\Requests\UploadFileRequest($localFile1,$remoteDataFolder."/".$remoteFileName1,null);
    $wordsApi->uploadFile($uploadRequest1);

    $requestDocumentListDocumentEntries0 = new Aspose\Words\Model\DocumentEntry(array(
            "href" => $remoteDataFolder . "/" . $remoteFileName1,
            "import_format_mode" => "KeepSourceFormatting",
        ));
    $requestDocumentListDocumentEntries = [
            $requestDocumentListDocumentEntries0,
        ];
    $requestDocumentList = new Aspose\Words\Model\DocumentEntryList(array(
            "document_entries" => $requestDocumentListDocumentEntries,
        ));
    $request = new Aspose\Words\Model\Requests\AppendDocumentRequest(
            $remoteFileName,
            $requestDocumentList,
            $remoteDataFolder,
            NULL,
            NULL,
            NULL,
            $remoteDataFolder . "/" . $outputFileName,
            NULL,
            NULL
        );

    $result = $wordsApi->appendDocument($request);
        
    ##Download file 
    $request = new Aspose\Words\Model\Requests\DownloadFileRequest($remoteDataFolder."/".$outputFileName,NULL,NULL);
    $result = $wordsApi->downloadFile($request);
    copy($result->getPathName(),"AppendOutput.docx");

    
} catch (Exception $e) {
    echo  "Something went wrong: ",  $e->getMessage(), "\n";
    PHP_EOL;
}

?>