Qt WORD/PDF(四)使用 QAxObject 對 Word 替換(QWidget)


關于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)


一、QAxObject 簡介

QAxObject 是 Qt 提供的一個類,它用于與 COM(Component Object Model)對象進行交互。COM 是一種微軟的技術,廣泛用于各種應用程序之間的通信,尤其在 Windows 平臺上,很多軟件和系統組件都是基于 COM 構建的。QAxObject 類提供了一個 Qt 風格的接口,簡化了與這些 COM 對象的交互。

本文主要使用 QAxObject 操作 word 文檔,使用鍵值對,對模板文件進行替換操作,導出相應的文檔,特別適合輸出報告。

本文采用 Qt Widget 純代碼的方式

環境:

QT5.15.2 + MSVC2019 + Widget

二、演示

在這里插入圖片描述

實現功能:

  • 用戶可以選擇一個模板文件,并進行占位符的批量替換。
  • 用戶可以設置替換后文檔的保存路徑。
  • 支持通過界面交互實現選擇文件、顯示信息以及執行替換操作。
  • 使用 QAxObject 實現了與 Word 的 COM 接口的交互,允許直接操作 Word 文檔中的內容。

三、代碼

完整代碼

mainwindow.cpp:

#include "mainwindow.h"
// #include "ui_mainwindow.h"#include <QFileDialog>
#include <QDebug>
#include <QMessageBox>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)// , ui(new Ui::MainWindow)
{// ui->setupUi(this);// 初始化 UIauto *centralWidget = new QWidget(this);auto *mainLayout = new QVBoxLayout;mainLayout->setContentsMargins(10, 10, 10, 10); // 設置布局邊距mainLayout->setSpacing(10); // 設置控件之間的間距// setMinimumSize(600, 520); // 設置窗口最小寬度為600,高度為400// 模板文件選擇auto *templateLayout = new QHBoxLayout;auto *templateLabel = new QLabel("打開模板:", this);templatePathEdit = new QLineEdit(this);auto *browseTemplateButton = new QPushButton("瀏覽", this);templateLayout->addWidget(templateLabel);templateLayout->addWidget(templatePathEdit);templateLayout->addWidget(browseTemplateButton);connect(browseTemplateButton, &QPushButton::clicked, this, &MainWindow::browseTemplateFile);// 輸出文件選擇auto *outputLayout = new QHBoxLayout;auto *outputLabel = new QLabel("輸出路徑:", this);outputPathEdit = new QLineEdit(this);auto *browseOutputButton = new QPushButton("瀏覽", this);outputLayout->addWidget(outputLabel);outputLayout->addWidget(outputPathEdit);outputLayout->addWidget(browseOutputButton);connect(browseOutputButton, &QPushButton::clicked, this, &MainWindow::browseOutputFile);// 鍵值對表格auto *placeholdersLabel = new QLabel("鍵值對替換:", this);placeholdersTable = new QTableWidget(this);placeholdersTable->setColumnCount(2);placeholdersTable->setHorizontalHeaderLabels({"占位符", "替換值"});placeholdersTable->setRowCount(5); // 默認三行// 設置默認值placeholdersTable->setItem(0, 0, new QTableWidgetItem("[A]"));placeholdersTable->setItem(0, 1, new QTableWidgetItem("柯布"));placeholdersTable->setItem(1, 0, new QTableWidgetItem("[B]"));placeholdersTable->setItem(1, 1, new QTableWidgetItem("阿瑟"));placeholdersTable->setItem(2, 0, new QTableWidgetItem("[C]"));placeholdersTable->setItem(2, 1, new QTableWidgetItem("杜拉"));placeholdersTable->setItem(3, 0, new QTableWidgetItem("[D]"));placeholdersTable->setItem(3, 1, new QTableWidgetItem("伊姆斯"));// 替換按鈕replaceButton = new QPushButton("執行替換", this);connect(replaceButton, &QPushButton::clicked, this, &MainWindow::replaceInWord);// 布局整合mainLayout->addLayout(templateLayout);mainLayout->addLayout(outputLayout);mainLayout->addWidget(placeholdersLabel);mainLayout->addWidget(placeholdersTable);mainLayout->addWidget(replaceButton);centralWidget->setLayout(mainLayout);setCentralWidget(centralWidget);setWindowTitle("Word 替換工具");resize(1000, 600); // 初始窗口大小
}MainWindow::~MainWindow()
{// delete ui;
}void MainWindow::browseTemplateFile() {QString filePath = QFileDialog::getOpenFileName(this, "選擇模板文件", QString(), "Word 文件 (*.docx *.doc)");if (!filePath.isEmpty()) {templatePathEdit->setText(filePath);wordApp = new QAxObject("Word.Application");if (wordApp->isNull()) {qDebug() << "Failed to initialize Word.Application.";delete wordApp;return ;}// 隱藏 Word 窗口wordApp->setProperty("Visible", true);//打開指定文檔QAxObject *documents = wordApp->querySubObject("Documents");QAxObject *document = documents->querySubObject("Open(const QString&)", filePath);if (document == nullptr) {QMessageBox::critical(this, "錯誤", "無法打開 Word 文件!");return;}}
}void MainWindow::browseOutputFile() {QString filePath = QFileDialog::getSaveFileName(this, "選擇輸出文件", QString(), "Word 文件 (*.docx *.doc)");if (!filePath.isEmpty()) {outputPathEdit->setText(filePath);}
}void MainWindow::replaceInWord() {QString templatePath = templatePathEdit->text();QString outputPath = outputPathEdit->text();if (templatePath.isEmpty() || outputPath.isEmpty()) {QMessageBox::warning(this, "錯誤", "請填寫模板路徑和輸出路徑!");return;}QMap<QString, QString> placeholders;for (int row = 0; row < placeholdersTable->rowCount(); ++row) {QString key = placeholdersTable->item(row, 0) ? placeholdersTable->item(row, 0)->text() : QString();QString value = placeholdersTable->item(row, 1) ? placeholdersTable->item(row, 1)->text() : QString();if (!key.isEmpty()) {placeholders.insert(key, value);}}if (placeholders.isEmpty()) {QMessageBox::warning(this, "錯誤", "請填寫至少一個占位符和替換值!");return;}if (replaceMultiple(templatePath, outputPath, placeholders)) {QMessageBox::information(this, "成功", "替換完成!");} else {QMessageBox::critical(this, "失敗", "替換失敗!");}
}bool MainWindow::replaceMultiple(const QString &templatePath, const QString &outputPath, const QMap<QString, QString> &placeholders) {qDebug() << "Received data:" << placeholders;qDebug() << "Template Path:" << templatePath;qDebug() << "Output Path:" << outputPath;if (!QFile::exists(templatePath)) {qDebug() << "Template file does not exist:" << templatePath;return false;}qDebug() << "QFile::exists ok" ;// 打開模板文件QAxObject *documents = wordApp->querySubObject("Documents");QAxObject *document = documents->querySubObject("Open(const QString&)", templatePath);// 查找占位符并替換//使用 Find.Execute 查找占位符,使用 TypeText 方法替換為新內容QAxObject *selection = wordApp->querySubObject("Selection");// 獲取 Find 對象QAxObject *find = selection->querySubObject("Find");qDebug() << "start placeholde";// 遍歷占位符鍵值對, 替換未成功,則有問題for (auto it = placeholders.begin(); it != placeholders.end(); ++it) {QString placeholder = it.key();QString newContent = it.value();bool isFound = true;//可替換多個,且重復的while (isFound) {// 查找目標文本并替換//            isFound = find->dynamicCall("Execute(const QString&)", placeholder).toBool();isFound = find->dynamicCall("Execute(QString, bool, bool, bool, bool, bool, bool, int)",placeholder,  // 要查找的字符串false,        // 區分大小寫false,        // 完整單詞false,        // 使用通配符false,        // 忽略標點符號false,        // 忽略空格true,         // 向前查找1).toBool();   // 查找范圍:整個文檔if (isFound) {// 替換文本selection->dynamicCall("TypeText(const QString&)", newContent);}}}qDebug() << "All Find operation succeed!";document->dynamicCall("SaveAs(const QString&)", outputPath);// 關閉文檔document->dynamicCall("Close()");wordApp->dynamicCall("Quit()");delete wordApp;return true;
}

mainwindow.h:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QTableWidget>
#include <QLineEdit>
#include <QPushButton>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QMap>
#include <QAxObject>
#include <QAxWidget>QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private slots:void browseTemplateFile();void browseOutputFile();void replaceInWord();private:QLineEdit *templatePathEdit;QLineEdit *outputPathEdit;QTableWidget *placeholdersTable;QPushButton *replaceButton;bool replaceMultiple(const QString &templatePath, const QString &outputPath, const QMap<QString, QString> &placeholders);QAxObject *wordApp = nullptr;QAxWidget *wordPreview = nullptr;private:Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

pro 中需要增加對 QAxObject 的支持

QT       += core gui axcontainer 

四、分析:

這段Qt C++代碼實現了一個簡單的“Word 文件替換工具”,允許用戶通過一個圖形界面選擇Word模板文件、設置輸出路徑,并在Word文檔中進行占位符的替換操作。

1. 類的構造函數 (MainWindow::MainWindow)

  • UI設置:
    • 使用 QWidget 創建中央窗口,QVBoxLayout 為主布局,內部包含多個控件(如標簽、輸入框、按鈕等)。
    • 通過 QHBoxLayout 設置了模板文件選擇區域(輸入框和瀏覽按鈕)、輸出路徑選擇區域(輸入框和瀏覽按鈕)、以及鍵值對表格用于占位符替換。
    • 還創建了一個 QTableWidget 來管理占位符和替換值的鍵值對。初始化了5行默認數據。
  • 控件連接:
    • 點擊“瀏覽”按鈕會觸發文件選擇對話框,并通過信號槽機制連接相應的函數(browseTemplateFilebrowseOutputFile)。
    • 替換按鈕 (replaceButton) 連接到 replaceInWord 函數。
  • Word預覽:
    • wordPreview 是一個 QAxWidget 控件,允許通過 ActiveX 技術與 Word 應用進行交互。它在 browseTemplateFile 中初始化并用于打開 Word 文件。

2. 瀏覽模板文件 (??browseTemplateFile?? )

  • 打開文件對話框 (QFileDialog::getOpenFileName) 選擇模板文件,文件路徑顯示在 templatePathEdit 中。
  • 使用 QAxWidget 來查詢 Word 的應用對象 wordApp,并打開用戶選擇的文件。
  • 通過 Word.Application 創建 ActiveX 對象,加載模板文件并將其顯示在打印預覽模式。
  • 如果沒有成功加載Word文件,會彈出錯誤提示。

3. 瀏覽輸出文件 (??browseOutputFile?? )

  • 打開保存文件對話框 (QFileDialog::getSaveFileName) 選擇輸出文件路徑,并將路徑顯示在 outputPathEdit 中。

4. 替換操作 (??replaceInWord?? )

  • 從 UI 中獲取模板文件路徑和輸出文件路徑,如果路徑為空,彈出警告。
  • 獲取表格中的占位符及其對應替換值,并構建一個 QMap 來存儲這些鍵值對。
  • 調用 replaceMultiple 函數進行批量替換操作。

5. 替換邏輯 (??replaceMultiple?? )

  • 文件存在性檢查: 使用 QFile::exists 檢查模板文件是否存在。
  • 打開Word文檔: 使用 QAxObject 打開模板文件,獲取 Selection 對象和 Find 對象來查找占位符。
  • 查找和替換: 遍歷占位符的鍵值對,使用 Find.Execute 查找占位符,并通過 TypeText 替換為新內容。替換過程中使用了 while 循環,確保文檔中所有的占位符都能被替換(即使它們重復出現)。
  • 保存文件: 替換完成后,使用 SaveAs 保存文件到指定的輸出路徑。
  • 關閉和退出: 完成替換后,關閉文檔并退出Word應用。

總結

該程序使用 Qt 的 QAxObject 來與 Microsoft Word 進行交互,實現了以下功能:

  • 用戶可以選擇一個模板文件,并進行占位符的批量替換。
  • 用戶可以設置替換后文檔的保存路徑。
  • 支持通過界面交互實現選擇文件、顯示信息以及執行替換操作。
  • 使用 QAxObject 實現了與 Word 的 COM 接口的交互,允許直接操作 Word 文檔中的內容。

關于QGC地面站其它文章請點擊這里: ????QT Widget

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/63300.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/63300.shtml
英文地址,請注明出處:http://en.pswp.cn/web/63300.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

設計一個基礎JWT的多開發語言分布式電商系統

在設計一個分布式電商系統時&#xff0c;保證系統的可擴展性、性能以及跨語言的兼容性是至關重要的。隨著微服務架構的流行&#xff0c;越來越多的電商系統需要在多個服務間共享信息&#xff0c;并且保證服務的安全性。在這樣的場景下&#xff0c;JSON Web Token&#xff08;JW…

實踐分享 | 公共數據金融應用的理論探索與實踐研究—以人民幣銀行結算賬戶數據應用為例

摘要:公共數據具有高權威性、高準確性、高價值性以及高應用性的特點,實現公共數據的金融應用對更好服務實體經濟、防控金融風險和提升金融服務水平具有重要現實意義。本文從理論探索與實踐研究兩個層面分析了公共數據金融應用的具體問題,一方面探索性的給出了公共數據金融應…

Node的學習以及學習通過Node書寫接口并簡單操作數據庫

Node的學習 Node的基礎上述是關于Node的一些基礎&#xff0c;總結的還行&#xff1b; 利用Node書寫接口并操作數據庫 1. 初始化項目 創建新的項目文件夾&#xff0c;并初始化 package.json mkdir my-backend cd my-backend npm init -y2. 安裝必要的依賴 安裝Express.js&…

計算機視覺中的特征提取算法

摘要&#xff1a; 本文聚焦于計算機視覺中的特征提取算法&#xff0c;深入探討尺度不變特征變換&#xff08;SIFT&#xff09;算法。詳細闡述 SIFT 算法的原理&#xff0c;包括尺度空間構建、關鍵點檢測、方向分配與特征描述子生成等核心步驟。通過 C#、Python 和 C 三種編程語…

MySQL 主從復制與 Binlog 深度解析

目錄 1. Binlog的工作原理與配置2. 主從復制的設置與故障排除3. 數據一致性與同步延遲的處理 小結 MySQL的binlog&#xff08;二進制日志&#xff09;和主從復制是實現數據備份、容災、負載均衡以及數據同步的重要機制。在高可用性架構和分布式數據庫設計中&#xff0c;binlog同…

排隊論、負載均衡和任務調度關系

目錄 排隊論、負載均衡和任務調度關系 一、排隊論 二、負載均衡 三、任務調度 四、總結 排隊論、負載均衡和任務調度關系 排隊論為負載均衡和任務調度提供了數學理論和方法支持 排隊論、負載均衡和任務調度是三個相關但不同的概念。以下是對這三個概念的詳細解釋和它們之…

java版詢價采購系統 招投標詢價競標投標系統 招投標公告系統源碼

功能描述 1、門戶管理&#xff1a;所有用戶可在門戶頁面查看所有的公告信息及相關的通知信息。主要板塊包含&#xff1a;招標公告、非招標公告、系統通知、政策法規。 2、立項管理&#xff1a;企業用戶可對需要采購的項目進行立項申請&#xff0c;并提交審批&#xff0c;查看所…

景聯文科技入選中國信通院發布的“人工智能數據標注產業圖譜”

近日&#xff0c;由中國信息通信研究院、中國人工智能產業發展聯盟牽頭&#xff0c;聯合中國電信集團、沈陽市數據局、保定高新區等70多家單位編制完成并發布《人工智能數據標注產業圖譜》。景聯文科技作為人工智能產業關鍵環節的代表企業&#xff0c;入選圖譜中技術服務板塊。…

【小沐學GIS】基于C++繪制三維數字地球Earth(OpenGL、glfw、glut、QT)第三期

&#x1f37a;三維數字地球系列相關文章如下&#x1f37a;&#xff1a;1【小沐學GIS】基于C繪制三維數字地球Earth&#xff08;456:OpenGL、glfw、glut&#xff09;第一期2【小沐學GIS】基于C繪制三維數字地球Earth&#xff08;456:OpenGL、glfw、glut&#xff09;第二期3【小沐…

實景視頻與模型疊加融合?

[視頻GIS系列]無人機視頻與與實景模型進行實時融合_無人機視頻融合-CSDN博客文章瀏覽閱讀1.5k次&#xff0c;點贊28次&#xff0c;收藏14次。將無人機視頻與實景模型進行實時融合是一個涉及多個技術領域的復雜過程&#xff0c;主要包括無人機視頻采集、實景模型構建、視頻與模型…

MySQL通過binlog日志進行數據恢復

記錄一次阿里云MySQL通過binlog日志進行數據回滾 問題描述由于阿里云遠程mysql沒有做安全策略 所以服務器被別人遠程攻擊把數據庫給刪除&#xff0c;通過查看binlog日志可以看到進行了drop操作&#xff0c;下面將演示通過binlog日志進行數據回滾操作。 1、查詢是否開始binlog …

IDEA 修改格式化僅格式化本次改動代碼

最近總是發現格式化的時候會格式化文件所有代碼&#xff0c;提交Git 后再看提交日志&#xff0c;就很不清晰。修改方式如下 中文&#xff1a; 格式化代碼快捷鍵[中文配置]&#xff1a; 英文&#xff1a; 格式化代碼快捷鍵[英文配置]&#xff1a;

el-table ToggleRowSelection實現取消選中沒效果(virtual-scroll)

場景&#xff1a; 就是在虛擬列表el-table選中之后 點擊查詢 默認之前選中的 現象&#xff1a; 就是實現選中&#xff0c; 但是無法去除勾選等等 問題發現&#xff1a; 看定位的數據 有多個一樣的&#xff0c;我想著勾選之前 先去掉勾選 &#xff0c;但是沒效果或者說“相同的…

【含開題報告+文檔+PPT+源碼】基于微信小程序的點餐系統的設計與實現

開題報告 隨著互聯網技術的日益成熟和消費者生活水平與需求層次的顯著提升&#xff0c;外賣點餐平臺在中國市場上迅速興起并深深植根于民眾日常生活的各個角落。這類平臺的核心在于構建了一個基于互聯網的強大訂餐服務系統&#xff0c;它無縫整合了餐飲商戶資源與廣大消費者的…

解決 MyBatis 中空字符串與數字比較引發的條件判斷錯誤

問題復現 假設你在 MyBatis 的 XML 配置中使用了如下代碼&#xff1a; <if test"isCollect ! null"><choose><when test"isCollect 1">AND exists(select 1 from file_table imgfile2 where task.IMAGE_SEQimgfile2.IMAGE_SEQ and im…

SpringBoot 手動實現動態切換數據源 DynamicSource (中)

大家好&#xff0c;我是此林。 SpringBoot 手動實現動態切換數據源 DynamicSource &#xff08;上&#xff09;-CSDN博客 在上一篇博客中&#xff0c;我帶大家手動實現了一個簡易版的數據源切換實現&#xff0c;方便大家理解數據源切換的原理。今天我們來介紹一個開源的數據源…

ASCII碼簡介以及在php中的使用

什么是 ASCII&#xff1f; ASCII&#xff08;American Standard Code for Information Interchange&#xff0c;美國信息交換標準代碼&#xff09;是一種字符編碼標準&#xff0c;用于在計算機、通信設備及其他設備中表示文字、符號和控制信息。它最早于 1963 年由美國國家標準…

前端學習一

一 進程與線程 線程是進程執行的最小單位&#xff0c;進程是系統分配任務的最小單位。 一個進程可執行最少一個線程。線程分為子線程和主線程。 主線程關閉則子線程關閉。 二 瀏覽器進程 瀏覽器是多進程多線程應用。 進程包括&#xff1a; 瀏覽器進程 負責程序交互渲染…

Go vendor

博主在編寫Go代碼時&#xff0c;遇到了這樣一個問題&#xff1a;想要修改某個外部包&#xff0c;添加幾個函數&#xff0c;而其余功能繼續使用&#xff0c;經過調研&#xff0c;發現可以將Go的外部包源碼復制到項目本地&#xff0c;對包的代碼進行修改&#xff0c;從而達到目的…

EasyExcel 動態設置表格的背景顏色和排列

項目中使用EasyExcel把數據以excel格式導出&#xff0c;其中設置某一行、某一列單元格的背景顏色、排列方式十分常用&#xff0c;記錄下來方便以后查閱。 1. 導入maven依賴&#xff1a; <dependency><groupId>com.alibaba</groupId><artifactId>easy…