轮子四:QT保存数据到 office word文档

1.需要准备一个模板,然后再添加书签,程序替换书签,生成文档

#ifndef WORDENGINE_H
#define WORDENGINE_H

#include <QObject>
#include <QAxObject>
#include <QAxWidget>
#include <QString>
#include <QDebug>
#include <QFile>
#include <QFileInfo>
#include <QDir>
#include <QTextStream>
#include <QDateTime>
#define EDWTABCOLUM 14

class WordEngine: public QObject
{
    Q_OBJECT

public:
    enum AlignmentType{
        AlignmentLeft,
        AlignmentCenter,
        AlignmentRight
    };

    WordEngine();
    ~WordEngine();

    void saveEdwToWord(QString workType,QVariant studentInfo,QVariant edwlist);
    bool open(bool isVisible = false, QString strFilename="");
    bool save(QString strNewFilename = "");
    void close();
    //书签处插入文本
    bool replaceText(QString strLabel, QString strText);
    //多个书签处批量插入文本
    int replaceTextBatch(QStringList labelList, QStringList textList);
    //书签处插入图片
    bool replacePic(QString strLabel, QString strPicFilename);
    //书签处插入表格
    QAxObject* insertTable(QString strLabel, int rows, int cols, QStringList headList={}, QString title="");
    //光标处插入表格
    QAxObject* insertTable(int rows, int cols, QStringList headList={}, QString title="");
    //设置表格列宽
    bool setColumnWidth(QAxObject* table, int colIdx, int width);
    //设置表格单元格文本
    bool setTableCellString(QAxObject* table, int rowIdx, int colIdx, QString strText);
    //设置表格行文本
    bool setTableRowString(QAxObject* table, int rowIdx, QStringList dataList);
    //增加表格行,rowIdx从1开始,默认在表尾插入
    int addTableRows(QAxObject* table, int rowCount, int rowIdx=-1);
    //设置光标处文本
    bool setText(QString strText);
    //设置光标处对齐格式
    bool setAlignment(AlignmentType align);
    //设置光标处字体
    bool setFont(QString strFamily, int size, bool isBold, bool isItalic, bool isUnderline);
    //设置对象字体
    bool setObjectFont(QAxObject* object, QString strFamily, int size, bool isBold, bool isItalic, bool isUnderline);
    //光标移动到文档末尾
    int moveToEnd();
    //光标跳转,实现表格中tab键
    int moveRight();

/*-------geting----------*/
    //根据表格编号获取表格对象
    QAxObject* getTable(int tableIdx);
    //获取表格单元格
    QAxObject* getTableCell(QAxObject* table, int rowIdx, int colIdx);
    //获取表格行
    QAxObject* getTableRow(QAxObject* table, int rowIdx);
signals:
    void  sig_finished(bool);
public slots:
    void errorCatch(int ID, QString str1, QString str2, QString str3);

private:
    QAxObject* m_word;   //指向用于打开文档的word应用程序
    QAxObject* m_documents; //指向word所有工作文档,即文档集
    QAxObject* m_document;  //指向要操作的文档
    QAxObject *m_selection; //指向光标对象,随文件编辑移动?

    QString m_strTemplatename;
    bool m_isOpen;
    bool m_isSave;
};

#endif // WORDENGINE_H




#include "wordengine.h"
#include "qt_windows.h"
#include"Global/GlobalInterface.h"

WordEngine::WordEngine():
    m_word(nullptr),
    m_documents(nullptr),
    m_document(nullptr),
    m_selection(nullptr),
    m_strTemplatename(""),
    m_isOpen(false),
    m_isSave(false)
{
    /*初始化OLE控件,包含在qt_windows.h头文件中,
     * 用于操作基于windows的应用程序*/
    HRESULT result = OleInitialize(0);
    if(result != S_OK && result != S_FALSE){
        qDebug()<<"Fail to initialize OLE!";
    }
}

