qt自动生成word报告

Posted by mudux on January 11, 2020

 最近做项目过程中需要自动生成word报告,Microsoft的word支持通过COM组件调用。因为项目是用qt来做,所以使用Qt提供的ActiveQt框架中的QAxContainer模块下的QAxobject、QAxWidget类调用COM组件。
 这里支持插入文字、表格、图片等。在调用之前需要先创建word模板文件,按照书签名来确定插入文字表格图片到相应位置。

注意应该在project.pro文件中添加 QT += axcontainer

wordengine

wordengine.h文件如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include <QObject>
#include <QAxObject>
#include <QAxWidget>

class WordEngine : public QObject
{
    Q_OBJECT
public:
    explicit WordEngine(QObject *parent = 0);

    WordEngine(const QString& strFile, QObject *parent = 0);
    ~WordEngine();

    bool open(bool bVisable = false);
    bool open(const QString& strFile, bool bVisable = false);
    bool close();
    bool isOpen();
    void save();
    bool saveAs(const QString& strSaveFile);
    // 设置标签内容
    bool setMarks(const QString& strMark, const QString& strContent);
    //插入标题 3
    bool setTitle(const QString& strMark, const QString& strContent);
    // 批量设置标签
    bool setBatchMarks(QStringList &itemList,QStringList sometexts);
    // 创建表格
    void insertTable(int nStart, int nEnd, int row, int column);
    QAxObject *insertTable(QString sLabel,int row, int column);
    //合并单元格
    void MergeCells(QAxObject *table, int nStartRow,int nStartCol,int nEndRow,int nEndCol);
    //插入图片
    void insertPic(QString sLabel,const QString& picPath);
    //设置列宽
    void setColumnWidth(QAxObject *table, int column, int width);
    // 设置表格内容
    void setCellString(QAxObject *table, int row, int column, const QString& text);
    // 为表格添加行
    void addTableRow(QAxObject *table, int nRow, int rowCount);
    // 设置内容粗体  isBold控制是否粗体
    void setCellFontBold(QAxObject *table, int row, int column, bool isBold);
    // 设置文字大小
    void setCellFontSize(QAxObject *table, int row, int column, int size);
    // 在表格中插入图片
    void insertCellPic(QAxObject *table, int row,int column,const QString& picPath);

private:
    bool m_bOpened;
    QString m_strFilePath;
    QAxObject *m_wordDocuments;
    QAxObject *m_wordWidget;
//    QThread *m_thread;
signals:

public slots:
};

wordengine.cpp文件如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
#include "wordengine.h"
#include "qt_windows.h"

WordEngine::WordEngine(QObject *parent) :
    QObject(parent),
    m_bOpened(false),
    m_wordDocuments(NULL),
    m_wordWidget(NULL)
{

}

WordEngine::WordEngine(const QString& strFilePath, QObject *parent):
    QObject(parent),
    m_bOpened(false),
    m_strFilePath(strFilePath),
    m_wordDocuments(NULL),
    m_wordWidget(NULL)
{
}

WordEngine::~WordEngine()
{
    close();
}

/******************************************************************************
 * 函数:open
 * 功能:打开文件
 * 参数:bVisable 是否显示弹窗
 * 返回值: bool
 *****************************************************************************/
bool WordEngine::open(bool bVisable)
{
    //新建一个word应用程序,并设置为可见
    m_wordWidget = new QAxObject();
    bool bFlag = m_wordWidget->setControl( "word.Application" );
    if(!bFlag)
    {
        // 用wps打开
        bFlag = m_wordWidget->setControl( "kwps.Application" );
        if(!bFlag)
        {
            return false;
        }
    }
    m_wordWidget->setProperty("Visible", bVisable);
    //获取所有的工作文档
    QAxObject *document = m_wordWidget->querySubObject("Documents");
    if(!document)
    {
        return false;
    }
    //以文件template.dot为模版新建一个文档
    document->dynamicCall("Add(QString)", m_strFilePath);
    //获取当前激活的文档
    m_wordDocuments = m_wordWidget->querySubObject("ActiveDocument");
    m_bOpened = true;
    return m_bOpened;
}

