簡體   English   中英

使用 OpenXml 和 C# 復制 Word 文檔

[英]Duplicating Word document using OpenXml and C#

我正在使用 Word 和 OpenXml 在 C# ASP.NET Web 應用程序中提供郵件合並功能:

1) 上傳的文檔帶有多個預定義的字符串進行替換。

2) 使用 OpenXML SDK 2.0 我打開 Word 文檔,獲取 mainDocumentPart 作為字符串並使用 Regex 執行替換。

3) 然后我使用 OpenXML 創建一個新文檔,添加一個新的 mainDocumentPart 並將替換產生的字符串插入到這個 mainDocumentPart 中。

但是,所有格式/樣式等都將在新文檔中丟失。

我猜我可以單獨復制和添加樣式、定義、注釋部分等來模仿原始文檔。

但是,是否有使用 Open XML 復制文檔的方法,允許我對新副本執行替換?

謝謝。

這段代碼應該將現有文檔中的所有部分復制到新文檔中。

using (var mainDoc = WordprocessingDocument.Open(@"c:\sourcedoc.docx", false))
using (var resultDoc = WordprocessingDocument.Create(@"c:\newdoc.docx",
  WordprocessingDocumentType.Document))
{
  // copy parts from source document to new document
  foreach (var part in mainDoc.Parts)
    resultDoc.AddPart(part.OpenXmlPart, part.RelationshipId);
  // perform replacements in resultDoc.MainDocumentPart
  // ...
}

我第二次推薦使用 Content Controls。 使用它們來標記要執行替換的文檔區域是迄今為止最簡單的方法。

至於復制文檔(並保留整個文檔內容、樣式等)相對容易:

string documentURL = "full URL to your document";
byte[] docAsArray = File.ReadAllBytes(documentURL);

using (MemoryStream stream = new MemoryStream)
{
    stream.Write(docAsArray, 0, docAsArray.Length);    // THIS performs doc copy
    using (WordprocessingDocument doc = WordprocessingDocument.Open(stream, true))
    {
        // perform content control substitution here, making sure to call .Save()
        // on any documents Part's changed.
    }
    File.WriteAllBytes("full URL of your new doc to save, including .docx", stream.ToArray());
}

實際上使用 LINQ 找到內容控件是小菜一碟。 以下示例查找所有簡單文本內容控件(類型為 SdtRun):

using (WordprocessingDocument doc = WordprocessingDocument.Open(stream, true))
{                    
    var mainDocument = doc.MainDocumentPart.Document;
    var contentControls = from sdt in mainDocument.Descendants<SdtRun>() select sdt;

    foreach (var cc in contentControls)
    {
        // drill down through the containment hierarchy to get to 
        // the contained <Text> object
        cc.SdtContentRun.GetFirstChild<Run>().GetFirstChild<Text>().Text = "my replacement string";
    }
}

<Run><Text>元素可能不存在,但創建它們很簡單:

cc.SdtContentRun.Append(new Run(new Text("my replacement string")));

希望能幫助某人。 :D

我做了一些非常相似的事情,但我沒有使用文本替換字符串,而是使用 Word 內容控件。 我在以下博客文章SharePoint 和 Open Xml 中記錄了一些詳細信息。 該技術並非特定於 SharePoint。 您可以在純 ASP.NET 或其他應用程序中重用該模式。

此外,我強烈建議您查看Eric White 的博客,了解有關 Open Xml 的提示、技巧和技術。 具體來說,查看Open Xml post 的內存操作,以及Word 內容控制帖子。 我認為從長遠來看,你會發現這些更有幫助。

希望這可以幫助。

作為上述內容的補充; 可能更有用的是查找已標記的內容控件(使用 GUI 一詞)。 我最近編寫了一些軟件來填充包含帶有附加標簽的內容控件的文檔模板。 找到它們只是上述 LINQ 查詢的擴展:

var mainDocument = doc.MainDocumentPart.Document;
var taggedContentControls = from sdt in mainDocument.Descendants<SdtElement>()
                            let sdtPr = sdt.GetFirstChild<SdtProperties>()
                            let tag = (sdtPr == null ? null : sdtPr.GetFirstChild<Tag>())
                            where (tag != null)
                            select new
                            {
                                SdtElem = sdt,
                                TagName = tag.GetAttribute("val", W).Value
                            };   

我從別處得到了這個代碼,但現在不記得在哪里; 完全歸功於他們。

該查詢只是創建一個匿名類型的 IEnumerable,其中包含內容控件及其關聯的標記作為屬性。 便利!

最初的問題是在向 Open XML SDK 添加許多有用功能之前提出的。 如今,如果您已經有一個打開的WordprocessingDocument ,您只需克隆原始文檔並對該克隆執行任何轉換。

// Say you have done this somewhere before you want to duplicate your document.
using WordprocessingDocument originalDoc = WordprocessingDocument.Open("original.docx", false);

// Then this is how you can clone the opened WordprocessingDocument.
using var newDoc = (WordprocessingDocument) originalDoc.Clone("copy.docx", true);

// Perform whatever transformation you want to do.
PerformTransformation(newDoc);

您還可以在StreamPackage上進行克隆。 總的來說,您有以下選擇:

OpenXmlPackage Clone()

OpenXmlPackage Clone(Stream stream)
OpenXmlPackage Clone(Stream stream, bool isEditable)
OpenXmlPackage Clone(Stream stream, bool isEditable, OpenSettings openSettings)

OpenXmlPackage Clone(string path)
OpenXmlPackage Clone(string path, bool isEditable)
OpenXmlPackage Clone(string path, bool isEditable, OpenSettings openSettings)

OpenXmlPackage Clone(Package package)
OpenXmlPackage Clone(Package package, OpenSettings openSettings)

有關這些方法的詳細信息,請查看 Open XML SDK 文檔。

話雖如此,如果您還沒有打開WordprocessingDocument ,那么至少有更快的方法來復制或克隆文檔。 我已經在有關克隆 Office Open XML 文檔的最有效方法的回答中證明了這一點。

當您通過將擴展名更改為 zip 並打開它來查看 openxml 文檔時,您會看到該 word 子文件夾包含一個 _rels 文件夾,其中列出了所有關系。 這些關系指向您提到的部分(樣式...)。 實際上您需要這些部分,因為它們包含格式的定義。 因此,不復制它們將導致新文檔使用 normal.dot 文件中定義的格式,而不是原始文檔中定義的格式。 所以我認為你必須復制它們。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM