国产linux系统(银河麒麟,统信uos)使用 PageOffice自定义Word模版中的数据区域
PageOffice 国产版 :支持信创系统,支持银河麒麟V10和统信UOS,支持X86(intel、兆芯、海光等)、ARM(飞腾、鲲鹏、麒麟等)、龙芯(Mips、LoogArch)芯片架构。
在实际的Word文档开发中,经常需要自动填充数据到Word模板中,以生成动态的Word文档,那么应该如何编辑制作Word模板呢?
方法一:直接打开Word文件插入书签
假如使用数据区域(DataRegion)来定义模板中动态填充数据的位置,那么直接打开一个Word文件,在其中添加“PO_”开头的书签即可制作word模板。例如,打开一个Word文件后,可以通过选中需要标记为书签的文字,例如“[姓名]”,然后点击Word菜单中的“插入”-“书签”来添加书签,在弹出的“书签”对话框中,输入新书签的名称PO_userName,并点击右侧的“添加”按钮,即可完成一个数据区域的定义。效果如下图所示:
注意 书签名必须以“PO_”开头,并由字母和数字组成,但中间不能有空格。
Word模板中需要多少个动态填充数据的位置,就在Word文件中相应的位置插入多少个“PO_”开头的书签即可,这种制作word模板的方法操作简单,但是常常用于新项目开发中开发人员定义Word模板。开发人员知道在Word模板的哪个位置要插入哪个数据,就比如上面所说的“姓名”的位置需要插入系统里的数据UserName,所以就定义了一个PO_userName的书签,然后就可以编程调用PageOffice接口,把web系统里的UserName赋值给数据区域PO_userName,其他的数据区域也是相同的处理方式。但是项目发布后用户需求变动,希望修改Word模板或创建新的Word模板,用户怎么知道如何制作word模板呢?如何插入书签?如何命名书签?哪些名字的书签与哪些系统数据是对应的呢?
方法二:给用户提供自定义模板功能
开发人员可以给系统增加一个模板管理的模块,拥有模板管理权限的用户可以查看系统中的模板列表,可以新增、删除和在线编辑模板,开发人员通过程序定义好编辑某种模板时可能用到的所有数据区域,用户自定义编辑Word模板时可以把全部数据区域插入到模板的相应位置,也可以根据实际需求只使用部分数据区域,但Word模板中数据区域的数量总是开发人员定义的数据区域集合的子集,这样一来就能实现开发人员与用户的分工合作。
比如说web系统中合同模板的制作,合同模板中可能会用到的数据有:合同编号、购货单位、供货单位、产品名称、购货单位地址、供货单位地址、担保人、担保人手机,那么开发人员可以编写代码定义好这些数据区域,让用户在线打开编辑模板时,只能在Word模板中插入这些系统定义好的数据区域,这样做不但实现了开发人员与用户的一种约定,而且规范了用户的操作。
- 开发人员编写代码定义好编辑模板时所有可用的数据区域:
开发人员调用PageOffice提供的defineDataRegion方法定义用户编辑模板时所有可用的数据区域,第一个参数是数据区域名称,也就是word书签的名称,第二个参数是数据区域在Word文件中显示的文字内容,格式没有特殊要求。下面示例代码中显示的文字内容都使用了中括号(也可以使用其他符号),仅仅是为了便于用户直观的查看Word模板中哪些位置是插入的数据区域。
WordDocumentWriter doc = new WordDocumentWriter();
doc.getTemplate().defineDataRegion("PO_Guarantor", "[担保人]");
doc.getTemplate().defineDataRegion("PO_SupplierAddress", "[供货单位地址]");
doc.getTemplate().defineDataRegion("PO_BuyerAddress", "[购货单位地址]");
doc.getTemplate().defineDataRegion("PO_No", "[合同编号]");
doc.getTemplate().defineDataRegion("PO_GuarantorPhone", "[担保人手机]");
doc.getTemplate().defineDataRegion("PO_ProductName", "[产品名称]");
doc.getTemplate().defineDataRegion("PO_Buyer", "[购货单位]");
doc.getTemplate().defineDataRegion("PO_Supplier", "[供货单位]");
- 用户编辑模板时,直接使用开发人员定义好的数据区域来制作模板:
开发人员可以根据实际需求,在自己的Web项目中实现下面的编辑模板效果。
把数据区域列表和Word文件编辑界面,一左一右放到同一个页面窗口中,用户在右侧Word文件中点击定位光标到需要插入数据的位置,然后在左侧选择相应的数据区域,添加到当前位置即可。比如下图所示:在Word中需要插入“合同编号”的位置点击一下鼠标,然后在左侧“待添加区域”中点击数据区域“PO_No”的添加按钮,数据区域“PO_No”就被插入到了Word光标所在位置,且“待添加区域”列表中的数据区域“PO_No”被移动到“已添加区域”的列表中。
此效果所用到的html、css和javascript代码:
<style>body {margin: 0;padding: 0;display: flex;}div{box-sizing: border-box; }#left-container {width: 360px;display: flex;flex-direction: column;border-right: 2px solid #ccc;padding: 20px;overflow: auto;font-size: 12px;height: 90vh;}#right-container {flex: 1;padding: 0px;height: 95vh;}#podiv{width: 100%;height: 100%;margin: 0;padding: 0;}#left-title{text-align: center;font-size: 16px;padding-bottom: 10px;margin-bottom: 10px;border-bottom: solid 1px #ccc;}.input-group {margin-bottom: 20px;display: flex;align-items: center;}input[type="text"] {width: 70%;padding: 10px;margin-top: 5px;box-sizing: border-box;border: 1px solid #ccc;border-radius: 5px;font-size: 12px;outline: none;}input[type="submit"] {width: 80px;padding: 10px;margin-top: 5px;margin-left: 10px;box-sizing: border-box;border: none;border-radius: 5px;background-color: #4E6EF2;color: white;font-size: 12px;outline: none;cursor: pointer;}/* 表格样式 */table {border-collapse: collapse;width: 100%;}th, td {padding: 8px;text-align: left;border-bottom: 1px solid #ddd;}th {position: sticky;top: 0;background-color: #f2f2f2;z-index: 1;}/* 容器样式 */.container {height: 300px;overflow: auto;border: solid 1px #ccc;scrollbar-width: thin;scrollbar-color: #888 #f2f2f2;}/* 滚动条样式 */.container::-webkit-scrollbar {width: 8px;}.container::-webkit-scrollbar-track {background: #f2f2f2;}.container::-webkit-scrollbar-thumb {background-color: #888;border-radius: 4px;}.container::-webkit-scrollbar-thumb:hover {background-color: #555;}.delete-button {padding: 6px 6px;border: none;border-radius: 5px;background-color: #f44336;color: white;font-size: 12px;cursor: pointer;}.delete-button:hover {background-color: #d32f2f;}.normal-button {padding: 6px 6px;border: none;border-radius: 5px;background-color: #4E7EFF;color: white;font-size: 12px;cursor: pointer;}.normal-button:hover {background-color: #4E6EF2;}.locate-button {padding: 6px 6px;border: none;border-radius: 5px;background-color: #0abb87;color: white;font-size: 12px;cursor: pointer;}.locate-button:hover {background-color: #0a9966;}</style><script type="text/javascript">//控件中的一些常用方法都在这里调用,比如保存,打印等等function OnPageOfficeCtrlInit() {pageofficectrl.AddCustomToolButton("保存", "Save", 1);}function Save() {pageofficectrl.WebSave();}//加载数据function loadData() {var kWord1 = document.getElementById("inputKey1").value;var kWord2 = document.getElementById("inputKey2").value;var definedDataRegionJson = pageofficectrl.word.DataRegionsDefinedAsJson;var dataRegionJson = pageofficectrl.word.DataRegionsAsJson;searchDataRegion(definedDataRegionJson, dataRegionJson, kWord1);searchDataRegion2(dataRegionJson, kWord2);}//加载上方数据列表function searchDataRegion(drDefinedJson, drJson, s){var tb1 = document.getElementById("bkmkTable");var rCount = tb1.rows.length;for (var i = 1; i < rCount; i++) {tb1.deleteRow(1);}if('' == drDefinedJson) drDefinedJson = '[]';let definedDataRegionObj = JSON.parse(drDefinedJson);let dataRegionsJson = drJson;if('' == dataRegionsJson) dataRegionsJson = '[]';let dataRegionsObj = JSON.parse(dataRegionsJson);var oTable = document.getElementById("bkmkTable");var tbodyObj = oTable.tBodies[0];for(let key in definedDataRegionObj ){let drName = definedDataRegionObj[key].name;let drCaption = definedDataRegionObj[key].caption;//alert("数据区域:"+drName+"; 值:"+drValue);let bFind = false;for(let k in dataRegionsObj){if(dataRegionsObj[k].name == drName){bFind = true;break;}}if(bFind) continue;if (drName.toLocaleLowerCase().indexOf(s.toLocaleLowerCase()) > -1) {var oTr = tbodyObj.insertRow();var oTd = oTr.insertCell();oTd.innerHTML = drName;oTd = oTr.insertCell();oTd.innerHTML = drCaption;oTd = oTr.insertCell();oTd.innerHTML = '<button class="normal-button" onclick="addDataRegion(\''+drName+'\',\''+drCaption+'\');loadData();">添加</button>';}}}//加载下方数据列表function searchDataRegion2(drJson, s) {//删除所有行var tb1 = document.getElementById("bkmkTable2");var rCount = tb1.rows.length;for (var i = 1; i < rCount; i++) {tb1.deleteRow(1);}let dataRegionsJson = drJson;if('' == dataRegionsJson) dataRegionsJson = '[]';let dataRegionsObj = JSON.parse(dataRegionsJson);var oTable = document.getElementById("bkmkTable2");var tbodyObj = oTable.tBodies[0];for(let key in dataRegionsObj ){let drName = dataRegionsObj[key].name;if (drName.toLocaleLowerCase().indexOf(s.toLocaleLowerCase()) > -1) {var oTr = tbodyObj.insertRow();var oTd = oTr.insertCell();oTd.innerHTML = drName;oTd = oTr.insertCell();oTd.innerHTML = '<button class="delete-button" onclick="deleteDataRegion(\''+ drName +'\');loadData();">删除</button> <button class="locate-button" onclick="locateDataRegion(\''+ drName +'\');">定位</button>';}}}function locateDataRegion(drName) {pageofficectrl.word.LocateDataRegion(drName);}function deleteDataRegion(drName){pageofficectrl.word.DeleteDataRegion(drName);}function addDataRegion(drName, drValue){pageofficectrl.word.AddDataRegion(drName, drValue);}function AfterDocumentOpened() {loadData();}</script><div id="left-container"><div id="left-title">定义数据区域</div><div class="input-group"><span style="font-size: 14px;">待添加区域:</span><input type="text" id="inputKey1" oninput="loadData();" placeholder="请输入数据区域关键字搜索"></div><div class="container"><table id="bkmkTable"><thead><tr><th>数据区域</th><th>显示文字</th><th>操作</th></tr></thead><tbody><!-- 数据行 --></tbody></table></div><div class="input-group" style="margin-top: 20px"><span style="font-size: 14px;">已添加区域:</span><input type="text" id="inputKey2" oninput="loadData();" placeholder="请输入数据区域关键字搜索"></div><div class="container"><table id="bkmkTable2"><thead><tr><th>数据区域</th><th>操作</th></tr></thead><tbody><!-- 数据行 --></tbody></table></div>
</div>
在最终需要动态填充数据到word模板中生成正式合同文件时,开发人员只管编写代码给所有的数据区域赋值即可,无需关心用户自定义的word模板中到底使用了哪些数据区域,因为那些没有使用的数据区域会被PageOffice自动忽略掉;而最终用户也可以根据自己的实际需要定义好word模板中各项数据及其位置,无需关心数据从哪里来,也不用事事都与开发人员沟通,当业务需求发生简单的变化时,可以自主修改word模板来满足新的需求。这样一来,不管是用户还是开发人员,都在一定程度上从这种纷杂多变的业务需求中解脱出来。
参考链接:用户自定义模板中数据区域
相关文章:

