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/…...
Win10家庭版别再卡了!保姆级教程:手动修复gpedit.msc路径,彻底关闭Antimalware Service
Win10家庭版性能优化实战:精准修复组策略路径与系统服务调优每次游戏激战正酣时突然卡顿,或是视频渲染到关键时刻系统响应迟缓,很多Win10家庭版用户都遭遇过这类困扰。任务管理器里那个名为"Antimalware Service Executable"的进程…...
Unity安卓构建72小时实战指南:从零到真机运行
1. 这不是“又一本Unity教程”,而是我带三个新人从零上线第一款安卓游戏的真实路径你点开这个标题,大概率正站在两个路口之间:一边是满屏“30天速成Unity”“零基础做爆款”的短视频封面,一边是你刚下载完Unity Hub、卡在Android …...
别再乱算相似度了!用Python实战二元变量聚类:从Jaccard系数到病人分组
医疗数据分析实战:用Python实现基于Jaccard系数的病人症状聚类在医疗数据分析领域,如何从海量病人症状数据中发现潜在规律一直是临床研究的难点。传统方法往往依赖医生经验或简单统计,而现代数据挖掘技术为我们提供了更科学的解决方案。本文将…...
炉石传说自动对战助手:5分钟上手,彻底解放双手的终极指南
炉石传说自动对战助手:5分钟上手,彻底解放双手的终极指南 【免费下载链接】Hearthstone-Script Hearthstone script(炉石传说脚本) 项目地址: https://gitcode.com/gh_mirrors/he/Hearthstone-Script 还在为每天重复的炉石…...
告别SVN恐惧症:美术策划也能轻松上手的Unity PlasticSCM极简入门(附团队项目拉取实战)
告别SVN恐惧症:美术策划也能轻松上手的Unity PlasticSCM极简入门(附团队项目拉取实战) 在游戏开发团队中,版本控制系统是协作的基石,但传统工具如SVN往往让非技术成员望而生畏。当美术资源频繁更新、策划案不断迭代时&…...
十年以上经验的建站公司推荐|策划强、落地稳的网站制作公司盘点
互联网时代,企业官网已从单纯的信息展示窗口升级为集品牌价值传递、用户体验连接与业务高效转化于一体的核心数字阵地。行业报告显示,优质官网可帮助企业线上转化率提升35%-60%,而低效官网则可能导致潜在客户大量流失。面对市场上众多的网站建…...
告别DLL缺失烦恼!Visual C++运行库合集一键搞定Windows应用依赖问题
告别DLL缺失烦恼!Visual C运行库合集一键搞定Windows应用依赖问题 【免费下载链接】vcredist AIO Repack for latest Microsoft Visual C Redistributable Runtimes 项目地址: https://gitcode.com/gh_mirrors/vc/vcredist 你是否曾经在打开某个软件或游戏时…...
OpenRASP原理与实战:Java应用层实时防护技术详解
1. 为什么我宁愿花三天部署OpenRASP,也不愿再写第五个自定义WAF过滤器去年冬天,我在给一家做在线教育SaaS平台做安全加固时,连续踩了三个坑:第一次用NginxLua写了套SQL注入规则,结果学生提交的“SELECT * FROM courses…...
AhMyth位置跟踪:GPS定位与地理围栏技术深度解析
AhMyth位置跟踪:GPS定位与地理围栏技术深度解析 【免费下载链接】AhMyth Cross-Platform Android Remote Administration Tool | The only maintained version of AhMyth on github | A revival of the original repository at https://GitHub.com/AhMyth/AhMyth-An…...
【C++】零基础入门 · 第 4 节:循环结构(while、for、do-while)
上一节我们学习了条件判断,这一节来学习循环结构。循环让程序能够重复执行某段代码,直到满足特定条件为止。C 提供了三种循环语句:while、for 和 do-while。 1. while 循环:先判断后执行 while 循环在每次执行前先检查条件&#x…...
