关于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