一.客户需求

    近期接到一个项目,在与客户初步沟通后,客户描述的需求听起来也非常简单,就是目前客户需要在Excel录入数据,然后把这些数据分别复制到多个Word的多个地方,除了单个值之外,还需要复制表格数据以及图片数据,客户觉得这么操作一是容易出错,二是重复操作的工作量太大。在初步了解用户的需求之后,得知客户需求的核心功能就是在Word中填充数据源,需要填充数据的数据源包括文字,表格以及图片等,本文以此为出发点,重点介绍如何在Word中使用“域”来填充外部数据。

  二.插件选型

    目前处理Word等Office文档类型的控件,微软自带的Com组件问题实在太多,一个比较麻烦的问题就是部分Com组件需要注册,并且如果客户端与开发电脑使用的Com组件版本不一致,还会出现各种问题,因此选择了Asponse.words插件,该软件为收费插件,具体的收费标准可以在官网进行查看。

  三.模板制作

    利用Asponse进行数据填充,其实代码不难,核心的工作就是需要在Word模板中设置标记,也就是需要让程序知道在什么填充数据,目前做标记的方式有两种,一种是使用书签,一种是使用域。目前网上大多的案例都是使用书签,但是在我实际开发的过程中,建议大家使用“域”,而不是使用书签,原因有以下几点:

    1.书签不能重复添加,比如我在第一个空白出需要插入数据源“姓名”,在最后签名处还要插入“姓名”,这个时候使用“域”的话可以在两处都插入“姓名”域,但是如果使用书签,需要设置不同的书签名称,生成数据源的时候会增加工作量

    2.书签不能在文档中直观的展示出来,如果插入书签比较多,很容易造成混乱

    此外,需要特别说明的是,制作书签或者“域"的时候务必务必使用Word而不是WPS制作,因为目前发现的一个问题就是,使用WPS制作的书签或者是”域“,在填充数据之后会自动增加一行空行,这个可能是WPS与Word的内部机制不同;还有一个技巧,在文档中使用Alt+F9,可以查看到模板的各种域代码,如下图所示:

    

  四.插入书签/域

    1.插入书签    

    

    2.插入域(插入->文档部件->域,选择"MergeField")

    

    

  五.实现代码

    1.获取文档

            Aspose.Words.Document doc = new Aspose.Words.Document(filePath);
Aspose.Words.DocumentBuilder builder = new Aspose.Words.DocumentBuilder(doc);

    2.利用word模板填充数据

       List<string> filedsValueList = new List<string>();
      string[] filedsName =doc.MailMerge.GetFieldNames();//获取文档中所有的域
for (int i = 0; i < filedsName.Length; i++)
{
if (dataTable.Columns.Contains(filedsName[i]))
{
filedsValueList.Add(dataTable.Rows[0][filedsName[i]].ToString()); }
else
{
filedsValueList.Add("");
}
}
       //核心代码其实就是这一句,上面的都是组织数据源
       //参数是两个数组,第一个数组是文档中所有”域“的名称,第二个是所对应域的值
doc.MailMerge.Execute(filedsName, filedsValueList.ToArray());

    3.插入图片

    插入图片并不需要特殊的代码,而是需要对Word模板中的域做特殊设置,设置的方式为:

    

    在弹出来的对话框中,把”域“名称的前面加上"Image:",如下图所示:

    

    设置好之后,只需要将该域的值设置为图片的路径,即可在文档中展示图片,如果需要在代码中控制图片的大小,需要给文档绑定图片处理的回调事件,代码如下:

