NPOI导出Word文档(读取数据渲染原有模板)
因为使用到了NPOI导出,所以在网上找了个方法,收藏在这里,以作记录(侵权联系删除)
原博客园地址:https://www.cnblogs.com/jomzhang/p/9555397.html
工具类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | /// <summary> /// 作者:jomz /// </summary> public class NpoiHeplper { /// <summary> /// 输出模板docx文档(使用字典) /// </summary> /// <param name="tempFilePath">docx文件路径</param> /// <param name="outPath">输出文件路径</param> /// <param name="data">字典数据源</param> public static void Export( string tempFilePath, string outPath,Dictionary< string , string > data) { using (FileStream stream = File.OpenRead(tempFilePath)) { XWPFDocument doc = new XWPFDocument(stream); //遍历段落 foreach ( var para in doc.Paragraphs) { ReplaceKey(para, data); } //遍历表格 foreach ( var table in doc.Tables) { foreach ( var row in table.Rows) { foreach ( var cell in row.GetTableCells()) { foreach ( var para in cell.Paragraphs) { ReplaceKey(para, data); } } } } //写文件 FileStream outFile = new FileStream(outPath, FileMode.Create); doc.Write(outFile); outFile.Close(); } } private static void ReplaceKey(XWPFParagraph para, Dictionary< string , string > data) { string text = "" ; foreach ( var run in para.Runs) { text = run.ToString(); foreach ( var key in data.Keys) { //$$模板中数据占位符为$KEY$ if (text.Contains($ "${key}$" )) { text = text.Replace($ "${key}$" , data[key]); } } run.SetText(text, 0); } } /// <summary> /// 输出模板docx文档(使用反射) /// </summary> /// <param name="tempFilePath">docx文件路径</param> /// <param name="outPath">输出文件路径</param> /// <param name="data">对象数据源</param> public static void ExportObjet( string tempFilePath, string outPath, object data) { using (FileStream stream = File.OpenRead(tempFilePath)) { XWPFDocument doc = new XWPFDocument(stream); //遍历段落 foreach ( var para in doc.Paragraphs) { ReplaceKeyObjet(para, data); } //遍历表格 foreach ( var table in doc.Tables) { foreach ( var row in table.Rows) { foreach ( var cell in row.GetTableCells()) { foreach ( var para in cell.Paragraphs) { ReplaceKeyObjet(para, data); } } } } //写文件 FileStream outFile = new FileStream(outPath, FileMode.Create); doc.Write(outFile); outFile.Close(); } } private static void ReplaceKeyObjet(XWPFParagraph para, object model) { string text = "" ; Type t = model.GetType(); PropertyInfo[] pi = t.GetProperties(); foreach ( var run in para.Runs) { text = run.ToString(); foreach (PropertyInfo p in pi) { //$$模板中数据占位符为$KEY$ string key = $ "${p.Name}$" ; if (text.Contains(key)) { try { text = text.Replace(key, p.GetValue(model, null ).ToString()); } catch (Exception ex) { //可能有空指针异常 text = text.Replace(key, "" ); } } } run.SetText(text, 0); } } } |
使用介绍,本工具类可根据字典数据源或者对象数据源导出标准的docx格式word,不考虑word排版问题,只考虑数据填充,排版由word模板使用office自行制作。
ExportObjet方法传入word模板对象地址tempFilePath,导出到地址outPath,以及类数据源data,通过反射获取字段匹配word模板中对应的$key$,我在项目中使用的是{{替换名称}}名称去替换其值达到最后效果,但是因为文字样式等问题有的会无法替换,这个时候多调整几次即可。同理
Export则使用字典作为数据源。
实际使用案例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | public Dictionary< string , object > Export(Guid Id) { //获取路径 var result = _dAL.Get(Id); var mubanFile = "纠正和预防措施报告.docx" ; string FilePath = Directory.GetCurrentDirectory(); FilePath += $ "\\{_AppConfig.TemplateFile}\\" ; var templatePath = Path.Combine(FilePath, mubanFile); //数据源,字段类型 var textDic = new Dictionary< string , object >() { [ "名称" ] = 结果 ?? "" , [ "一般" ] = "口" , //选择框处理 }; //特殊情况特殊处理 if (result.CauseAnalysisList.Count > 0) { textDic.Add( "名称" , 结果 ?? "" ); } string exportFileName = result.ReportCode + " 纠正和预防措施报告.docx" ; string targetPath = $ @"{_AppConfig.TempExportDir}\{exportFileName}" ; //调用工具类 CommonTool.Export(targetPath, templatePath, textDic); var returnInfo = new Dictionary< string , object >() { [ "targetPath" ] = targetPath, [ "exportFileName" ] = exportFileName }; return returnInfo; } |
在处理数据源的时候,可以使用字典直接进行数据传输,但是有一些特殊的情况,也是需要进行特殊处理的