qt5 windows Excel QAxObject导入导出

1、点击导入按钮,弹出excel表格选择框,选择后读取内容:

//在头文件中定义
QScopedPointer<ExcelBase> m_xls;
//下面是点击导入excel代码
QString xlsFile = QFileDialog::getOpenFileName(this,QString(),QString(),"excel(*.xls*.xlsx)");
qDebug()<<xlsFile;
if(xlsFile.isEmpty()){
    return;
}
QList< QList<QVariant> > m_datas;
if(m_xls.isNull())
     m_xls.reset(new ExcelBase);
m_xls->open(xlsFile);

m_xls->setCurrentSheet(1);
m_xls->readAll(m_datas);
for (int j = 0; j < m_datas[i].size(); ++j) {
    for (int j = 0; j < m_datas[i].size(); ++j) {
          QString imei = m_datas[i][j].toString();
           //这个imei就是第i行第j列读取出来的数据     
    }      
 }
//这mxls中操作创建文件比较耗时,建议新建线程使用。

2、点击到处按钮,弹出选择保存excel的路径,然后存入数据。

//头文件定义
QScopedPointer<ExcelBase> m_xls;

//点击导出
//生成导出数据
QList< QList<QVariant> > m_datas;
for(int i = 0;i < 1000;i++){
    QList<QVariant> rows;
    for(int j = 0; j < 8;j++){
        rows<<"这里写入值";
    }
    m_datas<<rows;
}   
//保存文件名
QString xlsFile = QFileDialog::getExistingDirectory(this);
    if(xlsFile.isEmpty()){
        return;
    }
QDateTime current_time = QDateTime::currentDateTime();
//显示时间,格式为:年-月-日 时:分:秒 周几
QString StrCurrentTime = current_time.toString("yyyy年MM月dd日_hh时mm分ss秒");
xlsFile += "/xds_";
xlsFile.append(StrCurrentTime).append(".xlsx");


 if(m_xls.isNull())
        m_xls.reset(new ExcelBase);
 m_xls->create(xlsFile);

 m_xls->setCurrentSheet(1);
 bool result = m_xls->writeCurrentSheet(m_datas);
 m_xls->save();
 m_xls.reset();
 if(result){
    //导出成功
  }else{
    //导出失败
}


//xls创建相关操作比较耗时,建议放在新线程中

3、别忘记pro文件中添加

QT += axcontainer

4、最后是一个别人写的工具类ExcelBase

h文件如下:

#ifndef EXCELREADER_H
#define EXCELREADER_H
#include <QObject>
#include <QAxObject>
#include <QString>
#include <QStringList>
#include <QVariant>

class ExcelBasePrivate;
///
/// \brief win下excel快速读取类
/// 参考天池项目源码,天池源码地址:https://github.com/qtcn/tianchi/blob/v0.0.2-build20130701/include/tianchi/file/tcmsexcel.h
///
class ExcelBase : public QObject
{
public:
    ExcelBase(QObject* par=NULL);
    ~ExcelBase();
private:
    Q_DISABLE_COPY(ExcelBase)
    Q_DECLARE_PRIVATE(ExcelBase)
    ExcelBasePrivate* const d_ptr;
public:
    /// @brief 设置方向的常数
    enum Alignment
    {
        xlTop    = -4160, ///< 靠上
        xlLeft   = -4131, ///< 靠左
        xlRight  = -4152, ///< 靠右
        xlCenter = -4108, ///< 居中
        xlBottom = -4107  ///< 靠下
    };

    /// @brief 创建一个Microsoft Excel文件
    bool create(const QString& filename = QString());
    /// @brief 打开一个Microsoft Excel文件
    bool open(const QString& filename = QString());
    /// @brief 另存Microsoft Excel文件
    void saveAs(const QString& filename);
    void save();
    /// @brief 关闭Microsoft Excel文件
    void close();
    /// @brief 踢出当前打开的 Microsoft Excel<br>
    /// @brief 放弃此对象对该 Excel 的控制权<br>
    /// @brief Excel 文件仍保持打开,但丧失了控制权
    void kick();

    /// @brief 设置当前打开的 Excel 是否可见
    void setVisible(bool value);
    /// @brief 设置 Excel 文档的标题
    void setCaption(const QString& value);

    /// @brief 新建一本 Excel 文档
    bool addBook();

    /// @brief 返回当前 Excel 的 Sheet 数量
    int sheetCount();

    /// @brief 返回当前打开的 Excel 全部 Sheet 名
    QStringList sheetNames();

