C# DocumentFormat OpenXML Word 2013 Repeating Content Control - c#

I have created a Word 2013 document with a series of content controls. I have a bunch of text controls in the header and then a table that has a repeating content control with more text controls
What I am trying to achieve is via my C# program build some XML that I can use to map to my content controls.
My XML looks like this
<Job>
<JobNo>123</JobNo>
<Staff>Chris Smith</Staff>
<Client>Client 2</Client>
<DateReceived>2015-05-08</DateReceived>
<SampleNo>3</SampleNo>
<Department>Product</Department>
<Status>Open</Status>
<JobSamples>
<Sample>
<SampleNo>1</SampleNo>
<SampleIdentification>Identifier</SampleIdentification>
<AnalyticalTest>AnalyticalTest</AnalyticalTest>
<SampleMatrix>SampleMatrix</SampleMatrix>
<TypeOfTest>TypeOfTest</TypeOfTest>
<SampleStaff>SampleStaff</SampleStaff>
<SampleDueDate>SampleDueDate</SampleDueDate>
</Sample>
<Sample>
<SampleNo>2</SampleNo>
<SampleIdentification>Identifier</SampleIdentification>
<AnalyticalTest>AnalyticalTest</AnalyticalTest>
<SampleMatrix>SampleMatrix</SampleMatrix>
<TypeOfTest>TypeOfTest</TypeOfTest>
<SampleStaff>SampleStaff</SampleStaff>
<SampleDueDate>SampleDueDate</SampleDueDate>
</Sample>
</JobSamples>
</Job>
I have created a word template that has a Custom XML part and have mapped the fields appropriately. My RepeatingContentControl has been mapped to the node and correctly displays two rows of Samples data
However at run time my XML may contain 1....N Samples and so I want the Repeating Content Control to correctly refresh
When I run my code all the other control outside of the repeating content control get refreshed, but the repeating control doesn't.
Do I need to get a handle on the repeating content control in code and add or remove rows accordingly?
If so, how can I do that?
If not, how can I get my repeating control to refresh?
Here is my code:-
var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Job Sheet.docx");
using (WordprocessingDocument myDoc = WordprocessingDocument.Open(path, true))
{
// Creates and saves JobXML file
CreateCustomXML(job);
XmlDocument doc = new XmlDocument();
doc.Load(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "JobXML.xml"));
MainDocumentPart mainPart = myDoc.MainDocumentPart;
//delete old xml part
mainPart.DeleteParts<CustomXmlPart>(mainPart.CustomXmlParts);
//add new xml part
CustomXmlPart customXml = mainPart.AddCustomXmlPart(CustomXmlPartType.CustomXml);
using (StreamWriter ts = new StreamWriter(customXml.GetStream()))
{
ts.Write(doc.OuterXml);
}
}

Related

PSPdfkit Saving after adding text annotations

I am using pspdfkit to add few text annotations via the viewer. After adding the annotations I want to change their contents when the user clicks save button, and then save the pdf. I am not sure how to save the original pdf and also if I want to create a copy of it ?
This is how I get the doc and change the annotations text.
var doc = PdfView.Controller.GetPdfDocument();
var annots =await doc.GetAnnotationsAsync(0);
//I am assuming all my anotations are text (just for testing)
foreach (IAnnotation item in annots)
{
((Text)item).Contents = "Changed content";
}
I can export it using
await pdfView.Document.ExportAsync(dataWriter);
but how to create dataWriter from the doc.
Help will be appreciated.
thanks

Retrieve hidden text blocks and replace all content between two of them

I want to use OpenXML to automate Word document creation by taking a given document as a template. This template contains text blocks with a special syntax (namely e.g. «tagname[»...«]tagname») in the form of hidden text (in the font dialog box, the 'Hidden' checkbox in the effects section is activated) so that they don't show up when the document is printed.
Depending on the tagname I want to replace any content which might be already there in the template file between the opening and closing tag with some other content (e.g. in «today[»01/01/2000«]today» the content 01/01/2000 would be substituted with 07/06/2018) preferably preserving the format (e.g. bold, italic or text color).
How can I retrieve the hidden text parts and is there an easy way to replace anything between corresponding tags using C#?
I am not sure what exactly are the text blocks in your template. Instead you can use Content Control from Developer options at the required place, then you can name them from the properties of content control.
today will be name of the Content Control
Once you have all the content control at your template, you can look for specific content control with name and add the new value you want to.
Here is the Snippet to give you an idea.
// Title is name of content control(today), value is what you want to add(1/01/2000)
private static void UpdateControl(WordprocessingDocument document, string title, string value)
{
MainDocumentPart mainPart = document.MainDocumentPart;
var sdtRuns = mainPart.Document.Descendants<SdtRun>()
.Where(run => run.SdtProperties.GetFirstChild<Tag>().Val.Value == title);
foreach (SdtRun sdtRun in sdtRuns)
{
sdtRun.Descendants<Text>().First().Text = value;
}
document.MainDocumentPart.Document.Save();
}

