title: Generate multi-page document in Open XML from List of data
body: <p>For a project I am working on, I'm investigating methods that our team doesn't usually use for generating documents.  Normally, we use ActiveReports to generate a PDF that we serve up to the client, but that's not an option due to our paper size - we've been having <strong>severe</strong> issues getting anything that's not 8.5" x 11" to play nicely with browser-side PDF plugins, or the printers that we support.</p>
  
  <p>The specific thing I'm trying to do, is to create a document with 1...n 4"x6" Index Cards.  As noted I can have a variable number of data entries that I need to generate.</p>
  
  <p>The only way I've used Open XML in the past is to take a template, replace keywords with data that I wanted to inject, then serve the resulting document up to the client, as below:</p>
  
  <p><strong>Report Class:</strong></p>
  
  <pre><code>public class ThingReport : IDisposable
  {
      #region Variables / Properties
  
      private readonly string _templatePath = string.Empty;
      private MemoryStream _reportStream;
  
      #endregion Variables / Properties
  
      #region Constructor
  
      public ThingReport(string templatePath)
      {
          _templatePath = templatePath;
      }
  
      #endregion Constructor
  
      #region Methods
  
      public void Dispose()
      {
          _reportStream.Dispose();
      }
  
      public void RunReport(IList&lt;Thing&gt; things)
      {
          _reportStream = new MemoryStream();
  
          using (FileStream fs = File.OpenRead(_templatePath))
          {
              fs.CopyTo(_reportStream);
              _reportStream.Seek(0x00000000, SeekOrigin.Begin);
              fs.Close();
          }
  
          using (WordprocessingDocument pkgDoc = WordprocessingDocument.Open(_reportStream, true))
          {
              // Set basic properties of the document...
              pkgDoc.PackageProperties.Creator = "My App";
              pkgDoc.PackageProperties.Created = DateTime.Now;
              pkgDoc.PackageProperties.Title = "Some document";
              pkgDoc.PackageProperties.ContentType = "application/msword";
  
              // Read the full document text, in prep for editing...
              string docText;
              using (StreamReader sr = new StreamReader(pkgDoc.MainDocumentPart.GetStream()))
              {
                  docText = sr.ReadToEnd();
                  sr.Close();
              }
  
              // Replace the recipient.
              // Source: https://msdn.microsoft.com/en-us/library/office/bb508261.aspx
              Regex recipientRegex = new Regex("«Recipient»");
              docText = recipientRegex.Replace(docText, things[0].PersonName);
  
              // Template has 3 fields in it; replace those fields with details of child data.
              for (int i = 0; i &lt; 3; i++)
              {
                  string presentedDate = string.Empty;
                  string presentedNotes = string.Empty;
                  if (i &lt;= things.Count - 1)
                  {
                      var thing = things[i];
                      presentedDate = thing.thingDate.ToString("MM/dd/yyyy");
                      presentedNotes = thing.Notes;
                  }
  
                  string dateReplaceText = string.Format("«ThingDate{0}»", i + 1);
                  Regex dateRegex = new Regex(dateReplaceText);
                  docText = dateRegex.Replace(docText, presentedDate);
  
                  string noteReplaceText = string.Format("«ThingNote{0}»", i + 1);
                  Regex noteRegex = new Regex(noteReplaceText);
                  docText = noteRegex.Replace(docText, presentedNotes);
              }
  
              // Write the modified document to the stream.
              using (StreamWriter sw = new StreamWriter(pkgDoc.MainDocumentPart.GetStream(FileMode.Create)))
              {
                  sw.Write(docText);
                  sw.Close();
              }
  
              // Close the unmanaged resource!
              pkgDoc.Close();
          }
      }
  
      public byte[] Export()
      {
          return _reportStream.ToArray();
      }
  
      #endregion Methods
  }    
  </code></pre>
  
  <p>I've never even tried to use a Word Template across multiple data entries at once.  As this is a technology that the rest of my team has the same experience with, I can't ask them how to do this, as they know exactly as much as I do.  </p>
  
  <p>I did look up the <a href="https://msdn.microsoft.com/en-us/library/documentformat.openxml.packaging.wordprocessingdocument_methods(v=office.14).aspx" rel="nofollow">Open XML API for word documents</a>, and some other requisite Google searches on how to get the Open XML API to do this...but I found nothing that I could make sense of.</p>
  
  <p><strong>Question:</strong> In what way can I take a <code>List&lt;Thing&gt;</code> with a variable number of members, and use Open XML to take a MS Word Template to generate a document that has a number of pages equal to the number of members, all using the exact same format?</p>