SharePoint下利用DocX組件導出Word


平常開發時,或多或少都需要和Word打交道,特變是編輯、導出Word。

利用DocX,開源的讀寫Word組件,可以快速幫助我們進行對Word的操作。

DocX官方網站:http://docx.codeplex.com/

DocX主要功能

  • 在文檔中(Word)插入,刪除或者替換文本,支持所有的標准文本格式,如字體{Family,Size,Color},出體,斜體、下划線、高亮等。
  • 提供段落屬性,你可以設置其對其方向,如從左到右,居中對齊等。
  • DocX同樣支持對圖片的操作、超鏈接、表格、頁首、頁眉等。
  • 最重要的一點DocX支持自定義文檔屬性(Custom Properties)

最近要對一個SharePoint項目進行修改,客戶希望對上報的文檔審批結束后(如下圖),可以導出Word,方便打印。對於OA系統而言,這是很重要的功能,客戶催着急,所以需要快速開發。

創建文檔屬性

DocX支持Load一個事先預定好的模版,通過對模版的修改即可創建出新的DocX類型對象,直接調用DocX.SaveAs方法即可對其進行保存到指定路徑,當然你也可以保存到一個內存流中。具體的強大功能,可以參考DocX提供Example,寫的非常詳細。

廢話少說,我們開始吧。Word2010(07不確定,沒用過)以上版本支持文檔屬性(Document Propery),文檔屬性對開發者來講是一個非常重要的功能,你可以擴展Word文檔的屬性,我以Word 2013為例,打開Word 2013,單擊左上角的文件,在新彈出的頁面,選擇屬性à高級屬性,如下所示:

接着,新建文檔屬性,注意取一個合適的名稱,別與已存在的屬性重名,對於上圖介紹的投訴審批,你可以新建以下文檔屬性:

 

 

當創建完畢后,插入文檔屬性:切換到插入Tab,找到文檔部件,單擊文檔部件選擇域,再彈出的新窗體中,在左邊域名選擇DocProperty,在右邊找到需要插入的屬性插入到相應位置即可:

這樣可以快速創建一個標准模版,如下圖。接下來的工作就是很簡單了,依次在這幾個“坑”中填充內容即可:

DocX邏輯實現

  • ComplaintModel屬性的創建

首先我們約定,屬性值不能包含換行(\r\n),否則插入含有換行符的屬性值文本會和預想的有問題,那我們怎樣去避免這個情況呢?很簡單,假設某個屬性的屬性值包含換行符,我們不將其作為屬性加入文檔屬性,而是直接Replace掉[]。有了這個約定后,我們接着創建我們對象(ComplainModel)的屬性(注意,ComplainModel類型對象的屬性必須要合之前創建的文檔屬性名稱相同,原因稍后解釋)

public class ComplainModel
        {
            //標題
            public string CTitle { get; set; }
            //投訴人
            public string Complainer { get; set; }
            //聯系電話
            public string Mobile { get; set; }
            //分類
            public string Sort { get; set; }
            //投訴內容
            public string Complain { get; set; }
            //街道
            public string Stretch { get; set; }
            //備注
            public string Remark { get; set; }
            //一級審批者
            public string FirstApprover { get; set; }
            //一級審批內容
            public string FirstApproveText { get; set; }
            //二級審批者
            public string SecondApprover { get; set; }
            //二級審批內容
            public string SecondApproveText { get; set; }
            //三級審批者
            public string ThirdApprover { get; set; }
            //三級審批內容
            public string ThirdApproveText { get; set; }
        }
  • 接下來就是核心步驟了,我們Load預先定義好的Template(如果拋出異常,請加上EveryOne權限,然后去掉只讀)。
DocX gDocument = DocX.Load(@"C:\Users\Administrator\Desktop\投訴審批表.docx");
  • 初始化ComplainModel
//創建CustomProperty對象
                        ComplainModel complainModel = new ComplainModel();
                        complainModel.CTitle = newItem["Title"].ToString();
                        complainModel.Complainer = newItem["Complainter"].ToString();
                        complainModel.Mobile = newItem["Tel"].ToString();
                        complainModel.Sort = newItem["ComplaintType"].ToString();
                        complainModel.Complain = newItem["ComplaintContent"].ToString();
                        complainModel.Stretch = newItem["RoadSelect"].ToString();
                        complainModel.Remark = newItem["Remark"].ToString();

                        //審批意見
                        complainModel.FirstApprover = newItem["FirstApprover"].ToString();
                        complainModel.FirstApproveText = newItem["FirstApproverText"].ToString();
                        complainModel.SecondApprover = newItem["SecondApprover"].ToString();
                        complainModel.SecondApproveText = newItem["SecondApproverText"].ToString();
                        complainModel.ThirdApprover = newItem["ThirdApprover"].ToString();
                        //還沒持久化到數據庫,所以直接 txtLevelThreeSuggestion.Text
                        complainModel.ThirdApproveText = txtLevelThreeSuggestion.Text;
  • 定義DocXHelper,他提供反射機制,給Load Template創建的新DocX對象添加文檔屬性
