using System.Collections; using System.Text.RegularExpressions; using NetModular.DocX.Core; namespace Infrastructure.Helpers; public class WordHelper { /// /// 导出word /// /// 模板路径 /// 保存路径 /// 数据 public static void Export(string tempFilePath, string outPath, Dictionary data) { bool isrewrite = true; // true=覆盖已存在的同名文件,false则反之 //if (!System.IO.Directory.Exists(outPath)) //{ // System.IO.Directory.CreateDirectory(outPath); //} File.Copy(tempFilePath, outPath, isrewrite); //新建一个Word文档,加载Load的方法和Create使用一样。 using (DocX document = DocX.Load(outPath)) { ReplaceDoc(document, data); //普通文本替换 ReplaceTable(document, data); //表格处理 ReplaceList(document, data); //文本列表处理 document.Save(); //保存 } } private static void ReplaceDoc(DocX doc, Dictionary data) { foreach (var item in doc.Paragraphs) { ReplaceParagraph(item, data); } } private static void ReplaceList(DocX doc, Dictionary data) { //一定要在 普通文本替换和表格处理之后 foreach (var p in doc.Paragraphs) { var li = GetListInfo(p, data); if (li.IsList) { var pc = li.PTemp; for (int i = 0; i < li.Data.Count; i++) { var pt = pc.InsertParagraphAfterSelf(p); if (li.IsDict) { pc = ReplaceParagraph(pt, (Dictionary)li.Data[i]); } else { pc = ReplaceParagraph(pt, li.Data[i]); } } //删除模板行 li.PTemp.Remove(false); } else { //do nonthing } } } private static void ReplaceTable(DocX doc, Dictionary data) { var tbs = doc.Tables; foreach (var table in tbs) { //需要先判断表格是列表还是表单 var ti = GetTableInfo(table, data); if (ti.IsList) { for (int i = 0; i < ti.Data.Count; i++) { var rt = table.InsertRow(ti.RowTemp); rt.Height = ti.RowTemp.Height; rt.MinHeight = ti.RowTemp.MinHeight; if (ti.IsDict) { ReplaceRow(rt, (Dictionary)ti.Data[i]); } else { ReplaceRow(rt, ti.Data[i]); } } //删除模板行 ti.RowTemp.Remove(); } else { //do nonthing } } } private static void ReplaceRow(Row row, Dictionary data) { foreach (var cell in row.Cells) { foreach (var item in cell.Paragraphs) { ReplaceParagraph(item, data); } } } private static void ReplaceRow(Row row, object data) { foreach (var cell in row.Cells) { foreach (var item in cell.Paragraphs) { ReplaceParagraph(item, data); } } } private static Paragraph ReplaceParagraph(Paragraph p, Dictionary data) { Paragraph pr = p; var ms = GetMatches(p.Text); var ks = new List(); var rs = new List(); foreach (Match m in ms) { if (m.Groups.Count > 1) { string text = m.Groups[1].Value; if (text.Contains(".")) { var ts = text.Split("."); text = ts[ts.Length - 1]; } ks.Add(text); rs.Add(m.Value); } } bool isCt = data.Any(op => ks.Any(o => o.Contains(op.Key))); bool isReplace = false; if (isCt) { if (ks.Count > 1) { for (int i = 0; i < ks.Count; i++) { if (data.ContainsKey(ks[i])) { p.ReplaceText(rs[i], data[ks[i]]?.ToString()); } } } else if (ks.Count == 1) { string text = ks[0]; if (data.ContainsKey(text)) { var ct = data[text]?.ToString(); var cts = ResolveText(ct); var pc = p; foreach (var item2 in cts) { if (string.IsNullOrWhiteSpace(item2)) continue; var pt = pc.InsertParagraphAfterSelf(p); pt.ReplaceText(rs[0], item2); pc = pt; pr = pc; } isReplace = true; } } if (isReplace) { //删除原来段落 p.Remove(false); } } return pr; } private static Paragraph ReplaceParagraph(Paragraph p, object data) { var ms = GetMatches(p.Text); var isReplace = false; Paragraph pr = p; foreach (Match item1 in ms) { if (item1.Groups.Count > 1) { string text = item1.Groups[1].Value; var ct = data?.ToString(); var cts = ResolveText(ct); var pc = p; foreach (var item2 in cts) { var pt = pc.InsertParagraphAfterSelf(p); pt.ReplaceText(item1.Value, item2); pc = pt; pr = pc; } isReplace = true; } } if (isReplace) { //删除原来段落 p.Remove(false); } return pr; } private static IList ResolveText(string text) { if (string.IsNullOrEmpty(text)) return new List(); text = text.Replace("\r\n", "\n").Replace("\r", "\n"); return text.Split('\n'); } private static MatchCollection GetMatches(string text) { if (string.IsNullOrEmpty(text)) text = ""; Regex regex = new Regex("[#|\\$]([a-zA-Z0-9_.]+?)[#|\\$]", RegexOptions.IgnoreCase | RegexOptions.Multiline); return regex.Matches(text); } /// /// 只获取列表匹配项 /// /// /// private static MatchCollection GetListMatches(string text) { if (string.IsNullOrEmpty(text)) text = ""; Regex regex = new Regex("\\$([a-zA-Z0-9_.]+?)\\$", RegexOptions.IgnoreCase | RegexOptions.Multiline); return regex.Matches(text); } //纯辅助方法 private class TableInfo { public bool IsList { get; set; } public bool IsDict { get; set; } public Row RowTemp { get; set; } public IList Data { get; set; } } //判断表格是列表还是表单 private static TableInfo GetTableInfo(Table table, Dictionary data) { TableInfo result = new TableInfo(); var r0 = table.Rows[table.Rows.Count - 1]; var c0 = r0.Cells[r0.Cells.Count - 1]; var ct = c0.Paragraphs[0].Text; var ms = GetListMatches(ct); foreach (Match item in ms) { if (item.Groups.Count > 1) { string text = item.Groups[1].Value; if (text.Contains(".")) { result.IsDict = true; text = text.Split('.')[0]; } if (data.ContainsKey(text) && (data[text] is IList)) //判断是否是列表 { result.RowTemp = r0; result.IsList = true; result.Data = new List(); foreach (var item1 in (data[text] as IList)) { result.Data.Add(item1); } break; } } } return result; } private class ListInfo { public bool IsList { get; set; } public bool IsDict { get; set; } public Paragraph PTemp { get; set; } public IList Data { get; set; } } private static ListInfo GetListInfo(Paragraph p, Dictionary data) { ListInfo result = new ListInfo(); var ms = GetListMatches(p.Text); foreach (Match item in ms) { if (item.Groups.Count > 1) { string text = item.Groups[1].Value; if (text.Contains(".")) { result.IsDict = true; text = text.Split('.')[0]; } if (data.ContainsKey(text) && (data[text] is IList)) //判断是否是列表 { result.PTemp = p; result.IsList = true; result.Data = new List(); foreach (var item1 in (data[text] as IList)) { result.Data.Add(item1); } break; } } } return result; } }