1 预览模板的准备 如图所示 我们需要导出此效果
2:替换/填充 资源 工作简历需要填充 基本信息需要替换占位符(一般对应数据库字段 好写代码)
c# 代码
/// <summary>
/// 根据数据源 生成word
/// </summary>
/// <returns></returns>
public string GetWordForExport(参数)
{
var data = 根据参数获取数据库内容;
if (data == null) throw new CustomException("没有可以导出的数据");
//工作简历
var workHistory = data.MHBasicLevelCadreWorkHistory.OrderByDescending(t => t.StartDate).ToList();
//读取word预览模板资源
string filepath = AppDomain.CurrentDomain.BaseDirectory + "\\Export\\Template\\项目预览模板路径.docx";
using (FileStream stream = File.OpenRead(filepath))
{
XWPFDocument doc = new XWPFDocument(stream);
//遍历表格
var tables = doc.Tables;
var i=0;
var j = 0;
var k = 0;
var m = 0;
foreach (var table in tables)
{
for (var index = 0; index < table.Rows.Count; index++)
{
//工作简历 填充资源 填充一行 数据库资源移出一行 这样不会重复
var row = table.Rows[index];
if (index >= 10 && index <= 16)
{
var w = workHistory.FirstOrDefault();
if(w==null) continue;
var cells = row.GetTableCells();
//没有样式的话 就直接设置内容
cells[0].SetText($"{w.StartDate:yyyy.MM}~{w.EndDate:yyyy.MM}");
cells[1].SetText(w.WorkUnit);
cells[2].SetText(w.Position);
cells[3].SetText(w.Witness);
//有样式的话 就用下面的代码 对单元格进行设置 字体什么的
//XWPFParagraph p1 = cells[0].AddParagraph(); //这样单元格里面内容会换行 如果不换行就直接 cells[0].Paragraphs[0];
//XWPFRun r1 = p1.CreateRun();
//r1.FontSize = 6;
//r1.SetText();
workHistory.Remove(w);
}
//替换占位符内容
else
{
foreach (var cell in row.GetTableCells())
{
foreach (var para in cell.Paragraphs)
{
ReplaceKey(para, datac);
}
}
}
}
}
// 3 保存资源 设置路径名 返回路径
var filename = data.Name+ "的个人档案.docx";
var savepath = AppDomain.CurrentDomain.BaseDirectory + "\\Export\\Temp\\" + filename;
//为了表格复制和插入图片功能不冲突,先保存文档再读
using (FileStream sw = File.Create(savepath))
{
doc.Write(sw);
}
return "/Export/Temp/" + filename;
}
}
//替换占位符 占位规则 按个人喜好
private void ReplaceKey(XWPFParagraph para, object data)
{
string text = para.ParagraphText;
var reg = new Regex(@"\{\{.+?\}\}");
var ms = reg.Matches(para.Text);
if (ms.Count > 0)
{
Type t = data.GetType();
PropertyInfo[] pi = t.GetProperties();
foreach (PropertyInfo p in pi)
{
if (text.Contains("{{" + p.Name + "}}"))
{
var val = p.GetValue(data);
//性别处理下 汉字
if (p.Name == "Sex")
{
val = val.ToString() == "1" ? "男" : "女";
}
//图片
if (p.Name == "PicUrl")
{
//把值清掉 不然后面就替换一段url内容在word上 不需要 只需要放图片即可
val = "";
var imgPath = HttpContext.Current.Server.MapPath("~/" + val);
if (!File.Exists(imgPath))
{
//换备用公共图片
imgPath = HttpContext.Current.Server.MapPath("~/Contents/images/noimg.png");
}
if (!File.Exists(imgPath))
{
//备用图片都没有 那就没添加图片操作了 空着内容
}
else
{
AddPicture(imgPath, para);
}
}
if (val != null)
{
para.ReplaceText("{{" + p.Name + "}}", val.ToString());
}
else
{
para.ReplaceText("{{" + p.Name + "}}", "");
}
}
}
}
}
//图片添加方法
public void AddPicture(string picurl, XWPFParagraph paragraph)
{
if (!File.Exists(picurl)) { return; }
var exname = Path.GetExtension(picurl)?.TrimStart('.').ToUpper();
if (exname == "JPG") exname = "JPEG";
if (!System.Enum.TryParse<NPOI.SS.UserModel.PictureType>(exname, out var pt))
{
pt = NPOI.SS.UserModel.PictureType.PNG;
}
XWPFParagraph par = paragraph;
par.Alignment = ParagraphAlignment.CENTER;//居中
XWPFRun run = par.CreateRun();
//run.SetText("test");
//var doc = paragraph.Document;
using (FileStream fsImg = new FileStream(picurl, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
//var image = System.Drawing.Image.FromStream(fsImg, true);
//var width = image.Width;
//var height = image.Height;
//if (width > 500)
//{
// width = 500;
// height = 500 * image.Height / image.Width;
//}
//fsImg.Position = 0;
var widthEmus = 80 * 9525; // (width * 9525);
var heightEmus = 100 * 9525;//(height * 9525);
run.AddPicture(fsImg, (int)pt, Guid.NewGuid().ToString() + "," + pt.ToString(), widthEmus, heightEmus);
//CreatePicture(doc, run, picID, widthEmus, heightEmus);
}
}
如果还需要动态 加行 比如 工作经历不止模板7行 可能更多的话
var workHistoryBegin = 11;
var workHistoryEnd = 18;
//补行数 如果模板上的 行不够 需要动态加的话
if (workHistory.Count() > 7)
{
var addRows = workHistory.Count() - 7;
//开始补行数了
CT_Row ctrow = tables[0].Rows[workHistoryBegin+1].GetCTRow(); //找模板
//tables[0].RemoveRow(12); //先移除模板行
for (int index = workHistoryEnd+1; index < workHistoryEnd + 1 + addRows; index++)
{
CT_Row targetRow = new CT_Row();
//复制cell结构
foreach (CT_Tc item in ctrow.Items)
{
CT_Tc addTc = targetRow.AddNewTc();
addTc.tcPr = item.tcPr;//cell样式,只包括列宽和cell对齐方式
IList<CT_P> list_p = item.GetPList();
foreach (var p in list_p)
{
CT_P addP = addTc.AddNewP();
addP.pPr = p.pPr;//段落样式
IList<CT_R> list_r = p.GetRList();
foreach (CT_R r in list_r)
{
CT_R addR = addP.AddNewR();
addR.rPr = r.rPr;//run样式 包括字体等
List<CT_Text> list_text = r.GetTList();
foreach (CT_Text text in list_text)
{
CT_Text addText = addR.AddNewT();
addText.space = text.space;
addText.Value = text.Value;
}
}
}
}
//增加数据行
XWPFTableRow mrow = new XWPFTableRow(targetRow, tables[0]);
tables[0].AddRow(mrow, index);
}
//吧结束行数更新下 供下面的去内容去开始使用
workHistoryEnd = 11 + workHistory.Count();
}