/******************************************************************************
 * 函数:open
 * 功能:打开文件
 * 参数:strFilePath 文件路径;bVisable 是否显示弹窗
 * 返回值:bool
 *****************************************************************************/
bool WordEngine::open(const QString& strFilePath, bool bVisable)
{
    m_strFilePath = strFilePath;
    close();
    return open(bVisable);
}

/******************************************************************************
 * 函数:close
 * 功能:关闭文件
 * 参数:无
 * 返回值:bool
 *****************************************************************************/
bool WordEngine::close()
{
//    qDebug()<<m_bOpened;
    if (m_bOpened)
    {
        if(m_wordDocuments)
            m_wordDocuments->dynamicCall("Close (bool)", true);//关闭文本窗口
        if(m_wordWidget)
            m_wordWidget->dynamicCall("Quit()");//退出word
        if(m_wordDocuments)
            delete m_wordDocuments;
        if(m_wordWidget)
            delete m_wordWidget;
        m_bOpened = false;
    }

    return m_bOpened;
}

/******************************************************************************
 * 函数:isOpen
 * 功能:获得当前的打开状态
 * 参数:无
 * 返回值:bool
 *****************************************************************************/
bool WordEngine::isOpen()
{
    return m_bOpened;
}

/******************************************************************************
 * 函数:save
 * 功能:保存文件
 * 参数:无
 * 返回值:void
 *****************************************************************************/
void WordEngine::save()
{
    m_wordDocuments->dynamicCall("Save()");
}

/******************************************************************************
 * 函数:saveAs
 * 功能:另存文件
 * 参数:strSaveFile 文件路径
 * 返回值:void
 *****************************************************************************/
bool WordEngine::saveAs(const QString& strSaveFile)
{
    return m_wordDocuments->dynamicCall("SaveAs (const QString&)",
                                 strSaveFile).toBool();
}

/******************************************************************************
 * 函数:setMarks
 * 功能:设置标签内容
 * 参数:strMark 标签名;strContent 文本
 * 返回值:bool
 *****************************************************************************/
bool WordEngine::setMarks(const QString& strMark, const QString& strContent)
{
    QAxObject* bookmarkCode = NULL;
    bookmarkCode = m_wordDocuments->querySubObject("Bookmarks(QVariant)", strMark);
    //选中标签,将字符textg插入到标签位置
    if(bookmarkCode)
    {
        bookmarkCode->dynamicCall("Select(void)");
        bookmarkCode->querySubObject("Range")->setProperty("Text", strContent);
        return true;
    }

    return false;
}

/******************************************************************************
 * 函数:setTitle
 * 功能:插入标题 3
 * 参数:strMark 标签名;strContent 文本
 * 返回值:bool
 *****************************************************************************/
bool WordEngine::setTitle(const QString& strMark, const QString& strContent)
{
    QAxObject* bookmarkCode = NULL;
    bookmarkCode = m_wordDocuments->querySubObject("Bookmarks(QVariant)", strMark);
    //选中标签,将字符textg插入到标签位置
    if(bookmarkCode)
    {
        bookmarkCode->dynamicCall("Select(void)");
        bookmarkCode->querySubObject("Range")->setProperty("Text", strContent+"\n");
        bookmarkCode->querySubObject("Range")->dynamicCall("SetStyle(QVariant)", QString::fromLocal8Bit("标题 3"));
        return true;
    }

    return false;
}
/******************************************************************************
 * 函数:setBatchMarks
 * 功能:批量设置标签内容
 * 参数:itemList 标签名列表;sometexts 内容列表
 * 返回值:bool
 *****************************************************************************/