    /// @brief 返回当前 Sheet.
    bool currentSheet();

    /// @brief 设置并指定当前 Sheet.
    /// @param [in] 当前 Sheet 索引,从 1 开始
    bool setCurrentSheet(int index);

    /// @brief 当前打开的 Excel 的 Sheet 名
    QString currentSheetName();

    /// @brief 读取单元格 Sheet 的内容
    /// @param [in] row 行号,从 1 开始
    /// @param [in] col 列号,从 1 开始
    /// @return 返回指定单元格的内容
    QVariant read(int row, int col);

    /// @brief 读取单元格 Sheet 的内容
    /// @param [in] row 行号,从 1 开始
    /// @param [in] col 列号,从 1 开始
    /// @return 返回指定单元格的内容
    inline QVariant cell(int row, int col) { return read(row, col); }

    /// @brief 写入单元格 Sheet 的内容
    /// @param [in] row 行号,从 1 开始
    /// @param [in] col 列号,从 1 开始
    /// @param [in] value 准备写入的内容
    void write(int row, int col, const QVariant& value);

    void cellFormat(int row, int col, const QString& format);
    void cellAlign(int row, int col, Alignment hAlign, Alignment vAlign);

    /// @brief 获取有效区域信息
    /// @see rowStart() const
    /// @see rowEnd() const
    /// @see colStart() const
    /// @see colEnd() const
    bool usedRange(int& rowStart, int& colStart, int &rowEnd, int &colEnd);

    QVariant readAll();
    void readAll(QList<QList<QVariant> > &cells);
    bool writeCurrentSheet(const QList<QList<QVariant> > &cells);

    static void convertToColName(int data, QString &res);
    static QString to26AlphabetString(int data);
    static void castListListVariant2Variant(const QList<QList<QVariant> > &cells, QVariant &res);
    static void castVariant2ListListVariant(const QVariant& var,QList<QList<QVariant> > &res);
};

#endif // EXCELREADER_H

cpp文件如下:

#include "ExcelBase.h"
#include <QFile>

#include <QList>
#include <QDebug>
#if defined(Q_OS_WIN)
#include <ActiveQt/QAxObject>
#endif // Q_OS_WIN



#define TC_FREE(x)  {delete x; x=NULL;}

class ExcelBasePrivate
{
    Q_DECLARE_PUBLIC(ExcelBase)
public:
    explicit ExcelBasePrivate(ExcelBase* qptr);
    ~ExcelBasePrivate();

    void construct();
    void destory();

    ExcelBase* const q_ptr;

#if defined(Q_OS_WIN)
    QAxObject*  excel;
    QAxObject*  books;
    QAxObject*  book;
    QAxObject*  sheets;
    QAxObject*  sheet;
#endif
    QString     filename;
    QString     sheetName;
};

ExcelBasePrivate::ExcelBasePrivate(ExcelBase *qptr)
    : q_ptr(qptr)
#if defined(Q_OS_WIN)
    , excel(NULL)
    , books(NULL)
    , book(NULL)
    , sheets(NULL)
    , sheet(NULL)
#endif // Q_OS_WIN
{
}

ExcelBasePrivate::~ExcelBasePrivate()
{
#if defined(Q_OS_WIN)
    if(excel)
    {
        if (!excel->isNull())
        {
            excel->dynamicCall("Quit()");
        }
    }
    TC_FREE(sheet );
    TC_FREE(sheets);
    TC_FREE(book  );
    TC_FREE(books );
    TC_FREE(excel );
#endif // Q_OS_WIN
}

void ExcelBasePrivate::construct()
{
#if defined(Q_OS_WIN)
    destory();
    excel = new QAxObject(q_ptr);
    excel->setControl("Excel.Application");
    excel->setProperty("Visible",false);
    if (excel->isNull())
    {
        excel->setControl("ET.Application");
    }
    if (!excel->isNull())
    {
        books = excel->querySubObject("Workbooks");
    }
#endif // Q_OS_WIN
}

void ExcelBasePrivate::destory()
{
#if defined(Q_OS_WIN)
    TC_FREE(sheet );
    TC_FREE(sheets);
    if (book != NULL && ! book->isNull())
    {
        book->dynamicCall("Close(Boolean)", false);
    }
    TC_FREE(book );
    TC_FREE(books);
    if (excel != NULL && !excel->isNull())
    {
        excel->dynamicCall("Quit()");
    }
    TC_FREE(excel);
    filename  = "";
    sheetName = "";
#endif // Q_OS_WIN
}