国产linux系统(银河麒麟,统信uos)使用 PageOffice自定义Word模版中的数据区域
PageOffice 国产版 :支持信创系统,支持银河麒麟V10和统信UOS,支持X86(intel、兆芯、海光等)、ARM(飞腾、鲲鹏、麒麟等)、龙芯(Mips、LoogArch)芯片架构。 在实际的Wor…...

基于基金净值百分位的交易策略
策略来源:睿思量化小程序 基金净值百分位,是衡量当前基金净值在过去一段时间内的相对位置。以近一年为例,若某基金净值百分位为30%,意味着过去一年中有30%的时间基金净值低于当前值,70%的时间高于当前值。这一指标犹如…...

2025蓝桥杯JAVA编程题练习Day8
1. 路径 题目描述 小蓝学习了最短路径之后特别高兴,他定义了一个特别的图,希望找到图 中的最短路径。 小蓝的图由 2021 个结点组成,依次编号 1 至 2021。 对于两个不同的结点 a, b,如果 a 和 b 的差的绝对值大于 21࿰…...

通信安全堡垒:profinet转ethernet ip主网关提升冶炼安全与连接
作为钢铁冶炼生产线的安全检查员,我在此提交关于使用profinet转ethernetip网关前后对生产线连接及安全影响的检查报告。 使用profinet转ethernetip网关前的情况: 在未使用profinet转ethernetip网关之前,我们的EtherNet/IP测温仪和流量计与PR…...