WordEngine::~WordEngine()
{
    OleUninitialize();
}
//保存文件
void WordEngine::saveEdwToWord(QString workType,QVariant stuInfo, QVariant edwlist)
{
    //试验基本信息
    StudentInfo info = stuInfo.value<StudentInfo>();

    HRESULT result = OleInitialize(0);
    if(result != S_OK && result != S_FALSE){
        qDebug()<<"Fail to initialize OLE!";
    }
    QString strWorkdir = QDir::currentPath();
    QString strTemplatename = strWorkdir + QStringLiteral("/report/技术实验报告模板.docx");
    QString strCurrentTime = QDateTime::currentDateTime().toString("yyyy-MM-dd_hh-mm-ss");
    QString strReportname = strWorkdir + QStringLiteral("/report/技术实验报告_")
            + strCurrentTime + ".docx"; //保存的报告名称
    if(!open(false, strTemplatename)){
        qDebug()<<"Fail to open the report template!";
    }

    //保存信息到报告
    QString strLabel = "label_user";    //用户
    if(!replaceText(strLabel, info.studentName)){
        qDebug()<<"Fail to save data:"<<strLabel<<"!";
    }
     strLabel = "label_StuID";    //学号
    if(!replaceText(strLabel, info.studentID)){
        qDebug()<<"Fail to save data:"<<strLabel<<"!";
    }
     strLabel = "label_DeviceID";    //设备ID
    if(!replaceText(strLabel, info.deviceID)){
        qDebug()<<"Fail to save data:"<<strLabel<<"!";
    }

    strLabel = "label_Time";    //报告生成时间
    if(!replaceText(strLabel, info.time)){
        qDebug()<<"Fail to save data:"<<strLabel<<"!";
    }
    strLabel = "label_testName";    //试验名称
    if(!replaceText(strLabel, info.testName)){
        qDebug()<<"Fail to save data:"<<strLabel<<"!";
    }
    strLabel = "label_testTarget";    //试验目的
    if(!replaceText(strLabel, info.testTarget)){
        qDebug()<<"Fail to save data:"<<strLabel<<"!";
    }


    
    QVector<QString> vec  = edwlist.value<QVector<QString>>();
    int edwNum = vec.size()/EDWTABCOLUM;   
    QAxObject* edwTable = getTable(1);
    int rows = addTableRows(edwTable, edwNum, 2);   //在表格中增加相应数量的行
    if(rows != edwNum){
        qDebug()<<"Fail to add rows to EDW table!";
    }
    for(int i = 0; i<edwNum; i++){
      
        QString strBandWidth = vec.at(i*EDWTABCOLUM+12);  
        QString strAngle = vec.at(i*EDWTABCOLUM+13);

        //保存到表格
        QStringList edwList;
        edwList<<strIdx<<strfirstTime<<strlastTime<<strPulse<<strFreqType<<strFreqNum<<strFreqValue
              <<strPriType<<strPriNum<<strPriValue
             <<strPulseWidth<<strPulseAmptitude0<<strPulseAmptitude1<<strBandWidth<<strAngle;
        if(!setTableRowString(edwTable, i+2, edwList)){
            qDebug()<<"Fail to insert the EDW, row:"<<i;
        }
    }
    bool b_finished=false;
    if(!save(strReportname)){
        qDebug()<<"Fail to save as: "<<strReportname<<"!";
        b_finished=false;
    }else{
        qDebug()<<"Succeed to save report:"<<strReportname;
        b_finished=true;
    }
    emit sig_finished(b_finished);
    close();
    OleUninitialize();
}

void WordEngine::errorCatch(int ID, QString str1, QString str2, QString str3)
{
    qDebug()<<ID<<str1<<str2<<str3;
}

bool WordEngine::open(bool isVisible, QString strFilename)
{
    close();

    m_strTemplatename = strFilename;

    //新建一个word应用程序
    m_word = new QAxObject();
    bool isControl = m_word->setControl("word.Application");
    if(!isControl){
        return false;
    }
    m_word->setProperty("Visible", isVisible);  //设置应用程序是否可见
    //获取word文档集
    m_documents = m_word->querySubObject("Documents");
    if(!m_documents){
        return false;
    }
    m_documents->dynamicCall("Add(QString)", strFilename);  //以指定文件为模板新建文档
    //获取当前激活的文档
    m_document = m_word->querySubObject("ActiveDocument");
    if(m_document){
        m_isOpen = true;
    }
    //获取当前光标位置
    m_selection = m_word->querySubObject("Selection");  //光标是应用程序的对象?
    m_selection->dynamicCall("InsertAfter(QString&)", "\r\n");    //在光标后插入空行,光标仍在当前位置

    /*要了解COM对象的详细用法,使用Qt可以自动生成API文档*/
//    QString doc = m_document->generateDocumentation();
//    QFile docFile("D:/doc.html");
//    docFile.open(QIODevice::WriteOnly|QIODevice::Append);
//    QTextStream tStream(&docFile);
//    tStream<<doc<<endl;
//    docFile.close();

    return  m_isOpen;
}

