1

I need to paste content of one docx file into another docx file.

Here's my document merger class:

public class DocumentMerger
{
    private readonly WordprocessingDocument _targetDocument;

    public DocumentMerger(WordprocessingDocument targetDocument)
    {
        _targetDocument = targetDocument;
    }

    public void Merge(WordprocessingDocument mergingDocument)
    {
        var toPlace = _targetDocument.MainDocumentPart.Document.Body.FirstChild;

        foreach (var element in mergingDocument.MainDocumentPart.Document.Body.Elements())
        {
            CopyRelativeElements(element, _targetDocument.MainDocumentPart, mergingDocument.MainDocumentPart);
            toPlace.InsertAfterSelf(element.CloneNode(true));
        }
    }

    private void CopyRelativeElements(OpenXmlElement element, MainDocumentPart docPartTo, MainDocumentPart docPartFrom)
    {
        //images
        element.Descendants<DocumentFormat.OpenXml.Drawing.Blip>().ToList()
            .ForEach(blip =>
            {
                var newRelation = CopyImagePart(docPartTo, blip.Embed, docPartFrom);
                blip.Embed = newRelation;
            });
    }

    private string CopyImagePart(MainDocumentPart docPartTo, string relId, MainDocumentPart docPartFrom)
    {
        var p = docPartFrom.GetPartById(relId) as ImagePart;
        var newPart = docPartTo.AddPart(p);
        newPart.FeedData(p.GetStream(FileMode.Open, FileAccess.Read));
        return docPartTo.GetIdOfPart(newPart);
    }
}

There's a program, that uses this class:

class Program
{
    static void Main(string[] args)
    {
        var firstDoc = WordprocessingDocument.Open("File1.docx", true);

        var secondDoc = WordprocessingDocument.Open("File2.docx", false);

        var merger = new DocumentMerger(firstDoc);

        merger.Merge(secondDoc);

        firstDoc.Close();
        secondDoc.Close();
    }
}

If mergingDocument doesn't contain images, everything works fine. But I cannot correctly perform it with images. While opening the result file, MS Office alerts that file is correpted. MS Office repairs result and everything looks how it should be.

But I can't understand what exactly repairs MS Office. Manually looking in unzipped result file I see only renaming Id of relationship.

For example, before repairing in /word/document.xml there is such <w:drawing> element:

<w:drawing>
    <wp:inline distT="0" distB="0" distL="0" distR="0" wp14:anchorId="34AA245D" wp14:editId="2ED47BBF">
        <wp:extent cx="189865" cy="189865"/>
        <wp:effectExtent l="0" t="0" r="635" b="635"/>
        <wp:docPr id="1" name="Picture 1"/>
        <wp:cNvGraphicFramePr>
            <a:graphicFrameLocks xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" noChangeAspect="1"/>
        </wp:cNvGraphicFramePr>
        <a:graphic xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">
            <a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture">
                <pic:pic xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture">
                    <pic:nvPicPr>
                        <pic:cNvPr id="0" name="Picture 1"/>
                        <pic:cNvPicPr>
                            <a:picLocks noChangeAspect="1" noChangeArrowheads="1"/>
                        </pic:cNvPicPr>
                    </pic:nvPicPr>
                    <pic:blipFill>
                        <a:blip r:embed="Rfa237844834a44c5">
                            <a:extLst>
                                <a:ext uri="{28A0092B-C50C-407E-A947-70E740481C1C}">
                                    <a14:useLocalDpi xmlns:a14="http://schemas.microsoft.com/office/drawing/2010/main" val="0"/>
                                </a:ext>
                            </a:extLst>
                        </a:blip>
                        <a:srcRect/>
                        <a:stretch>
                            <a:fillRect/>
                        </a:stretch>
                    </pic:blipFill>
                    <pic:spPr bwMode="auto">
                        <a:xfrm>
                            <a:off x="0" y="0"/>
                            <a:ext cx="189865" cy="189865"/>
                        </a:xfrm>
                        <a:prstGeom prst="rect">
                            <a:avLst/>
                        </a:prstGeom>
                        <a:noFill/>
                        <a:ln>
                            <a:noFill/>
                        </a:ln>
                    </pic:spPr>
                </pic:pic>
            </a:graphicData>
        </a:graphic>
    </wp:inline>
</w:drawing>

File /word/_rels/document.xml.rels contains such a relationship:

<Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="/word/media/image12.png" Id="Rfa237844834a44c5" />

