Qt批量操作Excel
2015-07-13 15:21
489 查看
最近在做一个项目,客户要求把查询到的数据导出Excel,而网上大部分资料描述的都很局限、很简单。
由于要导出的数据量很大(QTableView中大约有几十万条数据),一开始我是找到一个单元格就写入一个值,但这样的话程序就会把大量的时间花费在线程切换中,导致效率太低(5000行数据大概需要5分钟)。
最后找到了一种方法,即为对Excel进行批量写入值操作,下面是我程序中导出excel部分的源码:
<span style="white-space:pre"> </span>QString strContent;
QAxObject *range;
QList<QVariant> mLstData;
QList<QString> mLstCurData;
int nColumns = 0;
QString strMergeCell;
int nIndex = 0, nTotal = 0; // 记录数据个数
QStringList strListParaName;
QMap<int,PidInfoStruct> mapPidInfo;
//建立Excel对象
HRESULT r = OleInitialize(0);<span style="white-space:pre"> </span>//由于我把导出数据的操作放在了一个新线程中,所以在调用activeX之前要初始化com组件
if (r != S_OK && r != S_FALSE) {
qWarning("Qt: Could not initialize OLE (error %x)", (unsigned int)r);
}
QAxObject *excel = new QAxObject("Excel.Application");
excel->dynamicCall("SetVisible(bool)", false);
excel->setProperty("Visible", false);
QAxObject *workbooks = excel->querySubObject("WorkBooks");
if (workbooks == NULL)
{
return;
}
workbooks->dynamicCall("Add");
QAxObject *workbook = excel->querySubObject("ActiveWorkBook");
QAxObject *worksheet = workbook->querySubObject("Worksheets(int)", 1);
nTotal = mapNdtPidVal.count();
mLstData.clear();
QMapIterator<uint, QMap<int,float>> itor(mapNdtPidVal);<span style="white-space:pre"> </span>//map中为到导出的数据(此为我项目中的数据)
while (itor.hasNext())
{
itor.next();
++nIndex;
QString strTime = QDateTime::fromTime_t(itor.key()).toString(
"yyyy-MM-dd hh:mm:ss");
QMapIterator<int, float> hashItOfPidVal(itor.value());
QList<QString> fListVal;
while (hashItOfPidVal.hasNext())
{
hashItOfPidVal.next();
if (nIndex <= 1) // 只有解析第一条数据时,装载参数列表
{
mapPidInfo.clear();
if (!WinManager::instance().getPidInfoByType(nDevType, mapPidInfo))
{
continue;
}
strListParaName.append(mapPidInfo.value(hashItOfPidVal.key()).strName);
}
fListVal.append(QString("%1").arg(hashItOfPidVal.value()));
}
// 参数个数和对应参数值个数不一致,丢掉此数据
if (strListParaName.count() != fListVal.count())
{
--nIndex;
continue;
}
if (nIndex <= 1) // 只有解析第一条数据时,设置表头
{
QStringList strHorizontalHeader;
strHorizontalHeader << QStringLiteral("序号") << QStringLiteral("时间") << strListParaName;
mLstData << QVariant(strHorizontalHeader);
}
mLstCurData.clear();
mLstCurData << QString("%1").arg(nIndex);
mLstCurData << strTime;
mLstCurData << fListVal;
if (mLstCurData.count() > nColumns)
{
nColumns = mLstCurData.count();
}
mLstData << QVariant(mLstCurData);
emit showExportState((int)(nIndex * 99 / nTotal));
}
<span style="white-space:pre"> </span>//指定导出数据的行列范围
strMergeCell.append(QChar('A')); //初始列
strMergeCell.append(QString::number(1)); //初始行
strMergeCell.append(":");
strMergeCell.append(QChar(nColumns - 1 + 'A')); //终止列
strMergeCell.append(QString::number(mLstData.count())); //终止行
由于要导出的数据量很大(QTableView中大约有几十万条数据),一开始我是找到一个单元格就写入一个值,但这样的话程序就会把大量的时间花费在线程切换中,导致效率太低(5000行数据大概需要5分钟)。
最后找到了一种方法,即为对Excel进行批量写入值操作,下面是我程序中导出excel部分的源码:
<span style="white-space:pre"> </span>QString strContent;
QAxObject *range;
QList<QVariant> mLstData;
QList<QString> mLstCurData;
int nColumns = 0;
QString strMergeCell;
int nIndex = 0, nTotal = 0; // 记录数据个数
QStringList strListParaName;
QMap<int,PidInfoStruct> mapPidInfo;
//建立Excel对象
HRESULT r = OleInitialize(0);<span style="white-space:pre"> </span>//由于我把导出数据的操作放在了一个新线程中,所以在调用activeX之前要初始化com组件
if (r != S_OK && r != S_FALSE) {
qWarning("Qt: Could not initialize OLE (error %x)", (unsigned int)r);
}
QAxObject *excel = new QAxObject("Excel.Application");
excel->dynamicCall("SetVisible(bool)", false);
excel->setProperty("Visible", false);
QAxObject *workbooks = excel->querySubObject("WorkBooks");
if (workbooks == NULL)
{
return;
}
workbooks->dynamicCall("Add");
QAxObject *workbook = excel->querySubObject("ActiveWorkBook");
QAxObject *worksheet = workbook->querySubObject("Worksheets(int)", 1);
nTotal = mapNdtPidVal.count();
mLstData.clear();
QMapIterator<uint, QMap<int,float>> itor(mapNdtPidVal);<span style="white-space:pre"> </span>//map中为到导出的数据(此为我项目中的数据)
while (itor.hasNext())
{
itor.next();
++nIndex;
QString strTime = QDateTime::fromTime_t(itor.key()).toString(
"yyyy-MM-dd hh:mm:ss");
QMapIterator<int, float> hashItOfPidVal(itor.value());
QList<QString> fListVal;
while (hashItOfPidVal.hasNext())
{
hashItOfPidVal.next();
if (nIndex <= 1) // 只有解析第一条数据时,装载参数列表
{
mapPidInfo.clear();
if (!WinManager::instance().getPidInfoByType(nDevType, mapPidInfo))
{
continue;
}
strListParaName.append(mapPidInfo.value(hashItOfPidVal.key()).strName);
}
fListVal.append(QString("%1").arg(hashItOfPidVal.value()));
}
// 参数个数和对应参数值个数不一致,丢掉此数据
if (strListParaName.count() != fListVal.count())
{
--nIndex;
continue;
}
if (nIndex <= 1) // 只有解析第一条数据时,设置表头
{
QStringList strHorizontalHeader;
strHorizontalHeader << QStringLiteral("序号") << QStringLiteral("时间") << strListParaName;
mLstData << QVariant(strHorizontalHeader);
}
mLstCurData.clear();
mLstCurData << QString("%1").arg(nIndex);
mLstCurData << strTime;
mLstCurData << fListVal;
if (mLstCurData.count() > nColumns)
{
nColumns = mLstCurData.count();
}
mLstData << QVariant(mLstCurData);
emit showExportState((int)(nIndex * 99 / nTotal));
}
<span style="white-space:pre"> </span>//指定导出数据的行列范围
strMergeCell.append(QChar('A')); //初始列
strMergeCell.append(QString::number(1)); //初始行
strMergeCell.append(":");
strMergeCell.append(QChar(nColumns - 1 + 'A')); //终止列
strMergeCell.append(QString::number(mLstData.count())); //终止行
<span style="white-space:pre"> </span>//批量写入所有数据 QAxObject *merge_range = worksheet->querySubObject("Range(const QString&)", strMergeCell); merge_range->setProperty("Value", QVariant(mLstData)); workbook->dynamicCall("SaveAs(const QString&)", QDir::toNativeSeparators(strFileName)); emit showExportState(100); workbook->dynamicCall("Close()"); worksheet->clear();//释放所有工作表 excel->dynamicCall("Quit()"); delete excel;//释放excel OleUninitialize();最后,由于这是一个耗时的操作,所以建议尽量把导出excel操作放在一个新线程里面,然后把导出进度通过信号发给UI线程,让UI显示导出进度。通过批量操作的方式,10万条数据只需要5秒钟。
相关文章推荐
- SPOJ QTREE6 lct
- HTML5 仿QT 示例Drag and Drop Robot 换装机器人
- 【Qt】字符编码、乱码总结
- Qt跨平台的一个例程
- SPOJ QTREE4 lct
- MQTT-SN协议乱翻之小结篇
- MQTT-SN协议乱翻之实现要点
- MQTT-SN协议乱翻之功能描述
- MQTT-SN协议乱翻之消息格式
- MQTT-SN协议乱翻之简要介绍
- MQTT 3.1.1,值得升级的6个新特性
- MQTT 3.1协议非严肃反思录
- MQTT协议笔记之mqtt.io项目HTTP协议支持
- MQTT协议笔记之mqtt.io项目Websocket协议支持
- MQTT协议笔记之订阅
- MQTT协议笔记之消息流
- qt4.7 opengl基础实例
- MQTT协议笔记之发布流程
- MQTT协议笔记之连接和心跳
- MQTT协议笔记之头部信息