bool WordEngine::setBatchMarks(QStringList &itemList,QStringList sometexts)
{
    QAxObject* allBookmarks = NULL;
    allBookmarks = m_wordDocuments->querySubObject("Bookmarks");
    //选中标签,将字符textg插入到标签位置
    if(allBookmarks)
    {
        int count = allBookmarks->property("Count").toInt();
        /*填写模板中的书签*/
        for(int i=count;i>0;--i)
        {
            QAxObject *bookmark = allBookmarks->querySubObject("Item(QVariant)", i);
            QString name= bookmark->property("Name").toString();
            int j=0;
            foreach(QString itemName , itemList){
                if (name == itemName) {
                    QAxObject *curBM = m_wordDocuments->querySubObject("Bookmarks(QString)", name);
                    curBM->querySubObject("Range")->setProperty("Text", sometexts.at(j));
                    break;
                }
                j++;
            }
             return true;
        }
    }
        return false;
}

/******************************************************************************
 * 函数:insertTable
 * 功能:创建表格
 * 参数:nStart 开始位置; nEnd 结束位置; row 行; column 列
 * 返回值: void
 *****************************************************************************/
void WordEngine::insertTable(int nStart,  int nEnd,  int row,  int column)
{
      QAxObject* ptst = m_wordDocuments->querySubObject( "Range( Long, Long )",  nStart, nEnd );
       QAxObject* pTable = m_wordDocuments->querySubObject( "Tables" );
       QVariantList params;
       params.append(ptst->asVariant());
       params.append(row);
       params.append(column);
       if( pTable )
       {
            pTable->dynamicCall( "Add(QAxObject*, Long ,Long )",params);
       }
}

QAxObject *WordEngine::insertTable(QString sLabel,int row, int column)
{
    QAxObject *bookmark = m_wordDocuments->querySubObject("Bookmarks(QVariant)", sLabel);
    if(bookmark)
     {
       bookmark->dynamicCall("Select(void)");
       QAxObject *selection = m_wordWidget->querySubObject("Selection");

       selection->dynamicCall("InsertAfter(QString&)", "\n");
       //selection->dynamicCall("MoveLeft(int)", 1);
       selection->querySubObject("ParagraphFormat")->dynamicCall("Alignment", "wdAlignParagraphCenter");
       //selection->dynamicCall("TypeText(QString&)", "Table Test");//设置标题

       QAxObject *range = selection->querySubObject("Range");
       QAxObject *tables = m_wordDocuments->querySubObject("Tables");
       QAxObject *table = tables->querySubObject("Add(QVariant,int,int)",range->asVariant(),row,column);

       for(int i=1;i<=6;i++)
       {
           QString str = QString("Borders(-%1)").arg(i);
           QAxObject *borders = table->querySubObject(str.toLocal8Bit().constData());
           borders->dynamicCall("SetLineStyle(int)",1);
       }
       return table;
     }
     return NULL;
}

/******************************************************************************
 * 函数:insertPic
 * 功能:插入图片
 * 参数:sLable 标签名;picPath 图片路径
 * 返回值:void
 *****************************************************************************/
void WordEngine::insertPic(QString sLabel,const QString& picPath)
{
    QAxObject *bookmark=m_wordDocuments->querySubObject("Bookmarks(QVariant)",sLabel);
    // 选中标签,将图片插入到标签位置
    if(bookmark){
        bookmark->dynamicCall("Select(void)");
        QAxObject *selection = m_wordWidget->querySubObject("Selection");
        selection->querySubObject("ParagraphFormat")->dynamicCall("Alignment", "wdAlignParagraphCenter");
        QAxObject *range = bookmark->querySubObject("Range");
        QVariant tmp = range->asVariant();
        QList<QVariant>qList;
        qList<<QVariant(picPath);
        qList<<QVariant(false);
        qList<<QVariant(true);
        qList<<tmp;
        QAxObject *Inlineshapes = m_wordDocuments->querySubObject("InlineShapes");
        Inlineshapes->dynamicCall("AddPicture(const QString&, QVariant, QVariant ,QVariant)",qList);
    }

}

