1. 程式人生 > >使用Asponse.Words處理Word模板

使用Asponse.Words處理Word模板

  一.客戶需求

    近期接到一個專案,在與客戶初步溝通後,客戶描述的需求聽起來也非常簡單,就是目前客戶需要在Excel錄入資料,然後把這些資料分別複製到多個Word的多個地方,除了單個值之外,還需要複製表格資料以及圖片資料,客戶覺得這麼操作一是容易出錯,二是重複操作的工作量太大。在初步瞭解使用者的需求之後,得知客戶需求的核心功能就是在Word中填充資料來源,需要填充資料的資料來源包括文字,表格以及圖片等,本文以此為出發點,重點介紹如何在Word中使用“域”來填充外部資料。

  二.外掛選型

    目前處理Word等Office文件型別的控制元件,微軟自帶的Com元件問題實在太多,一個比較麻煩的問題就是部分Com元件需要註冊,並且如果客戶端與開發電腦使用的Com元件版本不一致,還會出現各種問題,因此選擇了Asponse.words外掛,該軟體為收費外掛,具體的收費標準可以在官網進行檢視。

  三.模板製作

    利用Asponse進行資料填充,其實程式碼不難,核心的工作就是需要在Word模板中設定標記,也就是需要讓程式知道在什麼地方填充資料,目前做標記的方式有兩種,一種是使用書籤,一種是使用域。目前網上大多的案例都是使用書籤,但是在我實際開發的過程中,建議大家使用“域”,而不是使用書籤,原因有以下幾點:

    1.書籤不能重複新增,比如我在第一個空白出需要插入資料來源“姓名”,在最後簽名處還要插入“姓名”,這個時候使用“域”的話可以在兩處都插入“姓名”域,但是如果使用書籤,需要設定不同的書籤名稱,生成資料來源的時候會增加工作量

    2.書籤不能在文件中直觀的展示出來,如果插入書籤比較多,很容易造成混亂

    此外,需要特別說明的是,製作書籤或者“域"的時候務必務必使用Word而不是WPS製作,因為目前發現的一個問題就是,使用WPS製作的書籤或者是”域“,在填充資料之後會自動增加一行空行,這個可能是WPS與Word的內部機制不同;還有一個技巧,在文件中使用Alt+F9,可以檢視到模板的各種域程式碼,如下圖所示:

    

  四.插入書籤/域

    1.插入書籤    

    

    2.插入域(插入->文件部件->域,選擇"MergeField")

    

     

  五.實現程式碼

    1.獲取文件

            Aspose.Words.Document doc = new Aspose.Words.Document(filePath);
            Aspose.Words.DocumentBuilder builder = new Aspose.Words.DocumentBuilder(doc);

    2.利用word模板填充資料

       List<string> filedsValueList = new List<string>();
      string[] filedsName =doc.MailMerge.GetFieldNames();//獲取文件中所有的域
            for (int i = 0; i < filedsName.Length; i++)
            {              
                if (dataTable.Columns.Contains(filedsName[i]))
                {
                    filedsValueList.Add(dataTable.Rows[0][filedsName[i]].ToString());

                }
                else
                {
                    filedsValueList.Add("");
                }
            }
       //核心程式碼其實就是這一句,上面的都是組織資料來源
       //引數是兩個陣列,第一個陣列是文件中所有”域“的名稱,第二個是所對應域的值 doc.MailMerge.Execute(filedsName, filedsValueList.ToArray());

    3.插入圖片

    插入圖片並不需要特殊的程式碼,而是需要對Word模板中的域做特殊設定,設定的方式為:

    

    在彈出來的對話方塊中,把”域“名稱的前面加上"Image:",如下圖所示:

    

     設定好之後,只需要將該域的值設定為圖片的路徑,即可在文件中展示圖片,如果需要在程式碼中控制圖片的大小,需要給文件繫結圖片處理的回撥事件,程式碼如下:

doc.MailMerge.FieldMergingCallback = new HandleMerFieldInsert();

    4.設定圖片尺寸

    在Asponse直接提供的方法中,沒有修改圖片尺寸的方法,但是可以重寫Asponse的IFieldMergingCallback類,用於設定圖片大小    

 class HandleMerFieldInsert : IFieldMergingCallback
    {
        //文字處理
        void IFieldMergingCallback.FieldMerging(FieldMergingArgs e)
        {

        }
        //圖片處理
        void IFieldMergingCallback.ImageFieldMerging(ImageFieldMergingArgs args)
        {
            Document doc = args.Document;
            DocumentBuilder builder = new DocumentBuilder(doc);
            builder.MoveToMergeField(args.FieldName);

             Shape shapeImage = builder.InsertImage(args.FieldValue.ToString());
                   //設定x,y座標和高寬.
                    shapeImage .Left = 0;
                    shapeImage .Top = 0;
                    shapeImage .Width = 50;
                    shapeImage .Height = 25;                                        
        }

    }

    5.填充表格

    填充表格資料,需要在模板中先設定表格繫結資料的起始位置,然後在每一列中設定資料來源中的列名稱,具體步驟如下圖:

    

    表格資料來源的起始標記為”TableStart“,結束標記為"TableEnd",設定好表格資料來源的起始與結束標記之後,再在每一列中單獨設定每一列需要繫結的欄位名稱即可,設定好的資料來源如下圖所示:

    

    通過Alt+F9可以看到設定好的各種域的程式碼,如下圖所示:

    

    設定好表格的各個域之後,通過如下程式碼完成對資料來源的填充:

dt.TableName = "UserInfo";//這裡的表格名稱必須和模板中表格的起始與結束源名稱相同
doc.MailMerge.ExecuteWithRegions(dt);

    6.刪除表格及對應的佔位符

     使用Asponse進行刪除的操作相對比較複雜,現有的業務是需要刪除模板中的某一個表格,但有個問題就是,在刪除了該表格之後,該表格所在頁面的佔位符還在,會導致生成的文件有一個空白頁,因此在刪除類似表格,圖片這種元素時,還需要刪除對應的段落佔位符

 NodeCollection nodeCollection = doc.GetChildNodes(NodeType.Table, true);//獲取所有表格

                    foreach (Table table in nodeCollection)
                    {
                        if (table.GetText().Contains("AAAAAA") && table.GetText().Contains("BBBBBB"))//To Do:這裡通過獲取表格中的內容來判定是否為刪除的表格,應該還有更好的辦法
                        {
                            Paragraph paragraph = (Paragraph)table.PreviousSibling;
                            paragraph.Remove();//刪除段落
                            table.Remove();//刪除表格
                        }
                    }

    7.儲存帶密碼的PDF    

   Aspose.Words.Saving.PdfSaveOptions saveOption = new Aspose.Words.Saving.PdfSaveOptions();
            saveOption.SaveFormat = Aspose.Words.SaveFormat.Pdf;
            PdfEncryptionDetails encryptionDetails = new PdfEncryptionDetails(pdfPwd, string.Empty, PdfEncryptionAlgorithm.RC4_128);
            encryptionDetails.Permissions = PdfPermissions.AllowAll;
            saveOption.EncryptionDetails = encryptionDetails;
            doc.Save(fullfilepath + ".pdf", saveOption);

    8.刪除未被賦值的“域”

doc.MailMerge.DeleteFields();

  寫在最後

      至此,Asponse利用模板處理資料的常規方法總結完畢,對於直接使用Asponse的方法,在Word中通過硬編碼的方式增加表格建議不到萬不得已不要使用,因為增加表格需要控制表格本身的樣式,還需要控制單元格的樣式,並且對於複雜的文件,定位表格也會增加難度。