2010-11-02 87 views
4

爲了根據來自SQL數據庫的數據創建Word文檔,我使用Office Open XML SDK來避免使用interop。這加快了這一過程,並且消除了客戶端系統上安裝的Microsoft Office套件的需求。Office Open XML SDK字替換

雖然這很有效,但在替換文檔中的某些文本時出現問題。爲了保持最終文檔的自定義選項,我創建了一個包含一些標籤的文檔作爲模板。該模板包含標籤,如[TagHere]。由於標籤名稱應該易於閱讀,因此可以在整個文檔中使用它們,這就是爲什麼我用大括號[]包圍標籤。

這很有效,但有時會出現問題。當你輸入一個docx文檔時,文本可以分成多個標籤,即使是在同一個單詞中。像[TagHere]標籤可以被分成

<tag>[</tag><tag>TagHere</tag><tag>]</tag>

發生這種情況時,更換將無法正常工作。

現在docx格式有一些替代選項可以執行此類操作,例如內容控件,但這些操作會使創建模板的過程更加複雜。更進一步,在這些文檔中獲取帶有標籤的表格的一行並複製多次,這可能會破壞內容標籤原理並不少見。因此我選擇不使用這個選項。

如果有人解決了這個問題,那將會很棒。

+0

如果你使這些東西成爲代碼部分,則不需要更換釣魚鉤(=尖括號?):選擇文本並單擊「101010」按鈕。 – LarsH 2010-11-02 09:32:01

+0

Thansk的評論,每天學習:) – 2010-11-02 11:15:50

回答

4

不是輸入純文本「taghere」,而是插入合併域。 (在word中,單擊插入>快速部分>字段,選擇「合併字段」並在「字段名稱」字段中鍵入「TagHere」。)

然後代替執行文本查找替換,並設置內部文本。

class Program 
{ 
    static void Main(string[] args) 
    { 
     string document = args[0]; 
     using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(document, true)) 
     { 
      Dictionary<string, string> replaceOperations = new Dictionary<string, string>(); 

      replaceOperations.Add("company", "alex's applications"); 
      replaceOperations.Add("first_name", "alexander"); 
      replaceOperations.Add("last_name", "taylor"); 
      //etc 

      Replace(wordDoc, replaceOperations); 
     } 
    } 

    public static char[] splitChar = new char[] {' '}; 
    public static void Replace(WordprocessingDocument document, Dictionary<string, string> replaceOperations) 
    { 
     //find all the fields 
     foreach (var field in document.MainDocumentPart.Document.Body.Descendants<SimpleField>()) 
     { 
      //parse the instruction 
      string[] instruction = field.Instruction.Value.Split(splitChar, StringSplitOptions.RemoveEmptyEntries); 

      //check if it's a merge field, and if so... 
      if (instruction[0].ToLower().Equals("mergefield")) 
      { 
       //get the field name 
       string fieldname = instruction[1]; 

       //find the text inside (there will only be one) 
       foreach (var fieldtext in field.Descendants<Text>()) 
       { 
        //see if we know what to set this value to 
        string value = replaceOperations.ContainsKey(fieldname) ? replaceOperations[fieldname] : null; 

        //if we found the replace value, set the text to this value 
        if (value != null) 
         fieldtext.Text = value; 

        //should only be one text inside 
        break; 
       } 
      } 
     } 
    } 
} 
+0

謝謝你的回覆,這個作品! – 2011-08-08 07:27:49

+1

我在嘗試類似的東西,但問題是合併字段並不總是表示爲'SimpleField',有時候它們是與FieldChar相關的'FieldCode'。 – 2014-02-25 19:10:49

相關問題