2012-05-01 19 views
2

MS OpenXml Sdkの使用テンプレートストリームをresultstreamにコピーし、本文の末尾にダイナミックテキスト(wp >> wr >> wt)を追加するには、次のコードを使用することができました:TextBoxのInnerTextの置換

var templateStream = File.OpenRead(templatePath); 
templateStream.CopyTo(resultStream); 

using (var resultPackage = WordprocessingDocument.Open(resultStream, true)) 
{ 
    var document = resultPackage.MainDocumentPart.Document; 

    var body = document.Body; 

    // Add new text. 
    var para = body.AppendChild(new Paragraph()); 
    var run = para.AppendChild(new Run()); 
    run.AppendChild(new Text(firstName)); 
    document.Save(); 
} 

私の次の論理的なステップは、resultStream内のテキストボックスのinnertextを、以下のコードのようにfirstNameに置き換えることでした。最初の例において、結果ストリームがDOCXに適切にシリアライズされ、Wordで見たときのfirstNameが本体の端部に付加されるいくつかの追加のコードで

// replacing code in using statement from above 
var document = resultPackage.MainDocumentPart.Document; 
var textbox = document.Descendants<TextBox>().First(); 
const string firstNametag = "<<IH.FirstName>>"; 
if (textbox.InnerText.Contains(firstNametag)) 
{ 
    var textboxContent = textbox.Elements<TextBoxContent>().First(); 
    textboxContent.RemoveAllChildren(); 
    var paragraph = textboxContent.AppendChild(new Paragraph()); 
    var run = paragraph.AppendChild(new Run()); 
    run.AppendChild(new Text(firstName)); 
} 
document.Save(); 

。 2番目の例では、デバッガでさらに検討した結果、textboxContentの子オブジェクトが上記の変更を反映していたとしても、テキストボックスとその内容は同じになりました。

私はOpenXML開発の初心者です。明らかなことがあれば、それを指摘してください。

答えて

4

ああ、私はこれの周りの全体の画像を理解していると思っていると思っていませんが、ここで簡単にそれを刺しています。 、

<w.r> 
    <mc.AlertnateContent> 
     <mc.Choice Requires="wps"> 
      <wps:txbx> 
       <w:txbxContent> 
        <w:r> 
         <w.t> 
          Text Goes Here 
         </w.t> 
        </w.r> 
       </w:txbxContent> 
      </wps:txbx> 
     </mc.Choice> 
     <mc.Fallback> 
      <v.textbox> 
       <w:txbxContent> 
        <w:r> 
         <w.t> 
          Text Goes Here 
         </w.t> 
        </w.r> 
       </w:txbxContent> 
      </v.textbox> 
     </mc.Fallback> 
    </mc.AlertnateContent> 
</w.r> 

お知らせmc.AlternateContent:より多くのOpenXMLの経験を持つ人は、Wordでテキストボックスを作成するときに

は、DOCX document.xmlファイルの取得には、次のマークアップだ上で判明...チャイムください。 mc.Choice、およびmc.Fallbackタグ。これらは一体何ですか?誰かがブログ記事でこのようにそれを置く私が出会った -

を「私はそれを理解したよう - しかし、福音として私の言葉を取ることはありません - がかかる場合AlternateContentは はどこにでも現れると強化 機能を含むためのメカニズムを提供することができますアプリケーションが対応できない場合は、 フォールバックと一緒に処理できます。 -Tony Jollans - 私の場合はhttp://social.msdn.microsoft.com/Forums/en-US/worddev/thread/f8a5c277-7049-48c2-a295-199d2914f4ba/

私はReSharperのを想定しているために、私の事故の(v.txbx wps.txbxない)代替テキストボックスを変更したが、右DocumentFormat.OpenXml.Vml名前空間をインポートするために私を求めていました私のTextBoxオブジェクトへの依存のために。私の既にインクルードされている名前空間、DocumentFormat.OpenXml.PackagingまたはDocumentFormat.OpenXml.Wordprocessingのいずれかにテキストボックス定義が存在しない理由はわかりませんが、それはこの質問の範囲を超えています。言うまでもなく、これを実現し、2つの共通のw.txbxContentを探すためにコードを更新すると、私は何をしたいのかを達成しました。

リファクタリングで更新されたコードを次に示します。元の質問のusingステートメントでReplaceTagメソッドを呼び出し、文字列ではなくモデルオブジェクトを指定します。また、便宜上、tagToValueSelector辞書を使用してください。

private void ReplaceTags(Document document, SomeModel model) 
{ 
    var textBoxContents = document.Descendants<TextBoxContent>().ToList(); 
    foreach (var textBoxContent in textBoxContents) 
    { 
     ReplaceTag(textBoxContent, model); 
    } 
} 

private void ReplaceTag(TextBoxContent textBoxContent, SomeModel model) 
{ 
    var tag = textBoxContent.InnerText.Trim(); 
    if (!tagsTomValues.ContainsKey(tag)) return; 
    var valueSelector = tagsTomValues[tag]; 
    textBoxContent.RemoveAllChildren(); 
    var paragraph = textBoxContent.AppendChild(new Paragraph()); 
    var run = paragraph.AppendChild(new Run()); 
    run.AppendChild(new Text(valueSelector(model))); 
} 

// called in the ctor 
private static void IntializeTags(IDictionary<string, Func<SomeModel, string>> dictionary) 
{ 
    dictionary.Add("<<IH.Name>>", m => string.Format("{0} {1}", m.FirstName, m.LastName)); 
} 

ハッピーopenXmling :)

関連する問題