使用Spire.Doc組件利用模板導出Word文檔
以前一直是用Office的組件實現Word文檔導出,但是讓客戶在服務器安裝Office,涉及到版權;而且Office安裝,包括權限配置也是比較麻煩。
現在流行使用第三方組件來實現對Office的操作,有NPOI,Spire等第三方組件。開始考慮的是NPOI,畢竟它在操作Excel方面還是很強大的;但是不知道是它本身沒有,還是我沒找到,無法實現利用Word模板的標簽插入內容,純靠代碼去生成Word文檔,排版是個大問題。最終找到了Spire.Doc組件,輕松實現!
Spire的官網地址:https://www.e-iceblue.com/
1、項目中引用 Free Spire.Doc 組件,我是直接用NuGet下載包的.

安裝完后,會引用其三個組件:

2、Word 模板制作
打開Word,點擊 文件->選項->自定義功能區,勾選上“開發工具”:

主要使用文本域控件,插入作為標簽:

如果有需要,可以添加“下划線”,或者“字符邊框”等效果:

底下三個,前2個我用的是開發工具中的復選框(窗體控件)效果不是勾選的,是×號,效果不是客戶想要的,所以使用了第二種解決方案“字符邊框”,最后看導出的效果:

3、代碼
可重用代碼:
1 using Spire.Doc;
2 using Spire.Doc.Documents;
3 using Spire.Doc.Fields;
4 using System;
5 using System.Collections.Generic;
6 using System.ComponentModel;
7 using System.IO;
8 using System.Linq;
9 using System.Text;
10 using System.Threading.Tasks;
11
12 namespace We.Framework.Spire
13 {
14 /// <summary>
15 /// Sprie.Doc
16 /// Designed by XIAO
17 /// 2017-05-09
18 /// </summary>
19 public class WordHandler
20 {
21 public static bool ExportWordByFields<T>(T mod, string TempleteFilePath, string ExpFilePath)
22 {
23 if (mod == null)
24 {
25 throw new Exception("模型為空!");
26 }
27
28 System.Reflection.PropertyInfo[] properties = mod.GetType().GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
29 if (properties.Length <= 0)
30 {
31 throw new Exception("模型屬性為空!");
32 }
33
34 if (!File.Exists(TempleteFilePath))
35 {
36 throw new Exception("指定路徑的模板文件不存在!");
37 }
38
39 try
40 {
41 Document doc = new Document();
42 doc.LoadFromFile(TempleteFilePath);
43
44 #region 替換文字
45 //doc.Replace("海關", "海關口岸", true, true);
46 //doc.Replace("報驗", "報檢", true, true);
47 #endregion
48
49 //清除表單域陰影
50 doc.Properties.FormFieldShading = false;
51
52 //遍歷Word模板中的文本域(field.name為文本域名稱)
53 foreach (FormField field in doc.Sections[0].Body.FormFields)
54 {
55 foreach (System.Reflection.PropertyInfo prop in properties)
56 {
57 string name = prop.Name; //屬性名稱
58 object value = prop.GetValue(mod, null); //屬性值
59 string des = ((DescriptionAttribute)Attribute.GetCustomAttribute(prop, typeof(DescriptionAttribute))).Description;// 屬性描述值
60
61 //注意:文本域名稱 == 模型中屬性的 Description 值 !!!!!!
62 //也可以: 文本域名稱 == 模型中屬性的 Name 值 !!!!!!
63 if (field.Name == des)
64 {
65 if (field.DocumentObjectType == DocumentObjectType.TextFormField) //文本域
66 {
67 if (prop.PropertyType.Name == "Boolean")
68 {
69 field.Text = "√"; //插入勾選符號
70 break;
71 }
72 else
73 {
74 field.Text = value.ToString(); //向Word模板中插入值
75 break;
76 }
77 }
78 else if (field.DocumentObjectType == DocumentObjectType.CheckBox) //復選框
79 {
80 (field as CheckBoxFormField).Checked = (value as bool?).HasValue ? (value as bool?).Value : false;
81 }
82 }
83 }
84 }
85
86 doc.SaveToFile(ExpFilePath, FileFormat.Docx);
87 doc.Close();
88
89 return true;
90 }
91 catch (Exception ex)
92 {
93 string msg = ex.Message;
94
95 return false;
96 }
97 }
98 }
99 }
測試代碼部分:
數據模型
1 private void button1_Click(object sender, EventArgs e)
2 {
3 SamplingRcd mod = new SamplingRcd();
4 mod.No = "No158922144";
5 mod.Year = 2017;
6 mod.Month = 5;
7 mod.Day = 8;
8 mod.DrugName = "門冬胰島素50注射液";
9 mod.GoodsName = "康胰素";
10 mod.RegistNo = "R12324552";
11 mod.NoticeNo = "N12324552";
12 mod.IsIntact = true;
13 mod.IsFixed = true;
14 mod.IsPb = true;
15
16 System.IO.Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory);
17 string templeteFileName = @"..\..\WordTemplete\進口葯品抽樣記錄單.docx";
18 string newFileName = string.Format("H:\\Exp_進口葯品抽樣記錄單_{0}.docx", DateTime.Now.ToString("yyyyMMddHHmmss"));
19
20 bool result = WordHandler.ExportWordByFields<SamplingRcd>(mod, templeteFileName, newFileName);
21 if (result)
22 {
23 MessageBox.Show("成功");
24 }
25 else
26 {
27 MessageBox.Show("失敗");
28 }
29 }
基本功能已經實現,還有待改進,希望各位提出寶貴意見!
(PS:如果有朋友知道NPOI如何實現類似功能的,望告知下!先謝謝了!^_^)