/******************************************************************************
 * 函数:MergeCells
 * 功能:合并单元格
 * 参数:table 表格; nStartRow 起始单元格行数; nStartCol ; nEndRow ; nEndCol
 * 返回值:void
 *****************************************************************************/
void WordEngine::MergeCells(QAxObject *table, int nStartRow,int nStartCol,int nEndRow,int nEndCol)
{
    QAxObject* StartCell =table->querySubObject("Cell(int, int)",nStartRow,nStartCol);
    QAxObject* EndCell = table->querySubObject("Cell(int, int)",nEndRow,nEndCol);
    StartCell->dynamicCall("Merge(LPDISPATCH)",EndCell->asVariant());
}

/******************************************************************************
 * 函数:setColumnWidth
 * 功能:设置表格列宽
 * 参数:table 表格; column 列数; width 宽度
 * 返回值:void
 *****************************************************************************/
void WordEngine::setColumnWidth(QAxObject *table, int column, int width)
{
    table->querySubObject("Columns(int)", column)->setProperty("Width", width);
}

/******************************************************************************
 * 函数:setCellString
 * 功能:设置表格内容
 * 参数:table 表格; row 行数; column 列数; text 插入文本
 * 返回值:void
 *****************************************************************************/
void WordEngine::setCellString(QAxObject *table, int row, int column, const QString& text)
{
    if(table)
    {
        table->querySubObject("Cell(int, int)", row, column)
                ->querySubObject("Range")
                ->dynamicCall("SetText(QString)", text);
    }
}

/******************************************************************************
 * 函数:addTableRow
 * 功能:为表格添加行
 * 参数:table 表格; nRow 插入行; rowCount 插入的行数
 * 返回值:void
 *****************************************************************************/
void WordEngine::addTableRow(QAxObject *table, int nRow, int rowCount)
{
    QAxObject* rows = table->querySubObject("Rows");

    int Count = rows->dynamicCall("Count").toInt();
    if(0 <= nRow && nRow <=Count)
    {
        for(int i = 0; i < rowCount; ++i)
        {
            QString sPos = QString("Item(%1)").arg(nRow + i);
            QAxObject* row = rows->querySubObject(sPos.toStdString().c_str());
            QVariant param = row->asVariant();
            rows->dynamicCall("Add(Variant)", param);
        }
    }
}


/******************************************************************************
 * 函数:setCellFontBold
 * 功能:设置内容粗体  isBold控制是否粗体
 * 参数:table 表格; row 插入行; column 列数; isBold 是否加粗
 * 返回值:void
 *****************************************************************************/
void WordEngine::setCellFontBold(QAxObject *table, int row, int column, bool isBold)
{
    table->querySubObject("Cell(int, int)",row,column)->querySubObject("Range")
            ->dynamicCall("SetBold(int)", isBold);
}

/******************************************************************************
 * 函数:setCellFontSize
 * 功能:设置文字大小
 * 参数:table 表格; row 插入行; column 列数; size 字体大小
 * 返回值:void
 *****************************************************************************/
void WordEngine::setCellFontSize(QAxObject *table, int row, int column, int size)
{
    table->querySubObject("Cell(int, int)",row,column)->querySubObject("Range")
            ->querySubObject("Font")->setProperty("Size", size);
}

/******************************************************************************
 * 函数:insertCellPic
 * 功能:在表格中插入图片
 * 参数:table 表格; row 插入行; column 列数; picPath 图片路径
 * 返回值:void
 *****************************************************************************/
void WordEngine::insertCellPic(QAxObject *table, int row, int column, const QString& picPath)
{
    QAxObject* range = table->querySubObject("Cell(int, int)", row, column)
            ->querySubObject("Range");
    range->querySubObject("InlineShapes")
            ->dynamicCall("AddPicture(const QString&)", picPath);

}

reference

QT word文档操作实例
Qt框架下的WORD文档生成方法