2016-07-25 6 views
0

私はテキストをある値で置き換えようとしている文書に約1MERGEFIELDを持っています。ここにコードがあります。Openxml C#で段落内の最初のMERGEFIELDのみを更新します。

using (WordprocessingDocument document = WordprocessingDocument.Open(destinationFileName, true)) 
      { 
       document.ChangeDocumentType(DocumentFormat.OpenXml.WordprocessingDocumentType.Document); 
       MainDocumentPart docPart = document.MainDocumentPart; 
       docPart.AddExternalRelationship("http://schemas.openxmlformats.org/officeDocument/2006/relationships/attachedTemplate", new Uri(destinationFileName, UriKind.RelativeOrAbsolute)); 
       docPart.Document.Save(); 

       IEnumerable<FieldChar> fldChars = document.MainDocumentPart.RootElement.Descendants<FieldChar>(); 
       if (fldChars == null) { return; } 

       string fieldList = string.Empty; 
       FieldChar fldCharStart = null; 
       FieldChar fldCharEnd = null; 
       FieldChar fldCharSep = null; 
       FieldCode fldCode = null; 
       string fldContent = String.Empty; 
       int i = 1; 
       foreach(var fldChar in fldChars) 
       { 

        System.Diagnostics.Debug.WriteLine(i + ": " + fldChar); 
        i++; 

        string fldCharPart = fldChar.FieldCharType.ToString(); 
        System.Diagnostics.Debug.WriteLine("Field Char Length: " + fldChar.Count()); 
        System.Diagnostics.Debug.WriteLine("Field Char part: " + fldCharPart); 

        switch(fldCharPart) 
        {  
         case "begin": // start of the field 
          fldCharStart = fldChar; 
          System.Diagnostics.Debug.WriteLine("Field Char Start: " + fldCharStart); 
          // get the field code, which will be an instrText element 
          // either as sibling or as a child of the parent sibling 

          fldCode = fldCharStart.Parent.Descendants<FieldCode>().FirstOrDefault(); 
          System.Diagnostics.Debug.WriteLine("Field Code: " + fldCode); 

          if (fldCode == null) 
          { 
           fldCode = fldCharStart.Parent.NextSibling<Run>().Descendants<FieldCode>().FirstOrDefault(); 
           System.Diagnostics.Debug.WriteLine("New Field Code: " + fldCode); 
          } 

          if (fldCode != null && fldCode.InnerText.Contains("MERGEFIELD")) 
          { 
           fldContent = getFieldValue(query, prescriber, fldCode.InnerText); 
           fieldList += fldContent + "\n"; 
           System.Diagnostics.Debug.WriteLine("Field content: " + fldContent); 

          } 
          break; 

         case "end": // end of the field 
          fldCharEnd = fldChar; 
          System.Diagnostics.Debug.WriteLine("Field char end: " + fldCharEnd); 
          break; 

         case "separate": // complex field with text result 
          fldCharSep = fldChar; 
          break; 

         default: 
          break; 

        } 

        if((fldCharStart != null) && (fldCharEnd != null)) 
        { 
         if(fldCharSep != null) 
         { 
          Text elemText = (Text)fldCharSep.Parent.NextSibling().Descendants<Text>().FirstOrDefault(); 
          elemText.Text = fldContent; 
          System.Diagnostics.Debug.WriteLine("Element text: " + elemText); 

          // Delete all field chas with their runs 
          DeleteFieldChar(fldCharStart); 
          DeleteFieldChar(fldCharEnd); 
          DeleteFieldChar(fldCharSep); 
          fldCode.Remove(); 
         } 
         else 
         { 
          Text elemText = new Text(fldContent); 
          fldCode.Parent.Append(elemText); 
          fldCode.Remove(); 
          System.Diagnostics.Debug.WriteLine("Element Text !sep: " + elemText); 

          DeleteFieldChar(fldCharStart); 
          DeleteFieldChar(fldCharEnd); 
          DeleteFieldChar(fldCharSep); 
         } 

         fldCharStart = null; 
         fldCharEnd = null; 
         fldCharSep = null; 
         fldCode = null; 
         fldContent = string.Empty; 
        } 
       } 
       System.Diagnostics.Debug.WriteLine("Field list: " + fieldList); 
      } 

これはある程度機能します。問題は、段落に複数のフィールドがある場合です。私はこの文書では1つの段落に約4つのマージフィールドがあり、それ以降は各段落に1つのフィールドがあります。段落内の最初のマージフィールドのみが更新され、段落内の残りのフィールドは変更されません。次に、次の段落に移動し、フィールドを探します。これをどうすれば解決できますか?

答えて

2

単純なMailmergeの置き換えが複雑すぎるようです。段落をループするのではなく、ドキュメント内のすべての差し込み印刷フィールドを取得して置き換えることができます。

private const string FieldDelimeter = " MERGEFIELD "; 

    foreach (FieldCode field in doc.MainDocumentPart.RootElement.Descendants<FieldCode>()) 
    { 
     var fieldNameStart = field.Text.LastIndexOf(FieldDelimeter, System.StringComparison.Ordinal); 
     var fieldName = field.Text.Substring(fieldNameStart + FieldDelimeter.Length).Trim(); 

     foreach (Run run in doc.MainDocumentPart.Document.Descendants<Run>()) 
     { 
       foreach (Text txtFromRun in run.Descendants<Text>().Where(a => a.Text == "«" + fieldName + "»")) 
       {        
        txtFromRun.Text = "Replace what the merge field here"; 
       } 
     } 
    } 


    doc.MainDocumentPart.Document.Save(); 

docはWordprocessingDocument型です。

これは、段落内のフィールドの量に関係なく、すべてのマージフィールドを置き換えます。

+0

これは機能しませんでした。フィールドを値に置き換えません。 fieldNameは鉱山で 'fieldName \ * MERGEFORMAT'と表示されますが、それは何か関係がありますか?しかし、 "<<" + fieldName + ">>"を '\ * MERGEFORMAT'に置き換えたとしても、それはまだ2番目のforeachループには入りません。助言がありますか? – user1828605

+0

これは正解です。私はフィールド名を抽出する間に間違いを犯しました。私はTrim()をやっていないので、フィールド名の後ろにスペースがあってテキストと一致しませんでした。 Trim()とDebuggingを実行した後でさえ、トリムされたデータに対して部分文字列をやり直してしまったので、私はまだエラーが発生していました。それは今働いている。私にそれを行う方法を教えてくれてありがとう。私は今それをよく理解しているように感じる。 – user1828605

+0

MERGEFIELDの "fldSimple"はどのように処理できますか? MERGEFIELDを使用してハイパーリンクが生成されるケースがあります。 – par

関連する問題