doc.MailMerge.FieldMergingCallback = new HandleMerFieldInsert();

    4.设置图片尺寸

    在Asponse直接提供的方法中,没有修改图片尺寸的方法,但是可以重写Asponse的IFieldMergingCallback类,用于设置图片大小    

 class HandleMerFieldInsert : IFieldMergingCallback
{
//文本处理
void IFieldMergingCallback.FieldMerging(FieldMergingArgs e)
{ }
//图片处理
void IFieldMergingCallback.ImageFieldMerging(ImageFieldMergingArgs args)
{
Document doc = args.Document;
DocumentBuilder builder = new DocumentBuilder(doc);
builder.MoveToMergeField(args.FieldName); Shape shapeImage = builder.InsertImage(args.FieldValue.ToString());
//设置x,y坐标和高宽.
shapeImage .Left = 0;
shapeImage .Top = 0;
shapeImage .Width = 50;
shapeImage .Height = 25;
} }

    5.填充表格

    填充表格数据,需要在模板中先设置表格绑定数据的起始位置,然后在每一列中设置数据源中的列名称,具体步骤如下图:

    

    表格数据源的起始标记为”TableStart“,结束标记为"TableEnd",设置好表格数据源的起始与结束标记之后,再在每一列中单独设置每一列需要绑定的字段名称即可,设置好的数据源如下图所示:

    

    通过Alt+F9可以看到设置好的各种域的代码,如下图所示:

    

    设置好表格的各个域之后,通过如下代码完成对数据源的填充:

dt.TableName = "UserInfo";//这里的表格名称必须和模板中表格的起始与结束源名称相同
doc.MailMerge.ExecuteWithRegions(dt);

    6.删除表格及对应的占位符

    使用Asponse进行删除的操作相对比较复杂,现有的业务是需要删除模板中的某一个表格,但有个问题就是,在删除了该表格之后,该表格所在页面的占位符还在,会导致生成的文档有一个空白页,因此在删除类似表格,图片这种元素时,还需要删除对应的段落占位符

 NodeCollection nodeCollection = doc.GetChildNodes(NodeType.Table, true);//获取所有表格

                    foreach (Table table in nodeCollection)
{
if (table.GetText().Contains("AAAAAA") && table.GetText().Contains("BBBBBB"))//To Do:这里通过获取表格中的内容来判定是否为删除的表格,应该还有更好的办法
{
Paragraph paragraph = (Paragraph)table.PreviousSibling;
paragraph.Remove();//删除段落
table.Remove();//删除表格
}
}

    7.保存带密码的PDF    

   Aspose.Words.Saving.PdfSaveOptions saveOption = new Aspose.Words.Saving.PdfSaveOptions();
saveOption.SaveFormat = Aspose.Words.SaveFormat.Pdf;
PdfEncryptionDetails encryptionDetails = new PdfEncryptionDetails(pdfPwd, string.Empty, PdfEncryptionAlgorithm.RC4_128);
encryptionDetails.Permissions = PdfPermissions.AllowAll;
saveOption.EncryptionDetails = encryptionDetails;
doc.Save(fullfilepath + ".pdf", saveOption);

    8.删除未被赋值的“域”

doc.MailMerge.DeleteFields();

  写在最后

      至此,Asponse利用模板处理数据的常规方法总结完毕,对于直接使用Asponse的方法,在Word中通过硬编码的方式增加表格建议不到万不得已不要使用,因为增加表格需要控制表格本身的样式,还需要控制单元格的样式,并且对于复杂的文档,定位表格也会增加难度。

    

