2016-09-04 1 views
0

contact_nameなどの特定の変数を使用するように設計された単一ページのdocxテンプレートファイルがあります。 OpenXml SDK + Open-Xml-PowerToolsを使用して処理する際、私はこのテンプレートに基づいてdocxファイルの多くのインスタンスを作成し、実際の値を変数に置き換えます。最後に、私は1つのdocx出力を必要とするので、Open-Xml-PowerTools DocumentBuilderを使って1つのdocxにマージします。docxファイルを1つにマージし、番号付きリストの書式設定を保持

これは、ユーザーが番号付きリストをテンプレートに挿入するまで機能していたようです。私の元の問題は番号が付けられていましたが、文書のポストマージ後の番号付けが続けられました。すなわち、リストの2番目のページの番号は、文書がすべて同じリストIDを参照していると思ったため1-10ではなく11-20でした。

これは、num idがドキュメント本文内で一意であることを保証することで解決できましたが、リストのフォーマットは最初のページを超えて失われています。最初のページでは、番号付きリスト項目はインデントされていますが、2番目以降では、ページ上に残っているのは、適切な番号付きリストではないためです。私はこれらの新しいnum idを一致させるために、スタイリングとナンバリングのセクションを更新する必要があるようですが、私はこの作業をすることはできません。