bool WordEngine::save(QString strNewFilename)
{
    if(!m_isOpen || !m_document){
        return false;
    }

    //未设置文件保存路径时,将文件保存至模板路径
    if(strNewFilename == ""){
        if(m_strTemplatename != ""){
            QFileInfo infoTemplate(m_strTemplatename);
            QDir dirTemplate = infoTemplate.dir();
            QString strAutoFilename = dirTemplate.path() + "/temp_" + QDateTime::currentDateTime().toString("yyyy-MM-dd_hh-mm-ss") + ".docx";
            m_document->dynamicCall("SaveAs(const QString&)", strAutoFilename);
        }else{
            //没有设置文件模板时,将文档保存至C:/temp.docx
            QString tempFilename = "D:/temp.docx";
            m_document->dynamicCall("SaveAs(const QString&)", tempFilename);
        }
    }else{   //否则将文件另存
        m_document->dynamicCall("SaveAs(const QString&)", strNewFilename);
    }

    m_isSave = true;
    return m_isSave;
}

void WordEngine::close()
{
    if(m_isOpen){
        //如果没有保存,则保存为当前文件
        if(!m_isSave){
            save();
        }

        if(m_word){
            m_word->setProperty("DisplayAlerts", true);
        }
        if(m_document){
            m_document->dynamicCall("Close(bool)", true);
        }
        if(m_word){
            m_word->dynamicCall("Quit()");
        }

        m_document = nullptr;
        m_selection = nullptr;
        if(m_documents){
            delete m_documents;
        }
        m_documents = nullptr;
        if(m_word){
           delete m_word;
        }
        m_word = nullptr;

        m_isOpen = false;
        m_isSave = false;
    }
}

bool WordEngine::replaceText(QString strLabel, QString strText)
{
    if(!m_document){
        return false;
    }
    //获取文档中名为strLabel的标签
    QAxObject* bookmark = m_document->querySubObject("Bookmarks(QString)", strLabel);
    if(!bookmark){
        return false;
    }
    bookmark->dynamicCall("Select(void)");  //选中当前书签
    bookmark->querySubObject("Range")->setProperty("Text", strText);    //获取位置并插入文本
    delete bookmark;

    return true;
}

int WordEngine::replaceTextBatch(QStringList labelList, QStringList textList)
{
    if(!m_document){
        return -1;
    }

    QAxObject* bookmarks = m_document->querySubObject("Bookmarks");
    if(!bookmarks){
        return -1;
    }
    int count = bookmarks->property("Count").toInt();
    int count_OK = 0;
    //选择遍历文档书签,避免设置多个书签时循环遍历文档
    for(int i=0; i<count; i++){
        QAxObject* bookmark = bookmarks->querySubObject("Item(QVariant)", i+1);
        QString strMark = bookmark->property("Name").toString();

        int textIdx = -1;
        for(int j=0; j<labelList.size(); j++){
            if(strMark == labelList.at(j)){
                textIdx = j;
                break;
            }
        }
        if(textIdx != -1){
            bookmark->querySubObject("Range")->setProperty("Text", textList.at(textIdx));
            count_OK++;
        }
    }

    return count_OK;
}

bool WordEngine::replacePic(QString strLabel, QString strPicFilename)
{
    if(!m_document){
        return false;
    }

    QAxObject* bookmark = m_document->querySubObject("Bookmarks(QString)", strLabel);
    if(bookmark){
        bookmark->dynamicCall("Select(void)");
        QAxObject* inlineShapes = m_document->querySubObject("InlineShapes");
        inlineShapes->dynamicCall("AddPicture(const QString&)", strPicFilename);
        //设置图片格式
        QAxObject* inlineShape = m_document->querySubObject("InlineShapes(1)"); //获取当前图片对象
        inlineShape->dynamicCall("Select(void)");   //选中当前图片
        QAxObject* range = inlineShape->querySubObject("Range");    //获取当前图片位置
        QAxObject* paraFormat = range->querySubObject("ParagraphFormat");   //获取段落格式
        paraFormat->dynamicCall("SetAlignment(int)", 1);    //设置段落格式居中
        inlineShape->setProperty("Height", 300);    //设置图片高度
        inlineShape->setProperty("Width", 150); //设置图片宽度

        delete inlineShapes;
    }else{
        return false;
    }

    return true;
}

