6
\$\begingroup\$

I have the following program that opens a Word document template using the OpenXML library and replaces a couple of phrases with their counterparts from what will be a database (right now its just dummy data). Something about the if-else struture in the nested foreach loops bothers me. Is there a better way I can accomplish this task? Would regular expressions be a more viable option?

using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using System;
namespace OpenXmlSearchExample
{
 class Program
 {
 static void Main(string[] args)
 {
 string templatePath = @"C:\users\example\desktop\template.dotx";
 string resultPath = @"C:\users\example\desktop\OpenXmlExample.docx";
 using (WordprocessingDocument document = WordprocessingDocument.CreateFromTemplate(templatePath))
 {
 var body = document.MainDocumentPart.Document.Body;
 var paragraphs = body.Elements<Paragraph>();
 // Iterate through paragraphs, runs, and text, finding the text we want and replacing it
 foreach (Paragraph paragraph in paragraphs)
 {
 foreach (Run run in paragraph.Elements<Run>())
 {
 foreach (Text text in run.Elements<Text>())
 {
 if (text.Text == "Plan")
 {
 text.Text = string.Format("{0} {1} Plan", DateTime.Now.Year, "Q2");
 }
 else if (text.Text == "Project Name")
 {
 text.Text = "SUPER SECRET CODE NAME";
 }
 else if (text.Text == "WO-nnnn Name")
 {
 text.Text = "Maintenance";
 }
 else
 {
 Console.WriteLine(text.Text);
 Console.ReadKey();
 }
 }
 }
 }
 // Save result document, not modifying the template
 document.SaveAs(resultPath);
 }
 }
 }
}
asked Jun 26, 2018 at 13:29
\$\endgroup\$

2 Answers 2

5
\$\begingroup\$

You can

  • replace inner foreach loops with LINQ
  • replace if-else with switch
  • replace string.Format with string interpolation
  • add const modifier for path variables if they will be constants
  • remove string[] args from Main if you won't use them

Result

using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using System;
namespace OpenXmlSearchExample
{
 class Program
 {
 static void Main()
 {
 const string templatePath = @"C:\users\example\desktop\template.dotx";
 const string resultPath = @"C:\users\example\desktop\OpenXmlExample.docx";
 using (WordprocessingDocument document = WordprocessingDocument.CreateFromTemplate(templatePath))
 {
 var body = document.MainDocumentPart.Document.Body;
 var paragraphs = body.Elements<Paragraph>();
 var texts = paragraphs.SelectMany(p => p.Elements<Run>()).SelectMany(r => r.Elements<Text>());
 foreach (Text text in texts)
 {
 switch (text.Text)
 {
 case "Plan":
 text.Text = $"{DateTime.Now.Year} Q2 Plan";
 break;
 case "Project Name":
 text.Text = "SUPER SECRET CODE NAME";
 break;
 case "WO-nnnn Name":
 text.Text = "Maintenance";
 break;
 default:
 Console.WriteLine(text.Text);
 Console.ReadKey();
 break;
 }
 }
 // Save result document, not modifying the template
 document.SaveAs(resultPath);
 }
 }
 }
}
answered Jun 26, 2018 at 15:00
\$\endgroup\$
2
  • \$\begingroup\$ Thanks for the response! I love LINQ, I'm just too new to use it effectively. \$\endgroup\$ Commented Jun 26, 2018 at 15:03
  • \$\begingroup\$ How can I install this library. I used this nuget.org/packages/DocumentFormat.OpenXml/%20 , but the CreateFromTemplate and SaveAs methods are not recognized \$\endgroup\$ Commented Jan 23, 2019 at 10:52
6
\$\begingroup\$

Using case-sensitive string matching like that is in my opinion the first nail in the coffin. Instead a case-insensitive dictionary would be a much better option.

Example:

var replacements = new Dictionary<string, Func<string>>(StringComparer.OrdinalIgnoreCase)
{
 ["Plan"] = () => $"{DateTime.Now.Year} Q2 Plan",
 ["Project Name"] = () => $"SUPER SECRET CODE NAME",
};
text.Text = replacements[text.Text]();

This is also much easier to extend/maintain.


You shouldn't mix full type names with var. You can use var not only for normal variables but also inside using statements or foreach loops. Keep it consistent.

answered Jun 26, 2018 at 15:14
\$\endgroup\$
2
  • \$\begingroup\$ How can I install this library? I used this nuget.org/packages/DocumentFormat.OpenXml/%20 , but the CreateFromTemplate and SaveAs methods are not recognized \$\endgroup\$ Commented Jan 23, 2019 at 10:52
  • 1
    \$\begingroup\$ Instructions can be found in Nuget: nuget.org/packages/DocumentFormat.OpenXml \$\endgroup\$ Commented Jun 21, 2021 at 12:33

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.