Majestic Majestic - 25 days ago 15
C# Question

Simplify double foreach instruction

I need to browse a word document and to retrieve some Text Boxes in order to modify them.

But I need to count them before, and I do think that what I wrote is really inefficient.

I'd like to know if it's possible to simplify the following:

foreach (Microsoft.Office.Interop.Word.HeaderFooter OHeader in documentOld.Sections[1].Headers)
{
foreach (Microsoft.Office.Interop.Word.Shape shape in OHeader.Shapes)
{
if (shape.Name.Contains("Text Box"))
{
listTextBox.Add(new KeyValuePair<string, string>(shape.Name.ToString(), shape.TextFrame.TextRange.Text.ToString()));
}
}
}

int count = listTextBox.Count();


I want to know how many elements which contain "Text Box" are in the Shapes.

Answer

I see two ways you can do this.

Using LINQ syntax:

var count = (
  from OHeader in documentOld.Sections[1].Headers
  from shape in OHeader.Shapes
  where shape.Name.Contains("Text Box")).Count();

Or, using IEnumerable extension methods:

var count = documentOld.Sections[1].Headers
              .SelectMany(h => h.Shapes)
              .Count(s => s.Name.Contains("Text Box"));

Note that your version is inefficient in that it creates a list and the KeyValuePairs needlessly, given that you only want to count the number of shapes that match some condition. Other that that, nested foreach blocks are fine for performance, but may lack in readability versus the LINQ equivalents.

Also, please note that I have not tested the code above.

Comments