私はericwhite.comのフォーラムでこれについて投稿しましたが、最新の問題(http://ericwhite.com/blog/forums/topic/list-numbering-on-merged-docs/)について聞いたことがありません。

これを修正する私の最近の試みは、OpenXml-Power-Toolsの中で例外を投げているので、新しいリストIDでいくつかのセクションを更新していないと思います。誰もこれを行う方法を知っていますか?コードは以下の例外を除いて以下のように試みます。あなたは、各パスの間に2回同じAbstractNumId基準値を更新しているように見えます

System.InvalidOperationException: Sequence contains no elements 
at System.Linq.Enumerable.First[TSource](IEnumerable`1 source) 
at OpenXmlPowerTools.DocumentBuilder.CopyNumbering(WordprocessingDocument sourceDocument, WordprocessingDocument newDocument, IEnumerable1 newContent, List1 images) 
at OpenXmlPowerTools.DocumentBuilder.AppendDocument(WordprocessingDocument sourceDocument, WordprocessingDocument newDocument, List1 newContent, Boolean keepSection, String insertId, List1 images) 
at OpenXmlPowerTools.DocumentBuilder.BuildDocument(List`1 sources, WordprocessingDocument output) 
at OpenXmlPowerTools.DocumentBuilder.BuildDocument(List`1 sources, String fileName) 
at BereavementMailing.TemplateEngine.Merge(List`1 inputFiles, String outputFilePath) in C:\caw\Underdog\Apps\Services\BereavementMailingEngine\BM_RequestProcessor\TemplateEngine.cs:line 508 

答えて

1

public bool Merge(List<InterchangeableWordProcessingDocument> inputFiles, string outputFilePath) 
    { 
     if (inputFiles == null) 
     { 
      logger.LogDebug("No files to merge."); 
      return true; 
     } 
     try 
     { 

      List<OpenXmlPowerTools.Source> sources = new List<OpenXmlPowerTools.Source>(); 
      int highestListNumbering = 0; 
      int highestAbstractListNumbering = 0; 
      foreach (var inputFile in inputFiles) 
      { 
       //Sometimes merge puts start of next page onto end of previous one so prevent 
       //Seems to cause extra blank page when there are labels so don't do on labels pages 
       if (inputFile.DocType == DocType.Letter) 
       { 
        using (var wordDoc = inputFile.GetAsWordProcessingDocument()) 
        { 
         var para = wordDoc.MainDocumentPart.Document.Body.ChildElements.First<Paragraph>(); 

         if (para.ParagraphProperties == null) 
         { 
          para.ParagraphProperties = new ParagraphProperties(); 
         } 

         para.ParagraphProperties.PageBreakBefore = new PageBreakBefore(); 

         //http://ericwhite.com/blog/forums/topic/list-numbering-on-merged-docs/ 
         //Numberings should be unique to each page otherwise they continue from the previous 
         //Keep track of how many we have so we can add on to always have a unique number 
         var numIds = wordDoc.MainDocumentPart.Document.Body.Descendants<NumberingId>().ToList(); 

         logger.LogDebug("Found " + numIds.Count + " num ids."); 

         foreach (var numId in numIds) 
          numId.Val += highestListNumbering; 

         var styleNumIds = wordDoc.MainDocumentPart.StyleDefinitionsPart.RootElement.Descendants<NumberingId>().ToList(); 

         if (wordDoc.MainDocumentPart.StyleDefinitionsPart != null) 
         { 

          logger.LogDebug("Found " + styleNumIds.Count + " stlye num ids."); 
          foreach (var styleNumId in styleNumIds) 
           styleNumId.Val += highestListNumbering; 
         } 

         if (wordDoc.MainDocumentPart.NumberingDefinitionsPart != null) 
         { 

          var numberingNumIds = wordDoc.MainDocumentPart.NumberingDefinitionsPart.RootElement.Descendants<NumberingInstance>().ToList(); 

          logger.LogDebug("Found " + numberingNumIds.Count + " numbering num ids."); 
          foreach (var numberingNumId in numberingNumIds) 
          { 
           numberingNumId.NumberID += highestListNumbering; 
           numberingNumId.AbstractNumId.Val += highestAbstractListNumbering; 
          } 

          var abstractNumberingNumIds = wordDoc.MainDocumentPart.NumberingDefinitionsPart.RootElement.Descendants<AbstractNumId>().ToList(); 

          logger.LogDebug("Found " + abstractNumberingNumIds.Count + " abstract num ids." + wordDoc.MainDocumentPart.NumberingDefinitionsPart.RootElement.XName.LocalName); 
          foreach (var abstractNumberingNumId in abstractNumberingNumIds) 
           abstractNumberingNumId.Val += highestAbstractListNumbering; 

          //Keep the max nums up to date 
          if (abstractNumberingNumIds.Count > 0) 
           highestAbstractListNumbering = Math.Max(highestAbstractListNumbering, abstractNumberingNumIds.Max(ln => (ln.Val.HasValue ? ln.Val.Value : 0))); 

         } 


         if (numIds.Count > 0) 
          highestListNumbering = Math.Max(highestListNumbering, numIds.Max(ln => (ln.Val.HasValue ? ln.Val.Value : 0))); 



         wordDoc.MainDocumentPart.Document.Save(); 
        } 
       } 
       sources.Add(new OpenXmlPowerTools.Source(inputFile.GetAsWmlDocument(), true)); 

      } 
      DocumentBuilder.BuildDocument(sources, outputFilePath); 
      return true; 

     } 
     catch (SystemException ex) 
     { 
      logger.LogError("Error occured while generating bereavement letters. ", ex); 

      return false; 
     } 
     finally 
     { 
      foreach (var inputFile in inputFiles) 
      { 
       inputFile.Dispose(); 
      } 
     } 
    } 

例外。代わりに、AbstractNum定義ID値を更新する必要があります。あなたのNumberingPartのXMLで

基準値は、次のようになります。

<w:num w:numId="58"> 
     <w:abstractNumId w:val="2"/> 
    </w:num> 

、あなたは二回、それらを更新しています。

abstractNumberの定義は次のようになります。

<w:abstractNum w:abstractNumId="0" 
       w15:restartNumberingAfterBreak="0"> 
    <w:nsid w:val="FFFFFF88"/> 
    <w:multiLevelType w:val="singleLevel"/> 
    <w:tmpl w:val="8EE6963C"/> 
    <w:lvl w:ilvl="0"> 
     <w:start w:val="1"/> 
     <w:numFmt w:val="decimal"/> 
     <w:pStyle w:val="ListNumber"/> 
     <w:lvlText w:val="%1."/> 
     <w:lvlJc w:val="left"/> 
     <w:pPr> 
      <w:tabs> 
       <w:tab w:val="num" 
         w:pos="360"/> 
      </w:tabs> 
      <w:ind w:left="360" 
        w:hanging="360"/> 
     </w:pPr> 
    </w:lvl> 
</w:abstractNum> 

は、このセクションを変更してみてください:

オリジナル

var abstractNumberingNumIds = wordDoc.MainDocumentPart.NumberingDefinitionsPart.RootElement.Descendants<AbstractNumId>().ToList(); 

logger.LogDebug("Found " + abstractNumberingNumIds.Count + " abstract num ids." + wordDoc.MainDocumentPart.NumberingDefinitionsPart.RootElement.XName.LocalName); 
foreach (var abstractNumberingNumId in abstractNumberingNumIds) 
abstractNumberingNumId.Val += highestAbstractListNumbering; 

//Keep the max nums up to date 
if (abstractNumberingNumIds.Count > 0) 
    highestAbstractListNumbering = Math.Max(highestAbstractListNumbering, abstractNumberingNumIds.Max(ln => (ln.Val.HasValue ? ln.Val.Value : 0))); 

var abstractNums = wordDoc.MainDocumentPart.NumberingDefinitionsPart.RootElement.Descendants<AbstractNum>().ToList(); 

logger.LogDebug("Found " + abstractNums.Count + " abstract nums." + wordDoc.MainDocumentPart.NumberingDefinitionsPart.RootElement.XName.LocalName); 
foreach (var abstractNum in abstractNums) 
    abstractNum.AbstractNumberId += highestAbstractListNumbering; 

//Keep the max nums up to date 
if (abstractNums.Count > 0) 
    highestAbstractListNumbering = Math.Max(highestAbstractListNumbering, abstractNums.Select(a => a.AbstractNumberId).Max(n => n.HasValue ? n.Value : 0)); 
関連する問題