none
Copy header with image from a docx file to another using open xml and c# RRS feed

  • Question

  • Hello,

    I'm a newbie but I'really would like to learn as much as possible about c# and the manipulation of docx files...

    I'm writing a program to merge some docx file to create a new file and it works quite well :) but i'm not able to copy the header and the footer from a template...

    I tried to use the code to replace the header that i found on msdn help but no header is created :(

    The point is that my header is an image and I'm not able to copy it...

    Does someone can help me? Maybe, if it's possible, can you show me a code that copy an header with images to another one?

    Thanks,

    Cristina

    Tuesday, October 9, 2012 8:04 AM

Answers

  • Hi Cristina1987,

    Thanks for posting in the MSDN Forum.

    First time you need to clarify the type of your head.

    As far as I know that Microsoft Office Word has three kind of Head, following reference will let you know well about them: http://msdn.microsoft.com/en-us/library/documentformat.openxml.wordprocessing.headerreference.aspx. And in open xml format Header information is stored in single xml file. We can retrieve the picture from that place, however we need to know the specific header which we need to retrieve.

    Have a good day,

    Tom


    Tom Xu [MSFT]
    MSDN Community Support | Feedback to us

    Monday, October 15, 2012 7:29 AM
    Moderator
  • Hi Cristina1987,

    I will show my snippet to copy header(Default type) to another Document. I suppose there only a png image in the header. You can modify the code to fit your goal. In this snippet you will see "com.mksword.Net.OpenXmlTools" Namespace and WordprocessingDocumentUtil Class. Please omit these due to it just a customized assembly to let the code short and clear. Please pay attention at ReadHeaderImage method, CopyHeader method and NewHeader method. That is the key of this issue. Especially NewHeader method, all key change will happen in this part.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using DocumentFormat.OpenXml;
    using DocumentFormat.OpenXml.Packaging;
    using DocumentFormat.OpenXml.Wordprocessing;
    using log4net;
    using com.mksword.Net.OpenXmlTools;
    using A = DocumentFormat.OpenXml.Drawing;
    using Pic = DocumentFormat.OpenXml.Drawing.Pictures;
    
    namespace ConsoleApplication3
    {
        public class CopyHeaderImage : WordprocessingDocumentUtil
        {
            private HeaderPart _Header = null;
            private ImagePart _Image = null;
    
            public void Action()
            {
                OpenedDocumentHander(ReadHeaderImage);
            }
    
            private bool ReadHeaderImage(WordprocessingDocument WPD)
            {
                bool result = false;
                MainDocumentPart MDP = WPD.MainDocumentPart;
                Document D = MDP.Document;
                SectionProperties SPS = D.Descendants<SectionProperties>()
                    .FirstOrDefault();
                HeaderReference HR = SPS.Descendants<HeaderReference>()
                    .Where(H => H.Type == HeaderFooterValues.Default)
                    .FirstOrDefault();
                HeaderPart HP = MDP.GetPartById(HR.Id) as HeaderPart;
                _Image = HP.ImageParts.FirstOrDefault();
                CopyHeader(HP);
                return result;
            }
    
            private void CopyHeader(HeaderPart HP)
            {
                _Header = HP;
                OpenedDocumentHander(CopyHeaderHandler,true);
            }
    
            private bool CopyHeaderHandler(WordprocessingDocument WPD)
            {
                bool result = false;
                MainDocumentPart MDP = WPD.MainDocumentPart;
                Document D = MDP.Document;
                SectionProperties SPS = D.Descendants<SectionProperties>()
                    .FirstOrDefault();
                HeaderReference HR = SPS.Descendants<HeaderReference>()
                    .Where(H => H.Type == HeaderFooterValues.Default)
                    .FirstOrDefault();
                if (HR != null)
                {
                    HeaderPart older = MDP.GetPartById(HR.Id) as HeaderPart;
                    MDP.DeletePart(older);
                    NewHeader(MDP, HR);
                }
                else
                {
                    HR = new HeaderReference()
                    {
                        Type = HeaderFooterValues.Default,
                        Id = string.Empty
                    };
                    NewHeader(MDP, HR);
                    SPS.Append(HR);
                }
                D.Save();
                return result;
            }
    
            private void NewHeader(MainDocumentPart MDP,HeaderReference HR)
            {
                HeaderPart newHeader = MDP.AddNewPart<HeaderPart>();
                if (_Header != null && _Image != null)
                {
                    newHeader.FeedData(_Header.GetStream());
                    ImagePart imagePart = newHeader.AddImagePart(ImagePartType.Png);
                    imagePart.FeedData(_Image.GetStream());
                    string ImageId = newHeader.GetIdOfPart(imagePart);
                    Header H = newHeader.Header;
                    Paragraph P = H.Descendants<Paragraph>().FirstOrDefault();
                    Run R = P.Descendants<Run>().First();
                    Drawing D = R.Descendants<Drawing>().First();
                    A.GraphicData GD = D.Inline.Graphic.GraphicData;
                    Pic.Picture Pic = GD.Descendants<Pic.Picture>()
                        .FirstOrDefault();
                    Pic.BlipFill BF = Pic.Descendants<Pic.BlipFill>()
                        .FirstOrDefault();
                    BF.Blip.Embed = ImageId;
                    HR.Id = MDP.GetIdOfPart(newHeader);
                }
                else
                {
                    SetLog("_Header wasn't set", OXULogType.FATAL);
                }
            }
        }
    }

    Have a good day,

    Tom


    Tom Xu [MSFT]
    MSDN Community Support | Feedback to us

    Tuesday, October 30, 2012 8:33 AM
    Moderator

All replies

  • Hi Cristina

    It's very difficult to help you without more detailed information about the approach you're taking, or want to take. However, if your main interest is in combing documents I recommend you start here

    http://blogs.msdn.com/b/ericwhite/archive/2008/10/27/how-to-use-altchunk-for-document-assembly.aspx
    http://blogs.msdn.com/b/ericwhite/archive/2010/01/22/inserting-content-that-contains-images-using-altchunk.aspx
    http://blogs.msdn.com/b/ericwhite/archive/2009/04/19/comparison-of-altchunk-to-the-documentbuilder-class.aspx


    Cindy Meister, VSTO/Word MVP, my blog

    Wednesday, October 10, 2012 12:44 PM
    Moderator
  • Hi Cristina1987,

    Thanks for posting in the MSDN Forum.

    First time you need to clarify the type of your head.

    As far as I know that Microsoft Office Word has three kind of Head, following reference will let you know well about them: http://msdn.microsoft.com/en-us/library/documentformat.openxml.wordprocessing.headerreference.aspx. And in open xml format Header information is stored in single xml file. We can retrieve the picture from that place, however we need to know the specific header which we need to retrieve.

    Have a good day,

    Tom


    Tom Xu [MSFT]
    MSDN Community Support | Feedback to us

    Monday, October 15, 2012 7:29 AM
    Moderator
  • Thank you for your kind reply,

    My problem is that the file has an header containg only an image and is the same for all the pages but, if i try tu use this code :

     public static void AddHeaderFromTo(string filepathFrom, string filepathTo)
            {
                // Replace header in target document with header of source document.
                using (WordprocessingDocument
                    wdDoc = WordprocessingDocument.Open(filepathTo, true))
                {
                    MainDocumentPart mainPart = wdDoc.MainDocumentPart;
                    // Delete the existing header part.
                    mainPart.DeleteParts(mainPart.HeaderParts);
                    // Create a new header part.
                    DocumentFormat.OpenXml.Packaging.HeaderPart headerPart =
                mainPart.AddNewPart<HeaderPart>();
                    // Get Id of the headerPart.
                    string rId = mainPart.GetIdOfPart(headerPart);
                    // Feed target headerPart with source headerPart.
                    using (WordprocessingDocument wdDocSource =
                        WordprocessingDocument.Open(filepathFrom, true))
                    {
                        DocumentFormat.OpenXml.Packaging.HeaderPart firstHeader =
                wdDocSource.MainDocumentPart.HeaderParts.FirstOrDefault();
                        wdDocSource.MainDocumentPart.HeaderParts.FirstOrDefault();
                      
                        
                        if (firstHeader != null)
                        {
                            headerPart.FeedData(firstHeader.GetStream());
                        }
                    }
                    // Get SectionProperties and Replace HeaderReference with new Id.
                    IEnumerable<DocumentFormat.OpenXml.Wordprocessing.SectionProperties> sectPrs =
                mainPart.Document.Body.Elements<SectionProperties>();
                    foreach (var sectPr in sectPrs)
                    {
                        // Delete existing references to headers.
                        sectPr.RemoveAllChildren<HeaderReference>();
                        // Create the new header reference node.
                        sectPr.PrependChild<HeaderReference>(new HeaderReference() { Id = rId });
                    }
                }
            }

    I cannot copy it.

    I tried also to use altchunk to copy the entire document and this way i resolved partially the problem.

    In fact now i can copy the header but, when I open the result document it results to be unreadble beacuse there are some trouble with the footer part...

    The structure of the file is not too complex, there are two footer that are composed only by text...

    The code that I use is:

     public void altchunkDocument()
            {
                string fileName1 = @"C:\Users\itcrsan\Documents\AQS\Fixed\ENG\Template2.docx";
                string fileName2 = @"C:\Users\itcrsan\Documents\Out.docx";
                string testFile = @"C:\Users\itcrsan\Documents\AQS\Fixed\ENG\TemplateH1.docx";
                File.Delete(fileName1);
                File.Copy(testFile, fileName1);
                using (WordprocessingDocument myDoc =
                    WordprocessingDocument.Open(fileName1, true))
                {
                    string altChunkId = "AltChunkId1";
                    MainDocumentPart mainPart = myDoc.MainDocumentPart;
                    AlternativeFormatImportPart chunk =
                        mainPart.AddAlternativeFormatImportPart(
                        AlternativeFormatImportPartType.WordprocessingML, altChunkId);
                    using (FileStream fileStream = File.Open(fileName2, FileMode.Open))
                        chunk.FeedData(fileStream);
                    AltChunk altChunk = new AltChunk();
                    altChunk.Id = altChunkId;
                    mainPart.Document
                        .Body
                        .InsertAfter(altChunk, mainPart.Document.Body
                        .Elements<Paragraph>().Last());
                    mainPart.Document.Save();
                    myDoc.MainDocumentPart.Document.Save();
                    SimplifyMarkupSettings settings = new SimplifyMarkupSettings
                    {
                        RemoveComments = true,
                        RemoveContentControls = true,
                        RemoveEndAndFootNotes = true,
                        RemoveFieldCodes = false,
                        RemoveLastRenderedPageBreak = true,
                        RemovePermissions = true,
                        RemoveProof = true,
                        RemoveRsidInfo = true,
                        RemoveSmartTags = true,
                        RemoveSoftHyphens = true,
                        ReplaceTabsWithSpaces = true,
                    };
                    MarkupSimplifier.SimplifyMarkup(myDoc, settings);
                    myDoc.Close();
                }
            }
    Can you help me?
    Friday, October 26, 2012 8:14 AM
  • Hi Cristina1987,

    I will show my snippet to copy header(Default type) to another Document. I suppose there only a png image in the header. You can modify the code to fit your goal. In this snippet you will see "com.mksword.Net.OpenXmlTools" Namespace and WordprocessingDocumentUtil Class. Please omit these due to it just a customized assembly to let the code short and clear. Please pay attention at ReadHeaderImage method, CopyHeader method and NewHeader method. That is the key of this issue. Especially NewHeader method, all key change will happen in this part.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using DocumentFormat.OpenXml;
    using DocumentFormat.OpenXml.Packaging;
    using DocumentFormat.OpenXml.Wordprocessing;
    using log4net;
    using com.mksword.Net.OpenXmlTools;
    using A = DocumentFormat.OpenXml.Drawing;
    using Pic = DocumentFormat.OpenXml.Drawing.Pictures;
    
    namespace ConsoleApplication3
    {
        public class CopyHeaderImage : WordprocessingDocumentUtil
        {
            private HeaderPart _Header = null;
            private ImagePart _Image = null;
    
            public void Action()
            {
                OpenedDocumentHander(ReadHeaderImage);
            }
    
            private bool ReadHeaderImage(WordprocessingDocument WPD)
            {
                bool result = false;
                MainDocumentPart MDP = WPD.MainDocumentPart;
                Document D = MDP.Document;
                SectionProperties SPS = D.Descendants<SectionProperties>()
                    .FirstOrDefault();
                HeaderReference HR = SPS.Descendants<HeaderReference>()
                    .Where(H => H.Type == HeaderFooterValues.Default)
                    .FirstOrDefault();
                HeaderPart HP = MDP.GetPartById(HR.Id) as HeaderPart;
                _Image = HP.ImageParts.FirstOrDefault();
                CopyHeader(HP);
                return result;
            }
    
            private void CopyHeader(HeaderPart HP)
            {
                _Header = HP;
                OpenedDocumentHander(CopyHeaderHandler,true);
            }
    
            private bool CopyHeaderHandler(WordprocessingDocument WPD)
            {
                bool result = false;
                MainDocumentPart MDP = WPD.MainDocumentPart;
                Document D = MDP.Document;
                SectionProperties SPS = D.Descendants<SectionProperties>()
                    .FirstOrDefault();
                HeaderReference HR = SPS.Descendants<HeaderReference>()
                    .Where(H => H.Type == HeaderFooterValues.Default)
                    .FirstOrDefault();
                if (HR != null)
                {
                    HeaderPart older = MDP.GetPartById(HR.Id) as HeaderPart;
                    MDP.DeletePart(older);
                    NewHeader(MDP, HR);
                }
                else
                {
                    HR = new HeaderReference()
                    {
                        Type = HeaderFooterValues.Default,
                        Id = string.Empty
                    };
                    NewHeader(MDP, HR);
                    SPS.Append(HR);
                }
                D.Save();
                return result;
            }
    
            private void NewHeader(MainDocumentPart MDP,HeaderReference HR)
            {
                HeaderPart newHeader = MDP.AddNewPart<HeaderPart>();
                if (_Header != null && _Image != null)
                {
                    newHeader.FeedData(_Header.GetStream());
                    ImagePart imagePart = newHeader.AddImagePart(ImagePartType.Png);
                    imagePart.FeedData(_Image.GetStream());
                    string ImageId = newHeader.GetIdOfPart(imagePart);
                    Header H = newHeader.Header;
                    Paragraph P = H.Descendants<Paragraph>().FirstOrDefault();
                    Run R = P.Descendants<Run>().First();
                    Drawing D = R.Descendants<Drawing>().First();
                    A.GraphicData GD = D.Inline.Graphic.GraphicData;
                    Pic.Picture Pic = GD.Descendants<Pic.Picture>()
                        .FirstOrDefault();
                    Pic.BlipFill BF = Pic.Descendants<Pic.BlipFill>()
                        .FirstOrDefault();
                    BF.Blip.Embed = ImageId;
                    HR.Id = MDP.GetIdOfPart(newHeader);
                }
                else
                {
                    SetLog("_Header wasn't set", OXULogType.FATAL);
                }
            }
        }
    }

    Have a good day,

    Tom


    Tom Xu [MSFT]
    MSDN Community Support | Feedback to us

    Tuesday, October 30, 2012 8:33 AM
    Moderator
  • In fact , I want to know where is the "com.mksword.Net.OpenXmlTools" namespace, I can not using it, and can not find it. Thank you.
    Thursday, July 10, 2014 3:22 AM