当前位置: 首页 > news >正文

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)); }}}
}

五、功能特点:

  1. 使用 QAxObject 实现了与 Word 的 COM 接口的交互,允许直接操作 Word 文档中的内容;
  2. Json 文件导入一键填充/替换模板表格,根据Json填充单元格内容,候选单元格背景高亮等;
  3. 各个路径可设置,合理性判定等。

六、可优化:

  1. 后续可使用 QScopedPointer 自动管理 QAxObject 的生命周期,避免内存泄漏;
  2. 可增加对失败情况的详细日志记录(例如,单元格索引等);
  3. 路径可通过 Setting 保存在内容中;
  4. 增加预览功能,可结合前文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&#xff08;一&#xff09;使用 QtPdfium库实现 PDF 操作》 《Qt WORD/PDF&#…...

vue3+ts的几个bug调试

由于编译问题&#xff0c;把几个type检查给关闭了&#xff0c;否则错误太多。 1&#xff09;第一个检查出的问题&#xff0c;拼写错误数组的length&#xff0c;写成了lengh。 2&#xff09;数组的对象引用。 torStatus Array(8).fill({ ...defaultStatus }) as TorStatus[]…...

DVWA靶场CSRF漏洞通关教程及源码审计

目录标题 CSRFlow源码审计 medium源码审计 high源码审计 impossible源码审计 CSRF low 先修改密码 看到地址栏 复制在另一个网页打开 成功登录 源码审计 没有任何过滤措施&#xff0c;很危险&#xff0c;并且采用了不安全的md5加密 <?phpif( isset( $_GET[ Change ] )…...

前端开发:HTML常见标签

1.注释标签 注释不会显示在界面上 . 目的是提高代码的可读性 . ctrl / 快捷键可以快速进行注释 / 取消注释 . <!-- 我是注释 --> 2.标题标签 有六个 , 从 h1 - h6. 数字越大 , 则字体越小 <h1> hello </h1> //我们所写的csdn的格式中的标题一…...

【机器学习】主动学习-增加标签的操作方法-样本池采样(Pool-Based Sampling)

Pool-Based Sampling Pool-based sampling 是一种主动学习&#xff08;Active Learning&#xff09;方法&#xff0c;与流式选择性采样不同&#xff0c;它假设有一个预先定义的未标注样本池&#xff0c;算法从中选择最有价值的样本进行标注&#xff0c;以提升模型的性能。这种…...

【Rust自学】11.9. 单元测试

喜欢的话别忘了点赞、收藏加关注哦&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 11.9.1. 测试的分类 Rust把测试分为两类&#xff0c;一个是单元测试&#xff0c;一个是集成测试。 单元测试比较小也比较专注&#xff…...

深入理解Web存储机制:Cookie、SessionStorage与LocalStorage的区别

文章目录 前言一、Cookie简介二、SessionStorage简介三、LocalStorage简介四、三者之间的比较五、最佳实践建议结语 前言 随着Web应用程序变得越来越复杂&#xff0c;开发者需要更有效的办法来管理客户端数据。Cookie、SessionStorage和LocalStorage是三种常用的Web存储机制&a…...

SpringBoot之BeanDefinitionLoader类源码学习

该类的作用 Spring 框架中用于加载和解析 Bean 定义的工具类。它主要用于从不同的资源&#xff08;如 XML 文件、注解、Java 配置类等&#xff09;中读取 Bean 定义&#xff0c;并将这些定义注册到 Spring 的 BeanFactory 或 ApplicationContext 中 基本属性 //指定的资源pri…...

【芯片封测学习专栏 -- 2D | 2.5D | 3D 封装的区别和联系】

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

从硬件设备看Linux

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

open3d+opencv实现矩形框裁剪点云操作(C++)

&#x1f451;主页&#xff1a;吾名招财 &#x1f453;简介&#xff1a;工科学硕&#xff0c;研究方向机器视觉&#xff0c;爱好较广泛… ​&#x1f4ab;签名&#xff1a;面朝大海&#xff0c;春暖花开&#xff01; open3dopencv实现矩形框裁剪点云操作&#xff08;C&#xff…...

git 本地操作

一、git.vscode 撤回本地提交 要在Git中撤销本地的最后一次提交&#xff0c;可以使用以下命令&#xff1a; git reset --soft HEAD^ 这将会撤销最后一次的提交&#xff0c;但是保留工作区以及暂存区的内容&#xff0c;方便重新提交。 如果你想完全撤销最后一次提交&#xf…...

PL/SQL语言的文件操作

PL/SQL语言的文件操作 PL/SQL&#xff08;Procedural Language/SQL&#xff09;是Oracle公司开发的一种过程化扩展SQL的语言&#xff0c;广泛应用于Oracle数据库的开发和管理。PL/SQL不仅支持SQL指令&#xff0c;还支持过程化编程&#xff0c;例如条件控制、循环控制、异常处理…...

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进阶