DL00219-基于深度学习的水稻病害检测系统含源码
🌾 基于深度学习的水稻病害检测系统 — 智能农业的未来,守护农田的每一寸土地! 🚜 完整系统获取见文末 水稻病害检测,一直是农业领域的一大难题。传统的人工检测不仅耗时耗力,还容易因经验不足导致漏检或误…...
在24GB显存大小的GPU上运行27GB的Pytorch模型
在24GB显存大小的GPU上运行27GB的Pytorch模型 一.背景:显存不足时的破局之道1.1 大模型时代的显存困境1.2 CUDA统一内存的魔法二.性能测试数据深度解读关键发现:三.复现过程3.1 准备自定义分配器3.2 准备测试程序3.3 执行流程3.4 开始测试四.原理深度剖析4.1 统一内存的工作机…...
【数据机构】2. 线性表之“链表”
- 第 97 篇 - Date: 2025 - 05 - 16 Author: 郑龙浩/仟墨 【数据结构 2】 续上一篇 线性表之“顺序表” 文章目录 3 链表(用指针来首位相连)① 基本介绍② 分类 与 变量命名1 )分类:2 )大体介绍不同结构: ③ “单链表” 的实现:*…...

【51单片机中断】
目录 配置流程 1.在IE寄存器中开启总中断通道和需要的某中断通道 2.在TCON寄存器开启所用中断的触发方式 3.使用中断函数完成中断 4.若需要中断嵌套则在IP寄存器中配置 5.若需要使用串口的中断,则配置SCON寄存器 6.代码示例 配置流程 1.在IE寄存器中开启总…...