ExcelBase::ExcelBase(QObject* par):QObject(par)
    ,d_ptr(new ExcelBasePrivate(this))
{
}

ExcelBase::~ExcelBase()
{
    close();
    delete d_ptr;
}

bool ExcelBase::create(const QString& filename)
{
    bool ret = false;
#if defined(Q_OS_WIN)
    Q_D(ExcelBase);
    d->construct();
    if (d->books != NULL && ! d->books->isNull())
    {
        d->books->dynamicCall("Add");
        d->book   = d->excel->querySubObject("ActiveWorkBook");
        d->sheets = d->book ->querySubObject("WorkSheets"    );
        currentSheet();
        d->filename = filename;
        ret = true;
    }
#else
    Q_UNUSED(filename)
#endif // Q_OS_WIN
    return ret;
}

bool ExcelBase::open(const QString& filename)
{
    bool ret = false;
#if defined(Q_OS_WIN)
    Q_D(ExcelBase);
    d->construct();
    if ( d->books != NULL && ! d->books->isNull() )
    {
        d->book = d->books->querySubObject("Open(QString, QVariant)", filename, 0);
        ret = d->book != NULL && ! d->book->isNull();
        if ( ret )
        {
            d->sheets = d->book->querySubObject("WorkSheets");
            d->filename = filename;
            currentSheet();
        }
    }
#else
    Q_UNUSED(filename)
#endif // Q_OS_WIN
    return ret;
}

void ExcelBase::saveAs(const QString& filename)
{
#if defined(Q_OS_WIN)
    Q_D(ExcelBase);
    if ( d->book != NULL && ! d->book->isNull() )
    {
        d->filename = filename;
        QString strPath = d->filename;
        strPath = strPath.replace('/','\\');
        qDebug()<<strPath;
        d->book->dynamicCall("SaveAs(const QString&,int,const QString&,const QString&,bool,bool)", strPath
                             ,56,QString(""),QString(""),false,false);
    }
#else
    Q_UNUSED(filename)
#endif // Q_OS_WIN
}
///
/// \brief 保存excel
///
void ExcelBase::save()
{
#if defined(Q_OS_WIN)
    Q_D(ExcelBase);
    if(d->filename.isEmpty())
        return;
    saveAs(d->filename);
#else
    Q_UNUSED(filename)
#endif // Q_OS_WIN
}

void ExcelBase::close()
{
#if defined(Q_OS_WIN)
    Q_D(ExcelBase);
    d->destory();
#endif // Q_OS_WIN
}

void ExcelBase::kick()
{
#if defined(Q_OS_WIN)
    Q_D(ExcelBase);

    if (d->excel != NULL && !d->excel->isNull())
    {
        d->excel->setProperty("Visible", true);
    }
    TC_FREE(d->sheet );
    TC_FREE(d->sheets);
    TC_FREE(d->book  );
    TC_FREE(d->books );
    TC_FREE(d->excel );
    d->destory();
#endif // Q_OS_WIN
}

QStringList ExcelBase::sheetNames()
{
    QStringList ret;
#if defined(Q_OS_WIN)
    Q_D(ExcelBase);
    if (d->sheets != NULL && !d->sheets->isNull())
    {
        int sheetCount = d->sheets->property("Count").toInt();
        for (int i = 1; i <= sheetCount; i++)
        {
            QAxObject* sheet = d->sheets->querySubObject("Item(int)", i);
            if(NULL == sheet || sheet->isNull())
                continue;
            ret.append(sheet->property("Name").toString());
            delete sheet;
        }
    }
#endif // Q_OS_WIN
    return ret;
}

QString ExcelBase::currentSheetName()
{
    Q_D(ExcelBase);
    return d->sheetName;
}

void ExcelBase::setVisible(bool value)
{
#if defined(Q_OS_WIN)
    Q_D(ExcelBase);
    if (d->excel != NULL && !d->excel->isNull())
    {
        d->excel->setProperty("Visible", value);
    }
#else
    Q_UNUSED(value)
#endif // Q_OS_WIN
}

void ExcelBase::setCaption(const QString& value)
{
#if defined(Q_OS_WIN)
    Q_D(ExcelBase);
    if (d->excel != NULL && !d->excel->isNull())
    {
        d->excel->setProperty("Caption", value);
    }
#else
    Q_UNUSED(value)
#endif // Q_OS_WIN
}