public static class DocXHelper
    {
        public static void AddCustomProperty<T>(this DocX docx, T source)
        { 
            Type type=typeof(T);
            //反射得到指定類型所有的非靜態公開屬性
            PropertyInfo[] props = type.GetProperties(BindingFlags.Instance|BindingFlags.Public);
            foreach (var prop in props)
            {
                //得到指定對象屬性值
                var value = string.Format("{0}",prop.GetValue(source,null));
                //如果包含\r\n,直接無視,不加入文檔屬性中,而是直接Replace
                if (!value.Contains(Environment.NewLine))
                {
                    CustomProperty customProperty = new CustomProperty(prop.Name, value);
                    docx.AddCustomProperty(customProperty);
                    continue;
                }
                //把[]替換成指定屬性值
                docx.ReplaceText(string.Format("[{0}]",prop.Name),value);
            }
        
        }

正如前面所說的那樣,必須文檔屬性和ComplainModel對象屬性名稱一樣,原因在於docx.AddCustomProperty方法內部(DocX組件是開源的,可以查看AddCustomPropery的實現),幫我們做了如下步驟:首先判斷文檔屬性是否存在,如果是,刪除它(Remove),之后創建一個新的文檔屬性(注意名稱是相同的哦,否則會出現錯誤!未知的文檔屬性名稱,具體可以拿個Word手動刪除文檔屬性后,更新域),最后Update更新域,這樣屬性值就同步到了文檔屬性插入的相應位置了。

  • 全部代碼如下
//創建投訴審批docx文檔,以附件形式附加到Attachment欄
                    DocX gDocument;
                    try
                    {
                        gDocument = DocX.Load(@"C:\Users\Administrator\Desktop\武林管委會\投訴審批表.docx");
                        //創建CustomProperty對象
                        ComplainModel complainModel = new ComplainModel();
                        complainModel.CTitle = newItem["Title"].ToString();
                        complainModel.Complainer = newItem["Complainter"].ToString();
                        complainModel.Mobile = newItem["Tel"].ToString();
                        complainModel.Sort = newItem["ComplaintType"].ToString();
                        complainModel.Complain = newItem["ComplaintContent"].ToString();
                        complainModel.Stretch = newItem["RoadSelect"].ToString();
                        complainModel.Remark = newItem["Remark"].ToString();

                        //審批意見
                        complainModel.FirstApprover = newItem["FirstApprover"].ToString();
                        complainModel.FirstApproveText = newItem["FirstApproverText"].ToString();
                        complainModel.SecondApprover = newItem["SecondApprover"].ToString();
                        complainModel.SecondApproveText = newItem["SecondApproverText"].ToString();
                        complainModel.ThirdApprover = newItem["ThirdApprover"].ToString();
                        //還沒持久化到數據庫,所以直接 txtLevelThreeSuggestion.Text
                        complainModel.ThirdApproveText = txtLevelThreeSuggestion.Text;
                        //給docx文檔添加CustomProperty對象
                        gDocument.AddCustomProperty<ComplainModel>(complainModel);

                        //從模版里取出的Docx文件另存為以流的形式
                        var stream = new System.IO.MemoryStream();
                        gDocument.SaveAs(stream);
                        //設置stream的位置為0
                        stream.Position = 0;
                        
                        //將得到的流附加到SharePoint List Attachment欄上
                        newItem.Attachments.Add("投訴審批表_導出打印.docx",stream.ReadFully());
                        //最后Update,執行工作流,執行審批歸檔
                        newItem.Update();
                        
                    }
                    catch (Exception ex)
                    {
                        
                      //如果模版文檔不存在,或者List Attachment中忘記設置了,那么什么也不發生,也就是沒有生成可以導出的文檔,不影響整個審批過程。
                    }

查看生成的審批附件

在審批結束歸檔后,即可在附件欄查看到他,相關領導即可下載打印。

  • 導出查看Word

總結

DocX是一個非常方便的輕量級開源組件,可以方便操作Word,更強大的功能可以查看DocX Codeplex官網Example,更強大的功能等着你去探索。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM