Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
708 views
in Technique[技术] by (71.8m points)

c# - copying openXML image from one document to another

We have conditional Footers that INCLUDETEXT based on the client:

IF $CLIENT = "CLIENT1" "{INCLUDETEXT "CLIENT1HEADER.DOCX"}" ""

Depending on our document, there could be a varying amount of IF/ELSE, and these all work correctly for merging the correct files in the correct place.

However, some of these documents may have client specific images/branding, which also need to be copied across from the INCLUDETEXT file.

Below is the method that is called to replace any Picture elements that exist in the IEnumerable<Run> that is copied from the Source document to the Target document.

The image is copied fine, however it doesn't appear to update the RID in my Picture or add a record into the .XML.Rels files. (I even tried adding a ForEach to add to all the headers and footers, to see if this made any difference.

    private void InsertImagesFromOldDocToNewDoc(WordprocessingDocument source, WordprocessingDocument target, IEnumerable<Picture> pics)
    {
        IEnumerable<Picture> imageElements = source.MainDocumentPart.Document.Descendants<Run>().Where(x => x.Descendants<Picture>().FirstOrDefault() != null).Select(x => x.Descendants<Picture>().FirstOrDefault());

        foreach (Picture pic in pics) //the new pics
        {
            Picture oldPic = imageElements.Where(x => x.Equals(pic)).FirstOrDefault();

            if (oldPic != null)
            {
                string imageId = "";

                ImageData shape = oldPic.Descendants<ImageData>().FirstOrDefault();

                ImagePart p = source.MainDocumentPart.GetPartById(shape.RelationshipId) as ImagePart;

                ImagePart newPart = target.MainDocumentPart.AddPart<ImagePart>(p);

                newPart.FeedData(p.GetStream());

                shape.RelId = target.MainDocumentPart.GetIdOfPart(newPart);
                string relPart = target.MainDocumentPart.CreateRelationshipToPart(newPart);
            }
        }
    }

Has anyone come across this issue before?

It appears the OpenXML SDK documentation is a 'little' sparse...

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Late reaction but this thread helped me a lot to got it working. Here my solution for copying a document with images

private static void CopyDocumentWithImages(string path)
{
    if (!Path.GetFileName(path).StartsWith("~$"))
    {
        using (var source = WordprocessingDocument.Open(path, false))
        {
            using (var newDoc = source.CreateNew(path.Replace(".docx", "-images.docx")))
            {
                foreach (var e in source.MainDocumentPart.Document.Body.Elements())
                {
                    var clonedElement = e.CloneNode(true);
                    clonedElement.Descendants<DocumentFormat.OpenXml.Drawing.Blip>()
                        .ToList().ForEach(blip =>
                        {
                            var newRelation = newDoc.CopyImage(blip.Embed, source);
                            blip.Embed = newRelation;
                        });
                    clonedElement.Descendants<DocumentFormat.OpenXml.Vml.ImageData>().ToList().ForEach(imageData =>
                    {
                        var newRelation = newDoc.CopyImage(imageData.RelationshipId, source);
                        imageData.RelationshipId = newRelation;
                    });
                    newDoc.MainDocumentPart.Document.Body.AppendChild(clonedElement);
                }
                newDoc.Save();
            }
        }
    }
}

CopyImage:

public static string CopyImage(this WordprocessingDocument newDoc, string relId, WordprocessingDocument org)
{
    var p = org.MainDocumentPart.GetPartById(relId) as ImagePart;
    var newPart = newDoc.MainDocumentPart.AddPart(p);
    newPart.FeedData(p.GetStream());
    return newDoc.MainDocumentPart.GetIdOfPart(newPart);
}

CreateNew:

public static WordprocessingDocument CreateNew(this WordprocessingDocument org, string name)
{
    var doc = WordprocessingDocument.Create(name, WordprocessingDocumentType.Document);
    doc.AddMainDocumentPart();
    doc.MainDocumentPart.Document = new Document(new Body());
    using (var streamReader = new StreamReader(org.MainDocumentPart.ThemePart.GetStream()))
    using (var streamWriter = new StreamWriter(doc.MainDocumentPart.AddNewPart<ThemePart>().GetStream(FileMode.Create)))
    {
        streamWriter.Write(streamReader.ReadToEnd());
    }
    using (var streamReader = new StreamReader(org.MainDocumentPart.StyleDefinitionsPart.GetStream()))
    using (var streamWriter = new StreamWriter(doc.MainDocumentPart.AddNewPart<StyleDefinitionsPart>().GetStream(FileMode.Create)))
    {
        streamWriter.Write(streamReader.ReadToEnd());
    }
    return doc;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...