Qt WORD/PDF(五)使用Json一键填充Word表格
关于QT Widget 其它文章请点击这里: QT Widget
国际站点 GitHub: https://github.com/chenchuhan
国内站点 Gitee : https://gitee.com/chuck_chee
姊妹篇:
《Qt WORD/PDF(一)使用 QtPdfium库实现 PDF 操作》
《Qt WORD/PDF(二)使用 QtPdfium库实现 PDF 预览、打印等》
《Qt WORD/PDF(三)使用 QAxObject 对 Word 替换(QML)》
《Qt WORD/PDF(四)使用 QAxObject 对 Word 替换(QWidget)》
《Qt WORD/PDF(五)使用Json一键填充Word表格》》
一、前言
QAxObject 是 Qt 提供的一个类,它用于与 COM(Component Object Model)对象进行交互。COM 是一种微软的技术,广泛用于各种应用程序之间的通信,尤其在 Windows 平台上,很多软件和系统组件都是基于 COM 构建的。QAxObject 类提供了一个 Qt 风格的接口,简化了与这些 COM 对象的交互。
此Demo主要功能是利用 Qt 和 Microsoft Word 的 COM 接口实现自动化操作,填充和高亮 Word 文档中的表格内容。
它可以应用于自动化报告生成,例如在教育系统中自动生成学生成绩单,或在企业中生成财务报表和考勤记录。模板文档与 JSON 数据源结合,减少了人工操作的工作量。
二、演示
Json 文件导入一键填充/替换模板表格,根据Json填充单元格内容,候选单元格背景高亮等:
三、部分代码
//表格填充方案
void WordTableOperation::fillWordTable()
{QString jsonPath = _jsonFile;QString templatePath = _templateFile;QString outputPath = _reportFile;qDebug() << "jsonPath:" << jsonPath;qDebug() << "templatePath:" << templatePath;qDebug() << "outputPath:" << outputPath;if (jsonPath.isEmpty() || templatePath.isEmpty() || outputPath.isEmpty()) {qDebug() << "请填写模板路径和输出路径!";return;}QFile file(jsonPath);if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {qWarning() << "Failed to open JSON file!";return;}wordApp = std::make_unique<QAxObject>("Word.Application");documents = wordApp->querySubObject("Documents");document = documents->querySubObject("Open(const QString&)", templatePath);if (!document) {qDebug() << "Failed to open document.";return ;}QAxObject *tables = document->querySubObject("Tables");QAxObject *table = tables->querySubObject("Item(int)", 1);QAxObject* cells = table->querySubObject("Range")->querySubObject("Cells");if (!cells) {qDebug() << "无法获取表格的 Cells。";return;}int cellCount = cells->dynamicCall("Count()").toInt();qDebug() << "表格总单元格数量:" << cellCount;///JsonQJsonDocument doc = QJsonDocument::fromJson(file.readAll());file.close();QJsonObject rootObj = doc.object();QJsonObject mainCard = rootObj.value("成绩表").toObject();//3~7_setCellValueint(3, cells, mainCard["姓名"].toString());_setCellValueint(5, cells, mainCard["年级"].toString());_setCellValueint(7, cells, mainCard["性别"].toString());//10~25QJsonObject grade = mainCard.value("分数").toObject();_setCellValueint(10, cells, grade.value("语文").toString());_setCellValueint(12, cells, grade.value("数学").toString());_setCellValueint(14, cells, grade.value("英语").toString());_highlightCells(16,20, cells, mainCard, "级别");document->dynamicCall("SaveAs(const QString&)", outputPath); //另存为wordqDebug() << "word 另存为:" << outputPath;document->dynamicCall("Close()");wordApp->dynamicCall("Quit()");}// 设置单元格内容的封装函数
void WordTableOperation::_setCellValueint(int cellIndex, QAxObject* cells, const QString& value) {// 获取目标单元格QAxObject* cell = cells->querySubObject("Item(int)", cellIndex);if (!cell) {qWarning() << "无法获取单元格,索引:" << cellIndex;cells->deleteLater();return;}// 获取 Range 并设置文本QAxObject* range = cell->querySubObject("Range");range->setProperty("Text", value);}void WordTableOperation::_highlightCells(int start, int end, QAxObject* cells, const QJsonObject& jsonObject, const QString& name) {QString targetValue = jsonObject.value(name).toString();for (int i = start; i <= end; ++i) {QAxObject* cell = cells->querySubObject("Item(int)", i);if (!cell) continue;QAxObject* range = cell->querySubObject("Range");if (!range) continue;QString cellText = range->property("Text").toString().simplified();QAxObject* shading = cell->querySubObject("Shading");//只要包含就行if (cellText.contains(targetValue)) {if (shading) {shading->setProperty("BackgroundPatternColor", QVariant(16753920));}} else {if (shading) {shading->setProperty("BackgroundPatternColor", QVariant(16777215)); // White color QVariant(QColor(Qt::white).rgb()));}}}
}
Json文件
{"成绩表": {"姓名": "小明","年级": "四年级","性别": "男","分数": {"语文": "92","数学": "98","英语": "91"},"级别": "优秀"}
}
四、简要分析
获取表格和单元格信息:
QAxObject* tables = document->querySubObject("Tables");
QAxObject* table = tables->querySubObject("Item(int)", 1);
QAxObject* cells = table->querySubObject("Range")->querySubObject("Cells");
int cellCount = cells->dynamicCall("Count()").toInt();qDebug() << "表格总单元格数量:" << cellCount;
注意因为表格中行和列是不规则的,所以通过行列获取单元格信息,不如直接获取每一个单元格更合适
int rowCount = table->querySubObject("Rows")->dynamicCall("Count()").toInt();
int colCount = table->querySubObject("Columns")->dynamicCall("Count()").toInt();
填充单元格数据:
void WordTableOperation::_setCellValueint(int cellIndex, QAxObject* cells, const QString& value) {// 获取目标单元格QAxObject* cell = cells->querySubObject("Item(int)", cellIndex);if (!cell) {qWarning() << "无法获取单元格,索引:" << cellIndex;cells->deleteLater();return;}QAxObject* range = cell->querySubObject("Range");range->setProperty("Text", value);
}
单元格背景高亮:
void WordTableOperation::_highlightCells(int start, int end, QAxObject* cells, const QJsonObject& jsonObject, const QString& name) {QString targetValue = jsonObject.value(name).toString();for (int i = start; i <= end; ++i) {QAxObject* cell = cells->querySubObject("Item(int)", i);if (!cell) continue;QAxObject* range = cell->querySubObject("Range");if (!range) continue;QString cellText = range->property("Text").toString().simplified();QAxObject* shading = cell->querySubObject("Shading");//只要包含就行if (cellText.contains(targetValue)) {if (shading) {shading->setProperty("BackgroundPatternColor", QVariant(16753920));}} else {if (shading) {shading->setProperty("BackgroundPatternColor", QVariant(16777215)); }}}
}
五、功能特点:
- 使用 QAxObject 实现了与 Word 的 COM 接口的交互,允许直接操作 Word 文档中的内容;
- Json 文件导入一键填充/替换模板表格,根据Json填充单元格内容,候选单元格背景高亮等;
- 各个路径可设置,合理性判定等。
六、可优化:
- 后续可使用 QScopedPointer 自动管理 QAxObject 的生命周期,避免内存泄漏;
- 可增加对失败情况的详细日志记录(例如,单元格索引等);
- 路径可通过 Setting 保存在内容中;
- 增加预览功能,可结合前文PDF的预览。
关于QGC地面站其它文章请点击这里: QT Widget
相关文章:

Qt WORD/PDF(五)使用Json一键填充Word表格
关于QT Widget 其它文章请点击这里: QT Widget 国际站点 GitHub: https://github.com/chenchuhan 国内站点 Gitee : https://gitee.com/chuck_chee 姊妹篇: 《Qt WORD/PDF(一)使用 QtPdfium库实现 PDF 操作》 《Qt WORD/PDF&#…...
vue3+ts的几个bug调试
由于编译问题,把几个type检查给关闭了,否则错误太多。 1)第一个检查出的问题,拼写错误数组的length,写成了lengh。 2)数组的对象引用。 torStatus Array(8).fill({ ...defaultStatus }) as TorStatus[]…...