使用Asponse.Words处理Word模板的更多相关文章

  1. JAVA Asponse.Word Office 操作神器,借助 word 模板生成 word 文档,并转化为 pdf,png 等多种格式的文件

    一,由于该 jar 包不是免费的, maven 仓库一般不会有,需要我们去官网下载并安装到本地 maven 仓库 1,用地址   https://www-evget-com/product/564  ...

  2. OpenXml Sdk 根据Word模板导出到word

    一:OpenXml Sdk 简介 Open XML标准的简单介绍:Ecma Office Open XML(“Open XML”)是针对字处理文档.演示文稿和电子表格的国际化开放标准,可免费供多个应用 ...

  3. 利用POI 技术动态替换word模板内容

    项目中需要实现一个功能,动态替换给定模板里面的内容,生成word文档提供下载功能. 中间解决了问题有: 1.页眉的文档logo图片解决,刚开始的时候,HWPFDocument 对象无法读取图片对象(已 ...

  4. C#操作word模板插入文字、图片及表格详细步骤

    c#操作word模板插入文字.图片及表格 1.建立word模板文件 person.dot用书签 标示相关字段的填充位置 2.建立web应用程序 加入Microsoft.Office.Interop.W ...

  5. 向Word模板中填充数据

    现在有这样的需求,给Word文档的指定位置填充上特定数据,例如我们有一个终端,用来打印员工的薪资证明,对于一个公司来说,他的薪资证明模板是固定的,变化的地方是员工姓名,部门,职位等.我们只需要将这些指 ...

  6. POI Word 模板 文字 图片 替换

    实验环境:POI3.7+Word2007 Word模板: 替换后效果: 代码: 1.入口文件 public class Test { public static void main(String[] ...

  7. Aspose Word模板使用总结

    Aspose Word模板使用总结 1.创建word模版,使用MergeFeild绑定数据     新建一个Word文档,命名为Template.doc     注意:这里并不是输入"< ...

  8. 根据指定Word模板生成Word文件

    最近业务需要批量打印准考证信息 1.根据Table数据进行循环替换,每次替换的时候只替换Word中第一个Table的数据, 2.每次替换之后将Word中第一个Table数据进行复制,将复制Table和 ...

  9. JSP利用freemarker生成基于word模板的word文档

    利用freemarker生成基于word模板的word文档 freemarker简介 FreeMarker是一个用Java语言编写的模板引擎,它基于模板来生成文本输出.FreeMarker与Web容器 ...

随机推荐

  1. PCIE_DMA实例五:基于XILINX XDMA的PCIE高速采集卡

    PCIE_DMA实例五:基于XILINX XDMA的PCIE高速采集卡 一:前言 这一年关于PCIE高速采集卡的业务量激增,究其原因,发现百度"xilinx pcie dma",出 ...

  2. C#入门——Console.Write()与Console.WriteLine()

    参考:https://blog.csdn.net/qujunyao/article/details/72884670 两者区别: Console.Write("abc"); 输出到 ...

  3. P 4315 月下毛景树

    题目描述 毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园. 毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校园里. 爬啊爬~爬啊爬毛毛虫爬到了一颗小小的"毛景树&quo ...

  4. Ubuntu通过Nginx安装Webdav

    使用KeePass保存密码,在个人服务器上安装WebDav协议. # nginx nginx-extras apache2-utils sudo aptitude install nginx ngin ...

  5. STM32之旅3——时钟数

    STM32之旅3--时钟数 STM32F1是M3内核,它的时钟数很庞大,让一个初学者去看,估计会很吃力,和我们入门的8051单片机的时钟不同,这里又倍频.又分频,而且还分成好多个时钟,不同的外设时钟不 ...

  6. GDB 调试 .NET 程序实录 - .NET 调用 .so 出现问题怎么解决

    注:本文重要信息使用 *** 屏蔽关键字. 最近国庆前,项目碰到一个很麻烦的问题,这个问题让我们加班到凌晨三点. 大概背景: 客户给了一些 C语言 写的 SDK 库,这些库打包成 .so 文件,然后我 ...

  7. JVM系列【5】JVM常用指令

    JVM系列笔记目录 虚拟机的基础概念 class文件结构 class文件加载过程 jvm内存模型 JVM常用指令 GC与调优 指令集分类 基于寄存器的指令集 基于栈的指令集 Hotspot中的Loca ...

  8. day20 Pyhton学习 面向对象-类与类之间的关系

    一.类与类之间的依赖关系 class Elphant: def __init__(self, name): self.name = name def open(self, ref): print(&q ...

  9. 解决/lib/ld-linux.so.2: bad ELF interpreter: No such file or directory报错 (转)

    解决/lib/ld-linux.so.2: bad ELF interpreter: No such file or directory报错 念淅 2020-01-03 15:02:25 3793 收 ...

  10. cve-2020-1472,netlogon特权提升漏洞复现

    cve-2020-1472,netlogon特权提升漏洞, 漏洞原理:攻击者通过NetLogon(MS-NRPC),建立与域控间易受攻击的安全通道时,可利用此漏洞获取域管访问权限.成功利用此漏洞的攻击 ...