|
|
using System.Collections;
|
|
|
using System.Text.RegularExpressions;
|
|
|
using NetModular.DocX.Core;
|
|
|
|
|
|
|
|
|
namespace Infrastructure.Helpers;
|
|
|
|
|
|
public class WordHelper
|
|
|
{
|
|
|
/// <summary>
|
|
|
/// 导出word
|
|
|
/// </summary>
|
|
|
/// <param name="tempFilePath">模板路径</param>
|
|
|
/// <param name="outPath">保存路径</param>
|
|
|
/// <param name="data">数据</param>
|
|
|
public static void Export(string tempFilePath, string outPath, Dictionary<string, object> 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<string, object> data)
|
|
|
{
|
|
|
foreach (var item in doc.Paragraphs)
|
|
|
{
|
|
|
ReplaceParagraph(item, data);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private static void ReplaceList(DocX doc, Dictionary<string, object> 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<string, object>)li.Data[i]);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
pc = ReplaceParagraph(pt, li.Data[i]);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//删除模板行
|
|
|
li.PTemp.Remove(false);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//do nonthing
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private static void ReplaceTable(DocX doc, Dictionary<string, object> 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<string, object>)ti.Data[i]);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
ReplaceRow(rt, ti.Data[i]);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//删除模板行
|
|
|
ti.RowTemp.Remove();
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//do nonthing
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private static void ReplaceRow(Row row, Dictionary<string, object> 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<string, object> data)
|
|
|
{
|
|
|
Paragraph pr = p;
|
|
|
var ms = GetMatches(p.Text);
|
|
|
var ks = new List<string>();
|
|
|
var rs = new List<string>();
|
|
|
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<string> ResolveText(string text)
|
|
|
{
|
|
|
if (string.IsNullOrEmpty(text)) return new List<string>();
|
|
|
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);
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 只获取列表匹配项
|
|
|
/// </summary>
|
|
|
/// <param name="text"></param>
|
|
|
/// <returns></returns>
|
|
|
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<object> Data { get; set; }
|
|
|
}
|
|
|
|
|
|
//判断表格是列表还是表单
|
|
|
private static TableInfo GetTableInfo(Table table, Dictionary<string, object> 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<object>();
|
|
|
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<object> Data { get; set; }
|
|
|
}
|
|
|
|
|
|
private static ListInfo GetListInfo(Paragraph p, Dictionary<string, object> 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<object>();
|
|
|
foreach (var item1 in (data[text] as IList))
|
|
|
{
|
|
|
result.Data.Add(item1);
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return result;
|
|
|
}
|
|
|
} |