目录
项目背景介绍
最近做了一个关于医疗机构证件审核的小型OA项目,项目中需要实现对医疗机构相关资料的文件归档功能,包含相关的文字信息、图片信息、表格信息以及pdf附件等文件的处理
关于Spire.Doc
详情参见 Spire.Doc
也可参见文档 .NET office开发组件_蓝晶之心的博客-CSDN博客查看简单介绍
功能实现
Nuget中安装 FreeSpire.Doc、FreeSpire.PDF、iTextSharp.LGPLv2.Core
创建Spire.Doc 帮助类SpireDocHelper.cs
模板文字替换方法
/// <summary>
/// word 模板替换
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="etity"></param>
/// <param name="doc"></param>
private static void ReplaceKey<T>(T etity, Spire.Doc.Document doc)
{
Type entityType = typeof(T);
PropertyInfo[] properties = entityType.GetProperties();
string entityName = entityType.Name;//实体类名称
foreach (var p in properties)
{
string propteryName = "{$" + p.Name + "}";//Word模板中设定的需要替换的标签
object value = p.GetValue(etity);
if (value == null)
{
value = "";
}
doc.Replace(propteryName, value.ToString(), true, true);
}
}
调用示例:
//Entity 数据信息
PublicNoticeView viewData = new PublicNoticeView();
viewData.OrgName = orgInfo.DeptName;
viewData.PersonName = legalPerson.PersonName;
viewData.OrgType = orgInfo.DeptType;
viewData.OrgAddress = orgProfile.OrgAddress;
viewData.ServiceTarget = orgProfile.ServiceTarget;
viewData.BedNum = (orgProfile.BedNum ?? 0).ToString();
viewData.ToothChairNum= (orgProfile.ToothChairNum ?? 0).ToString();
viewData.DiagnosisItems = diagnosisInfoTxt.ToString().TrimEnd('、');
viewData.OperationNature = orgProfile.OperationNature;
//加载文档
Spire.Doc.Document doc = new Spire.Doc.Document();
doc.LoadFromFile(@"D:\templete.docx");//加载模板文件路径
ReplaceKey(viewData, doc);
//保存替换后的模板文件
string savePath = @"D:\"+ "newTemplete.docx";
if (File.Exists(savePath))
{
File.Delete(savePath);//删除原文件
}
doc.SaveToFile(savePath, FileFormat.Docx);
doc.Close();
文档插入附件
/// <summary>
/// 文档插入附件
/// </summary>
/// <param name="doc"></param>
/// <param name="filePath">附件路径</param>
/// <param name="docRootPath">文件根目录</param>
private void InsertFile(Spire.Doc.Document doc, string filePath, string docRootPath)
{
string fullPath = docRootPath + filePath;
if (File.Exists(fullPath))
{
try
{
string extension = Path.GetExtension(fullPath).ToLower();//获取文件名后缀
//图片
if (extension == ".png" || extension == ".jpg" || extension == ".jpeg" || extension == ".bmp")
{
InsertImg(doc, fullPath);
}
else if (extension == ".doc" || extension == ".docx")
{
doc.InsertTextFromFile(fullPath, FileFormat.Docx);
doc.AddSection();
}
else if (extension == ".pdf")
{
InsertPdf(doc, docRootPath, fullPath);
}
}
catch (Exception ex)
{
logger.Error($"插入附件{fullPath}失败:" + ex.StackTrace);
}
}
}
/// <summary>
/// 插入pdf
/// </summary>
/// <param name="doc"></param>
/// <param name="rootPath"></param>
/// <param name="pdfPath"></param>
private void InsertPdf(Spire.Doc.Document doc, string rootPath, string pdfPath)
{
try
{
//由于Spire.Pdf只可以转换前3页内容,因此超过三页内容的pdf使用itextSharp处理单页,再使用Spire.Pdf转换为图片保存
//Spire.Pdf.PdfDocument docPdf = new Spire.Pdf.PdfDocument();
//docPdf.LoadFromFile(pdfPath);
//int pdfPages = docPdf.Pages.Count;
iTextSharp.text.pdf.PdfReader pdfReaderAll = new iTextSharp.text.pdf.PdfReader(pdfPath);
int pdfPages = pdfReaderAll.NumberOfPages;
pdfReaderAll.Close();
if (pdfPages <= 3)
{
string wordPath = "";
PdfHelper.DocToPdf(rootPath, pdfPath, out wordPath);
if (!string.IsNullOrEmpty(wordPath))
{
doc.InsertTextFromFile(wordPath, FileFormat.Docx);
doc.AddSection();
File.Delete(wordPath);
}
//docPdf.Close();
}
else
{
//docPdf.Close();
string newDirPath = rootPath + "\\PdfConvert\\" + DateTime.Now.ToString("yyyyMMdd") + "\\";
if (!Directory.Exists(newDirPath))
{
Directory.CreateDirectory(newDirPath);
}
iTextSharp.text.pdf.PdfReader pdfReader = new iTextSharp.text.pdf.PdfReader(pdfPath);
for (int j = 1; j <= pdfPages; j++)
{
string pdfNewPath = newDirPath + Guid.NewGuid().ToString() + ".pdf";
//保存单页信息为新的pdf
iTextSharp.text.Document pdfDoc = new iTextSharp.text.Document();
FileStream fs = new FileStream(pdfNewPath, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
iTextSharp.text.pdf.PdfWriter pdfWriter = iTextSharp.text.pdf.PdfWriter.GetInstance(pdfDoc, fs);
pdfDoc.Open();
pdfDoc.NewPage();
iTextSharp.text.pdf.PdfContentByte cb = pdfWriter.DirectContent;
cb.AddTemplate(pdfWriter.GetImportedPage(pdfReader, j), 0, 0);
pdfDoc.Close();
pdfWriter.Close();
fs.Close();
//spire.pdf 读取新的保存的pdf,转换成图片插入word文档
Spire.Pdf.PdfDocument docNew = new Spire.Pdf.PdfDocument();
docNew.LoadFromFile(pdfNewPath);
System.Drawing.Image bmp = docNew.SaveAsImage(0);
InsertImg(doc, "", bmp);
docNew.Close();
File.Delete(pdfNewPath);//删除新的单页pdf文件
}
pdfReader.Close();
}
}
catch(Exception ex)
{
logger.Error($"插入pdf附件{pdfPath}失败:" + ex.StackTrace);
}
}
/// <summary>
/// 插入图片
/// </summary>
/// <param name="doc"></param>
/// <param name="imgPath"></param>
/// <param name="img"></param>
private void InsertImg(Spire.Doc.Document doc, string imgPath, Image img = null)
{
Section section = null;
Paragraph para = null;
try
{
var pageCount = doc.Sections.Count;
if (pageCount > 0)
{
section = doc.Sections[pageCount - 1];
}
else
{
section = doc.AddSection();
}
para = section.AddParagraph();
Image image = (!string.IsNullOrWhiteSpace(imgPath)) ? ReduceImg(imgPath) : ReduceImg("", img);
DocPicture docPic = para.AppendPicture(image);
}
catch(Exception ex)
{
logger.Error($"插入图片{imgPath}失败{ex.StackTrace}");
}
}
/// <summary>
/// 适当缩小图片高度和宽度
/// </summary>
/// <param name="filePath"></param>
/// <param name="img">图片</param>
/// <returns></returns>
private Image ReduceImg(string filePath, Image img = null)
{
logger.Info($"图片路径{filePath}");
Image originImg = (!string.IsNullOrWhiteSpace(filePath)) ? Image.FromFile(filePath) : img;
int width = originImg.Width;
int height = originImg.Height;
logger.Info($"图片宽度{width},图片高度{height}");
//当图片宽度超过word文档宽度,那么根据比例缩小图片
if (width > 590)
{
int newWidth = 580;
int newHeight = height * newWidth / width;
Image newImg = new Bitmap(newWidth, newHeight);
Graphics g = Graphics.FromImage(newImg);
g.DrawImage(originImg, 0, 0, newWidth, newHeight);
return newImg;
}
else
{
return originImg;
}
}
/// <summary>
/// 电子签证图片设置
/// </summary>
/// <param name="doc">document</param>
/// <param name="imgPath">电子图片路径</param>
/// <param name="findText">需要替换的文本</param>
/// <param name="width">电子图宽度</param>
/// <param name="height">电子图高度</param>
/// <param name="hp">HorizontalPosition</param>
/// <param name="vp">VerticalPosition</param>
/// <param name="replaceEmpty">是否需要将文本替换为空</param>
private void SetESign(Spire.Doc.Document doc, string imgPath, string findText, float width, float height, float hp, float vp, bool replaceEmpty = false)
{
if (File.Exists(imgPath))
{
TextSelection selection = doc.FindString(findText, false, false);
TextRange range = selection.GetAsOneRange();
Paragraph para = range.OwnerParagraph;
DocPicture picture = para.AppendPicture(Image.FromFile(imgPath));
picture.Width = width;
picture.Height = height;
picture.HorizontalPosition = hp;//指定图片位置
picture.VerticalPosition = vp;
picture.TextWrappingStyle = TextWrappingStyle.InFrontOfText; //指定文字环绕方式
picture.TextWrappingType = TextWrappingType.Both;
}
if (replaceEmpty)
{
doc.Replace(findText, "", true, true);
}
}
指定位置插入电子签名、电子公章等
/// <summary>
/// 电子签证图片设置
/// </summary>
/// <param name="doc">document</param>
/// <param name="imgPath">电子图片路径</param>
/// <param name="findText">需要替换的文本</param>
/// <param name="width">电子图宽度</param>
/// <param name="height">电子图高度</param>
/// <param name="hp">HorizontalPosition</param>
/// <param name="vp">VerticalPosition</param>
/// <param name="replaceEmpty">是否需要将文本替换为空</param>
private void SetESign(Spire.Doc.Document doc, string imgPath, string findText, float width, float height, float hp, float vp, bool replaceEmpty = false)
{
if (File.Exists(imgPath))
{
TextSelection selection = doc.FindString(findText, false, false);
TextRange range = selection.GetAsOneRange();
Paragraph para = range.OwnerParagraph;
DocPicture picture = para.AppendPicture(Image.FromFile(imgPath));
picture.Width = width;
picture.Height = height;
picture.HorizontalPosition = hp;//指定图片位置
picture.VerticalPosition = vp;
picture.TextWrappingStyle = TextWrappingStyle.InFrontOfText; //指定文字环绕方式
picture.TextWrappingType = TextWrappingType.Both;
}
if (replaceEmpty)
{
doc.Replace(findText, "", true, true);
}
}
创建复选框
/// <summary>
/// 需要生成的checkbox信息
/// </summary>
public class CheckBoxInfo
{
/// <summary>
/// 需要替换的文本
/// </summary>
public string ReplaceTxt { get; set; }
/// <summary>
/// 是否选中
/// </summary>
public bool IsChecked { get; set; }
}
/// <summary>
/// 动态创建复选框
/// </summary>
/// <param name="doc"></param>
/// <param name="checkBoxInfos"></param>
private void CreateCheckBox(Spire.Doc.Document doc, List<CheckBoxInfo> checkBoxInfos)
{
foreach (var item in checkBoxInfos)
{
string charTxt = item.IsChecked == true ? ((char)82).ToString() : ((char)163).ToString();
TextSelection selection = doc.FindString(item.ReplaceTxt, true, true);
TextRange tr = selection.GetAsOneRange();
tr.CharacterFormat.FontName = "Wingdings 2";
doc.Replace(selection.SelectedText, charTxt, true, true);
}
}
去除word空白节
/// <summary>
/// 去除空白节
/// </summary>
/// <param name="doc"></param>
/// <returns></returns>
private Document RemoveWhiteSec(Spire.Doc.Document doc)
{
Spire.Doc.Document docNew = new Spire.Doc.Document();
foreach (Section section in doc.Sections)
{
if (section.Paragraphs.Count > 0)
{
docNew.Sections.Add(section.Clone());
}
}
return docNew;
}
table 表格动态添加行并填充数据
//加载文档
Spire.Doc.Document doc = new Spire.Doc.Document();
doc.LoadFromFile(@"D:\templete.docx");
//数据处理 生成表格数据
Section section = doc.Sections[0];
Table tb = section.Tables[0] as Table;//获取第一个表格
int rowNum = staffCvDatas.Count();//需要添加的行数
//添加行数
for (int i = 1; i <= rowNum; i++)
{
tb.AddRow(true, 9);//添加一行到表格的最后,9列
tb.Rows[i].Height = 20;//设置行高
}
//表格数据填充
int currentIndex = 1;//当前table数据索引
foreach (var item in staffCvDatas)//注:此处的staffCvDatas是需要处理的数据集合
{
tb[currentIndex, 0].AddParagraph().AppendText(item.StaffName);
tb[currentIndex, 1].AddParagraph().AppendText(item.Sex);
tb[currentIndex, 2].AddParagraph().AppendText(item.Age.ToString());
tb[currentIndex, 3].AddParagraph().AppendText(item.PositionName);
tb[currentIndex, 4].AddParagraph().AppendText(item.Special);
tb[currentIndex, 5].AddParagraph().AppendText(item.DeptName);
tb[currentIndex,6].AddParagraph().AppendText(item.ProfessionalRange);
tb[currentIndex, 7].AddParagraph().AppendText(item.CertNo);
tb[currentIndex, 8].AddParagraph().AppendText(item.OrgName);
currentIndex++;
}
string savePath = @"D:\newtemplete.docx";
if (File.Exists(savePath))
{
File.Delete(savePath);//删除原文件
}
doc.SaveToFile(savePath, FileFormat.Docx);
doc.Close();