近期做一个关于C# 操作 Word 模板 文档的功能模块,查阅资料,最终完美完成任务,记录下来,以便后面还会用到。
第一部分:为了防止动态数据,撑开样式,所以采用的是,无边框的word表格(表格属性-》边框和底纹-》边框(无))即可,A只是表示表格那儿有个单元格而已。
第二部分:用占位符,到时候用真实的数据来替换。
第三部分:产品项为动态生成。
下面看具体代码实现:
using Microsoft.Office.Interop.Word; using WinForm = System.Windows.Forms; public class XXController : BaseController { public ActionResult Print() { // pdf 路径 string PdfPath = AppDomain.CurrentDomain.BaseDirectory + "PurcharseContract.pdf"; // word模板地址 string WordTemplatePath = AppDomain.CurrentDomain.BaseDirectory + @"App_Data\PurcharseContract.docx"; // 定义WORD Application相关 Application appWord = new Application { // WORD程序不可见 Visible = false, // 不弹出警告框 DisplayAlerts = WdAlertLevel.wdAlertsNone }; lock (LockObj) { // 打开word模板文件 Document doc = appWord.Documents.Open(WordTemplatePath, OMissing, false); try { Table table = doc.Tables[1]; // 第1行 table.Cell(1, 2).Range.Text = "名称"; table.Cell(1, 4).Range.Text = "编号"; // 第2行 table.Cell(2, 2).Range.Text = "编码"; table.Cell(2, 4).Range.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); // 准备需替换的数据 Dictionary<string, string> datas = new Dictionary<string, string>(); datas.Add("{PurchaseTotalMoney}", "500"); datas.Add("{TotalMoneyChCapital}", GetChineseNum((decimal)500)); // 替换占位符 foreach (var data in datas) { SearchReplace(appWord, data.Key, data.Value); } // 2.填充产品项数据 // 获取word文档里面的表格 Table table = doc.Tables[2]; // 第二行产品模板,插入产品项 行 const int RowIdx = 2; foreach (var product in products.GroupBy(x => x.Name)) { // 始终在第二行产品模板前插入新行 object beforeRow = table.Rows[2]; table.Rows.Add(ref beforeRow); foreach (var item in product) { string info = "产品编码:ProductCode" + "\r产品名称:ProductName" + "\r规格型号:No"; string info2 = "单位:Unit" + "\r币别:RMB" + "\r品牌:AN"; string info3 = "单价:2" + "\r数量:2" + "\r金额:4"; table.Cell(RowIdx, 1).Range.Text = info; table.Cell(RowIdx, 2).Range.Text = info2; table.Cell(RowIdx, 3).Range.Text = info3; table.Cell(RowIdx, 4).Range.Text = DateTime.Now.ToString("yyyy-MM-dd"); table.Cell(RowIdx, 5).Range.Text = "2"; table.Cell(RowIdx, 6).Range.Text = "2"; table.Cell(RowIdx, 7).Range.Text = "2.0"; table.Cell(RowIdx, 8).Range.Text = "备注"; } } int count = table.Rows.Count; // 删除位于表格倒数第4行的产品模板项 table.Rows[count - 3].Delete(); double money = 200.00; // 运费 table.Cell(count - 3, 3).Range.Text = (money * 0.02).ToString("F2"); // 汇总 table.Cell(count - 2, 3).Range.Text = money.ToString("F2"); // 总金额(大写) table.Cell(count - 1, 2).Range.Text = GetChineseNum((decimal)money); // 3. 弹出 Windows 打印机选择项 WinForm.PrintDialog pd = new WinForm.PrintDialog(); if (pd.ShowDialog() != WinForm.DialogResult.Cancel) { // 设置选择的打印机名称 appWord.ActivePrinter = pd.PrinterSettings.PrinterName; } // true后台打印,false前台打印。 // 必须false,否则后台打印时,尚未打印,就调用了后续的Close,造成打印任务无法执行 object printbackgroud = false; // 4. 开始打印 doc.PrintOut(ref printbackgroud); // 5. 保存为PDF文档 doc.ExportAsFixedFormat(PdfPath, WdExportFormat.wdExportFormatPDF); } catch (Exception ex) { //throw ex; } finally { // 关闭Word if (doc != null) { doc.Close(ref SaveOption); } // 退出word appWord.Quit(ref SaveOption); } } FileStream fs = new FileStream(PdfPath, FileMode.Open); // 6. 返回致客服端提供下载 return File(fs, "application/octet-stream", "Test.pdf"); } }
替换占位符字符串:
/// <summary> /// 查找并替换文本 /// </summary> /// <param name="app">word application</param> /// <param name="strOldText">旧字符</param> /// <param name="strNewText">新字符</param> /// <returns>处理结果</returns> public static bool SearchReplace(Application app, string strOldText, string strNewText) { object replaceAll = WdReplace.wdReplaceAll; object missing = Type.Missing; // 首先清除任何现有的格式设置选项,然后设置搜索字符串 strOldText。 app.Selection.Find.ClearFormatting(); app.Selection.Find.Text = strOldText; app.Selection.Find.Replacement.ClearFormatting(); app.Selection.Find.Replacement.Text = strNewText; bool result = app.Selection.Find.Execute( ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref replaceAll, ref missing, ref missing, ref missing, ref missing); return result; }
附属功能,金额转中文大写:
/// <summary> /// 金额小写转大写 /// </summary> /// <param name="value">金额</param> /// <returns>中文大写</returns> public static string GetChineseNum(decimal value) { const string Chinese = "零壹贰叁肆伍陆柒捌玖"; const string Unit = "元十百千万十百千亿十百千兆十百千"; const string Unit2 = "角分"; StringBuilder builder = new StringBuilder(); long u = 1; int i = 0; // 整数 while (value >= u) { int n = (int)((long)value / u % 10); u *= 10; if (n == 0) { i++; continue; } if (i > 1 && i < 4) { builder.Insert(0, "元"); } else if (i > 4 && i < 8) { builder.Insert(0, "万"); } else if (i > 8) { builder.Insert(0, "亿"); } builder.Insert(0, Unit[i++]); builder.Insert(0, Chinese[n]); } // 小数 if ((long)value != value) { long value2 = (long)((value - (long)value) * 100); int n = (int)(value2 / 10 % 10); builder.Append(Chinese[n]); builder.Append(Unit2[0]); n = (int)(value2 % 10); builder.Append(Chinese[n]); builder.Append(Unit2[1]); } else { builder.Append("整"); } return builder.ToString(); }
参考博客:http://www.jb51.net/article/37615.htm
学无止境,共勉!!!