目录 第一课&#xff1a;Vue方法、计算机属性及侦听器 一、数组变化侦测 方法1&#xff1a;变更方法 方法2&#xff1a;替换一个数组 例子&#xff1a;小Demo:合并两个数组 二、计算属性 1.基础&#xff08;不推荐&#xff09; 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.数据传输的安全性&#xff1a;http非加密&#xff0c;https加密 2.端口号&#xff1a;http默认80端口&#xff0c;https默认443端口 3.性能&#xff1a;http基于tcp三次握手建立连接&#xff0c;https在tcp三次握手后还有TLS协议的四次握手确认加密…...

PL/SQL语言的数据库交互

PL/SQL语言的数据库交互 引言 在当今的信息化时代&#xff0c;数据库管理系统&#xff08;DBMS&#xff09;在各行各业中扮演着至关重要的角色。为了高效地与数据库进行交互&#xff0c;许多程序员、数据库管理员和系统分析师选择使用PL/SQL&#xff08;Procedural Language/…...

如何快速评估网络性能:Windows平台iperf3完整指南

如何快速评估网络性能&#xff1a;Windows平台iperf3完整指南 【免费下载链接】iperf3-win-builds iperf3 binaries for Windows. Benchmark your network limits. 项目地址: https://gitcode.com/gh_mirrors/ip/iperf3-win-builds iperf3是一款专业的网络性能测试工具&…...

猫抓:网页资源嗅探与下载的全功能解决方案

猫抓&#xff1a;网页资源嗅探与下载的全功能解决方案 【免费下载链接】cat-catch 猫抓 浏览器资源嗅探扩展 / cat-catch Browser Resource Sniffing Extension 项目地址: https://gitcode.com/GitHub_Trending/ca/cat-catch 在数字化内容爆炸的时代&#xff0c;网页资源…...

老Mac重生引擎:OpenCore Legacy Patcher系统焕新全攻略

老Mac重生引擎&#xff1a;OpenCore Legacy Patcher系统焕新全攻略 【免费下载链接】OpenCore-Legacy-Patcher Experience macOS just like before 项目地址: https://gitcode.com/GitHub_Trending/op/OpenCore-Legacy-Patcher 当你的2015款MacBook Pro无法更新到最新ma…...

3步零成本改造:让老旧打印机秒变AirPrint无线打印服务器

3步零成本改造&#xff1a;让老旧打印机秒变AirPrint无线打印服务器 【免费下载链接】cups-avahi-airprint Docker image for CUPS intended as an AirPrint relay 项目地址: https://gitcode.com/gh_mirrors/cu/cups-avahi-airprint 当iPad遇上旧打印机&#xff1a;现代…...

ShortURL MCP 集成指南

在今天的数字时代&#xff0c;短链接的生成和管理变得越来越重要。Ace Data Cloud 提供的 ShortURL MCP 服务器&#xff0c;利用 MCP (模型上下文协议)&#xff0c;允许 AI 模型&#xff08;如 Claude、GPT 等&#xff09;通过标准化接口调用外部工具&#xff0c;从而更加便利地…...

Lepton AI与FastAPI集成:构建高性能AI API服务的终极指南

Lepton AI与FastAPI集成&#xff1a;构建高性能AI API服务的终极指南 【免费下载链接】leptonai A Pythonic framework to simplify AI service building 项目地址: https://gitcode.com/gh_mirrors/le/leptonai Lepton AI是一个Pythonic框架&#xff0c;专门用于简化AI…...

cat-catch:突破网页资源捕获限制的高效下载解决方案

cat-catch&#xff1a;突破网页资源捕获限制的高效下载解决方案 【免费下载链接】cat-catch 猫抓 浏览器资源嗅探扩展 / cat-catch Browser Resource Sniffing Extension 项目地址: https://gitcode.com/GitHub_Trending/ca/cat-catch 问题&#xff1a;网页资源获取的三…...

突破网盘下载限制:八大平台直链获取的高效方案

突破网盘下载限制&#xff1a;八大平台直链获取的高效方案 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 &#xff0c;支持 百度网盘 / 阿里云盘 / 中国移动云盘 / 天翼云盘 / …...

Gemini 2.0与Gemma混搭开发:手把手教你构建低成本AI代理系统

Gemini 2.0与Gemma混搭开发&#xff1a;构建低成本AI代理系统的实战指南 1. 双轨战略的技术架构设计 谷歌的闭源Gemini与开源Gemma组合为开发者提供了独特的混合部署可能。这种架构设计的核心在于分层处理&#xff1a;将计算密集型任务交给云端Gemini处理&#xff0c;而设备端则…...

Vue项目调试神器Code-Inspector-Plugin全适配指南:从Vite、Webpack到Nuxt.js

Vue项目调试神器Code-Inspector-Plugin全适配指南&#xff1a;从Vite、Webpack到Nuxt.js 在Vue生态中&#xff0c;开发效率的提升往往依赖于工具的精准选择。当项目规模扩大、组件层级加深时&#xff0c;如何在浏览器中快速定位到源代码中的对应位置&#xff0c;成为影响开发体…...