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();
}
Related
I'm trying to set a specific style on a iText.Forms.Field.PdfFormField to add margin-bottom or padding-bottom as the default input text being added to the PDF isn't aligning with the hard-coded text the PDF template already has.
Here's the code to add attributes only to one specific cell in the PDF template. The field object is a PdfFormField instance:
PdfString fieldName = field.GetFieldName();
if(fieldName.ToString() == "topmostSubform[0].CopyB[0].CopyHeader[0].CalendarYear[0].f2_1[0]"
|| fieldName.ToString() == "topmostSubform[0].CopyC[0].CopyHeader[0].CalendarYear[0].f2_1[0]")
{
field.SetFontSize(8f);
field.SetJustification(0);
field.SetDefaultStyle(new PdfString("padding-bottom: 4px")); --not being applied
}
I tried to go off of the solution on SO here: Using iText.Forms.Fields.PdfFormField.SetRichText () but I think I'm just missing something obvious in my approach.
I have a PDF template with form fields where I used iText 7.1.0 to replace some placeholder text inside different form fields which is working fine:
PdfReader reader = new PdfReader(pdf_template);
PdfDocument pdf = new PdfDocument(reader, new PdfWriter(pdf_output));
PdfAcroForm form = PdfAcroForm.GetAcroForm(pdf, true);
form.GetField("Vertragsnummer").SetValue("12345");
form.FlattenFields();
pdf.Close();
reader.Close();
Now I have a form field for which option is set to allow rich text format as there are some parts with bold font etc..
Inside the form field standard text there are again placeholders which I want to replace.
Currently I've got the following code:
PdfFormField tf_maintext = form.GetField("maintext");
tf_maintext.SetRichText(tf_maintext.GetRichText());
Now I need to replace the placeholders but I didn't find any working solution for C#.
For normal form fields I can use
PdfFormField kdnr = form.GetField("Kundennummer");
kdnr.SetValue(kdnr.GetValueAsString().Replace("7777777777", "1111111111"));
the normal Replace function to achieve this.
But I need a solution to replace text in the rich text format field to ensure that the formatting is still there afterwards.
How can I do this?
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();
I have a Word 2010 add-in that pulls certain information from the server and displays it in Word within a bookmark. One is the "Rich Text Content Control" found in the Developer tab. Is there a way to "get" it programmatically so I can manipulate it? I am using this method to do something similar for getting a table that is also put in Word by the server:
private Table GetTableByBookmarkName(Bookmark bookmark, int i)
{
Table tbl = bookmark.Range.Tables[i];
if (tbl != null)
{
return tbl;
}
else
{
return null;
}
}
I undertand your question is that you want to get a reference to a RichText content control, directly (as opposed to using a bookmark). Yes, this is possible.
Use an Index value (1-based!) for the Collection (order in the document): Document.ContentControls[index]
Use the Document.SelectContentControlsByTag method to return a collection of content controls having the same value in the Tag property
Use the Document.SelectContentControlsByTitle method to return a collection of content controls having the same value in the Title property.
Similarly to bookmarks, a Title and/or a Tag can be assigned to a content control when the document/template is being designed. There's a "Properties" button in the Developer tab, in the same group as the content controls.
Unlike bookmarks, more than one content control can have the same Title / Tag, which is why a collection is returned.
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();