QAxObject* WordEngine::insertTable(QString strLabel, int rows, int cols, QStringList headList, QString title)
{
    QAxObject* bookmark = m_document->querySubObject("Bookmarks(QVariant)", strLabel);
    if(!bookmark){
        return nullptr;
    }

    bookmark->dynamicCall("Select(void)");
    QAxObject* selection = m_word->querySubObject("Selection");
    selection->dynamicCall("InsertAfter(QString&)", "\r\n");    //在光标后插入空行,光标仍在当前位置
    selection->querySubObject("ParagraphFormat")->dynamicCall("Alignment", "wdAlignParagraphCenter");

    if(title != ""){ //设置标题
        selection->dynamicCall("TypeText(QString&)", title);
    }

    QAxObject* range = selection->querySubObject("Range");
    QAxObject* tables = m_document->querySubObject("Tables");
    QAxObject* table = tables->querySubObject("Add(QVariant,int,int)", range->asVariant(), rows, cols);

    //表格列自动拉伸,0固定,1根据内容调整,2根据窗口调整
    table->dynamicCall("AutoFitBehavior(wdAutoFitBehavior)", 2);

    //设置表头
    if(!headList.isEmpty()){
        for(int i=0; i<headList.size(); i++){
            table->querySubObject("Cell(int,int)", 1, i+1)->querySubObject("Range")->dynamicCall("SetText(QString)", headList.at(i));
            table->querySubObject("Cell(int,int)", 1, i+1)->querySubObject("Range")->dynamicCall("SetBold(int)", true); //表头加粗
        }
    }

    //设置表格线风格,-1~-4分别为上、左、下、右边框,-5为水平线,-6为垂直线
    for(int i=1; i<=6; i++){
        QString strBorder = QString("Borders(-%1)").arg(i);
        QAxObject* borders = table->querySubObject(strBorder.toLatin1().constData());
        borders->dynamicCall("SetLineStyle(int)", 1);
    }

    return table;
}

QAxObject* WordEngine::insertTable(int rows, int cols, QStringList headList, QString title)
{
    m_selection->querySubObject("ParagraphFormat")->dynamicCall("Alignment", "wdAlignParagraphCenter");
    if(title != ""){
        m_selection->dynamicCall("TypeText(QString&)", title); //设置标题
    }

    QAxObject* range = m_selection->querySubObject("Range");
    QAxObject* tables = m_document->querySubObject("Tables");
    QAxObject* table = tables->querySubObject("Add(QVariant,int,int)", range->asVariant(), rows, cols);
    //表格列自动拉伸,0固定,1根据内容调整,2根据窗口调整
    table->dynamicCall("AutoFitBehavior(wdAutoFitBehavior)", 2);

    //设置表头
    if(!headList.isEmpty()){
        for(int i=0; i<headList.size(); i++){
            table->querySubObject("Cell(int,int)", 1, i+1)->querySubObject("Range")->dynamicCall("SetText(QString)", headList.at(i));
            table->querySubObject("Cell(int,int)", 1, i+1)->querySubObject("Range")->dynamicCall("SetBold(int)", true); //表头加粗
        }
    }

    //设置表格线
    for(int i=1; i<=6; i++){
        QString strBorder = QString("Borders(-%1)").arg(i);
        QAxObject* borders = table->querySubObject(strBorder.toLatin1().constData());
        borders->dynamicCall("SetLineStyle(int)", 1);
    }

    return table;
}

bool WordEngine::setColumnWidth(QAxObject *table, int colIdx, int width)
{
    if(!table){
        return false;
    }

    return table->querySubObject("Columns(int)", colIdx)->setProperty("Width", width);
}

bool WordEngine::setTableCellString(QAxObject *table, int rowIdx, int colIdx, QString strText)
{
    if(!table){
        return false;
    }

    QAxObject *cell = table->querySubObject("Cell(int,int)", rowIdx, colIdx);
    if(!cell){
        return false;
    }
    cell->dynamicCall("Select(void)");
    return cell->querySubObject("Range")->setProperty("Text", strText);
}