bool ExcelBase::addBook()
{
    bool ret = false;
#if defined(Q_OS_WIN)
    Q_D(ExcelBase);
    if (d->excel != NULL && !d->excel->isNull())
    {
        TC_FREE(d->sheet );
        TC_FREE(d->sheets);
        TC_FREE(d->book  );
        TC_FREE(d->books );
        d->books = d->excel->querySubObject("WorkBooks");
        ret = d->books != NULL && !d->books->isNull();
    }
#endif // Q_OS_WIN
    return ret;
}

bool ExcelBase::currentSheet()
{
    bool ret = false;
#if defined(Q_OS_WIN)
    Q_D(ExcelBase);
    TC_FREE(d->sheet);
    if (d->excel != NULL && !d->excel->isNull())
    {
        TC_FREE(d->sheet);
        d->sheet = d->excel->querySubObject("ActiveWorkBook");
        ret = d->sheet != NULL && !d->sheet->isNull();
        d->sheetName = ret ? d->sheet->property("Name").toString() : "";
    }
#endif // Q_OS_WIN
    return ret;
}

bool ExcelBase::setCurrentSheet(int index)
{
    bool ret = false;
#if defined(Q_OS_WIN)
    Q_D(ExcelBase);
    if (d->sheets != NULL && !d->sheets->isNull())
    {
        TC_FREE(d->sheet);
        d->sheet = d->sheets->querySubObject("Item(int)", index);
        ret = d->sheet != NULL && ! d->sheet->isNull();
        if(ret)
        {
            d->sheet->dynamicCall("Activate(void)");
        }
        d->sheetName = ret ? d->sheet->property("Name").toString() : "";
    }
#else
    Q_UNUSED(index)
#endif // Q_OS_WIN
    return ret;
}

int ExcelBase::sheetCount()
{
    int ret = 0;
#if defined(Q_OS_WIN)
    Q_D(ExcelBase);
    if (d->sheets != NULL && ! d->sheets->isNull())
    {
        ret = d->sheets->property("Count").toInt();
    }
#endif // Q_OS_WIN
    return ret;
}

void ExcelBase::cellFormat(int row, int col, const QString& format)
{
#if defined(Q_OS_WIN)
    Q_D(ExcelBase);
    if (d->sheet != NULL && ! d->sheet->isNull())
    {
        QAxObject* range = d->sheet->querySubObject("Cells(int, int)", row, col);
        range->setProperty("NumberFormatLocal", format);
        delete range;
    }
#else
    Q_UNUSED(row)
    Q_UNUSED(col)
    Q_UNUSED(format)
#endif // Q_OS_WIN
}

void ExcelBase::cellAlign(int row, int col, Alignment hAlign, Alignment vAlign)
{
#if defined(Q_OS_WIN)
    Q_D(ExcelBase);
    if (d->sheet != NULL && !d->sheet->isNull())
    {
        QAxObject* range = d->sheet->querySubObject("Cells(int, int)", row, col);
        range->setProperty("HorizontalAlignment", hAlign);
        range->setProperty("VerticalAlignment",   vAlign);
        delete range;
    }
#else
    Q_UNUSED(row)
    Q_UNUSED(col)
    Q_UNUSED(hAlign)
    Q_UNUSED(vAlign)
#endif // Q_OS_WIN
}

QVariant ExcelBase::read(int row, int col)
{
    QVariant ret;
#if defined(Q_OS_WIN)
    Q_D(ExcelBase);
    if (d->sheet != NULL && ! d->sheet->isNull())
    {
        QAxObject* range = d->sheet->querySubObject("Cells(int, int)", row, col);
        //ret = range->property("Value");
        ret = range->dynamicCall("Value()");
        delete range;
    }
#else
    Q_UNUSED(row)
    Q_UNUSED(col)
#endif // Q_OS_WIN
    return ret;
}

void ExcelBase::write(int row, int col, const QVariant& value)
{
#if defined(Q_OS_WIN)
    Q_D(ExcelBase);
    if (d->sheet != NULL && ! d->sheet->isNull())
    {
        QAxObject* range = d->sheet->querySubObject("Cells(int, int)", row, col);
//        range->setProperty("Value", value);
        range->setProperty("Value2", value);//这里不能用Value他只能在office中写入,不能写入wps。  Value2两个都可以写入
        delete range;
    }
#else
    Q_UNUSED(row)
    Q_UNUSED(col)
    Q_UNUSED(value)
#endif // Q_OS_WIN
}

