ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
## **实现用户自定义Word模板** >[info]导读: 在涉及到word文档生成的项目中,一般采用编程将数据填充到word模板中生成文件的实现方式,如果模板由开发人员自己设计,那么编程填充数据是相对容易实现的;但如果用户希望可以自己修改模板或自己定义新模板,并且又不需要开发人员针对新模板重写代码,那么应该使用怎样的技术来实现这种需求呢?本文就此问题展开论述。 在实际的开发过程中,针对导出生成word文档的需求,都是用程序填充数据到word模板中来实现的。所谓模板也就是标记了数据位置和字体段落样式的Word文件。一般来说,模板中的数据可以分为两种:一种是一对一的,一个数据在模版中对应一个数据位置,比如一个模板只需要使用“部门、姓名、原因、天数、日期”5个数据,每个数据只需要在文件中使用一次,如下图模板所示: :-: ![1710](https://box.kancloud.cn/1677dcf0eb204628dcdd4e7077307567_877x471.png) 用户定义模板时可以使用全部数据,也可以使用5个数据中的任意4个、3个甚至1个,但模板中数据标签的数量总是这个集合的子集。 另一种是一对多,一个数据在同一个模版中可以使用一次,也可以使用多次。例如下图的介绍信的模板,每一个数据都需要在文件中出现两次。 :-: ![1711](https://box.kancloud.cn/6d5afe997b1b120520442e0ee76423b3_939x696.png) 如果一个项目系统中所有的模板都是固定的,那么只需要在系统开发过程中由开发人员和用户一起把模板做好,之后,开发人员根据业务逻辑编写程序,给模板中的数据位置填充具体的数据即可实现,但在实际的应用中,很多时候不是这样的,最终用户还是希望能自己随时新建和修改模板,以满足不断变化的业务需求,如果每次模板的变化都需要和开发人员一起来完成,那么这个项目就永远不会完工。 为了满足用户的这一需求,在项目中就需要提供一个模板制作和管理的模块,又为了让程序可以控制和识别用户定义模板中的数据位置,那么就需要开发人员来制作一个约定,让最终用户在新建或编辑模板时必须按照约定来制作模板。那么应该如何约定呢? PageOffice提供的解决方案就是使用书签和特殊格式的文本来对文档中需要插入数据的位置做标记。 第一种方法使用书签来标记数据位置。Word文档中插入书签的方法:把光标定位到需要标记数据位置的地方,点Word菜单中的“插入”-“书签”,就会弹出一个标题为“书签”的对话框,输入新书签的名称,书签名可以包含数字但中间不能有空格,用PageOffice开发的时候不推荐使用中文命名书签名。注意:如果新插入位置或新对象采用的是已有的书签名,原有的书签将自动取消,所以使用书签来标记数据位置的话,肯定是一个数据对应模板中一个位置的一对一模式。 在使用PageOffice开发的过程中,为了避免出现与用户自己定义的书签出现冲突,要求插入的书签名称必须以“PO_”开头。注意是字母o,不是数字0。书签名是不区分大小写的也可以写成“po_”。在PageOffice的概念里提到的数据区域,本质上就是书签,但是只有“po_”开头的书签才叫数据区域(DataRegion),请大家注意这点。 第二种方法就是使用特殊格式的文本来标记数据位置,比如说:【合同日期】、【##合同日期##】、[*合同日期*]……等等。使用书签标记数据位置有一个明显的缺点,同一个书签名称在一个word文档中只能出现一次,也就是说一个数据区域在文档中肯定是唯一的,但是很多时候模版中需要多处位置使用同样的数据变量,例如上面举例使用的“合同日期”可能就需要在一个合同中多个位置出现,使用数据区域肯定是无法满足需求的,但是使用特殊格式的文本来标记就没有这种限制了。 >[danger]在PageOffice的概念里,这种【合同日期】、【##合同日期##】、[*合同日期*]……等等特殊格式的文本都可以被认为是数据标签(DataTag),同一个数据标签可以在一份文件中多个位置出现多次,动态填充数据标签生成文件的时候,同一个数据标签都会被同样的数据替换。 >[warning]注意:【合同日期】和【##合同日期##】是两个不同的数据标签,同一个数据标签一定要是文本格式完全一致,比如:【##合同日期##】和【##合同日期##】虽然字体颜色和大小都不一样,但是文本内容是完全一样的,就被认为是同一个数据标签,所以在模版制作的时候定义数据标签是很简单的,只需要插入同样格式的文本就可以了。 虽然以上的两点约定已经定好了,但是让用户在编辑模版的时候使用office自身的功能来制作和编辑模版,还是步骤繁琐、困难重重,制作的模板也容易出现一些问题,为此,PageOffice提供了定义模板的接口,由开发人员使用程序预先定义好用户可以使用的数据区域和数据标签,当用户编辑模版的时候,给用户弹出一个数据区域和数据标签的选择窗口,用户只需要选择使用这些数据区域和数据标签插入到word模版中,设置好数据的段落格式、字体、样式、颜色等等。这样以来,不但处理好了约定的问题,而且使得用户自定义模板的操作更加简单快捷。 ### **一、 使用PageOffice提供的编辑模版功能:** PageOffice给开发人员提供了定义模版的接口DefineDataRegion和DefineDataTag方法, * PageOffice.WordWriter.WordDocument.Template.DefineDataRegion * PageOffice.WordWriter.WordDocument.Template.DefineDataTag ----- 1. 使用DefineDataRegion定义数据区域,例如Java代码如下: ~~~ WordDocument doc = new WordDocument(); doc.getTemplate().defineDataRegion("Name", "[ 姓名 ]"); doc.getTemplate().defineDataRegion("Address", "[ 地址 ]"); doc.getTemplate().defineDataRegion("Tel", "[ 电话 ]"); doc.getTemplate().defineDataRegion("Phone", "[ 手机 ]"); doc.getTemplate().defineDataRegion("Sex", "[ 性别 ]"); doc.getTemplate().defineDataRegion("Age", "[ 年龄 ]"); doc.getTemplate().defineDataRegion("Email", "[ 邮箱 ]"); doc.getTemplate().defineDataRegion("QQNo", "[ QQ号 ]"); doc.getTemplate().defineDataRegion("MSNNo", "[ MSN号 ]"); ~~~ 或者用ASP.NET开发的话,代码如下: ~~~ PageOffice.WordWriter.WordDocument doc = new PageOffice.WordWriter.WordDocument(); doc.Template.DefineDataRegion("Name", "[ 姓名 ]"); doc.Template.DefineDataRegion("Address", "[ 地址 ]"); doc.Template.DefineDataRegion("Tel", "[ 电话 ]"); doc.Template.DefineDataRegion("Phone", "[ 手机 ]"); doc.Template.DefineDataRegion("Sex", "[ 性别 ]"); doc.Template.DefineDataRegion("Age", "[ 年龄 ]"); doc.Template.DefineDataRegion("Email", "[ 邮箱 ]"); doc.Template.DefineDataRegion("QQNo", "[ QQ号 ]"); doc.Template.DefineDataRegion("MSNNo", "[ MSN号 ]"); ~~~ 开发人员用服务器端程序定义好用户可使用的数据区域,用户在客户端编辑模版的时候就可以使用这些数据区域。注意,这里的代码中不需要写PO_ 开头,PageOffice会自动添加这个前缀。用户编辑模版时看到的数据区域管理窗口,如下图所示: :-: ![1712](https://box.kancloud.cn/c577698ccf526217f827f46f41284796_520x410.jpg) 左侧“待添加数据区域”列表是可以用户目前可以使用的数据区域,右侧“已添加数据区域”列表是文档中已经添加的数据区域。此窗口的实现代码已经由PageOffice封装完毕,无需开发人员自己写复杂的js+html代码去实现,并且此窗口中内容的样式是可以修改的,如果对那些样式不太满意,只需要对此窗口html代码的样式做简单的调整即可。用户编辑数据区域时的效果,如下图所示: :-: ![1713](https://box.kancloud.cn/5cb4e114d3a96e60ec0408991a89a807_887x549.jpg) 2. 使用DefineDataTag定义数据标签,例如Java的代码如下: ~~~ WordDocument doc = new WordDocument(); doc.getTemplate().defineDataTag("{ 甲方 }"); doc.getTemplate().defineDataTag("{ 乙方 }"); doc.getTemplate().defineDataTag("{ 担保人 }"); doc.getTemplate().defineDataTag("【 合同日期 】"); doc.getTemplate().defineDataTag("【 合同编号 】"); ~~~ 或者用ASP.NET开发的代码如下: ~~~ PageOffice.WordWriter.WordDocument doc = new PageOffice.WordWriter.WordDocument(); doc.Template.DefineDataTag("{ 甲方 }"); doc.Template.DefineDataTag("{ 乙方 }"); doc.Template.DefineDataTag("{ 担保人 }"); doc.Template.DefineDataTag("【 合同日期 】"); doc.Template.DefineDataTag("【 合同编号 】"); ~~~ 开发人员用服务器端程序定义好用户可使用的数据标签,用户在客户端编辑模版的时候就可以使用这些数据标签。用户编辑模版时看到的数据标签管理窗口,如下图所示: :-: ![1714](https://box.kancloud.cn/3d7549e8824954b13ad22f6ff0ee9d13_430x410.jpg) 同数据区域一样,对此窗口的实现代码,PageOffice也已经封装完毕,无需开发人员自己写复杂的js+html代码去实现,并且此窗口中内容的样式是可以修改的,如果对那些样式不太满意,只需要简单的调整一下此窗口html代码中的样式即可。开发人员只管编写程序给数据标签赋值对应的数据,用户自己定义模版的样式、数据位置和数据的多少,用户可以使用全部的数据区域,也可以只使用部分, PageOffice在生成文件的时候,会自动忽略没有使用的数据标签,而不需要开发人员做任何代码的调整。 与数据区域的管理不同的是,由于数据标签在文件中不是唯一的,所以不管在文件中添加了多少个数据标签,在数据标签管理窗口中的数据标签都是不会减少的。 ### **二. 使用PageOffice.WordWriter 命名空间中的对象填充数据到Word模版,动态生成文档:** * PageOffice.WordWriter.WordDocument.OpenDataRegion 方法 * PageOffice.WordWriter.WordDocument.OpenDataTag 方法 开发人员只需要使用上面的两个方法,针对word模版编写程序,给所有的数据区域和数据标签赋值相应的数据即可,无需关心模版中到底使用了多少个数据区域和数据标签,那些Word模版中从来没有使用过的数据区域和数据标签,PageOffice会自动忽略,而无需开发人员做任何代码的修改,从而完美实现用户自定义模板的需求。 Java开发的赋值代码如下: ~~~ WordDocument doc = new WordDocument(); doc.openDataRegion("Name").setValue("张三"); doc.openDataRegion("Age").setValue("21"); …… doc.openDataTag("{ 甲方公司名称 }").setValue("微软中国总部"); doc.openDataTag("{ 乙方公司名称 }").setValue( "北京幻想科技公司"); …… poCtrl.setWriter(doc); ~~~ ASP.NET开发的赋值代码如下, ~~~ PageOffice.WordWriter.WordDocument doc = new PageOffice.WordWriter.WordDocument(); doc.OpenDataRegion("Name").Value = "张三"; doc.OpenDataRegion("Age").Value = "21"; …… doc.OpenDataTag("{ 甲方公司名称 }").Value = "微软中国总部"; doc.OpenDataTag("{ 乙方公司名称 }").Value = "北京幻想科技公司"; …… PageOfficeCtrl1.SetWriter(doc); ~~~ >[info]详细请参考PageOffice开发包里Samples4中的相关示例演示: >二、30、用户自定义模板中数据区域(DataRegion)的位置(专业版、企业版) >二、31、用户自定义模板中数据标签(DataTag)的位置(专业版、企业版) >三、12、实现“用户自定义Word模板”动态生成文件(专业版、企业版)