ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

NocoBase 模板打印插件指南:用 Word/Excel/PPT 模板动态生成业务文档与 PDF

NocoBase 模板打印插件指南:用 Word/Excel/PPT 模板动态生成业务文档与 PDF NocoBase 模板打印插件指南用 Word/Excel/PPT 模板动态生成业务文档与 PDF【免费下载链接】nocobaseNocoBase is an open-source AI no-code platform for building business systems fast. Instead of generating everything from scratch, AI works on top of production-proven infrastructure and a WYSIWYG no-code interface, so you get both speed and reliability.项目地址: https://gitcode.com/GitHub_Trending/no/nocobase模板打印nocobase/plugin-action-template-print是 NocoBase 的商业插件之一支持用户在应用内直接以 Word、Excel、PowerPoint 文件为模板通过占位符与逻辑结构动态填充业务数据一键生成报价单、发票、合同等预定格式文件并可直接输出 PDF。本文将以 模板打印文档 为主线完整覆盖从安装配置、界面操作、模板语法到 HTTP API 集成对应 配置说明、基础用法、循环处理、HTTP API的实战路径帮助你在自己的业务系统中快速落地文档自动生成能力。插件概述与核心能力模板打印插件支持使用 Word、Excel 和 PowerPoint 编辑模板文件支持.docx、.xlsx、.pptx格式在模板中设置占位符和逻辑结构从而动态生成预定格式的文件包括.docx、.xlsx、.pptx以及 PDF。它适合在业务系统内批量生成各类正式文档例如报价单发票合同其核心能力可以归纳为以下几个方面多格式支持兼容 Word、Excel 和 PowerPoint 模板满足不同文档生成需求。动态数据填充通过占位符和逻辑结构自动填充和生成文档内容。灵活的模板管理支持添加、编辑、删除和分类管理模板便于维护和使用。丰富的模板语法支持基本替换、数组访问、循环、条件输出等多种模板语法满足复杂文档生成需求。格式化器支持提供条件输出、日期格式化、数字格式化等功能提升文档的可读性和专业性详见 格式化器文档 及日期、数字、货币、文本、时间间隔、数组格式化、媒体字段等子文档。图片字段支持支持在模板中输出附件图片与手写签名图片。高效的输出格式支持直接生成 PDF 文件方便分享和打印。从插件的元信息插件页可以看到该插件面向 NocoBase 1.x 与 2.x 版本属于商业插件isFree: false非内置builtIn: false默认不启用defaultEnabled: false需要单独安装激活后使用。安装与运行环境准备安装插件该插件属于商业插件详细的安装与升级方式请参考 NocoBase 商业插件激活指南在 NocoBase 官网博客可查阅路径为nocobase-commercial-license-activation-guide。安装完成并激活后插件才会出现在界面操作菜单中。安装 LibreOffice生成 PDF 的前置条件模板打印生成 PDF 必须依赖 LibreOffice。你可以前往 LibreOffice 官网下载对应操作系统版本安装。对于 Docker 部署的 NocoBase可以在./storage/scripts目录下编写一段安装脚本随容器启动时执行。mkdir ./storage/scripts cd ./storage/scripts vim install-libreoffice.shinstall-libreoffice.sh的内容如下以 Debian bookworm 为例将 LibreOffice 安装到/opt/libreoffice24.8并建立libreoffice软链接#!/bin/bash # Define variables INSTALL_DIR/opt/libreoffice24.8 DOWNLOAD_URLLibreOffice 24.8.5.2 Linux x86-64 deb 安装包下载地址 # Check if LibreOffice is already installed if [ -d $INSTALL_DIR ]; then echo LibreOffice is already installed, skipping installation. exit 0 fi # Update APT sources tee /etc/apt/sources.list /dev/null EOF deb http://mirrors.aliyun.com/debian/ bookworm main contrib non-free deb-src http://mirrors.aliyun.com/debian/ bookworm main contrib non-free deb http://mirrors.aliyun.com/debian-security/ bookworm-security main contrib non-free deb-src http://mirrors.aliyun.com/debian-security/ bookworm-security main contrib non-free deb http://mirrors.aliyun.com/debian/ bookworm-updates main contrib non-free deb-src http://mirrors.aliyun.com/debian/ bookworm-updates main contrib non-free deb http://mirrors.aliyun.com/debian/ bookworm-backports main contrib non-free deb-src http://mirrors.aliyun.com/debian/ bookworm-backports main contrib non-free EOF # Update APT and install dependencies apt-get update apt-get install -y \ libfreetype6 \ fontconfig \ libgssapi-krb5-2 \ libxml2 \ libnss3 \ libdbus-1-3 \ libcairo2 \ libxslt1.1 \ libglib2.0-0 \ libcups2 \ libx11-xcb1 \ fonts-liberation \ fonts-noto-cjk \ wget rm -rf /var/lib/apt/lists/* cd /app/nocobase/storage/scripts # Download and install LibreOffice if not already present if [ ! -d ./libreoffice ]; then rm -rf libreoffice.tar.gz wget --no-check-certificate -O libreoffice.tar.gz $DOWNLOAD_URL if [ $? -ne 0 ]; then echo Failed to download LibreOffice. exit 1 fi rm -rf libreoffice mkdir libreoffice tar -zxvf libreoffice.tar.gz -C ./libreoffice --strip-components1 if [ $? -ne 0 ]; then echo Failed to extract LibreOffice. exit 1 fi fi # Install LibreOffice dpkg -i libreoffice/DEBS/*.deb ln -s /opt/libreoffice24.8/program/soffice.bin /usr/bin/libreoffice libreoffice --version if [ $? -ne 0 ]; then echo Failed to install LibreOffice. exit 1 fi echo LibreOffice installation completed successfully.脚本要点说明脚本会先检查/opt/libreoffice24.8是否已存在已安装则直接跳过保证容器重启不会重复安装安装过程会写入阿里云镜像的 Debian bookworm APT 源并安装 LibreOffice 运行所需的系统依赖字体、图形库等其中fonts-noto-cjk用于保证中文文档的正常渲染最后建立libreoffice全局软链接并执行libreoffice --version校验安装结果。安装完成后重启 app 容器使脚本生效docker compose restart app # 查看日志 docker compose logs app检测是否安装成功$ docker compose exec app bash -c libreoffice --version LibreOffice 24.8.4.2 bb3cfa12c7b1bf994ecc5649a80400d06cd71002看到类似上面的版本输出即表示 LibreOffice 环境就绪可以正常转换 PDF。界面配置激活模板打印功能模板打印目前支持详情区块和表格区块两类场景二者的激活与配置流程基本一致。详情区块打开详情区块在应用中进入需要使用模板打印功能的详情区块。进入配置操作菜单在界面上方点击配置操作菜单。选择模板打印在下拉菜单中点击模板打印选项以激活插件功能。配置模板进入模板配置页面在模板打印按钮的配置菜单中选择模板配置选项。添加新模板点击添加模板按钮进入模板添加页面。填写模板信息在模板表单中填写模板名称选择模板类型Word、Excel、PowerPoint并上传相应的模板文件支持.docx、.xlsx、.pptx格式。编辑和保存模板来到字段列表页面复制字段并填充到模板中。这里有两个重要建议模板打印已支持附件字段与手写签名字段字段列表会自动生成对应的模板表达式若希望在模板中输出图片建议始终从字段列表直接复制变量而不要手写:attachment()或:signature()表达式以保证表达式与当前版本兼容。填写完毕后点击保存按钮完成模板的添加。模板管理点击模板列表右侧的使用按钮可以激活模板点击编辑按钮可以修改模板名称或替换模板文件点击下载按钮可以下载已经配置好的模板文件点击删除按钮可以移除不再需要的模板系统会提示确认操作以避免误删。表格区块表格区块的用法和详情区块基本相同区别在于两点支持多条数据打印需先勾选要打印的记录最多可同时打印 100 条界面限制。模板隔离管理表格区块与详情区块的模板互不通用——因为数据结构不同一个是对象一个是数组模板中引用的字段路径也因此不同。模板基础语法占位符替换与数据访问模板打印插件提供了多种语法可以在模板中灵活地插入动态数据和逻辑结构。完整语法说明见 基础用法。基本替换使用{d.xxx}格式的占位符进行数据替换。d代表当前数据集点号后跟字段名{d.title}读取数据集中的title字段。{d.date}读取数据集中的date字段。示例模板内容如下——尊敬的客户您好 感谢您购买我们的产品{d.productName}。 订单编号{d.orderId} 订单日期{d.orderDate} 祝您使用愉快数据集{ productName: 智能手表, orderId: A123456789, orderDate: 2025-01-01 }渲染结果尊敬的客户您好 感谢您购买我们的产品智能手表。 订单编号A123456789 订单日期2025-01-01 祝您使用愉快访问子对象若数据集中包含子对象可以通过点符号逐级访问子对象的属性。语法{d.parent.child}数据集{ customer: { name: 李雷, contact: { email: lileiexample.com, phone: 13800138000 } } }模板内容客户姓名{d.customer.name} 邮箱地址{d.customer.contact.email} 联系电话{d.customer.contact.phone}渲染结果客户姓名李雷 邮箱地址lileiexample.com 联系电话13800138000访问数组若数据集中包含数组可使用保留关键字i来访问数组中的元素i表示数组下标。语法{d.arrayName[i].field}数据集{ staffs: [ { firstname: James, lastname: Anderson }, { firstname: Emily, lastname: Roberts }, { firstname: Michael, lastname: Johnson } ] }模板内容第一个员工姓是 {d.staffs[i0].lastname}名是 {d.staffs[i0].firstname}渲染结果第一个员工姓是 Anderson名是 James循环与高级数据处理循环处理用于对数组或对象中的数据进行重复渲染通过定义循环起始和结束标记来识别需要重复的内容。详见 循环处理。遍历数组语法说明使用标签{d.array[i].属性}定义当前循环项用{d.array[i1].属性}指定下一项以标识循环区域循环时会自动以第一行[i]部分作为模板进行重复模板中只需写一次循环示例即可。示例语法格式{d.数组名[i].属性} {d.数组名[i1].属性}示例简单数组循环数据{ cars: [ { brand: Toyota, id: 1 }, { brand: Hyundai, id: 2 }, { brand: BMW, id: 3 }, { brand: Peugeot,id: 4 } ] }模板Carsid {d.cars[i].brand}{d.cars[i].id} {d.cars[i1].brand}结果Carsid Toyota1 Hyundai2 BMW3 Peugeot4示例嵌套数组循环适用于数组内嵌套数组的情况可以无限层级嵌套。数据[ { brand: Toyota, models: [ { size: Prius 4, power: 125 }, { size: Prius 5, power: 139 } ] }, { brand: Kia, models: [ { size: EV4, power: 450 }, { size: EV6, power: 500 } ] } ]模板{d[i].brand} Models {d[i].models[i].size} - {d[i].models[i].power} {d[i].models[i1].size} {d[i1].brand}结果Toyota Models Prius 4 - 125 Prius 5 - 139 Kia示例双向循环高级功能v4.8.0双向循环可同时在行和列上进行迭代适用于生成对比表等复杂布局。注意部分格式目前仅 DOCX、HTML、MD 模板官方支持。数据{ titles: [ { name: Kia }, { name: Toyota }, { name: Hopium } ], cars: [ { models: [ EV3, Prius 1, Prototype ] }, { models: [ EV4, Prius 2, ] }, { models: [ EV6, Prius 3, ] } ] }模板{d.titles[i].name}{d.titles[i1].name} {d.cars[i].models[i]}{d.cars[i].models[i1]} {d.cars[i1].models[i]}结果KiaToyotaHopium EV3Prius 1Prototype EV4Prius 2 EV6Prius 3示例访问循环迭代器值v4.0.0在循环中可以直接访问当前迭代的索引值便于实现特殊格式需求。模板示例{d[i].cars[i].other.wheels[i].tire.subObject:add(.i):add(..i):add(...i)}点号的数量用于表示不同层级的索引值例如.i表示当前层..i表示上一层。需要说明的是当前该能力存在逆序问题使用时请以官方说明为准。遍历对象对于对象中的属性可以使用.att获取属性名称使用.val获取属性值迭代时每次会遍历一个属性项。示例语法格式{d.对象名[i].att} // 属性名称 {d.对象名[i].val} // 属性值示例对象属性遍历数据{ myObject: { paul: 10, jack: 20, bob: 30 } }模板People namePeople age {d.myObject[i].att}{d.myObject[i].val} {d.myObject[i1].att}{d.myObject[i1].val}结果People namePeople age paul10 jack20 bob30排序处理利用排序功能可以在模板中直接对数组数据进行排序适用于需要按字段如金额、时间排列输出的场景。升序排序语法在循环标签中使用属性作为排序依据——{d.array[排序属性, i].属性} {d.array[排序属性1, i1].属性}若需要多重排序可在方括号内以逗号分隔多个排序属性。示例按数字属性排序数据{ cars: [ { brand: Ferrari, power: 3 }, { brand: Peugeot, power: 1 }, { brand: BMW, power: 2 }, { brand: Lexus, power: 1 } ] }模板Cars {d.cars[power, i].brand} {d.cars[power1, i1].brand}结果Cars Peugeot Lexus BMW Ferrari示例多属性排序数据{ cars: [ { brand: Ferrari, power: 3, sub: { size: 1 } }, { brand: Aptera, power: 1, sub: { size: 20 } }, { brand: Peugeot, power: 1, sub: { size: 20 } }, { brand: BMW, power: 2, sub: { size: 1 } }, { brand: Kia, power: 1, sub: { size: 10 } } ] }模板先按power排序再按sub.size排序Cars {d.cars[power, sub.size, i].brand} {d.cars[power1, sub.size1, i1].brand}结果Cars Kia Aptera Peugeot BMW Ferrari筛选处理筛选处理用于根据特定条件过滤循环中的数据行适合只打印符合条件的明细这类需求。数字筛选语法在循环标签中增加条件例如age 19——{d.array[i, 条件].属性}示例数字筛选数据[ { name: John, age: 20 }, { name: Eva, age: 18 }, { name: Bob, age: 25 }, { name: Charly, age: 30 } ]模板筛选 19 age 30 的记录People {d[i, age 19, age 30].name} {d[i1, age 19, age 30].name}结果People John Bob字符串筛选语法使用单引号标明字符串条件——{d.array[i, typerocket].name}示例字符串筛选数据[ { name: Falcon 9, type: rocket }, { name: Model S, type: car }, { name: Model 3, type: car }, { name: Falcon Heavy,type: rocket } ]模板People {d[i, typerocket].name} {d[i1, typerocket].name}结果People Falcon 9 Falcon Heavy筛选前 N 项可利用循环索引i过滤出前 N 个元素——{d.array[i, i N].属性}示例筛选前两项People {d[i, i 2].name} {d[i1, i 2].name}结果为People Falcon 9 Model S排除最后 N 项通过负索引i表示倒数项——{d.array[i-1].属性}获取最后一项{d.array[i, i!-1].属性}排除最后一项。示例最后一项: {d[i-1].name} 排除最后一项: {d[i, i!-1].name} {d[i1, i!-1].name} 排除最后两项: {d[i, i-2].name} {d[i1, i-2].name}结果最后一项: Falcon Heavy 排除最后一项: Falcon 9 Model S Model 3 排除最后两项: Falcon 9 Model S去重处理通过自定义迭代器可根据某个属性的值获取唯一不重复的项。语法与普通循环类似但会自动忽略重复的项。示例格式{d.array[属性].属性} {d.array[属性1].属性}示例选择唯一数据数据[ { type: car, brand: Hyundai }, { type: plane, brand: Airbus }, { type: plane, brand: Boeing }, { type: car, brand: Toyota } ]模板Vehicles {d[type].brand} {d[type1].brand}结果每种type只保留首项Vehicles Hyundai Airbus通过 HTTP API 触发打印除了界面操作模板打印支持通过 HTTP API 直接触发文档渲染与下载。无论是详情区块还是表格区块本质上都是对当前业务资源发起templatePrint动作。完整说明见 HTTP API。接口形态curl -X POST \ -H Authorization: Bearer JWT \ -H Content-Type: application/json \ http://localhost:3000/api/resource_name:templatePrint \ --data-raw {...}说明resource_name为当前数据表对应的资源名接口返回的是二进制文件流而不是 JSON 数据调用方需要具备当前资源的查询权限以及对应模板打印按钮的使用权限调用接口需要通过 Authorization 请求头传递基于用户登录的 JWT 令牌否则将被拒绝访问。请求体参数参数类型必填说明templateNamestring是模板名称对应模板管理中配置的模板标识。blockNamestring是区块类型。表格区块传table详情区块传details。timezonestring否时区例如Asia/Shanghai。用于模板中的日期时间渲染。uidstring否模板打印按钮的 schema uid用于权限校验。convertedToPDFboolean否是否转换为 PDF。传true时返回.pdf文件。queryParamsobject否传递给底层数据查询的参数。queryParams.pagenumber \| null否分页页码。设为null表示不按页截取。queryParams.pageSizenumber \| null否每页条数。设为null表示不按页截取。queryParams.filterobject否过滤条件会与 ACL 固定过滤条件自动合并。queryParams.appendsstring[]否需要附加查询的关联字段。queryParams.filterByTkstring \| object否详情区块常用用于指定主键值。queryParams.sort等其他参数any否其他查询参数会原样透传到底层资源查询。表格区块打印选中记录或当前页结果表格区块使用同一个接口通过blockName: table指定列表打印模式服务端会对资源执行find查询并把结果数组传入模板。适用于从表格区块中勾选部分记录进行打印或者保留当前页分页上下文进行打印。常见做法是将queryParams.page和queryParams.pageSize设置为当前表格页码与每页条数将勾选记录的主键拼成filter.id.$in条件。curl https://your-host/api/resource_name:templatePrint \ -H Authorization: Bearer JWT \ -H Content-Type: application/json \ --data-raw { queryParams: { pageSize: 20, filter: { id: { $in: [1, 2] } }, appends: [], page: 1 }, templateName: 9012hy7ahn4, blockName: table, timezone: Asia/Shanghai, uid: ixs3fx3x6is }这类请求的含义如下blockName为table表示按列表数据渲染模板filter.id.$in用于指定需要打印的记录集合page与pageSize保留当前分页上下文便于与界面行为一致appends可以按需补充关联字段。表格区块打印全部符合条件的数据适用于点击表格区块中的打印全部记录时的调用方式。此时不再按当前页分页截取而是直接拉取所有符合当前筛选条件的数据关键点是将queryParams.page和queryParams.pageSize显式传为null。curl https://your-host/api/resource_name:templatePrint \ -H Authorization: Bearer JWT \ -H Content-Type: application/json \ --data-raw { queryParams: { pageSize: null, filter: {}, appends: [], page: null }, templateName: 9012hy7ahn4, blockName: table, timezone: Asia/Shanghai, uid: ixs3fx3x6is }这类请求的含义如下page: null与pageSize: null表示取消分页限制filter: {}表示不额外附加筛选条件如果界面上已有筛选条件也可以直接放入这里服务端会查询全部符合条件的数据并批量渲染模板。注意表格区块单次最多打印 300 条记录。超过限制时接口会返回400错误。需要留意的是界面勾选打印的上限为 100 条而 API 批量的上限为 300 条两者限制不同。详情区块详情区块同样使用templatePrint动作但通常传入blockName: detailsqueryParams.filterByTk指定当前记录主键queryParams.appends指定需要追加查询的关联字段服务端会对资源执行findOne查询并把结果对象传入模板因此详情区块的模板中数据结构是单个对象与表格区块的数组结构不同这也是两类区块模板互不通用的根本原因。返回结果调用成功后接口直接返回文件流典型响应头如下Content-Type: application/octet-stream Content-Disposition: attachment; filenametemplate-title-suffix.ext说明当convertedToPDF为true时返回文件扩展名为.pdf否则返回模板原始类型对应的文件例如.docx、.xlsx或.pptx前端通常根据Content-Disposition中的文件名触发浏览器下载。延伸阅读模板打印文档首页介绍与安装模板打印配置说明模板基础语法模板循环与高级处理模板格式化器日期、数字、货币、文本、时间间隔、数组、媒体字段模板打印 HTTP API模板打印常见问题 FAQ模板打印实际场景示例使用 API 密钥进行接口调用可参考 在 NocoBase 中使用 API 密钥【免费下载链接】nocobaseNocoBase is an open-source AI no-code platform for building business systems fast. Instead of generating everything from scratch, AI works on top of production-proven infrastructure and a WYSIWYG no-code interface, so you get both speed and reliability.项目地址: https://gitcode.com/GitHub_Trending/no/nocobase创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表