bool ExcelBase::usedRange(int& rowStart, int& colStart, int& rowEnd, int& colEnd)
{
    bool ret = false;
#if defined(Q_OS_WIN)
    Q_D(ExcelBase);
    if (d->sheet != NULL && ! d->sheet->isNull())
    {
        QAxObject* urange  = d->sheet->querySubObject("UsedRange");
        rowStart = urange->property("Row"   ).toInt();
        colStart = urange->property("Column").toInt();
        rowEnd   = urange->querySubObject("Rows"   )->property("Count").toInt();
        colEnd   = urange->querySubObject("Columns")->property("Count").toInt();
        delete urange;
        ret = true;
    }
#else
    Q_UNUSED(rowStart)
    Q_UNUSED(colStart)
    Q_UNUSED(rowEnd)
    Q_UNUSED(colEnd)
#endif // Q_OS_WIN
    return ret;
}
///
/// \brief 读取整个sheet
/// \return
///
QVariant ExcelBase::readAll()
{
    QVariant var;
#if defined(Q_OS_WIN)
    Q_D(ExcelBase);
    if (d->sheet != NULL && ! d->sheet->isNull())
    {
        QAxObject *usedRange = d->sheet->querySubObject("UsedRange");
        if(NULL == usedRange || usedRange->isNull())
        {
            return var;
        }
        var = usedRange->dynamicCall("Value");
        delete usedRange;
    }
#endif
    return var;
}
///
/// \brief 读取整个sheet的数据,并放置到cells中
/// \param cells
///
void ExcelBase::readAll(QList<QList<QVariant> > &cells)
{
#if defined(Q_OS_WIN)
    castVariant2ListListVariant(readAll(),cells);
#else
    Q_UNUSED(cells);
#endif

}

///
/// \brief 写入一个表格内容
/// \param cells
/// \return 成功写入返回true
/// \see readAllSheet
///
bool ExcelBase::writeCurrentSheet(const QList<QList<QVariant> > &cells)
{
#if defined(Q_OS_WIN)
    Q_D(ExcelBase);
    if(cells.size() <= 0)
        return false;
    if(NULL == d->sheet || d->sheet->isNull())
        return false;
    int row = cells.size();
    int col = cells.at(0).size();
    QString rangStr;
    convertToColName(col,rangStr);
    rangStr += QString::number(row);
    rangStr = "A1:" + rangStr;
    qDebug()<<rangStr;
//    QAxObject *range = d->sheet->querySubObject("Range(const QString&)",rangStr);
    QVariantList params;
    params<<"A1"<<rangStr;
    QAxObject *range = d->sheet->querySubObject("Range(QVariant,QVariant)",params);
    range->setProperty("ColumnWidth",25);
    if(NULL == range || range->isNull())
    {
        return false;
    }
    bool succ = false;
    QVariant var;
    castListListVariant2Variant(cells,var);
    succ = range->setProperty("Value2", var);//这里不能用Value他只能在office中写入,不能写入wps。  Value2两个都可以写入
    delete range;
    return succ;
#else
    return true;
#endif
}
///
/// \brief 把列数转换为excel的字母列号
/// \param data 大于0的数
/// \return 字母列号,如1->A 26->Z 27 AA
///
void ExcelBase::convertToColName(int data, QString &res)
{
    Q_ASSERT(data>0 && data<65535);
    int tempData = data / 26;
    if(tempData > 0)
    {
        int mode = data % 26;
        convertToColName(mode,res);
        convertToColName(tempData,res);
    }
    else
    {
        res=(to26AlphabetString(data)+res);
    }
}
///
/// \brief 数字转换为26字母
///
/// 1->A 26->Z
/// \param data
/// \return
///
QString ExcelBase::to26AlphabetString(int data)
{
    QChar ch = data + 0x40;//A对应0x41
    return QString(ch);
}
///
/// \brief QList<QList<QVariant> >转换为QVariant
/// \param cells
/// \return
///
void ExcelBase::castListListVariant2Variant(const QList<QList<QVariant> > &cells, QVariant &res)
{
    QVariantList vars;
    const int rows = cells.size();
    for(int i=0;i<rows;++i)
    {
        vars.append(QVariant(cells[i]));
    }
    res = QVariant(vars);
}
///
/// \brief 把QVariant转为QList<QList<QVariant> >
/// \param var
/// \param res
///
void ExcelBase::castVariant2ListListVariant(const QVariant &var, QList<QList<QVariant> > &res)
{
    QVariantList varRows = var.toList();
    if(varRows.isEmpty())
    {
        return;
    }
    const int rowCount = varRows.size();
    QVariantList rowData;
    for(int i=0;i<rowCount;++i)
    {
        rowData = varRows[i].toList();
        res.push_back(rowData);
    }
}

 

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值