After repairing <w:drawing> changes only r:embed value:

    <w:drawing>
    <wp:inline distT="0" distB="0" distL="0" distR="0" wp14:anchorId="34AA245D" wp14:editId="2ED47BBF">
        <wp:extent cx="189865" cy="189865"/>
        <wp:effectExtent l="0" t="0" r="635" b="635"/>
        <wp:docPr id="1" name="Picture 1"/>
        <wp:cNvGraphicFramePr>
            <a:graphicFrameLocks xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" noChangeAspect="1"/>
        </wp:cNvGraphicFramePr>
        <a:graphic xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">
            <a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture">
                <pic:pic xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture">
                    <pic:nvPicPr>
                        <pic:cNvPr id="0" name="Picture 1"/>
                        <pic:cNvPicPr>
                            <a:picLocks noChangeAspect="1" noChangeArrowheads="1"/>
                        </pic:cNvPicPr>
                    </pic:nvPicPr>
                    <pic:blipFill>
                        <a:blip r:embed="rId7">
                            <a:extLst>
                                <a:ext uri="{28A0092B-C50C-407E-A947-70E740481C1C}">
                                    <a14:useLocalDpi xmlns:a14="http://schemas.microsoft.com/office/drawing/2010/main" val="0"/>
                                </a:ext>
                            </a:extLst>
                        </a:blip>
                        <a:srcRect/>
                        <a:stretch>
                            <a:fillRect/>
                        </a:stretch>
                    </pic:blipFill>
                    <pic:spPr bwMode="auto">
                        <a:xfrm>
                            <a:off x="0" y="0"/>
                            <a:ext cx="189865" cy="189865"/>
                        </a:xfrm>
                        <a:prstGeom prst="rect">
                            <a:avLst/>
                        </a:prstGeom>
                        <a:noFill/>
                        <a:ln>
                            <a:noFill/>
                        </a:ln>
                    </pic:spPr>
                </pic:pic>
            </a:graphicData>
        </a:graphic>
    </wp:inline>
</w:drawing>

In the file /word/_rels/document.xml.rels relationship changes Id. Target is correct (MS Office renames image file):

<Relationship Id="rId7" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/image2.png"/>

If I manually remove in word/document.xml <w:drawing> element in unzipped docx file, MS Office opens result file without alerts.

I saw these questions 1, 2 but it didn't helped me. Maybe I missed something. Please, can you help me?

Timothy
  • 584
  • 3
  • 14
  • Did you read all the comments in the links? It says " the only problem when you copy fragment of word-document into another word-document? Themes, spreadsheets, styles... they must be copied the same complex way in order to be correctly viewed in the result document". – jdweng Sep 28 '20 at 08:26
  • @jdweng so what elements must I search in w:drawing element to copy in complex way? Thank you for an answer! – Timothy Sep 28 '20 at 08:29
  • See following : https://social.msdn.microsoft.com/Forums/Lync/en-US/aa7ed8a9-5061-4789-9da3-6ab9c9464c53/copy-body-of-a-word-document-into-another-document-including-contained-pictures?forum=oxmlsdk – jdweng Sep 28 '20 at 08:36
  • @jdweng following instructions in link I've found a bug in my code. toPlace.InsertAfterSelf(element.CloneNode(true)); Using method MainDocumentPart.Document.Body.Append works fine. But how can I paste new content in exact place of my document? – Timothy Sep 28 '20 at 10:50
  • @jdweng I've understood my problem. When I paste new elements after element SectionProperties it's ok. But I need to paste it in exact place, not only at the end of the document? "Themes, spreadsheets, styles..." - perhaps can you advise me what else should I copy in order to MS Office didn't alert error messages? – Timothy Sep 28 '20 at 13:22
  • Look at answer by PasMeisterSuperG on my link. – jdweng Sep 28 '20 at 13:24
  • His advise helped me to understand why office alerts error messages. But in his example there's appending at the end of the document... attachment.MainDocumentPart.Document.Body.Append(body2Insert.Elements().Where(e => !(e is SectionProperties)).Select(e => e.Clone() as OpenXmlElement)); – Timothy Sep 28 '20 at 13:29
  • No he is not. Look at the WHERE : attachment.MainDocumentPart.Document.Body.Append(body2Insert.Elements().Where(e => !(e is SectionProperties)).Select(e => e.Clone() as OpenXmlElement)) – jdweng Sep 28 '20 at 13:36
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/222181/discussion-between-timothy-and-jdweng). – Timothy Sep 28 '20 at 13:39

0 Answers0