2

C# で OpenXML を使用して、docx ファイルの内容を複製し、同じファイル内に保存しようとしています。

コードは次のとおりです。

using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(wordFileNamePath, true))
{
    foreach(OpenXmlElement element in wordDoc.MainDocumentPart.Document.ChildElements)
    {
        OpenXmlElement cloneElement = (OpenXmlElement)element.Clone();
        wordDoc.MainDocumentPart.Document.Append(cloneElement);
    }
    wordDoc.MainDocumentPart.Document.Save();
}

コードは正常に機能しており、必要なことを行っています。私の問題は、結果の docx ファイルが部分的に破損していることです。ファイルを開くと、次の 2 つのメッセージが表示されます。 ここに画像の説明を入力

[OK] をクリックしてから [はい] をクリックすると、通常どおりファイルが開きます。ただし、「名前を付けて保存」するまで、ファイルは破損し続けます(同じ名前または別の名前で)。それが、新しく保存されたファイルが固定される方法です。

Open XML SDK 2.5 Productivity Tool for Microsoft Office を使用することで、ファイルを検証し、反映されたコードを確認できます。ファイルを検証すると、次の 5 つのエラーが発生します。

ここに画像の説明を入力

私のコードで使用している「Clone」機能は、要素をそのままコピーするため、ドキュメントに追加すると、いくつかの ID の重複が発生すると思います。

それ自体を複製した後、適切に機能する DOCX ファイルを取得するためのアイデアはありますか? 代替コードは大歓迎です。

4

2 に答える 2

1

メソッドの問題は、無効な Open XML マークアップが作成されることです。これが理由です。

次のマークアップで表される非常に単純な Word 文書があるとします。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
  <w:body>
    <w:p>
      <w:r>
        <w:t>First paragraph</w:t>
      </w:r>
    </w:p>
    <w:p>
      <w:r>
        <w:t>Second paragraph</w:t>
      </w:r>
    </w:p>
  <w:body>
<w:document>

foreachループでwordDoc.MainDocumentPart.Document.ChildElementsは、要素のみを含む単一要素のリストになりますw:body。したがって、w:body要素のディープ クローンを作成し、それをw:document. 結果の Open XML マークアップは次のようになります。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
  <w:body>
    <w:p>
      <w:r>
        <w:t>First paragraph</w:t>
      </w:r>
    </w:p>
    <w:p>
      <w:r>
        <w:t>Second paragraph</w:t>
      </w:r>
    </w:p>
  <w:body>
  <w:body>
    <w:p>
      <w:r>
        <w:t>First paragraph</w:t>
      </w:r>
    </w:p>
    <w:p>
      <w:r>
        <w:t>Second paragraph</w:t>
      </w:r>
    </w:p>
  <w:body>
<w:document>

上記はw:document2つの子要素を持つ です。これは、子要素を1 つだけ持つ必要がw:bodyあるため、無効な Open XML マークアップです。したがって、Word はそのエラー メッセージを表示します。w:documentw:body

これを修正するには、Document.Body使用する場所で作業する必要がありますDocument。次の合理化された例は、その方法を示しています。

using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(wordFileNamePath, true))
{
    Body body = wordDoc.MainDocumentPart.Document.Body;
    IEnumerable<OpenXmlElement> clonedElements = body
        .Elements()
        .Select(e => e.CloneNode(true))
        .ToList();

    body.Append(clonedElements);
}

ステートメントと、これらのドキュメントがデフォルトで自動保存されるという事実Documentのために、明示的に保存する必要がないため、明示的に保存しなかったことがわかります。using次に、ToList()追加する前にコレクションを実体化していました。これは、同時に変更される要素を列挙する際の問題を回避するためです。

于 2019-11-28T12:10:34.230 に答える