關于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行默認數據。
- 使用
- 控件連接:
- 點擊“瀏覽”按鈕會觸發文件選擇對話框,并通過信號槽機制連接相應的函數(
browseTemplateFile
和browseOutputFile
)。 - 替換按鈕 (
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