以前一直是用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 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Linq; 5 using System.Text; 6 using System.Threading.Tasks; 7 8 namespace WordHelper.TestModel 9 { 10 /// <summary> 11 /// 抽样记录单 12 /// </summary> 13 public class SamplingRcd 14 { 15 [Description("记录单编号")] 16 public string No { get; set; } 17 18 [Description("年")] 19 public int Year { get; set; } 20 21 [Description("月")] 22 public int Month { get; set; } 23 24 [Description("日")] 25 public int Day { get; set; } 26 27 [Description("药品名称")] 28 public string DrugName { get; set; } 29 30 [Description("商品名")] 31 public string GoodsName { get; set; } 32 33 [Description("注册证号")] 34 public string RegistNo { get; set; } 35 36 [Description("检验通知号")] 37 public string NoticeNo { get; set; } 38 39 [Description("外包装是否完整")] 40 public bool IsIntact { get; set; } 41 42 [Description("是否封固")] 43 public bool IsFixed { get; set; } 44 45 [Description("铅封")] 46 public bool IsPb { get; set; } 47 } 48 }
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如何实现类似功能的,望告知下!先谢谢了!^_^)