关于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;
///Json
QJsonDocument 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~25
QJsonObject 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); //另存为word
qDebug() << "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