I have a function that is suppose to copy an existing header from a given .docx file, edit the copied header and add original as first page header and copied as even page header.
public byte[] AddExtraHeader(byte[] report)
{
using (WordprocessingDocument
wdDoc = WordprocessingDocument.Open(new MemoryStream(report), true))
{
MainDocumentPart mainPart = wdDoc.MainDocumentPart;
var settingsPart = wdDoc.MainDocumentPart.DocumentSettingsPart;
var element = new Settings(new TitlePage());
element.Save(settingsPart);
//Get existing header
DocumentFormat.OpenXml.Packaging.HeaderPart oldHeader = mainPart.HeaderParts.FirstOrDefault();
// Create a new header part.
DocumentFormat.OpenXml.Packaging.HeaderPart newHeader = mainPart.AddNewPart<HeaderPart>();
// Get Id of the headerPart.
string rIdOld = mainPart.GetIdOfPart(oldHeader);
string rIdNew = mainPart.GetIdOfPart(newHeader);
if (oldHeader != null)
{
newHeader.FeedData(oldHeader.GetStream()); //Error right here
}
//Gets the text in headers
foreach (var currentText in newHeader.RootElement.Descendants<DocumentFormat.OpenXml.Wordprocessing.Text>())
{
currentText.Text = currentText.Text.Replace("trecio", "");
}
// 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() { Type = HeaderFooterValues.First, Id = rIdOld});
sectPr.PrependChild<HeaderReference>(new HeaderReference() { Type = HeaderFooterValues.Even, Id = rIdNew });
}
}
return report;
}
But when I try to feed data from the original header to the newly created copy I get an
MEMORY STREAM IS NOT EXPANDABLE
Error. I tried to copy the example from https://learn.microsoft.com/en-us/office/open-xml/how-to-replace-the-header-in-a-word-processing-document
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()); // No error here
}
}
// 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 });
}
}
}
The example works fine for me and gets the desired result, but I can't tell the difference between my FeedData and examples FeedData.
Am I missing something?
Based on Memory stream is not expandable answer
If you create a MemoryStream over a pre-allocated byte array, it can't expand (ie. get longer than the size you specified when you started).
So the solution is to create a memory stream based on the byte array, then create a new empty memory stream and copy the contents of the first memory stream to the second one and then work with the second memory stream, like so:
var ms = new MemoryStream();
var reportStream = new MemoryStream(report);
reportStream.CopyTo(ms);
using (WordprocessingDocument wdDoc = WordprocessingDocument.Open(ms, true))
{
// rest of the code
}