DVWA靶场CSRF漏洞通关教程及源码审计
目录标题 CSRFlow源码审计 medium源码审计 high源码审计 impossible源码审计 CSRF low 先修改密码 看到地址栏 复制在另一个网页打开 成功登录 源码审计 没有任何过滤措施,很危险,并且采用了不安全的md5加密 <?phpif( isset( $_GET[ Change ] )…...
前端开发:HTML常见标签
1.注释标签 注释不会显示在界面上 . 目的是提高代码的可读性 . ctrl / 快捷键可以快速进行注释 / 取消注释 . <!-- 我是注释 --> 2.标题标签 有六个 , 从 h1 - h6. 数字越大 , 则字体越小 <h1> hello </h1> //我们所写的csdn的格式中的标题一…...
【机器学习】主动学习-增加标签的操作方法-样本池采样(Pool-Based Sampling)
Pool-Based Sampling Pool-based sampling 是一种主动学习(Active Learning)方法,与流式选择性采样不同,它假设有一个预先定义的未标注样本池,算法从中选择最有价值的样本进行标注,以提升模型的性能。这种…...

【Rust自学】11.9. 单元测试
喜欢的话别忘了点赞、收藏加关注哦,对接下来的教程有兴趣的可以关注专栏。谢谢喵!(・ω・) 11.9.1. 测试的分类 Rust把测试分为两类,一个是单元测试,一个是集成测试。 单元测试比较小也比较专注ÿ…...
深入理解Web存储机制:Cookie、SessionStorage与LocalStorage的区别
文章目录 前言一、Cookie简介二、SessionStorage简介三、LocalStorage简介四、三者之间的比较五、最佳实践建议结语 前言 随着Web应用程序变得越来越复杂,开发者需要更有效的办法来管理客户端数据。Cookie、SessionStorage和LocalStorage是三种常用的Web存储机制&a…...
SpringBoot之BeanDefinitionLoader类源码学习
该类的作用 Spring 框架中用于加载和解析 Bean 定义的工具类。它主要用于从不同的资源(如 XML 文件、注解、Java 配置类等)中读取 Bean 定义,并将这些定义注册到 Spring 的 BeanFactory 或 ApplicationContext 中 基本属性 //指定的资源pri…...

【芯片封测学习专栏 -- 2D | 2.5D | 3D 封装的区别和联系】
请阅读【嵌入式开发学习必备专栏 Cache | MMU | AMBA BUS | CoreSight | Trace32 | CoreLink | ARM GCC | CSH】 文章目录 Overview线键合(wire-bonding)封装FOWLP2D封装2.5D 封装硅通孔(TSV)硅中介层无TSV的2.5D 3D封装 Overview 我们先要了解一下&…...

从硬件设备看Linux
一、介绍 DM3730通过各种连接方式连接了各种设备,输入输出设备根据不同的类型大体可 以分为电源管理、用户输人、显示输出、图像采集、存储以及无线设备等。我们可以将DM 3730与这些设备的数据接口分为总线和单一的数据接口总线。总线的显著特点是单个总线上可以连…...

open3d+opencv实现矩形框裁剪点云操作(C++)
👑主页:吾名招财 👓简介:工科学硕,研究方向机器视觉,爱好较广泛… 💫签名:面朝大海,春暖花开! open3dopencv实现矩形框裁剪点云操作(Cÿ…...
git 本地操作
一、git.vscode 撤回本地提交 要在Git中撤销本地的最后一次提交,可以使用以下命令: git reset --soft HEAD^ 这将会撤销最后一次的提交,但是保留工作区以及暂存区的内容,方便重新提交。 如果你想完全撤销最后一次提交…...
PL/SQL语言的文件操作
PL/SQL语言的文件操作 PL/SQL(Procedural Language/SQL)是Oracle公司开发的一种过程化扩展SQL的语言,广泛应用于Oracle数据库的开发和管理。PL/SQL不仅支持SQL指令,还支持过程化编程,例如条件控制、循环控制、异常处理…...
linux lsof 和 fuser命令介绍
lsof 和 fuser 是两个在 Linux 系统中用于查看文件占用情况的重要工具。它们都可以用于查看哪些进程正在使用某些文件、设备或端口。下面是这两个命令的介绍、举例和背景。 lsof (List Open Files) 命令介绍: lsof 命令用于列出当前系统中所有打开的文件以及与之相关的进程。它…...

[Python学习日记-76] 网络编程中的 socket 开发 —— 介绍、工作流程、socket 模块用法和函数介绍
[Python学习日记-76] 网络编程中的 socket 开发 —— 介绍、工作流程、socket 模块用法和函数介绍 简介 socket 介绍 socket 的工作流程及用法 简介 前面在[Python学习日记-75] 计算机基础与网络当中介绍了一大堆基础知识之后我们终于开始进入到网络编程的开发阶段了&#x…...

vue(七) vue进阶
目录 第一课:Vue方法、计算机属性及侦听器 一、数组变化侦测 方法1:变更方法 方法2:替换一个数组 例子:小Demo:合并两个数组 二、计算属性 1.基础(不推荐) 2.使用计算属性来完成案例 3.使用函数的方…...

[Transformer] The Structure of GPT, Generative Pretrained Transformer
The Structure of Generative Pretrained Transformer Reference: The Transformer architecture of GPT models How GPT Models Work...
Django Admin 自定义操作封装
1. 为什么需要封装? 在Django开发中,我们经常需要在Admin界面添加自定义操作按钮,以便管理员执行特定的任务。通过封装,我们可以: 减少重复代码统一管理自定义操作的逻辑提高代码的可维护性和可扩展性 © ivwdcwso (ID: u012172506)2. CustomActionMixin 的实现 让我…...

http和https有哪些不同
http和https有哪些不同 1.数据传输的安全性:http非加密,https加密 2.端口号:http默认80端口,https默认443端口 3.性能:http基于tcp三次握手建立连接,https在tcp三次握手后还有TLS协议的四次握手确认加密…...
PL/SQL语言的数据库交互
PL/SQL语言的数据库交互 引言 在当今的信息化时代,数据库管理系统(DBMS)在各行各业中扮演着至关重要的角色。为了高效地与数据库进行交互,许多程序员、数据库管理员和系统分析师选择使用PL/SQL(Procedural Language/…...
Vue记事本应用实现教程
文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展:显示创建时间8. 功能扩展:记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...

无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...

高频面试之3Zookeeper
高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个?3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制(过半机制࿰…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...

UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)
UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...

ios苹果系统,js 滑动屏幕、锚定无效
现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...
MySQL 主从同步异常处理
阅读原文:https://www.xiaozaoshu.top/articles/mysql-m-s-update-pk MySQL 做双主,遇到的这个错误: Could not execute Update_rows event on table ... Error_code: 1032是 MySQL 主从复制时的经典错误之一,通常表示ÿ…...

归并排序:分治思想的高效排序
目录 基本原理 流程图解 实现方法 递归实现 非递归实现 演示过程 时间复杂度 基本原理 归并排序(Merge Sort)是一种基于分治思想的排序算法,由约翰冯诺伊曼在1945年提出。其核心思想包括: 分割(Divide):将待排序数组递归地分成两个子…...