Create a Picture Content Control in the OpenXML

I'm trying to create content controls using the OpenXML SDK so that a different program can then pick up the document and edit it as required.
I manage to create Text Content Controls successfully but picture content controls have proven to be more challenging.
The closest I got was with the following code:
var sdtCBlock = new SdtContentBlock(new Paragraph(new Run()));
var sdtPr = new SdtProperties(
new SdtAlias {Val = "" },
new Tag {Val = ""},
new SdtContentPicture(),
new DataBinding {XPath = ""}
);
wordDoc.MainDocumentPart.Document.Body.AppendChild(new SdtCell(sdtPr, sdtCBlock));
This creates an empty content control that word recognises as a picture:
Empty picture content control
The problem is that the second program will not insert the picture into this content control as is. However, if we open the word file manually and click on the content control to pop up the blue square template then the second program successfully detects and changes the image in the content control.
Content control with blue square template after being manually clicked on
Am I doing something wrong? And how can I use the OpenXml code to generate the placeholder with the template in order to be picked up by the second program?

VSTO Word Add-in - insert Content Control around selected text

I'm trying to add a rich text content control around the user's selected text in a Word document.
I'm new to VSTO and Content Controls so i'm using the MSDN examples as a baseline. The example shows this, which adds the Content Control at the chosen position:
private void AddRichTextControlAtSelection()
{
word.Document currentDocument = Globals.ThisAddIn.Application.ActiveDocument;
currentDocument.Paragraphs[1].Range.InsertParagraphBefore();
currentDocument.Paragraphs[1].Range.Select();
Document extendedDocument = Globals.Factory.GetVstoObject(currentDocument);
richTextControl1 = extendedDocument.Controls.AddRichTextContentControl("richTextControl1");
richTextControl1.PlaceholderText = "Enter your first name";
}
However i want the Content Control to wrap around the user's selected text. Any help, please?
What you found is one possibility. More efficient and "cleaner" (IMO) would be to use the constructor that accepts a RANGE object and pass the Range. If you want the user's selection then
richTextControl1 = extendedDocument.Controls.AddRichTextContentControl(extendedDocument.Parent.Selection.Range, "richTextControl1");
//the Parent of a Document is the Word.Application
//Selection is a dependent of the Word.Application
Otherwise, building on your code sample:
richTextControl1 = extendedDocument.Controls.AddRichTextContentControl(currentDocument.Paragraphs[1].Range, "richTextControl1");
Note that if you don't need to work with VSTO's extensions of the Content Controls you don't need to go through the GlobalFactory steps, you can simply insert the "interop" versions of the Content Controls.
Simple fix in the end: currentDocument.ActiveWindow.Selection.Range.Select();

C# : Remove a Picture Content Control fro .docx

I use the following code to find a Picture Content Control using the tagname of this one and after I use the function Remove to remove it in the Word document :
System.IO.File.Copy(templatePath, outputPath, true);
using (WordprocessingDocument doc = WordprocessingDocument.Open(outputPath, true))
{
tagName = "portrait";
controlBlock = doc.MainDocumentPart.Document.Body.Descendants<SdtElement>().Where(r => r.SdtProperties.GetFirstChild<Tag>().Val == tagName).SingleOrDefault();
if (controlBlock != null)
{
controlBlock.Remove();
}
doc.Close();
}
But when I open the created file in Word, the document need to be repaired by Word if not I can't open it. Word also give me this message in the detail of error :
<p> elements are required before every </tc>
When I inspect the word document with Open Xml before and after it been repaired, I don't see any difference
So what is the best way to remove a Picture Content Control in a Word document?
I resolved my problem easily, in fact the error message provided by Word is clear. So I get the parent element of my Picture Control Content and add a new empty paragraph and after I tried to delete the Picture Control Content and it was enough to resolved my problem.
Here is the code :
controlBlock.Parent.AppendChild(new DocumentFormat.OpenXml.Wordprocessing.Paragraph());
controlBlock.Remove();

Categories

Resources