<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://openxmldeveloper.org/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Blog</title><link>http://openxmldeveloper.org/blog/default.aspx</link><description>Samples, Demos, and Reference Articles</description><dc:language /><generator>Telligent Community 5.6.582.12783 (Build: 5.6.582.12783)</generator><item><title>Blog Post: Screen-Cast: Grouping Content Controls to Create Forms</title><link>http://openxmldeveloper.org/blog/b/openxmldeveloper/archive/2013/06/17/screen-cast-grouping-content-controls-to-create-forms.aspx</link><pubDate>Mon, 17 Jun 2013 16:01:00 GMT</pubDate><guid isPermaLink="false">1ff61f26-0981-41c7-ad52-ff725e9b1da8:160968</guid><dc:creator>Eric White</dc:creator><description>&lt;p&gt;One of the more interesting scenarios with Open XML WordprocessingML is creating a document that contains a form. &amp;nbsp;You can send this document to others, who fill out the form and return it to you. &amp;nbsp;You can then retrieve that data directly from the Open XML markup. &amp;nbsp;There are two approaches to creating a form when using content controls:&lt;/p&gt;  &lt;ul&gt;  &lt;li&gt;You can create content controls, and then protect the document, prohibiting editing except for within the content controls. &amp;nbsp;This has one disadvantage - spell checking no longer works, so users can&amp;#39;t tell if they have misspelled words within those content controls.&lt;/li&gt;  &lt;li&gt;You can create content controls, and then group the content controls. &amp;nbsp;Spell checking works properly when using this approach.&lt;/li&gt;  &lt;/ul&gt;  &lt;p&gt;The following screen-cast shows the approach of creating content controls and then grouping them. &amp;nbsp;It presents a bit of Open XML code that programmatically groups the content controls.&lt;/p&gt;  &lt;p&gt;(Please visit the site to view this video)&lt;/p&gt;  &lt;p&gt;Following is the listing of the small program that I develop in the screen-cast:&lt;/p&gt;  &lt;p&gt;  &lt;pre class="prettyprint"&gt;using System;  using System.Collections.Generic;  using System.IO;  using System.Linq;  using System.Text;  using System.Threading.Tasks;  using System.Xml.Linq;  using DocumentFormat.OpenXml;  using DocumentFormat.OpenXml.Packaging;  using DocumentFormat.OpenXml.Wordprocessing;    namespace GroupContentControls  {      class Program      {          // Creates an SdtBlock instance and adds its children.          public static SdtBlock GenerateSdtBlock()          {              SdtBlock sdtBlock1 = new SdtBlock();                SdtProperties sdtProperties1 = new SdtProperties();              SdtId sdtId1 = new SdtId() { Val = -1013684659 };              Lock lock1 = new Lock() { Val = LockingValues.ContentLocked };                SdtPlaceholder sdtPlaceholder1 = new SdtPlaceholder();              DocPartReference docPartReference1 = new DocPartReference() { Val = &amp;quot;DefaultPlaceholder_1081868574&amp;quot; };                sdtPlaceholder1.Append(docPartReference1);              SdtContentGroup sdtContentGroup1 = new SdtContentGroup();                sdtProperties1.Append(sdtId1);              sdtProperties1.Append(lock1);              sdtProperties1.Append(sdtPlaceholder1);              sdtProperties1.Append(sdtContentGroup1);              SdtContentBlock sdtContentBlock1 = new SdtContentBlock();                sdtBlock1.Append(sdtProperties1);              sdtBlock1.Append(sdtContentBlock1);              return sdtBlock1;          }            static void Main(string[] args)          {              FileInfo f = new FileInfo(&amp;quot;../../../EricWhiteForm.docx&amp;quot;);              FileInfo f2 = new FileInfo(&amp;quot;../../../EricWhiteForm - ProgrammaticallyGrouped.docx&amp;quot;);              if (f2.Exists)                  f2.Delete();              File.Copy(f.FullName, f2.FullName);              using (WordprocessingDocument wDoc = WordprocessingDocument.Open(f2.FullName, true))              {                  var sdtBlock = GenerateSdtBlock();                  var sdtContent = sdtBlock.SdtContentBlock;                  var body = wDoc.MainDocumentPart.Document.Body;                  foreach (var child in body.ChildElements)                  {                      if (child is SectionProperties)                      {                          continue;                      }                      sdtContent.Append((OpenXmlElement)child.Clone());                  }                  var newBody = new Body();                  newBody.AppendChild(sdtBlock);                  wDoc.MainDocumentPart.Document.ReplaceChild(newBody, body);              }          }      }  }  &lt;/pre&gt;  &lt;/p&gt;</description></item><item><title>Blog Post: Screen-Cast: Debugging Open XML when the Office Client Crashes</title><link>http://openxmldeveloper.org/blog/b/openxmldeveloper/archive/2013/05/30/screen-cast-debugging-open-xml-when-the-office-client-crashes.aspx</link><pubDate>Thu, 30 May 2013 14:26:00 GMT</pubDate><guid isPermaLink="false">1ff61f26-0981-41c7-ad52-ff725e9b1da8:160903</guid><dc:creator>Eric White</dc:creator><description>&lt;p&gt;Document formats are pretty complex. &amp;nbsp;It is fairly easy to generate a document that is invalid. &amp;nbsp;In many cases, the Open XML SDK productivity tool will help us by informing us of where the errors are. &amp;nbsp;In other cases, a Microsoft Office client application such as Word or Excel may inform us that we have generated an invalid document. &amp;nbsp;In the worst case, it is possible to generate a document that causes Word or Excel to crash. &amp;nbsp;This screen-cast shows how I debug these types of situations.&lt;/p&gt;  &lt;p&gt;(Please visit the site to view this video)&lt;/p&gt;</description></item><item><title>Blog Post: Using Both the Strongly Typed Object Model and LINQ to XML in an Open XML Application</title><link>http://openxmldeveloper.org/blog/b/openxmldeveloper/archive/2013/05/09/using-both-the-strongly-typed-object-model-and-linq-to-xml-in-an-open-xml-application.aspx</link><pubDate>Thu, 09 May 2013 10:45:00 GMT</pubDate><guid isPermaLink="false">1ff61f26-0981-41c7-ad52-ff725e9b1da8:160846</guid><dc:creator>Eric White</dc:creator><description>&lt;p&gt;&lt;a href="http://openxmldeveloper.org/discussions/open_xml_scenarios/f/22/t/6268.aspx"&gt;Sometimes developers want to use the strongly-typed object model&lt;/a&gt; of the Open XML SDK in combination with code written using LINQ to XML. &amp;nbsp;You may want to use functionality from PowerTools for Open XML (which is written using LINQ to XML), and you may want to write your code using the strongly typed OM. &amp;nbsp;&lt;span style="font-size:12px;"&gt;There are variations between the two approaches in how you get and set the contents of parts. &amp;nbsp;If you don&amp;#39;t take care of the mechanics properly, then you will make changes using one or the other of the approaches, and those changes will not be saved to your document. &amp;nbsp;There is a super-simple formula, though, for taking care of these issues. &amp;nbsp;Once you know the formula, you can use either approach whenever it makes sense for your application.&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size:12px;"&gt;The key ideas:&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size:12px;"&gt;Whenever you make changes using the strongly-typed object model, you need to save it before accessing that content using LINQ to XML:&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;  &lt;pre class="prettyprint"&gt;// call Save on the root element of the part  wDoc.MainDocumentPart.RootElement.Save();&lt;/pre&gt;  &lt;/p&gt;  &lt;p&gt;Whenever you are finished making changes using LINQ to XML, you can call a simple function, SaveAllParts:&lt;/p&gt;  &lt;p&gt;  &lt;pre class="prettyprint"&gt;private static void SaveAllParts(WordprocessingDocument wDoc)  {      foreach (var part in wDoc.GetAllParts())      {          XDocument partXDocument = part.Annotation&amp;lt;XDocument&amp;gt;();          if (partXDocument == null)              continue;            XDocument xDoc = part.GetXDocument();          part.RootElement.InnerXml = xDoc              .Root              .Elements()              .Select(e =&amp;gt; e.ToString())              .StringConcatenate();            part.RemoveAnnotations&amp;lt;XDocument&amp;gt;();      }  }  &lt;/pre&gt;  &lt;/p&gt;  &lt;p&gt;This method, SaveAllParts uses the GetAllParts() extension method from PowerTools for Open XML. &amp;nbsp;This method returns a list of all parts in a document. &amp;nbsp;The method can then iterate through all the parts, see if there is an XDocument annotation on the part, and if so, replace the inner XML of the root element, using the strongly typed OM. &amp;nbsp;Here is a complete example that first makes a change using the strongly-typed OM, then makes a change using PowerTools for Open XML, and then again makes a change using the strongly typed OM. &amp;nbsp;The example, as well as the test documents, are attached to this post.&lt;/p&gt;  &lt;p&gt;  &lt;pre class="prettyprint"&gt;using System;  using System.IO;  using System.Linq;  using System.Xml.Linq;  using DocumentFormat.OpenXml;  using DocumentFormat.OpenXml.Packaging;  using DocumentFormat.OpenXml.Wordprocessing;  using OpenXmlPowerTools;  using System.Collections.Generic;    class Program  {      static void Main(string[] args)      {          FileInfo fi = new FileInfo(@&amp;quot;..\..\Test.docx&amp;quot;);          fi.Delete();          fi = new FileInfo(@&amp;quot;..\..\Test - Copy.docx&amp;quot;);          var dfi = new FileInfo(@&amp;quot;..\..\Test.docx&amp;quot;);          fi.CopyTo(dfi.FullName);            using (WordprocessingDocument wDoc =              WordprocessingDocument.Open(@&amp;quot;..\..\Test.docx&amp;quot;, true))          {              // make some changes using the strongly typed OM of the Open XML SDK              var p = wDoc                  .MainDocumentPart                  .Document                  .Body                  .Elements&amp;lt;Paragraph&amp;gt;()                  .FirstOrDefault();              var r = p.Elements&amp;lt;Run&amp;gt;().FirstOrDefault();              if (r != null)              {                  var t = r.Elements&amp;lt;Text&amp;gt;().FirstOrDefault();                  if (t != null)                  {                      t.Text = &amp;quot;That is &amp;quot;;                  }              }                // save back into the document              wDoc.MainDocumentPart.RootElement.Save();                // see the changes made by the Open XML SDK strongly-typed OM              DumpFirstParagraph(wDoc);                // make some changes using PowerTools for Open XML (using LINQ to XML)              SimplifyMarkupSettings settings = new SimplifyMarkupSettings()              {                  RemoveBookmarks = true,                  RemoveRsidInfo = true,                  AcceptRevisions = true,              };              MarkupSimplifier.SimplifyMarkup(wDoc, settings);                // save the changes back into the document              SaveAllParts(wDoc);                // see the changes made by PowerTools for OpenXML              DumpFirstParagraph(wDoc);                // again make some changes using the strongly typed OM of the Open XML SDK              p = wDoc                  .MainDocumentPart                  .Document                  .Body                  .Elements&amp;lt;Paragraph&amp;gt;()                  .FirstOrDefault();              r = p.Elements&amp;lt;Run&amp;gt;().FirstOrDefault();              if (r != null)              {                  var t = r.Elements&amp;lt;Text&amp;gt;().FirstOrDefault();                  if (t != null)                  {                      t.Text = &amp;quot;The paragraph has only one run.&amp;quot;;                  }              }                // save back into the document              wDoc.MainDocumentPart.RootElement.Save();                // see the changes made by the Open XML SDK strongly-typed OM              DumpFirstParagraph(wDoc);              Console.ReadKey();            }      }        private static void DumpFirstParagraph(WordprocessingDocument wDoc)      {          Paragraph p = wDoc              .MainDocumentPart              .Document              .Body              .Elements&amp;lt;Paragraph&amp;gt;()              .FirstOrDefault();          // dump out the first paragraph          XElement z = XElement.Parse(              &amp;quot;&amp;lt;w:p xmlns:w=&amp;#39;http://schemas.openxmlformats.org/wordprocessingml/2006/main&amp;#39;&amp;gt;&amp;quot; +              p.InnerXml + &amp;quot;&amp;lt;/w:p&amp;gt;&amp;quot;);          z.Elements()              .Attributes()              .Where(a =&amp;gt; a.IsNamespaceDeclaration)              .Remove();          Console.WriteLine(z);          Console.WriteLine(&amp;quot;==============================&amp;quot;);      }        private static void SaveAllParts(WordprocessingDocument wDoc)      {          foreach (var part in wDoc.GetAllParts())          {              XDocument partXDocument = part.Annotation&amp;lt;XDocument&amp;gt;();              if (partXDocument == null)                  continue;                XDocument xDoc = part.GetXDocument();              part.RootElement.InnerXml = xDoc                  .Root                  .Elements()                  .Select(e =&amp;gt; e.ToString())                  .StringConcatenate();                part.RemoveAnnotations&amp;lt;XDocument&amp;gt;();          }      }  }  &lt;/pre&gt;  &lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size:12px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;</description></item><item><title>Blog Post: Fine-Grained Control When Importing Content Using DocumentBuilder</title><link>http://openxmldeveloper.org/blog/b/openxmldeveloper/archive/2013/05/08/fine-grained-control-when-importing-content-using-documentbuilder.aspx</link><pubDate>Wed, 08 May 2013 18:02:00 GMT</pubDate><guid isPermaLink="false">1ff61f26-0981-41c7-ad52-ff725e9b1da8:160832</guid><dc:creator>Eric White</dc:creator><description>&lt;p&gt;Recently I had a question about how to import the contents of one cell in one table into a cell in a different table in another document. &amp;nbsp;As you probably know, moving content from one document to another in Open XML is complicated, because of interrelated markup. &amp;nbsp;It isn&amp;#39;t enough just to move the markup in the cell to the cell in the destination table; you need to also bring along any auxiliary information such as images, drawings, comments, and other such artifacts. &amp;nbsp;DocumentBuilder addresses this problem of interrelated markup. &amp;nbsp;However, it works at the granularity of child elements of the w:body element. &amp;nbsp;Out-of-the-box, it will not import content from one cell in one table into a cell in another table. &amp;nbsp;However, you can use some advanced techniques with DocumentBuilder that enable you to assemble documents from sources with a high degree of control. &amp;nbsp;This screen-cast shows how.&lt;/p&gt;  &lt;p&gt;(Please visit the site to view this video)&lt;/p&gt;</description></item><item><title>Blog Post: Screen-Cast: Starting Chapters on Odd Pages in WordprocessingML</title><link>http://openxmldeveloper.org/blog/b/openxmldeveloper/archive/2013/05/06/screen-cast-starting-chapters-on-odd-pages-in-wordprocessingml.aspx</link><pubDate>Mon, 06 May 2013 14:21:00 GMT</pubDate><guid isPermaLink="false">1ff61f26-0981-41c7-ad52-ff725e9b1da8:160785</guid><dc:creator>Eric White</dc:creator><description>&lt;p&gt;Scenario: You need to generate a document for a book, and you want each chapter to start on an odd-numbered page, so that the chapter title page is on the right-hand side of the binding. This question has been &lt;a href="http://openxmldeveloper.org/discussions/formats/f/13/t/703.aspx"&gt;asked on the forum here at OpenXMLDeveloper.org&lt;/a&gt;, so I recorded a screen-cast explaining exactly how to accomplish this. &amp;nbsp;Along the way, this screen-cast can serve to fill-in your knowledge about sections and headers.&lt;/p&gt;  &lt;p&gt;&lt;span style="float:right;width:57%;margin:0 8px 6px 8px;border:1px black solid;padding:8px 5px 5px 8px;"&gt;&lt;a href="http://openxmldeveloper.org/wiki/w/wiki/introduction-to-wordprocessingml.aspx"&gt;Return to the Table of Contents&lt;/a&gt; of this screen-cast series. &lt;/span&gt;  &lt;/p&gt;  &lt;p&gt;This screen-cast is a part of an on-going series of screen-casts on Open XML WordprocessingML.&lt;/p&gt;  &lt;p&gt;(Please visit the site to view this video)&lt;/p&gt;</description></item><item><title>Blog Post: Screen-Cast: Writing a Custom Axis Method</title><link>http://openxmldeveloper.org/blog/b/openxmldeveloper/archive/2013/04/29/screen-cast-writing-a-custom-axis-method.aspx</link><pubDate>Mon, 29 Apr 2013 14:50:00 GMT</pubDate><guid isPermaLink="false">1ff61f26-0981-41c7-ad52-ff725e9b1da8:160750</guid><dc:creator>Eric White</dc:creator><description>&lt;p&gt;Sometimes the easiest way to accomplish a particular task is to write an axis method that returns just the elements in an Open XML document that you are interested in. &amp;nbsp;Sometimes you want to write the axis method in a lazy fashion so that it performs as well as possible on large documents. &amp;nbsp;You also may need to use some form or another of recursion as the easiest way to write your axis method. &amp;nbsp;However, recursion and laziness are at odds. &amp;nbsp;You can&amp;#39;t write a method that uses &amp;#39;yield return&amp;#39; in some places (to implement laziness) and uses &amp;#39;return&amp;#39; in other places to implement recursion. &amp;nbsp;This screen-cast shows how to get around this limitation in the C# language.&lt;/p&gt;  &lt;p&gt;&lt;span style="float:right;width:20%;margin:0 8px 6px 8px;border:1px black solid;padding:8px 5px 5px 8px;"&gt;&lt;a href="http://openxmldeveloper.org/wiki/w/wiki/recursive-pure-functional-transforms-of-xml.aspx"&gt;Return to the Table of Contents&lt;/a&gt; of this screen-cast series. &lt;/span&gt;To demonstrate this scenario, I write an axis method that returns just certain runs of a WordprocessingML document, in document order.&lt;/p&gt;  &lt;p&gt;(Please visit the site to view this video)&lt;/p&gt;</description></item><item><title>Blog Post: Screen-Cast: WordprocessingML Tables Part 2</title><link>http://openxmldeveloper.org/blog/b/openxmldeveloper/archive/2013/04/02/screen-cast-wordprocessingml-tables-part-2.aspx</link><pubDate>Wed, 03 Apr 2013 02:13:00 GMT</pubDate><guid isPermaLink="false">1ff61f26-0981-41c7-ad52-ff725e9b1da8:160660</guid><dc:creator>Eric White</dc:creator><description>&lt;p&gt;&lt;span&gt;This screen-cast continues our discussion about table markup in WordprocessingML. Going beyond the basic structure of tables, it discusses various issues about rendering.  This screen-cast explains the w:cnfStyle element, and how it relates to the w:tblLook element.&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="float:right;width:57%;margin:0 8px 6px 8px;border:1px black solid;padding:8px 5px 5px 8px;"&gt;&lt;a href="http://openxmldeveloper.org/wiki/w/wiki/introduction-to-wordprocessingml.aspx"&gt;Return to the Table of Contents&lt;/a&gt; of this screen-cast series. &lt;/span&gt;  &lt;/p&gt;  &lt;p&gt;&lt;span&gt;(Please visit the site to view this video)&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;</description></item><item><title>Blog Post: Screen-Cast: WordprocessingML Tables Part 1</title><link>http://openxmldeveloper.org/blog/b/openxmldeveloper/archive/2013/04/01/screen-cast-wordprocessingml-tables-part-1.aspx</link><pubDate>Mon, 01 Apr 2013 10:40:00 GMT</pubDate><guid isPermaLink="false">1ff61f26-0981-41c7-ad52-ff725e9b1da8:160654</guid><dc:creator>Eric White</dc:creator><description>&lt;p&gt;&lt;span&gt;This screen-cast discusses table markup in WordprocessingML. It explains the basic structure of tables, and discusses how WordprocessingML table markup differs from HTML.  The following screen-cast in this series (coming soon) examines various issues around table rendering.&lt;/span&gt;&lt;/p&gt;  &lt;p&gt;&lt;span style="float:right;width:57%;margin:0 8px 6px 8px;border:1px black solid;padding:8px 5px 5px 8px;"&gt;&lt;a href="http://openxmldeveloper.org/wiki/w/wiki/introduction-to-wordprocessingml.aspx"&gt;Return to the Table of Contents&lt;/a&gt; of this screen-cast series. &lt;/span&gt;  &lt;/p&gt;  &lt;p&gt;&lt;span&gt;(Please visit the site to view this video)&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;</description></item><item><title>Blog Post: Screen-Cast: Complex Transforms of XML Elements</title><link>http://openxmldeveloper.org/blog/b/openxmldeveloper/archive/2013/03/28/screen-cast-complex-transforms-of-xml-elements.aspx</link><pubDate>Thu, 28 Mar 2013 14:13:00 GMT</pubDate><guid isPermaLink="false">1ff61f26-0981-41c7-ad52-ff725e9b1da8:160651</guid><dc:creator>Eric White</dc:creator><description>&lt;p&gt;This is the nineteenth screen-cast in a series on writing Recursive Pure Functional Transformations (RPFT) of XML. In this screen-cast, I discuss an interesting idiom / pattern for doing complex transforms of XML elements.&lt;/p&gt;  &lt;p&gt;&lt;span style="float:right;width:20%;margin:0 8px 6px 8px;border:1px black solid;padding:8px 5px 5px 8px;"&gt;&lt;a href="http://openxmldeveloper.org/wiki/w/wiki/recursive-pure-functional-transforms-of-xml.aspx"&gt;Return to the Table of Contents&lt;/a&gt; of this screen-cast series. &lt;/span&gt;To demonstrate this scenario, I write code to set the paragraph and character styles for specific paragraphs.&lt;/p&gt;  &lt;p&gt;(Please visit the site to view this video)&lt;/p&gt;</description></item><item><title>Blog Post: Does Functional Programming Matter?</title><link>http://openxmldeveloper.org/blog/b/openxmldeveloper/archive/2013/03/14/does-functional-programming-matter.aspx</link><pubDate>Thu, 14 Mar 2013 19:39:00 GMT</pubDate><guid isPermaLink="false">1ff61f26-0981-41c7-ad52-ff725e9b1da8:160583</guid><dc:creator>Eric White</dc:creator><description>&lt;p style="color:black;font-size:12px;font-family:arial,sans-serif;font-weight:normal;"&gt;A number of years ago, I gave a talk at a tech conference, and in the feedback, I received a &amp;lsquo;complaint&amp;rsquo; that I didn&amp;rsquo;t really explain how I was writing the code that I was publishing as part of PowerTools for Open XML &amp;ndash; code such as RevisionAccepter, ListItemRetriever, and HtmlConverter.  Developers sometimes look at the code in those modules, and their reaction is &amp;ldquo;Huh????&amp;rdquo;  The main problem with presenting those coding techniques was that I had one hour at that conference, and to explain the techniques I was using, it requires something more like five hours.&lt;/p&gt;  &lt;p style="color:black;font-size:12px;font-family:arial,sans-serif;font-weight:normal;"&gt;Flash-forward four years &amp;ndash; those techniques have held up well over time.  I still regularly use the approach.  I can write robust code that performs well.  For example, after publishing RevisionAccepter, I have not needed to touch the code even once.  I have translated large chunks of that code to JavaScript and the approach works equally as well there.  (I&amp;rsquo;ll publish that JavaScript code, all in good time.)&lt;/p&gt;  &lt;p style="color:black;font-size:12px;font-family:arial,sans-serif;font-weight:normal;"&gt;Why does Functional Programming work for me?&lt;/p&gt;  &lt;p style="color:black;font-size:12px;font-family:arial,sans-serif;font-weight:normal;"&gt;&lt;b&gt;It lets me work in my domain.&lt;/b&gt;  My domain is document formats, and more specifically, Open XML.  When writing transformation code, I want to be thinking about the various Open XML elements and attributes, and their semantics, and contemplating on what I want to do to them.  I don&amp;rsquo;t want to be writing large chunks of procedural code that doesn&amp;rsquo;t have a close correlation to the algorithm I am implementing.&lt;/p&gt;  &lt;p style="color:black;font-size:12px;font-family:arial,sans-serif;font-weight:normal;"&gt;While you must learn new patterns and idioms, after you master them you can write code that directly reflects your intent.  Further, you can come back to code that you&amp;rsquo;ve written years previously, and read, understand, and modify it.  But you must learn the patterns and idioms.&lt;/p&gt;  &lt;p style="color:black;font-size:12px;font-family:arial,sans-serif;font-weight:normal;"&gt;I have recorded a &lt;a href="http://openxmldeveloper.org/wiki/w/wiki/recursive-pure-functional-transforms-of-xml.aspx"&gt;screen-cast series on writing Recursive Pure Functional Transforms&lt;/a&gt;. A single weekend invested now will yield dividends over your entire career.  And further, functional programming is fun.  It is an enjoyable way to write resilient, non-brittle code.  It lets me leverage my time and write more code that does what I want it to.  The economic benefit is clear.&lt;/p&gt;  &lt;p style="color:black;font-size:12px;font-family:arial,sans-serif;font-weight:normal;"&gt;So yes, functional programming matters very much.&lt;/p&gt;  &lt;p style="color:black;font-size:12px;font-family:arial,sans-serif;font-weight:normal;"&gt;Cheers,&lt;br /&gt;Eric White&lt;/p&gt;</description></item><item><title>Blog Post: Screen-Cast: Why Do Transform Methods Return Object?</title><link>http://openxmldeveloper.org/blog/b/openxmldeveloper/archive/2013/02/28/screen-cast-why-do-transform-methods-return-object.aspx</link><pubDate>Thu, 28 Feb 2013 11:11:00 GMT</pubDate><guid isPermaLink="false">1ff61f26-0981-41c7-ad52-ff725e9b1da8:160518</guid><dc:creator>Eric White</dc:creator><description>&lt;p&gt;This is the eighteenth screen-cast in a series on writing Recursive Pure Functional Transformations (RPFT) of XML. In this screen-cast, I discuss why the transform methods return object instead of some other type such as XObject, XElement, or XNode.  The short answer is that sometimes the transform method needs to return a single element or node, and sometimes it needs to return a collection of elements or nodes.&lt;/p&gt;  &lt;p&gt;&lt;span style="float:right;width:20%;margin:0 8px 6px 8px;border:1px black solid;padding:8px 5px 5px 8px;"&gt;&lt;a href="http://openxmldeveloper.org/wiki/w/wiki/recursive-pure-functional-transforms-of-xml.aspx"&gt;Return to the Table of Contents&lt;/a&gt; of this screen-cast series. &lt;/span&gt;To demonstrate this scenario, I replace a content control with three paragraphs of content.&lt;/p&gt;  &lt;p&gt;(Please visit the site to view this video)&lt;/p&gt;</description></item><item><title>Blog Post: Open XML Markup Explorer App for Word 2013</title><link>http://openxmldeveloper.org/blog/b/openxmldeveloper/archive/2013/02/26/open-xml-markup-explorer-app-for-word-2013.aspx</link><pubDate>Tue, 26 Feb 2013 14:40:00 GMT</pubDate><guid isPermaLink="false">1ff61f26-0981-41c7-ad52-ff725e9b1da8:160510</guid><dc:creator>Eric White</dc:creator><description>&lt;p&gt;This screen-cast introduces a small Word 2013 &amp;quot;app&amp;quot; that enables you to select content in a Word document, click a button in a task pane, and see the markup for the selected content. &amp;nbsp;Further, you can modify the markup in the task pane, click a button, and replace the selected content in the document with the markup.&lt;/p&gt;  &lt;p&gt;This functionality is pretty valuable to a developer new to Open XML development. &amp;nbsp;You can explore the markup for a wide variety of Word document artifacts. &amp;nbsp;It is also helpful to experienced Open XML developers. &amp;nbsp;I, of course, can&amp;#39;t remember all of the details of all aspects of Word markup, and when writing a complex query, it is helpful to be able to have good examples of the markup side-by-side to Visual Studio as I write the code.&lt;/p&gt;  &lt;p&gt;The video demos the app, and then walks through the process of building it. &amp;nbsp;The app is included in an attached zip file, but if you want to build the app yourself (an enjoyable and instructive task), the listings follow the video.&lt;/p&gt;  &lt;p&gt;(Please visit the site to view this video)&lt;/p&gt;  &lt;p&gt;Following is the HTML file showing the inclusion of the linq.js and ltxml.js modules, as well as the small about of UI markup.&lt;/p&gt;  &lt;p&gt;  &lt;pre class="prettyprint"&gt;&amp;lt;!DOCTYPE html&amp;gt;  &amp;lt;html&amp;gt;  &amp;lt;head&amp;gt;      &amp;lt;meta charset=&amp;quot;UTF-8&amp;quot; /&amp;gt;      &amp;lt;meta http-equiv=&amp;quot;X-UA-Compatible&amp;quot; content=&amp;quot;IE=Edge&amp;quot; /&amp;gt;      &amp;lt;title&amp;gt;WordMarkupExplorer&amp;lt;/title&amp;gt;        &amp;lt;link rel=&amp;quot;stylesheet&amp;quot; type=&amp;quot;text/css&amp;quot; href=&amp;quot;../Content/Office.css&amp;quot; /&amp;gt;        &amp;lt;!-- Add your CSS styles to the following file --&amp;gt;      &amp;lt;link rel=&amp;quot;stylesheet&amp;quot; type=&amp;quot;text/css&amp;quot; href=&amp;quot;../Content/App.css&amp;quot; /&amp;gt;        &amp;lt;script src=&amp;quot;../Scripts/jquery-1.7.1.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;        &amp;lt;!-- Use the CDN reference to Office.js when deploying your app --&amp;gt;      &amp;lt;!--&amp;lt;script src=&amp;quot;https://appsforoffice.microsoft.com/lib/1.0/hosted/office.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;--&amp;gt;        &amp;lt;!-- Use the local script references for Office.js to enable offline debugging --&amp;gt;      &amp;lt;script src=&amp;quot;../Scripts/Office/1.0/MicrosoftAjax.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;      &amp;lt;script src=&amp;quot;../Scripts/Office/1.0/office.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;        &amp;lt;!-- Add your JavaScript to the following file --&amp;gt;      &amp;lt;script src=&amp;quot;../Scripts/linq.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;      &amp;lt;script src=&amp;quot;../Scripts/ltxml.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;      &amp;lt;script src=&amp;quot;../Scripts/WordMarkupExplorer.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;  &amp;lt;/head&amp;gt;  &amp;lt;body&amp;gt;      &amp;lt;div id=&amp;quot;Content&amp;quot; style=&amp;quot;padding: 0; margin: 0;&amp;quot;&amp;gt;          &amp;lt;input type=&amp;quot;button&amp;quot; value=&amp;quot;Get Markup&amp;quot; id=&amp;quot;getMarkupBtn&amp;quot; style=&amp;quot;padding: 0px; width: 100px;&amp;quot; /&amp;gt;          &amp;lt;input type=&amp;quot;button&amp;quot; value=&amp;quot;Set Markup&amp;quot; id=&amp;quot;setMarkupBtn&amp;quot; style=&amp;quot;padding: 0px; width: 100px;&amp;quot; /&amp;gt;      &amp;lt;/div&amp;gt;      &amp;lt;div id=&amp;quot;Error&amp;quot; style=&amp;quot;margin: 0; padding: 0;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;      &amp;lt;div id=&amp;quot;Markup&amp;quot; style=&amp;quot;padding: 0; margin: 0;&amp;quot;&amp;gt;          &amp;lt;textarea rows=&amp;quot;33&amp;quot; cols=&amp;quot;120&amp;quot; id=&amp;quot;txMarkup&amp;quot; spellcheck=&amp;quot;false&amp;quot; style=&amp;quot;font: 12px courier; height: 100%; min-height: 50%; padding: 0; width: 100%; margin: 10pt 0 0 0;&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;      &amp;lt;/div&amp;gt;  &amp;lt;/body&amp;gt;  &amp;lt;/html&amp;gt;&lt;/pre&gt;  &lt;/p&gt;  &lt;p&gt;Here is the listing of WordMarkupExplorer.js:&lt;/p&gt;  &lt;p&gt;  &lt;pre class="prettyprint"&gt;// This function is run when the app is ready to start interacting with the host application  // It ensures the DOM is ready before adding click handlers to buttons  Office.initialize = function (reason) {      $(document).ready(function () {          $(&amp;#39;#getMarkupBtn&amp;#39;).click(function () {              getMarkup();          });          $(&amp;#39;#setMarkupBtn&amp;#39;).click(function () {              setMarkup();          });          $(&amp;#39;#Error&amp;#39;).hide(0, function () {              $(&amp;#39;#Error&amp;#39;).html(&amp;quot;&amp;lt;p/&amp;gt;&amp;quot;);          });      });  };    var getMarkup, setMarkup;    (function (root) {        var XDocument = Ltxml.XDocument;      var XElement = Ltxml.XElement;      var XAttribute = Ltxml.XAttribute;      var XNamespace = Ltxml.XNamespace;      var XName = Ltxml.XName;        var wpc = new XNamespace(          &amp;#39;http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas&amp;#39;);      var mc = new XNamespace(          &amp;quot;http://schemas.openxmlformats.org/markup-compatibility/2006&amp;quot;);      var o = new XNamespace(          &amp;quot;urn:schemas-microsoft-com:office:office&amp;quot;);      var r = new XNamespace(          &amp;#39;http://schemas.openxmlformats.org/officeDocument/2006/relationships&amp;#39;);      var m = new XNamespace(          &amp;quot;http://schemas.openxmlformats.org/officeDocument/2006/math&amp;quot;);      var v = new XNamespace(&amp;quot;urn:schemas-microsoft-com:vml&amp;quot;);      var wp14 = new XNamespace(          &amp;quot;http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing&amp;quot;);      var wp = new XNamespace(          &amp;quot;http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing&amp;quot;);      var w10 = new XNamespace(&amp;quot;urn:schemas-microsoft-com:office:word&amp;quot;);      var w = new XNamespace(          &amp;#39;http://schemas.openxmlformats.org/wordprocessingml/2006/main&amp;#39;);      var w14 = new XNamespace(          &amp;quot;http://schemas.microsoft.com/office/word/2010/wordml&amp;quot;);      var w15 = new XNamespace(          &amp;quot;http://schemas.microsoft.com/office/word/2012/wordml&amp;quot;);      var wpg = new XNamespace(          &amp;quot;http://schemas.microsoft.com/office/word/2010/wordprocessingGroup&amp;quot;);      var wpi = new XNamespace(          &amp;quot;http://schemas.microsoft.com/office/word/2010/wordprocessingInk&amp;quot;);      var wne = new XNamespace(          &amp;quot;http://schemas.microsoft.com/office/word/2006/wordml&amp;quot;);      var wps = new XNamespace(          &amp;quot;http://schemas.microsoft.com/office/word/2010/wordprocessingShape&amp;quot;);        var W = {          rsid: new XName(w + &amp;quot;rsid&amp;quot;),          rsidDel: new XName(w + &amp;quot;rsidDel&amp;quot;),          rsidP: new XName(w + &amp;quot;rsidP&amp;quot;),          rsidR: new XName(w + &amp;quot;rsidR&amp;quot;),          rsidRDefault: new XName(w + &amp;quot;rsidRDefault&amp;quot;),          rsidRPr: new XName(w + &amp;quot;rsidRPr&amp;quot;),          rsidSect: new XName(w + &amp;quot;rsidSect&amp;quot;),          rsidTr: new XName(w + &amp;quot;rsidTr&amp;quot;),          sectPr: new XName(w + &amp;quot;sectPr&amp;quot;),          body: new XName(w + &amp;quot;body&amp;quot;),      };        function simplifyTransform(node) {          var element = node;          if (element.nodeType === &amp;#39;Element&amp;#39;) {              if (element.name === W.sectPr &amp;amp;&amp;amp; element.parent.name === W.body) {                  return null;              }              if (element.name == W.rsid)                  return null;              var newElement = new Ltxml.XElement(element.name,                  element.attributes().where(function (a) {                      return a.name != W.rsid &amp;amp;&amp;amp;                      a.name != W.rsidDel &amp;amp;&amp;amp;                      a.name != W.rsidP &amp;amp;&amp;amp;                      a.name != W.rsidR &amp;amp;&amp;amp;                      a.name != W.rsidRDefault &amp;amp;&amp;amp;                      a.name != W.rsidRPr &amp;amp;&amp;amp;                      a.name != W.rsidSect &amp;amp;&amp;amp;                      a.name != W.rsidTr;                  }),                  element.nodes().select(function (n) {                      return simplifyTransform(n);                  }))              return newElement;          }          return node;      }        var regArray = [          {              regEx: /xmlns:[^\r\n]*&amp;quot;(\r\n|\n|\r)/g,              replaceWith: &amp;quot;&amp;quot;          },          {              regEx: /xmlns:[^\r\n]*&amp;#39;(\r\n|\n|\r)/g,              replaceWith: &amp;quot;&amp;quot;          },          {              regEx: /xmlns:[^&amp;gt;\r\n]*&amp;quot;&amp;gt;/g,              replaceWith: &amp;quot;&amp;gt;&amp;quot;          },          {              regEx: /xmlns:[^&amp;gt;\r\n]*&amp;#39;&amp;gt;/g,              replaceWith: &amp;quot;&amp;gt;&amp;quot;          },      ];        function simplifyMarkup(body) {          var simplified = simplifyTransform(body);          simplified.add(              new XAttribute(XNamespace.xmlns + &amp;quot;wpc&amp;quot;, wpc),              new XAttribute(XNamespace.xmlns + &amp;quot;mc&amp;quot;, mc),              new XAttribute(XNamespace.xmlns + &amp;quot;o&amp;quot;, o),              new XAttribute(XNamespace.xmlns + &amp;quot;r&amp;quot;, r),              new XAttribute(XNamespace.xmlns + &amp;quot;m&amp;quot;, m),              new XAttribute(XNamespace.xmlns + &amp;quot;v&amp;quot;, v),              new XAttribute(XNamespace.xmlns + &amp;quot;wp14&amp;quot;, wp14),              new XAttribute(XNamespace.xmlns + &amp;quot;wp&amp;quot;, wp),              new XAttribute(XNamespace.xmlns + &amp;quot;w10&amp;quot;, w10),              new XAttribute(XNamespace.xmlns + &amp;quot;w&amp;quot;, w),              new XAttribute(XNamespace.xmlns + &amp;quot;w14&amp;quot;, w14),              new XAttribute(XNamespace.xmlns + &amp;quot;w15&amp;quot;, w15),              new XAttribute(XNamespace.xmlns + &amp;quot;wpg&amp;quot;, wpg),              new XAttribute(XNamespace.xmlns + &amp;quot;wpi&amp;quot;, wpi),              new XAttribute(XNamespace.xmlns + &amp;quot;wne&amp;quot;, wne),              new XAttribute(XNamespace.xmlns + &amp;quot;wps&amp;quot;, wps));          var simpString = simplified.toString(true);          for (var i = 0; i &amp;lt; regArray.length; i++) {              simpString = simpString.replace(regArray[i].regEx,                  regArray[i].replaceWith);          }          simpString = simpString.replace(/&amp;lt;w:body[ ]*&amp;gt;(\r\n|\n|\r)/, &amp;quot;&amp;quot;);          simpString = simpString.replace(/&amp;lt;\/w:body&amp;gt;(\r\n|\n|\r)/, &amp;quot;&amp;quot;);          simpString = simpString.replace(/^  /g, &amp;quot;&amp;quot;);          simpString = simpString.replace(/(\r\n|\n|\r)  /g, &amp;quot;\r\n&amp;quot;);          simpString = simpString.replace(/&amp;lt;w:p\/&amp;gt;(\r\n|\n|\r)$/, &amp;quot;&amp;quot;);          return simpString;      }        // Reads the data from current selection of the document and displays it in a textbox      getMarkup = function () {          Office.context.document.getSelectedDataAsync(Office.CoercionType.Ooxml,          function (asyncResult) {              var t = document.getElementById(&amp;#39;txMarkup&amp;#39;);              var error = asyncResult.error;              if (asyncResult.status === Office.AsyncResultStatus.Failed) {                  t.value = error.name + &amp;quot;: &amp;quot; + error.message;              }              else {                  var parsedResult = XElement.parse(asyncResult.value);                  var body = parsedResult.descendants(w + &amp;quot;body&amp;quot;).firstOrDefault();                  var simpString = simplifyMarkup(body);                  t.value = simpString;                  $(&amp;#39;#Error&amp;#39;).hide(500, function () {                      $(&amp;#39;#Error&amp;#39;).html(&amp;quot;&amp;quot;);                  });              }          });      }        function fixUpMarkup(markup) {          var newMarkup =  &amp;#39;&amp;lt;w:body xmlns:wpc=&amp;quot;http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas&amp;quot;&amp;#39; +  &amp;#39; xmlns:mc=&amp;quot;http://schemas.openxmlformats.org/markup-compatibility/2006&amp;quot;&amp;#39; +  &amp;#39; xmlns:o=&amp;quot;urn:schemas-microsoft-com:office:office&amp;quot;&amp;#39; +  &amp;#39; xmlns:r=&amp;quot;http://schemas.openxmlformats.org/officeDocument/2006/relationships&amp;quot;&amp;#39; +  &amp;#39; xmlns:m=&amp;quot;http://schemas.openxmlformats.org/officeDocument/2006/math&amp;quot;&amp;#39; +  &amp;#39; xmlns:v=&amp;quot;urn:schemas-microsoft-com:vml&amp;quot;&amp;#39; +  &amp;#39; xmlns:wp14=&amp;quot;http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing&amp;quot;&amp;#39; +  &amp;#39; xmlns:wp=&amp;quot;http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing&amp;quot;&amp;#39; +  &amp;#39; xmlns:w10=&amp;quot;urn:schemas-microsoft-com:office:word&amp;quot;&amp;#39; +  &amp;#39; xmlns:w=&amp;quot;http://schemas.openxmlformats.org/wordprocessingml/2006/main&amp;quot;&amp;#39; +  &amp;#39; xmlns:w14=&amp;quot;http://schemas.microsoft.com/office/word/2010/wordml&amp;quot;&amp;#39; +  &amp;#39; xmlns:w15=&amp;quot;http://schemas.microsoft.com/office/word/2012/wordml&amp;quot;&amp;#39; +  &amp;#39; xmlns:wpg=&amp;quot;http://schemas.microsoft.com/office/word/2010/wordprocessingGroup&amp;quot;&amp;#39; +  &amp;#39; xmlns:wpi=&amp;quot;http://schemas.microsoft.com/office/word/2010/wordprocessingInk&amp;quot;&amp;#39; +  &amp;#39; xmlns:wne=&amp;quot;http://schemas.microsoft.com/office/word/2006/wordml&amp;quot;&amp;#39; +  &amp;#39; xmlns:wps=&amp;quot;http://schemas.microsoft.com/office/word/2010/wordprocessingShape&amp;quot;&amp;#39; +  &amp;#39; mc:Ignorable=&amp;quot;w14 w15 wp14&amp;quot;&amp;gt;&amp;#39; + markup + &amp;quot;&amp;lt;/w:body&amp;gt;&amp;quot;;          return newMarkup;      }        // Reads the data from current selection of the document and displays it in a textbox      setMarkup = function () {          Office.context.document.getSelectedDataAsync(Office.CoercionType.Ooxml,          function (asyncResult) {              var t = document.getElementById(&amp;#39;txMarkup&amp;#39;);              var error = asyncResult.error;              if (asyncResult.status === Office.AsyncResultStatus.Failed) {                  $(&amp;#39;#Error&amp;#39;).html(  &amp;quot;&amp;lt;p style=&amp;#39;font-size: 12px;background-color: red; color: white;&amp;#39;&amp;gt;Error setting markup: &amp;quot;                      + error.name + &amp;quot;: &amp;quot; + error.message + &amp;quot;&amp;lt;/p&amp;gt;&amp;quot;);                  $(&amp;#39;#Error&amp;#39;).show(500, function () { });              }              else {                  var parsedResult = XDocument.parse(asyncResult.value);                  var body = parsedResult.descendants(w + &amp;quot;body&amp;quot;).firstOrDefault();                  var newMarkup = fixUpMarkup(t.value);                  try {                      var newBody = XElement.parse(newMarkup);                      body.replaceWith(newBody);                      $(&amp;#39;#Error&amp;#39;).hide(500, function () {                          $(&amp;#39;#Error&amp;#39;).html(&amp;quot;&amp;quot;);                      });                      Office.context.document.setSelectedDataAsync(                          parsedResult.toString(false), {                              coercionType: &amp;quot;ooxml&amp;quot;                          }, function (asyncResult) {                              var error = asyncResult.error;                              if (asyncResult.status === &amp;quot;failed&amp;quot;) {                                  $(&amp;#39;#Error&amp;#39;).html(  &amp;quot;&amp;lt;p style=&amp;#39;font-size: 12px;background-color: red; color: white;&amp;#39;&amp;gt;Error setting markup: &amp;quot;                                      + error.name + &amp;quot;: &amp;quot; + error.message + &amp;quot;&amp;lt;/p&amp;gt;&amp;quot;);                                  $(&amp;#39;#Error&amp;#39;).show(500, function () { });                              }                              else {                                  // get the markup back out from Word so that display                                  // any adjustments that Word made to the markup.                                  getMarkup();                              }                          });                  }                  catch (e) {                      $(&amp;#39;#Error&amp;#39;).html(  &amp;quot;&amp;lt;p style=&amp;#39;font-size: 12px;background-color: red; color: white;&amp;#39;&amp;gt;XML Parsing Error: &amp;quot;                          + e.toString() + &amp;quot;&amp;lt;/p&amp;gt;&amp;quot;);                      $(&amp;#39;#Error&amp;#39;).show(500, function () { });                  }                }          });      }  })(this);&lt;/pre&gt;  &lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;</description></item><item><title>Blog Post: Screen-Cast: Exploring the Structure of Embedded Spreadsheets in Word Documents</title><link>http://openxmldeveloper.org/blog/b/openxmldeveloper/archive/2013/02/20/screen-cast-exploring-the-structure-of-embedded-spreadsheets-in-word-documents.aspx</link><pubDate>Wed, 20 Feb 2013 12:00:00 GMT</pubDate><guid isPermaLink="false">1ff61f26-0981-41c7-ad52-ff725e9b1da8:160479</guid><dc:creator>Eric White</dc:creator><description>&lt;p&gt;Most users of Microsoft Office are aware that you can directly embed an Excel spreadsheet (XLSX) in a Word document (DOCX). &amp;nbsp;In Open XML terms, the XLSX is stored in a binary part. In addition, there is an image of the view of that spreadsheet, also in its own separate part. &amp;nbsp;This screen-cast shows how to unzip the DOCX, see where the embedded XLSX is, unzip the XLSX, change some markup in one of the worksheets, re-zip the XLSX, and re-zip the DOCX. &amp;nbsp;Further, it is interesting to see where the image of the embedded workbook is stored in the DOCX, and to replace that image with a different one. &amp;nbsp;This screen-cast shows how to accomplish all this and end up with a valid DOCX that is put together correctly.&lt;/p&gt;  &lt;p&gt;(Please visit the site to view this video)&lt;/p&gt;</description></item><item><title>Blog Post: Screen-Cast: Transforming Attributes in Recursive Pure Functional Transformations (RPFT) of XML</title><link>http://openxmldeveloper.org/blog/b/openxmldeveloper/archive/2013/02/15/screen-cast-transforming-attributes-in-recursive-pure-functional-transformations-rpft-of-xml.aspx</link><pubDate>Fri, 15 Feb 2013 21:41:00 GMT</pubDate><guid isPermaLink="false">1ff61f26-0981-41c7-ad52-ff725e9b1da8:160445</guid><dc:creator>Eric White</dc:creator><description>&lt;p&gt;This is the seventeenth screen-cast in a series on writing Recursive Pure Functional Transformations (RPFT) of XML. In this screen-cast, we discuss transforming attributes.  If you have been following along closely, you probably could imagine what this code looks like, but it is worthwhile to see this in action.&lt;/p&gt;  &lt;p&gt;&lt;span style="float:right;width:20%;margin:0 8px 6px 8px;border:1px black solid;padding:8px 5px 5px 8px;"&gt;&lt;a href="http://openxmldeveloper.org/wiki/w/wiki/recursive-pure-functional-transforms-of-xml.aspx"&gt;Return to the Table of Contents&lt;/a&gt; of this screen-cast series. &lt;/span&gt;To demonstrate this scenario, I write code to remove the RSID attributes from a WordprocessingML document.&lt;/p&gt;  &lt;p&gt;(Please visit the site to view this video)&lt;/p&gt;</description></item><item><title>Blog Post: Innovative Use of Open XML with SAP</title><link>http://openxmldeveloper.org/blog/b/openxmldeveloper/archive/2013/02/13/innovative-use-of-open-xml-with-sap.aspx</link><pubDate>Wed, 13 Feb 2013 13:56:00 GMT</pubDate><guid isPermaLink="false">1ff61f26-0981-41c7-ad52-ff725e9b1da8:160426</guid><dc:creator>Eric White</dc:creator><description>&lt;p style="padding-left:30px;"&gt;&lt;em&gt;This is a guest post by Ronen Almog, showing an innovative use of Open XML with SAP. &amp;nbsp;This Open XML application combines two of the main scenarios of Open XML: Document Generation, and Content Extraction. &amp;nbsp;As a way to make it easier for SAP users to maintain certain data, this program generates some Open XML documents, the user then edits those documents, and then finally, the documents are parsed, their contents extracted, and the SAP database is updated.&lt;/em&gt;&lt;/p&gt;  &lt;p style="padding-left:30px;"&gt;&lt;em&gt;Enjoy!&lt;/em&gt;&lt;/p&gt;  &lt;p style="padding-left:30px;"&gt;&lt;em&gt;-Eric&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;SAP systems are very popular among big businesses.&amp;nbsp; They  serve big enterprise organizations and manage a huge number of transactions.&amp;nbsp;  Sometimes SAP users feel that the SAP user interface is difficult to use.&amp;nbsp; It  is fairly complicated, and less than intuitive.&lt;/p&gt;  &lt;p&gt;This blog post shows another way of putting together an  intuitive, easy-to-use user interface to some aspects of SAP using Open XML.&lt;/p&gt;  &lt;p&gt;As delivered, SAP uses Microsoft Word and Microsoft Excel to  present some aspects of the user interface, using OLE.&amp;nbsp; This has the  disadvantaging that it works slowly and on only one document at a time.&amp;nbsp;  Further, using SAP and OLE, you can&amp;rsquo;t create objects such as tables, graphics,  and dynamic documents.&lt;/p&gt;  &lt;p&gt;But if you use Open XML instead of OLE, you can give a much  better experience to your users.&lt;/p&gt;  &lt;p&gt;First you use Microsoft Word to create a template.&lt;/p&gt;  &lt;p&gt;&lt;img border="0" src="http://openxmldeveloper.org/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-00-07/0728.Img1.png" alt=" " /&gt;&lt;/p&gt;  &lt;p&gt;I use an empty template because on the last step in the  process, I&amp;#39;m going to merge template and data using XSLT.&amp;nbsp; We store the template  on a server directory so it can be accessed by the Open XML programs.&lt;/p&gt;  &lt;p&gt;Then connect to the SAP system:&lt;/p&gt;  &lt;p&gt;&lt;img border="0" src="http://openxmldeveloper.org/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-00-07/3146.Img2.png" alt=" " /&gt;&lt;/p&gt;  &lt;p&gt;I created an Xml transformation for merging Open XML tags  and SAP data (internal tables and fields) using Xpath.&lt;/p&gt;  &lt;p&gt;&lt;img border="0" src="http://openxmldeveloper.org/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-00-07/4201.Img3.png" alt=" " /&gt;&lt;/p&gt;  &lt;p&gt;You can then run the SAP program to create Word Documents  including SAP data&lt;/p&gt;  &lt;p&gt;&lt;img border="0" src="http://openxmldeveloper.org/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-00-07/5672.Img4.png" alt=" " /&gt;&lt;/p&gt;  &lt;p&gt;This process created 20 documents, each containing data  about a purchase order.&lt;/p&gt;  &lt;p&gt;&lt;img border="0" src="http://openxmldeveloper.org/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-00-07/7345.Img5.png" alt=" " /&gt;&lt;/p&gt;  &lt;p&gt;Now let&amp;#39;s open one of the word files created.&lt;/p&gt;  &lt;p&gt;The arrows showed merging of SAP data inside the document.&lt;/p&gt;  &lt;p&gt;&lt;img border="0" src="http://openxmldeveloper.org/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-00-07/3750.Img6.png" alt=" " /&gt;&lt;/p&gt;  &lt;p&gt;The user can change the text in the short text column in the  in the first 2 rows and then save the document.&lt;/p&gt;  &lt;p&gt;&lt;img border="0" src="http://openxmldeveloper.org/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-00-07/1732.Img7.png" alt=" " /&gt;&lt;/p&gt;  &lt;p&gt;Then upload the document(s) into SAP:&lt;/p&gt;  &lt;p&gt;&lt;img border="0" src="http://openxmldeveloper.org/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-00-07/4604.Img8.png" alt=" " /&gt;&lt;/p&gt;  &lt;p&gt;The next step is to run the transformation of data from Open  XML file into SAP.&amp;nbsp; We can see the changes in the rows inside SAP.&lt;/p&gt;  &lt;p&gt;&lt;img border="0" src="http://openxmldeveloper.org/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-00-07/8284.Img9.png" alt=" " /&gt;&lt;/p&gt;  &lt;p&gt;This system is working in a production environment in one of  the biggest insurance companies in Israel.&amp;nbsp; It produces thousands of letters in  each batch run. A large governmental organization plans to use this approach to  create letters for the SAP HCM module.&lt;/p&gt;  &lt;p&gt;I will be happy to answer questions about this system and  implementation.&lt;/p&gt;  &lt;p&gt;Ronen Almog&lt;/p&gt;  &lt;p&gt;SAP Development Consultant&lt;/p&gt;  &lt;p&gt;A.R.P. Solutions&lt;/p&gt;  &lt;p&gt;Mail: arp.solutions.il@gmail.com&lt;/p&gt;  &lt;p&gt;Cell: 972-505602184&lt;/p&gt;</description></item><item><title>Blog Post: Inserting an Image into a Bookmark in an OpenXML WordprocessingML Document</title><link>http://openxmldeveloper.org/blog/b/openxmldeveloper/archive/2013/02/11/inserting-an-image-into-a-bookmark-in-an-openxml-wordprocessingml-document.aspx</link><pubDate>Mon, 11 Feb 2013 07:06:00 GMT</pubDate><guid isPermaLink="false">1ff61f26-0981-41c7-ad52-ff725e9b1da8:160396</guid><dc:creator>Eric White</dc:creator><description>&lt;p&gt;Bookmarks provide a convenient way in WordprocessingML to  provide insertion points for various items, such as text, images, etc.&amp;nbsp;  Previously, I have outlined how to programmatically &lt;a href="http://openxmldeveloper.org/blog/b/openxmldeveloper/archive/2011/09/01/how-to-retrieve-the-text-of-a-bookmark-from-an-openxml-wordprocessingml-document.aspx"&gt;retrieve&lt;/a&gt;  and &lt;a href="http://openxmldeveloper.org/blog/b/openxmldeveloper/archive/2011/09/06/replacing-text-of-a-bookmark-in-an-openxml-wordprocessingml-document.aspx"&gt;replace&lt;/a&gt;  text within a bookmark.&amp;nbsp; In a recent project, a client wanted to use bookmarks  as insertion points for one or more images.&amp;nbsp; Using with the replace bookmark  text sample code as a starting point, I extended it to include image  insertion.&amp;nbsp; There are a number of additional steps to create an Open XML  package that contains a properly inserted image. The main points are described below  and sample code is attached.&lt;/p&gt;  &lt;p&gt;In a recent &lt;a href="http://openxmldeveloper.org/blog/b/openxmldeveloper/archive/2013/01/19/screen-cast-images-in-wordprocessingml.aspx"&gt;screencast&lt;/a&gt;,  I discuss the mechanics of how images are handled in OpenXml.&amp;nbsp; At the end of  that screencast, I show how to manually insert an image into a word document  package.&amp;nbsp; In order to implement this in code, the following steps are performed:&lt;/p&gt;  &lt;ol&gt;  &lt;li&gt;Flatten the paragraphs&lt;/li&gt;  &lt;li&gt;Create a resource ID for the image&lt;/li&gt;  &lt;li&gt;Create the image XElement&lt;/li&gt;  &lt;li&gt;Insert the image element into the bookmark&lt;/li&gt;  &lt;li&gt;Move the bookmark&lt;/li&gt;  &lt;li&gt;Create a new image part and stream the image into that part&lt;/li&gt;  &lt;/ol&gt;  &lt;h2&gt;Flattening the paragraphs&lt;/h2&gt;  &lt;p&gt;Flattening the paragraphs is a technique that I use in order  to simplify XML operations.&amp;nbsp; It creates temporarily invalid WordprocessingML,  but is useful as an intermediate step.&amp;nbsp; For example, it is valid for bookmarks to  span different levels in the XML hierarchy.&amp;nbsp; However, for inserting an image in  between bookmark start and end tags, our job is significantly easier if the  bookmarks are at the same level of hierarchy in the XML.&amp;nbsp; &amp;nbsp;&lt;/p&gt;  &lt;h2&gt;Create a Resource ID for the Image&lt;/h2&gt;  &lt;p&gt;The resource ID links the image part to the main document  part. The only constraint for the image resource ID is that it must be unique.&amp;nbsp;  To create a resource ID, the code uses a GUID, strips out the dashes and  prepends the number with &amp;ldquo;r&amp;rdquo;.&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;pre class="prettyprint"&gt;string imageRId = &amp;quot;r&amp;quot; + Guid.NewGuid().ToString().Replace(&amp;quot;-&amp;quot;, String.Empty);  &lt;/pre&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;h2&gt;Create the Image XElement&lt;/h2&gt;  &lt;p&gt;There is no easy way to create the markup for the image  other than hand-coding the image element tree.&amp;nbsp; In order to see this markup, I  created a Word document, inserted an image, saved the document, opened it in  the &lt;a href="http://visualstudiogallery.msdn.microsoft.com/450a00e3-5a7d-4776-be2c-8aa8cec2a75b"&gt;Open  XML Package Editor Power Tool for Visual Studio 2010&lt;/a&gt;, and then examined the  markup for the image.&amp;nbsp; A fragment of the markup is shown below.&amp;nbsp; We can see  that the markup for the image is below a w:r element and begins with the w:drawing  element:&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;pre class="prettyprint"&gt;&amp;lt;w:r&amp;gt;    &amp;lt;w:drawing&amp;gt;      &amp;lt;wp:inline distT=&amp;quot;0&amp;quot;                  distB=&amp;quot;0&amp;quot;                  distL=&amp;quot;0&amp;quot;                  distR=&amp;quot;0&amp;quot;&amp;gt;        &amp;lt;wp:extent cx=&amp;quot;2314575&amp;quot;                    cy=&amp;quot;1647825&amp;quot; /&amp;gt;        &amp;lt;wp:effectExtent l=&amp;quot;0&amp;quot;                          t=&amp;quot;0&amp;quot;                          r=&amp;quot;0&amp;quot;                          b=&amp;quot;0&amp;quot; /&amp;gt;        &amp;lt;wp:docPr id=&amp;quot;1&amp;quot;                  name=&amp;quot;Image1&amp;quot; /&amp;gt;        &amp;lt;wp:cNvGraphicFramePr&amp;gt;          &amp;lt;a:graphicFrameLocks xmlns:a=&amp;quot;http://schemas.openxmlformats.org/drawingml/2006/main&amp;quot;                                noChangeAspect=&amp;quot;1&amp;quot; /&amp;gt;        &amp;lt;/wp:cNvGraphicFramePr&amp;gt;  &lt;/pre&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;Using the &lt;a href="http://powertools.codeplex.com/"&gt;PowerTools  for OpenXml&lt;/a&gt; utility PtOpenXmlUtil.cs, which contains the intialized XName  objects for WordprocessingML, I created an image element that produces similar image  markup, as shown below.&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;pre class="prettyprint"&gt;XElement imageElement =      new XElement(W.drawing,          new XElement(WP.inline,              new XAttribute(&amp;quot;distT&amp;quot;, &amp;quot;0&amp;quot;),              new XAttribute(&amp;quot;distB&amp;quot;, &amp;quot;0&amp;quot;),              new XAttribute(&amp;quot;distL&amp;quot;, &amp;quot;0&amp;quot;),              new XAttribute(&amp;quot;distR&amp;quot;, &amp;quot;0&amp;quot;),              new XElement(WP.extent,                  new XAttribute(&amp;quot;cx&amp;quot;, imageWidthExtent),                  new XAttribute(&amp;quot;cy&amp;quot;, imageHeightExtent)              ),              new XElement(WP.effectExtent,                  new XAttribute(&amp;quot;l&amp;quot;, &amp;quot;0&amp;quot;),                  new XAttribute(&amp;quot;t&amp;quot;, &amp;quot;0&amp;quot;),                  new XAttribute(&amp;quot;r&amp;quot;, &amp;quot;0&amp;quot;),                  new XAttribute(&amp;quot;b&amp;quot;, &amp;quot;0&amp;quot;)              ),              new XElement(WP.docPr,                  new XAttribute(&amp;quot;id&amp;quot;, &amp;quot;1&amp;quot;),                     new XAttribute(&amp;quot;name&amp;quot;, name)                                                      ),              new XElement(WP.cNvGraphicFramePr,                  new XElement(A.graphicFrameLocks,                      new XAttribute(XNamespace.Xmlns + &amp;quot;a&amp;quot;, A.a),                      new XAttribute(&amp;quot;noChangeAspect&amp;quot;, &amp;quot;1&amp;quot;))              ),              new XElement(A.graphic,                      new XAttribute(XNamespace.Xmlns + &amp;quot;a&amp;quot;, A.a),                      new XElement(A.graphicData,                          new XAttribute(&amp;quot;uri&amp;quot;, Pic.pic),                          new XElement(Pic._pic,                              new XAttribute(XNamespace.Xmlns + &amp;quot;pic&amp;quot;, Pic.pic),                              new XElement(Pic.nvPicPr,                                  new XElement(Pic.cNvPr,                                      new XAttribute(&amp;quot;id&amp;quot;, &amp;quot;0&amp;quot;),                                      new XAttribute(&amp;quot;name&amp;quot;, &amp;quot;&amp;quot;)                                  ),                                  new XElement(Pic.cNvPicPr)                              ),                              new XElement(Pic.blipFill,                                  new XElement(A.blip,                                      new XAttribute(R.r + &amp;quot;embed&amp;quot;, imageRId)                                  ),                                  new XElement(A.stretch,                                      new XElement(A.fillRect)                                  )                              ),                              new XElement(Pic.spPr,                                  new XElement(A.xfrm,                                      new XElement(A.off,                                          new XAttribute(&amp;quot;x&amp;quot;, &amp;quot;0&amp;quot;),                                          new XAttribute(&amp;quot;y&amp;quot;, &amp;quot;0&amp;quot;)                                      ),                                      new XElement(A.ext,                                          new XAttribute(&amp;quot;cx&amp;quot;, imageWidth),                                          new XAttribute(&amp;quot;cy&amp;quot;, imageHeight)                                      )                                  ),                              new XElement(A.prstGeom,                                  new XAttribute(&amp;quot;prst&amp;quot;, &amp;quot;rect&amp;quot;),                                  new XElement(A.avLst)                              )                          )                      )                  )              )          )  );  &lt;/pre&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;There are several input parameters for this image element:  the image dimensions, the dimensions of the space reserved for the image  (extent), and the resource ID. &amp;nbsp;The image name is not critical as the image  part is referenced by the resource ID, not the image name.&lt;/p&gt;  &lt;p&gt;The height and width of the image and the dimensions  reserved for it are defined by the attributes in the A:ext and wp:extent elements,  respectively.&amp;nbsp; These values are in EMUs, English Metric Units, where 1 EMU =  1/914400 inch = 1/360000 cm.&amp;nbsp; In this sample code, the image to be inserted is  passed in as a Bitmap object.&amp;nbsp; The methods that return the width and height for  a Bitmap object return the values in a different unit, where 1 unit = 1/96  inch.&amp;nbsp; Thus, the Bitmap image width and height are first converted into EMUs  and then assigned as attribute values in the A:ext and wp:extent elements.&amp;nbsp; &amp;nbsp;&lt;/p&gt;  &lt;p&gt;To understand how these dimensions effect the layout, see the  examples below:&lt;/p&gt;  &lt;p&gt;&lt;img src="http://openxmldeveloper.org/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-00-07/1207.Img1.png" border="0" alt=" " /&gt;&lt;/p&gt;  &lt;table class="MsoTableGrid" border="1" cellspacing="0" cellpadding="0" style="border-collapse:collapse;border:none;"&gt;  &lt;tbody&gt;  &lt;tr&gt;  &lt;td width="91" valign="top" style="width:.95in;border:solid windowtext 1.0pt;padding:0in 5.4pt 0in 5.4pt;"&gt;  &lt;p align="center" style="margin-bottom:.0001pt;text-align:center;line-height:normal;"&gt;Image Size, Extent&lt;/p&gt;  &lt;/td&gt;  &lt;td width="162" style="width:121.5pt;border:solid windowtext 1.0pt;border-left:none;padding:0in 5.4pt 0in 5.4pt;"&gt;  &lt;p style="margin-bottom:.0001pt;line-height:normal;"&gt;Example 1&lt;/p&gt;  &lt;/td&gt;  &lt;td width="246" style="width:184.5pt;border:solid windowtext 1.0pt;border-left:none;padding:0in 5.4pt 0in 5.4pt;"&gt;  &lt;p style="margin-bottom:.0001pt;line-height:normal;"&gt;Example 2&lt;/p&gt;  &lt;/td&gt;  &lt;td width="139" style="width:1.45in;border:solid windowtext 1.0pt;border-left:none;padding:0in 5.4pt 0in 5.4pt;"&gt;  &lt;p style="margin-bottom:.0001pt;line-height:normal;"&gt;Example 3&lt;/p&gt;  &lt;/td&gt;  &lt;/tr&gt;  &lt;tr&gt;  &lt;td width="91" valign="top" style="width:.95in;border:solid windowtext 1.0pt;border-top:none;padding:0in 5.4pt 0in 5.4pt;"&gt;  &lt;p style="margin-bottom:.0001pt;line-height:normal;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:#a31515;"&gt;a:ext&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/p&gt;  &lt;/td&gt;  &lt;td width="162" valign="top" style="width:121.5pt;border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0in 5.4pt 0in 5.4pt;"&gt;  &lt;p style="margin-bottom:.0001pt;line-height:normal;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:red;"&gt;cx&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;"&gt;=&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;"&gt;&amp;quot;&lt;span style="color:blue;"&gt;2400000&lt;/span&gt;&amp;quot;&lt;/span&gt;&lt;/p&gt;  &lt;p style="margin-bottom:.0001pt;line-height:normal;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:red;"&gt;cy&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;"&gt;=&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;"&gt;&amp;quot;&lt;span style="color:blue;"&gt;1600000&lt;/span&gt;&amp;quot;&lt;span style="color:blue;"&gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/td&gt;  &lt;td width="246" valign="top" style="width:184.5pt;border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0in 5.4pt 0in 5.4pt;"&gt;  &lt;p style="margin-bottom:.0001pt;line-height:normal;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:red;"&gt;cx&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;"&gt;=&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;"&gt;&amp;quot;&lt;span style="color:blue;"&gt;2400000&lt;/span&gt;&amp;quot;&lt;/span&gt;&lt;/p&gt;  &lt;p style="margin-bottom:.0001pt;line-height:normal;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:red;"&gt;cy&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;"&gt;=&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;"&gt;&amp;quot;&lt;span style="color:blue;"&gt;800000&lt;/span&gt;&amp;quot;&lt;span style="color:blue;"&gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/td&gt;  &lt;td width="139" valign="top" style="width:1.45in;border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0in 5.4pt 0in 5.4pt;"&gt;  &lt;p style="margin-bottom:.0001pt;line-height:normal;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:red;"&gt;cx&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;"&gt;=&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;"&gt;&amp;quot;&lt;span style="color:blue;"&gt;2400000&lt;/span&gt;&amp;quot;&lt;/span&gt;&lt;/p&gt;  &lt;p style="margin-bottom:.0001pt;line-height:normal;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:red;"&gt;cy&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;"&gt;=&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;"&gt;&amp;quot;&lt;span style="color:blue;"&gt;1600000&lt;/span&gt;&amp;quot;&lt;span style="color:blue;"&gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/td&gt;  &lt;/tr&gt;  &lt;tr&gt;  &lt;td width="91" valign="top" style="width:.95in;border:solid windowtext 1.0pt;border-top:none;padding:0in 5.4pt 0in 5.4pt;"&gt;  &lt;p style="margin-bottom:.0001pt;line-height:normal;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:#a31515;"&gt;wp:extent &lt;/span&gt;&lt;/p&gt;  &lt;/td&gt;  &lt;td width="162" valign="top" style="width:121.5pt;border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0in 5.4pt 0in 5.4pt;"&gt;  &lt;p style="margin-bottom:.0001pt;line-height:normal;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:red;"&gt;cx&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;"&gt;=&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;"&gt;&amp;quot;&lt;span style="color:blue;"&gt;2400000&lt;/span&gt;&amp;quot;&lt;br /&gt;    &lt;span style="color:red;"&gt;cy&lt;/span&gt;&lt;span style="color:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color:blue;"&gt;1600000&lt;/span&gt;&amp;quot;&lt;span style="color:blue;"&gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/td&gt;  &lt;td width="246" valign="top" style="width:184.5pt;border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0in 5.4pt 0in 5.4pt;"&gt;  &lt;p style="margin-bottom:.0001pt;line-height:normal;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:red;"&gt;cx&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;"&gt;=&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;"&gt;&amp;quot;&lt;span style="color:blue;"&gt;2400000&lt;/span&gt;&amp;quot;&lt;br /&gt;    &lt;span style="color:red;"&gt;cy&lt;/span&gt;&lt;span style="color:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color:blue;"&gt;1600000&lt;/span&gt;&amp;quot;&lt;span style="color:blue;"&gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/td&gt;  &lt;td width="139" valign="top" style="width:1.45in;border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0in 5.4pt 0in 5.4pt;"&gt;  &lt;p style="margin-bottom:.0001pt;line-height:normal;"&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:red;"&gt;cx&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;color:blue;"&gt;=&lt;/span&gt;&lt;span style="font-size:9.5pt;font-family:Consolas;"&gt;&amp;quot;&lt;span style="color:blue;"&gt;1200000&lt;/span&gt;&amp;quot;&lt;br /&gt;    &lt;span style="color:red;"&gt;cy&lt;/span&gt;&lt;span style="color:blue;"&gt;=&lt;/span&gt;&amp;quot;&lt;span style="color:blue;"&gt;800000&lt;/span&gt;&amp;quot;&lt;span style="color:blue;"&gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;/td&gt;  &lt;/tr&gt;  &lt;/tbody&gt;  &lt;/table&gt;  &lt;p&gt;Notice in Example 2 that when the image size is smaller than  the space reserved for it (extent), then the space is left unfilled.&amp;nbsp; And when  the extent dimensions are smaller than the image size, the image is squeezed  into the extent space, as shown in Example 3. &lt;/p&gt;  &lt;p&gt;After this image element has been instantiated, it is  inserted between the bookmark start and end elements. &lt;/p&gt;  &lt;h2&gt;Move the Bookmark&lt;/h2&gt;  &lt;p&gt;The client requested to be able to insert multiple images at  the same bookmark.&amp;nbsp; Because the image is inserted between w:bookmarkStart and  w:bookmarkEnd, one of these needed to be moved adjacent to the other.&amp;nbsp;  Otherwise the current image would be replaced by the new one. &amp;nbsp;By moving the w:bookmarkEnd  to after the w:bookmarkStart and before the image markup, the next image added  via the method call to the same bookmark moves the existing image(s) to the right.&lt;/p&gt;  &lt;p&gt;One important point about bookmark names in Word is that  bookmark names are treated as case-insensitive within Word.&amp;nbsp; That is, you  cannot create bookmarks by name &amp;ldquo;A&amp;rdquo; and &amp;ldquo;a&amp;rdquo;; only one will be accepted.&amp;nbsp;&amp;nbsp; So  when we work with bookmarks within code, we convert the bookmark name to  uppercase to eliminate case-sensitivity.&amp;nbsp; For example:&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;pre class="prettyprint"&gt;XElement bookmark = xDoc.Descendants(W.bookmarkStart)     .FirstOrDefault(d =&amp;gt;          ((string)d.Attribute(W.name)).ToUpper() == bookmarkName.ToUpper());  &lt;/pre&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;h2&gt;Create a New Part and Stream the Image into that Part&lt;/h2&gt;  &lt;p&gt;After adding the image element, the image part is created  and then the image is streamed into that part.&amp;nbsp; In this example, the image to  be inserted at the bookmark is passed into the method as a Bitmap object: &lt;b&gt;image&lt;/b&gt;.&amp;nbsp;  The variable &lt;b&gt;imageFormatForSave&lt;/b&gt; specifies the format to save the image  part as: e.g., ImageFormat.Png, ImageFormat.Jpeg, etc.&amp;nbsp; &lt;/p&gt;  &lt;p&gt;Lastly, the document&amp;rsquo;s root element is replaced with the new  root element with the image markup, and then that is put into the  MainDocumentPart.&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;pre class="prettyprint"&gt;MainDocumentPart mainPart = doc.MainDocumentPart;  ImagePart imagePart = mainPart.AddImagePart(ImageElement.GetImagePartType (imageFormatForSave), imageRId);                using (MemoryStream ms = new MemoryStream())  {      image.Save(ms, imageFormatForSave);      byte[] ba = ms.ToArray();      using (Stream s = imagePart.GetStream(FileMode.Create, FileAccess.ReadWrite))          s.Write(ba, 0, ba.GetUpperBound(0) + 1);  }                    xDoc.Elements().First().ReplaceWith(newRoot);  doc.MainDocumentPart.PutXDocument();  &lt;/pre&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;  &lt;p&gt;The sample code is attached.&amp;nbsp; It provides several test cases  to show the functionality of the image insertion utility. &lt;/p&gt;</description></item><item><title>Blog Post: Integrating Open XML Functionality in a PowerShell Script by using Managed Code via the Add-Type Cmdlet</title><link>http://openxmldeveloper.org/blog/b/openxmldeveloper/archive/2013/02/07/integrating-open-xml-functionality-in-a-powershell-script-by-using-managed-code-via-the-add-type-cmdlet.aspx</link><pubDate>Thu, 07 Feb 2013 09:40:00 GMT</pubDate><guid isPermaLink="false">1ff61f26-0981-41c7-ad52-ff725e9b1da8:160375</guid><dc:creator>Eric White</dc:creator><description>&lt;p&gt;A &lt;a href="http://openxmldeveloper.org/discussions/development_tools/f/17/p/5992/160215.aspx"&gt;question in a forum here at OpenXMLDeveloper.org&lt;/a&gt; clued me into a cool new way to add Open XML functionality into a PowerShell cmdlet -&lt;/p&gt;  &lt;p&gt;&lt;span style="font-size:12px;"&gt;PowerShell 2.0 and above enable you to directly embed C# code in a PowerShell script using the Add-Type cmdlet. &amp;nbsp;To use this cmdlet, you pass two arguments:&lt;/span&gt;&lt;/p&gt;  &lt;ul&gt;  &lt;li&gt;A list of the fully qualified names of the assemblies that your C# code requires.&lt;/li&gt;  &lt;li&gt;A string containing the C# code.&lt;/li&gt;  &lt;/ul&gt;  &lt;p&gt;After calling the cmdlet, that type is available for your use in your PowerShell script. &amp;nbsp;I&amp;#39;ve recorded a short video showing this approach. &amp;nbsp;Here is the script that I show in the video (which is at the bottom of this post).&lt;/p&gt;  &lt;p&gt;  &lt;pre class="prettyprint"&gt;$assem = (    &amp;quot;windowsbase, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35&amp;quot;,    &amp;quot;DocumentFormat.OpenXml, Version=2.0.5022.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35&amp;quot;  )    $source = @&amp;quot;  using System;  using System.Collections;  using System.Collections.Generic;  using System.Linq;  using DocumentFormat.OpenXml.Packaging;  using DocumentFormat.OpenXml.Wordprocessing;    public class BasicTest  {    public static string DoOpenXmlFunc(string fileName)    {      using (WordprocessingDocument wDoc = WordprocessingDocument.Open(fileName, false))      {        var paragraphs = wDoc.MainDocumentPart.Document.Descendants&amp;lt;Paragraph&amp;gt;();        return paragraphs.Count().ToString();      }    }  }  &amp;quot;@    Add-Type -ReferencedAssemblies $assem -TypeDefinition $source  [BasicTest]::DoOpenXmlFunc(&amp;quot;.\test.docx&amp;quot;)  &lt;/pre&gt;  &lt;/p&gt;  &lt;p&gt;(Please visit the site to view this video)&lt;/p&gt;  &lt;p&gt;Happy scripting!&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt;</description></item><item><title>Blog Post: Screen-Cast: Removing Elements in Recursive Pure Functional Transforms (RPFT) of XML</title><link>http://openxmldeveloper.org/blog/b/openxmldeveloper/archive/2013/02/04/screen-cast-removing-elements-in-recursive-pure-functional-transforms-rpft-of-xml.aspx</link><pubDate>Mon, 04 Feb 2013 15:33:00 GMT</pubDate><guid isPermaLink="false">1ff61f26-0981-41c7-ad52-ff725e9b1da8:160344</guid><dc:creator>Eric White</dc:creator><description>&lt;p&gt;This is the sixteenth screen-cast in a series on writing Recursive Pure Functional Transformations (RPFT) of XML. In this screen-cast, we discuss the selective elimination of elements from the newly cloned XML tree.  We are, in effect, &amp;#39;removing&amp;#39; an element from the original XML tree in the newly created XML tree.&lt;/p&gt;  &lt;p&gt;&lt;span style="float:right;width:20%;margin:0 8px 6px 8px;border:1px black solid;padding:8px 5px 5px 8px;"&gt;&lt;a href="http://openxmldeveloper.org/wiki/w/wiki/recursive-pure-functional-transforms-of-xml.aspx"&gt;Return to the Table of Contents&lt;/a&gt; of this screen-cast series. &lt;/span&gt;To demonstrate this scenario, I remove proofing marks from a WordprocessingML document.  I also show removal of comments using this approach.&lt;/p&gt;  &lt;p&gt;(Please visit the site to view this video)&lt;/p&gt;</description></item><item><title>Blog Post: How to Research Open XML PresentationML</title><link>http://openxmldeveloper.org/blog/b/openxmldeveloper/archive/2013/01/31/how-to-research-open-xml-presentationml.aspx</link><pubDate>Thu, 31 Jan 2013 09:30:00 GMT</pubDate><guid isPermaLink="false">1ff61f26-0981-41c7-ad52-ff725e9b1da8:160285</guid><dc:creator>Eric White</dc:creator><description>&lt;p&gt;Recently, I received a question on one of forums here on OpenXMLDeveloper.org - how do you control the height for a table row, and also how to set the font size, background color, and etc. for a cell in a table in PresentationML. &amp;nbsp;Rather than directly answer the question, I recorded a screen-cast that shows how to use the various tools to answer such questions for yourself. &amp;nbsp;Once you have a good grasp of the tools, these things are pretty easy to research. &amp;nbsp;So this screen-cast is called, How to Set Colors and Fonts in Cells in PresentationML, but it could as easily be called, How to Research Open XML Markup.&lt;/p&gt;  &lt;p&gt;(Please visit the site to view this video)&lt;/p&gt;</description></item><item><title>Blog Post: Screen-Cast: Replacing Elements in Recursive Pure Functional Transforms (RPFT) of XML</title><link>http://openxmldeveloper.org/blog/b/openxmldeveloper/archive/2013/01/28/screen-cast-replacing-elements-in-recursive-pure-functional-transforms-rpft-of-xml.aspx</link><pubDate>Mon, 28 Jan 2013 12:32:00 GMT</pubDate><guid isPermaLink="false">1ff61f26-0981-41c7-ad52-ff725e9b1da8:160257</guid><dc:creator>Eric White</dc:creator><description>&lt;p&gt;This is the fifteenth screen-cast in a series on writing Recursive Pure Functional Transformations (RPFT) of XML. In this screen-cast, we discuss transforming one particular element in an XML tree with a different element.  We are, in effect, &amp;#39;replacing&amp;#39; an element from the original XML tree with a new element in the newly created XML tree.&lt;/p&gt;  &lt;p&gt;&lt;span style="float:right;width:20%;margin:0 8px 6px 8px;border:1px black solid;padding:8px 5px 5px 8px;"&gt;&lt;a href="http://openxmldeveloper.org/wiki/w/wiki/recursive-pure-functional-transforms-of-xml.aspx"&gt;Return to the Table of Contents&lt;/a&gt; of this screen-cast series. &lt;/span&gt;To demonstrate this scenario, I transform a simple WordprocessingML document into an Html page.  This transform is a pretty rudimentary transform - it&amp;#39;s main goal is to demonstrate the point of the screen-cast.  It is not a comprehensive, high fidelity transform from WordprocessingML to HTML.  That is going to come later!&lt;/p&gt;  &lt;p&gt;From here on, these screen-casts are more and more fun!  If you are not having fun yet, the geek police are going to require you to turn in your pocket protector! &lt;/p&gt;  &lt;p&gt;(Please visit the site to view this video)&lt;/p&gt;</description></item></channel></rss>