JavaSE基础语法之方法
方法 一、方法入门 1.方法定义 方法是一种语法结构,它可以把一段代码封装成一个功能,以便重复调用。 2.方法的格式 修饰符 返回值类型 方法名( 形参列表 ){方法体代码(需要执行的功能代码) }示例: public static int sum ( int a ,…...

华为网路设备学习-22(路由器OSPF-LSA及特殊详解)
一、基本概念 OSPF协议的基本概念 OSPF是一种内部网关协议(IGP),主要用于在自治系统(AS)内部使路由器获得远端网络的路由信息。OSPF是一种链路状态路由协议,不直接传递路由表,而是通过交换链路…...

go-数据库基本操作
1. 配置数据库 package mainimport ("gorm.io/driver/mysql""gorm.io/gorm" ) #配置表结构 type User struct {ID int64 json:"id" gorm:"primary_key" // 主键ID自增长Username stringPassword string } #配置连接接信息 func…...
vue 中绑定样式 【style样式绑定】
style样式绑定 在 Vue 中,style 的绑定与 class 类似,也是通过 v-bind:style(或简写 :style)实现的,允许你动态地控制内联样式。Vue 对 style 做了非常智能的处理,支持对象、数组、字符串等多种语法&#…...
印刷业直角坐标型码垛机器人系统设计与应用研究
摘要 随着印刷行业自动化水平的提升,本文针对传统人工码垛存在的效率低、标准化程度不足等问题,提出基于直角坐标系的专用码垛机器人解决方案。重点阐述机械臂结构设计、运动控制系统及智能抓取装置三大核心模块,通过实际应用验证系统在速度、…...

Mysql存储过程(附案例)
文章目录 存储过程概述1、基本语法2、变量①、系统变量②、用户自定义变量③、局部变量 3、流程控制语句①、if语句②、参数③、case语句④、while语句⑤、repeat语句⑥、loop语句⑦、cursor游标⑧、handler 4、存储函数 存储过程概述 存储过程是事先经过编译并存储在数据…...

【Web应用】Vue 项目前端项目文件夹和文件介绍
文章目录 ⭐前言⭐一、文件夹介绍🌟1、.idea🌟2、bin🌟3、build🌟4、node_modules🌟5、public🌟6、src ⭐二、文件介绍🌟1、.editorconfig🌟2、.env.development、.env.production、…...

Stratix 10 FPGA DDR4 选型
文章目录 前言DDR3 和 DDR4 的区别Micron 8Gb DDR4 规格书详解Micron 8Gb DDR4 编码规则ConfigurationDDR4 寻址原理 Speed Grade内存的频率MT/s 与 MHz:更好的内存速度衡量指标为什么 DDR4 的核心频率与 I/O 总线频率的比例是 1:4 呢? 带宽 Altera FPGA…...
Rust 输出到命令行
Rust 输出到命令行 引言 Rust 是一门系统编程语言,以其高性能、内存安全、并发支持和零成本抽象等特性而闻名。在开发过程中,将 Rust 程序的输出传递到命令行是常见的需求。本文将详细介绍 Rust 输出到命令行的多种方法,帮助读者掌握这一技…...
费曼技巧及提高计划
费曼技巧及提高计划 一、什么是费曼技巧? 费曼技巧(Feynman Technique)由诺贝尔物理学奖得主理查德费曼提出,是一种通过“以教代学”来彻底理解复杂概念的学习方法。其核心逻辑是: “如果你不能简单解释一件事&#x…...
扩展:React 项目执行 yarn eject 后的 config 目录结构详解
扩展:React 项目执行 yarn eject 后的 config 目录结构详解 什么是 yarn eject?React 项目执行 yarn eject 后的 config 目录结构详解📁 config 目录结构各文件作用详解env.jsgetHttpsConfig.jsmodules.jspaths.jswebpack.config.jswebpackDe…...

CMU-15445(4)——PROJECT#1-BufferPoolManager-Task#2
PROJECT#1-BufferPoolManager Task #2 - Disk Scheduler 在前一节我实现了 TASK1 并通过了测试,在本节中,我将逐步实现 TASK2。 如上图,Page Table(页表)通过哈希表实现,用于跟踪当前存在于内存中的页&am…...

百度智能云千帆携手联想,共创MCP生态宇宙
5月7日,2025联想创新科技大会(Tech World)在上海世博中心举行,本届大会以“让AI成为创新生产力”为主题。会上,联想集团董事长兼CEO杨元庆展示了包括覆盖全场景的超级智能体矩阵,包括个人超级智能体、企业超…...
Python 中的 typing.ClassVar 详解
一、ClassVar 的定义和基本用途 ClassVar 是 typing 模块中提供的一种特殊类型,用于在类型注解中标记类变量(静态变量)。根据官方文档,使用 ClassVar[…] 注释的属性表示该属性只在类层面使用,不应在实例上赋值 例如&…...

【动态导通电阻】GaN HEMT动态导通电阻的精确测量
2023 年 7 月,瑞士洛桑联邦理工学院的 Hongkeng Zhu 和 Elison Matioli 在《IEEE Transactions on Power Electronics》期刊发表了题为《Accurate Measurement of Dynamic ON-Resistance in GaN Transistors at Steady-State》的文章,基于提出的稳态测量方法,研究了氮化镓(…...

java 使用zxing生成条形码(可自定义文字位置、边框样式)
最新工作中遇到生成条形码的需求,经过一番摸索之后找到了zxing这个工具类,实现效果如下: 首先引入依赖: <!-- 条形码生成器 --><dependency><groupId>com.google.zxing</groupId><artifactId&g…...

day19-线性表(顺序表)(链表I)
一、补充 安装软件命令: sudo apt-get install (软件名) 安装格式化对齐:sudo apt-get install clang-format内存泄漏检测工具: sudo apt-get install valgrind 编译后,使用命令 valgrind ./a.out 即可看内存是…...

CSS- 2.1 实战之图文混排、表格、表单、学校官网一级导航栏
本系列可作为前端学习系列的笔记,代码的运行环境是在HBuilder中,小编会将代码复制下来,大家复制下来就可以练习了,方便大家学习。 HTML系列文章 已经收录在前端专栏,有需要的宝宝们可以点击前端专栏查看! 点…...
Armijo rule
非精线搜索步长规则Armijo规则&Goldstein规则&Wolfe规则_armijo rule-CSDN博客 [原创]用“人话”解释不精确线搜索中的Armijo-Goldstein准则及Wolfe-Powell准则 – 编码无悔 / Intent & Focused...

从零搭建AI工作站:Gemma3大模型本地部署+WebUI配置全套方案
文章目录 前言1. 安装Ollama2.Gemma3模型安装与运行3. 安装Open WebUI图形化界面3.1 Open WebUI安装运行3.2 添加模型3.3 多模态测试 4. 安装内网穿透工具5. 配置固定公网地址总结 前言 如今各家的AI大模型厮杀得如火如荼,每天都有新的突破。今天我要给大家安利一款…...

贝叶斯优化Transformer融合支持向量机多变量时间序列预测,Matlab实现
贝叶斯优化Transformer融合支持向量机多变量时间序列预测,Matlab实现 目录 贝叶斯优化Transformer融合支持向量机多变量时间序列预测,Matlab实现效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.BO-TransformerSVM多变量时间序列预测,…...
执行apt-get update 报错ModuleNotFoundError: No module named ‘apt_pkg‘的解决方案汇总
Ubuntu版本ubuntu18.04 报错内容: //执行apt-get upgrade报错: Traceback :File “/usr/lib/cnf-update-db”, line 8, in <module>from CommandNotFound.db.creator import DbcreatorFile “/usr/lib/python3/dist-packages/CommandNotFound/db…...