Chunk
Forum Replies Created
-
AuthorPosts
-
May 27, 2020 at 10:38 pm in reply to: Replace placeholders enclosed in {} in .docx file from MVC app #8688
I think I had similar case. I’ve had placeholder in my template. I’ve used DocumentAssembler provided by Eric White for this purpose.
I needed to put AltChunks in that placeholder. This AltChunks were HTML pages with the encoded images (I had to download the external sources and convert them to Base64 previously).
During generating that AltChunk I’ve created a placeholder for each of the Chunks. So DocumentAssembler was putting only that ChunkId as a string in the generated document. Then replacing that string with my AltChunk (you can replace it with anything) was pretty easy.I’ve written two methods for this purpose, one is preparing the data, the second is consuming them:
private void PrepareEmbeddedContent()
{
var htmlFields = DataModel.XPathSelectElements(“//Fields/*[@Type=’Html’]”).Where(node => !string.IsNullOrWhiteSpace(node.Value)).ToList();
if (!htmlFields.Any())
{
return;
}using (var document = WordprocessingDocument.Open(_processedFilePath, true))
{
var mainDocumentPart = document.MainDocumentPart;foreach (var htmlField in htmlFields)
{
var workItemId = htmlField.XPathSelectElement(“../ID”).Value;
var fieldName = htmlField.Name;
var altChunkId = $”Chunk{workItemId}{fieldName}”;
var htmlText = XmlHelper.GetDataEmbeddedHtml(htmlField.Value, NetworkCredentials);var ms = new MemoryStream(Encoding.UTF8.GetBytes(htmlText));
// Create alternative format import part.
var formatImportPart = mainDocumentPart.AddAlternativeFormatImportPart(AlternativeFormatImportPartType.Html, altChunkId);// Feed HTML data into format import part (chunk).
formatImportPart.FeedData(ms);htmlField.Value = $@”{{altChunkId:{altChunkId}}}”;
}
document.Close();
}
}private void InsertEmbeddedContent()
{
XNamespace w = “http://schemas.openxmlformats.org/wordprocessingml/2006/main”;
XNamespace r = “http://schemas.openxmlformats.org/officeDocument/2006/relationships”;using (var document = WordprocessingDocument.Open(_processedFilePath, true))
{
var mainDocumentXDoc = GetXDocument(document);
var pattern = @”{altChunkId:(.*)}”;
var regex = new Regex(pattern);
var paragraphs = mainDocumentXDoc.Descendants(W.p).ToList();OpenXmlRegex.Match(paragraphs, regex, (element, match) =>
{
var altChunkId = match.Groups[1].Value;
var chunkElement = new XElement(w + “altChunk”,
new XAttribute(r + “id”, altChunkId)
);var chunkPlaceholder = paragraphs.First(p => p.Value.Contains(altChunkId));
chunkPlaceholder.ReplaceWith(chunkElement);});
SaveXDocument(document, mainDocumentXDoc);
}
}GetXDocument and SaveXDocument are helper methods provided by Eric White.
Basically what could facilitate your need is that that RegEx, Match and ReplaceWith method.
I hope this helps you.Hi,
Actually I’ve found semi-solution with the use of Interop. I was able to open, tidy and update TOC for that document with the following code:
var wordApplication = new Application();
var document = wordApplication.Documents.Open(FileName: filePath, OpenAndRepair: true);document.TablesOfContents[1].Update();
document.SaveAs(filePath);document.Close();
wordApplication.Quit();Anyway if there’s some neat way to do it without the Interop I’d still be grateful.
-
AuthorPosts