bool WordEngine::setTableRowString(QAxObject *table, int rowIdx, QStringList dataList)
{
    if(!table){
        return false;
    }

    for(int i=0; i<dataList.size(); i++){
        QAxObject *cell = table->querySubObject("Cell(int,int)", rowIdx, i+1);
        if(!cell){
            return false;
        }
        cell->dynamicCall("Select(void)");
        cell->querySubObject("Range")->setProperty("Text", dataList.at(i));
    }

    return true;
}

int WordEngine::addTableRows(QAxObject *table, int rowCount, int rowIdx)
{
    QAxObject* rows = table->querySubObject("Rows");
    int count = rows->dynamicCall("Count").toInt();
    if(rowIdx == -1){
        rowIdx = count;
    }
    if(rowIdx<=0 || rowIdx>count){
        return -1;
    }

    int count_OK = 0;
    for(int i=0; i<rowCount; i++){
        QString strPos = QString("Item(%1)").arg(rowIdx+i);
        QAxObject* row = rows->querySubObject(strPos.toStdString().c_str());
        if(!row){
            break;
        }
        QVariant param = row->asVariant();
        rows->dynamicCall("Add(Variant)", param);
        count_OK++;
    }

    return count_OK;
}

bool WordEngine::setText(QString strText)
{
    return m_selection->dynamicCall("TypeText(QString&)", strText).toBool();    //执行成功,无返回值
}

bool WordEngine::setAlignment(AlignmentType align)
{
    bool isOK = false;
    switch(align){
    case 0:
        isOK = m_selection->querySubObject("ParagraphFormat")->dynamicCall("Alignment", "wdAlignParagraphLeft").toBool();
        break;
    case 1:
        isOK = m_selection->querySubObject("ParagraphFormat")->dynamicCall("Alignment", "wdAlignParagraphCenter").toBool();
        break;
    case 2:
        isOK = m_selection->querySubObject("ParagraphFormat")->dynamicCall("Alignment", "wdAlignParagraphRight").toBool();
        break;
    }

    return isOK;    //该函数调用成功,无返回值,导致dynamicCall返回invalid
}

bool WordEngine::setFont(QString strFamily, int size, bool isBold, bool isItalic, bool isUnderline)
{
    bool isOK = false;
    isOK = m_selection->querySubObject("Font")->setProperty("Name", strFamily);
    isOK = m_selection->querySubObject("Font")->setProperty("Size", size);
    isOK = m_selection->querySubObject("Font")->setProperty("Bold", isBold);
    isOK = m_selection->querySubObject("Font")->setProperty("Italic", isItalic);
    if(isUnderline){
        isOK = m_selection->querySubObject("Font")->setProperty("Underline", 2);
    }else{
        isOK = m_selection->querySubObject("Font")->setProperty("Underline", 0);
    }

    return isOK;
}

bool WordEngine::setObjectFont(QAxObject *object, QString strFamily, int size, bool isBold, bool isItalic, bool isUnderline)
{
    if(!object){
        return false;
    }

    object->dynamicCall("Select(void)");  //移动文档光标选中当前对象
    object->querySubObject("Range");

    return setFont(strFamily, size, isBold, isItalic, isUnderline);
}

int WordEngine::moveToEnd()
{
    QAxObject* selection = m_word->querySubObject("Selection");
    QVariantList params;
    params.append(6);
    params.append(0);
    return selection->dynamicCall("EndOf(QVariant, QVariant)", params).toInt();
}

int WordEngine::moveRight()
{
    QAxObject* selection = m_word->querySubObject("Selection");
    return selection->dynamicCall("MoveRight(int)", 1).toInt();
}

/**************************************************
****************getting object*********************
***************************************************/

QAxObject* WordEngine::getTable(int tableIdx)
{
    QAxObject *tables = m_document->querySubObject("Tables");
    if(!tables){
        return nullptr;
    }
    return tables->querySubObject("Item(int)", tableIdx);
}

QAxObject* WordEngine::getTableCell(QAxObject *table, int rowIdx, int colIdx)
{
    if(!table){
        return nullptr;
    }
    return table->querySubObject("Cell(int,int)", rowIdx, colIdx);
}

QAxObject* WordEngine::getTableRow(QAxObject *table, int rowIdx)
{
    if(!table){
        return nullptr;
    }
    return table->querySubObject("Rows(int)", rowIdx);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老赵的博客

叮咚,你的赏钱已到账,嘿嘿嘿

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值