QAxObject新建并保存Excel表格

C++中有三种常用的操作Excel的方式,Xlnt、QtXlsx以及QAxObject
本文使用QAxObject来新建并保存Excel表格

1:初始化Excel程序

 /*初始化Excel对象*/QAxObject *_excelObject = NULL; ///< 代表了EXCEL服务器,QAxObject *_curWorkbook;        ///< 当前工作簿QAxObject *_curWorkSheet;       ///< 当前sheet(实际就是第一个sheet)QAxObject *_usedRange;          ///< sheet里的数据区域范围/*初始化服务,否则报错误CoCreateInstance failure <CoInitialize has not been called.>QAxBase::setControl: requested control Excel.Application could not be instantiatedQAxBase::dynamicCallHelper: Object is not initialized, or initialization failed*/HRESULT r = OleInitialize(0);if (r != S_OK && r != S_FALSE){return -1;}if (_excelObject == NULL){/*代表整个 Microsoft Excel 应用程序。*/_excelObject = new QAxObject("Excel.Application");if (!_excelObject){return -1;}}

2:隐藏Excel窗口

 /*隐藏Excel窗口*/_excelObject->setProperty("Visible", false);

3:新建一个Excel

 /*返回一个表示所有打开的工作簿的**工作簿** 集合。 此为只读属性*/QAxObject * workbooks = _excelObject->querySubObject("WorkBooks");/*打开存在的Excel文件*///workbooks->dynamicCall("Open (const QString&)", "D:/123.xlsx");/*新建一个工作表。 新工作表将成为活动工作表。*/workbooks->dynamicCall("Add");/*workbooks必须指向活跃 WorkBook,否则保存时报错:QAxBase::dynamicCallHelper: SaveCopyAs(QString): No such property in  [unknown]  Candidates are:*/workbooks = _excelObject->querySubObject("ActiveWorkBook");  // ToDo .../*活动工作表*/_curWorkbook = _excelObject->querySubObject("ActiveWorkBook");/*第一个sheet*/_curWorkSheet = _curWorkbook->querySubObject("Worksheets(int)", 1);///< 当前sheet(实际就是第一个sheet)

3:常用操作

快速填充数据块

    /*快速填充数据块, 填充B1到C20这一数据块*//*https://www.cnblogs.com/lifexy/p/10743316.html*/QAxObject *user_range = _curWorkSheet->querySubObject("Range(const QString&)", cols_range);QList<QList<QVariant> > datas;for (int i = 0; i<20; i++){QList<QVariant> rows;rows.append(i);rows.append(3 * i + 0.1);datas.append(rows);}QVariant var;castListListVariant2Variant(datas, var);user_range->setProperty("Value", var);

设置单个单元格的数据和颜色

/*设置单个单元格的内容,第5行,第1列填入字符串‘Hello’*/QAxObject *singleCell = _curWorkSheet->querySubObject("Cells(int,int)", 5, 1);singleCell->dynamicCall("SetValue(const QVariant&)", QVariant(QStringLiteral("Hello")));/*设置背景色为红色:http://blog.sina.com.cn/s/blog_a6fb6cc90101gv2p.html*/QAxObject* interior = singleCell->querySubObject("Interior");interior->setProperty("Color", QColor(0, 255, 0));   //设置单元格背景色(绿色)

使用批量公式

 /*使用批量公式:https://github.com/muellerj/hexplorer/blob/master/src/excel.cpp*/const int average_use_cnt = 100;cols_range.sprintf("E%d:E%d", 1, 20);QAxObject *user_range_formular = _curWorkSheet->querySubObject("Range(const QString&)", cols_range);QList<QList<QVariant> > datas_formular;for (int i = 0; i<19; i++){QList<QVariant> rows;QString formular;//formular.sprintf("=RC[-2]*100");formular.sprintf("=AVERAGE(RC[-2]:R[1]C[-2])");rows.append(formular);datas_formular.append(rows);}QVariant var_formular;castListListVariant2Variant(datas_formular, var_formular);user_range_formular->setProperty("Value", var_formular);

添加折线图

 /*画折线图*/// 先选中一个空白的地方,不然后面的SeriesCollection会先将所有行都做个散点图。。。_usedRange = _curWorkSheet->querySubObject("UsedRange");QAxObject *clos = _usedRange->querySubObject("Columns");QAxObject *emptyCell = _curWorkSheet->querySubObject("Cells(int,int)", 1, clos->property("Count").toInt() + 3);emptyCell->dynamicCall("Select(void)");/*表达式。AddChart2(Style、 XlChartType、 Left、 Top、 Width、 Height、 NewLayout)*/QAxObject *shapes = _curWorkSheet->querySubObject("Shapes");shapes->dynamicCall("AddChart(int)", 74, 100, 100, 500, 800); //74:折线散点图,左 上 宽 高// 再将视野拖回到左上角区域QAxObject *range = _curWorkSheet->querySubObject("Range(QVariant)", "$A$1:$A$2");range->dynamicCall("Select(void)");int nbChart = shapes->property("Count").toInt();QAxObject *shape = shapes->querySubObject("Range(int)", nbChart);/*根据指定的系数缩放图形宽度。 对于图片和 OLE 对象,您可以说明是相对于原始大小还是相对于当前大小缩放形状。 图片和 OLE 对象以外的形状总是相对于当前宽度缩放。*///shape->dynamicCall("ScaleWidth(QVariant,QVariant)",2,0);shape->dynamicCall("Select(void)");QAxObject *chart = _curWorkbook->querySubObject("ActiveChart");QAxObject *seriesCollection = chart->querySubObject("SeriesCollection()");seriesCollection->dynamicCall("NewSeries (void)");int nb = seriesCollection->property("Count").toInt();QAxObject *series = chart->querySubObject("SeriesCollection(int)", nb);series->setProperty("Name", "Linear parameter");/*x轴最大最小值*/QAxObject* aixs_x = chart->querySubObject("Axes(int)", 1);aixs_x->setProperty("MinimumScale", 0);aixs_x->setProperty("MaximumScale", 25);/*y轴最大最小值*/QAxObject* aixs_y = chart->querySubObject("Axes(int)", 2);aixs_y->setProperty("MinimumScale", 0);aixs_y->setProperty("MaximumScale", 80);// 给图表添加数据//range->dynamicCall("Select(void)");cols_range.sprintf("B%d:B%d", 1, 20);/*B1:C20*/QAxObject * xvalues = _curWorkSheet->querySubObject("Range(const QString&)", cols_range);cols_range.sprintf("C%d:C%d", 1, 20);/*B1:C20*/QAxObject * yvalues = _curWorkSheet->querySubObject("Range(const QString&)", cols_range);series->setProperty("XValues", xvalues->asVariant());series->setProperty("Values", yvalues->asVariant());

添加趋势线

 // 添加趋势线QAxObject *trendLines = series->querySubObject("Trendlines()");if (trendLines){trendLines->dynamicCall("Add()");int nbTrendLines = trendLines->property("Count").toInt();QAxObject *trendLine = series->querySubObject("Trendlines(int)", nbTrendLines);// 设定图标格式为 “散点图”,数字-4133来自 枚举变量 XlTrendlineType  : xlLogarithmic/*各种变量的值和属性名的关系:http://mugiseyebrows.ru/excel/Excel.Range.html#Cells*/trendLine->setProperty("Type", -4132);trendLine->setProperty("Name", "TrendLineName");trendLine->setProperty("DisplayEquation", true);/*显示公式,显示R2*/trendLine->setProperty("DisplayRSquared",true);/*获取公式*/QAxObject *dataLabel = trendLine->querySubObject("DataLabel");QString strFormula = dataLabel->property("Formula").toString();getFormulaCoeffcient_kx_plus_b(strFormula, out_k, out_b);out_formular = strFormula.toStdString();}/*将公式中的值自动填入,但是不能随着图表选择的数据范围动态刷新*/QAxObject *kvalue_Cell = _curWorkSheet->querySubObject("Cells(int,int)", 1, 7);QString formular;formular.sprintf("=INDEX(LINEST(R1C3:R20C3,R1C2:R20C2),1)");/*注意:Y值在左,X值在右,绝对位置*/kvalue_Cell->setProperty("Formula", formular);QAxObject *bvalue_Cell = _curWorkSheet->querySubObject("Cells(int,int)", 2, 7);formular.sprintf("=INDEX(LINEST(R1C3:R20C3,R1C2:R20C2),2)");/*注意:Y值在左,X值在右,绝对位置*/bvalue_Cell->setProperty("Formula", formular);

保存并退出Excel

 /* ./ 会将文件保存在我的文档目录下面*/QString filepath = "./test.xlsx";/*文件名字转换,否则Excel一直卡住,QDir::toNativeSeparators*/workbooks->dynamicCall("SaveCopyAs(QString)", QDir::toNativeSeparators(filepath));/*在关闭Excel之前先调用这个不显示警告框,否则会弹出是否保存sheet1的对话框*/_excelObject->setProperty("DisplayAlerts", false);_excelObject->dynamicCall("Quit()");
运行结果

示例代码

main.cpp

#include <QAxObject>
#include <QDebug>
#include <QDir>
#include <QColor>
#include <ole2.h>
#include <utility>
#include "iostream"
#include "stdio.h"
using namespace std;//! 形如:"y = -9.113x + 78.016"
//! 则 a=-9.113 b=78.016
void getFormulaCoeffcient_kx_plus_b(QString strFormula, double &k, double &b)
{int posEqual = strFormula.indexOf('=');int posX = strFormula.indexOf('x');QString strK = strFormula.mid(posEqual + 1, posX - posEqual - 1);if (strK == " ") k = 1;else k = strK.toDouble();bool isPositive = true;QString str_after_x = strFormula.mid(posX + 1);int posB = str_after_x.indexOf('+');if (posB == -1){isPositive = false;posB = str_after_x.indexOf('-');}else{isPositive = true;}if (-1 == posB){b = 0;}else{QString strB = str_after_x.mid(posB + 1);b = strB.toDouble();if (!isPositive)b *= -1.0;}
}//把QList<QList<QVariant> > 转为QVariant,用于快速写入的
void 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);
}int main()
{std::string out_formular;double out_k;double out_b;/*初始化Excel对象*/QAxObject *_excelObject = NULL; ///< 代表了EXCEL服务器,QAxObject *_curWorkbook;        ///< 当前工作簿QAxObject *_curWorkSheet;       ///< 当前sheet(实际就是第一个sheet)QAxObject *_usedRange;          ///< sheet里的数据区域范围/*初始化服务,否则报错误CoCreateInstance failure <CoInitialize has not been called.>QAxBase::setControl: requested control Excel.Application could not be instantiatedQAxBase::dynamicCallHelper: Object is not initialized, or initialization failed*/HRESULT r = OleInitialize(0);if (r != S_OK && r != S_FALSE){return -1;}if (_excelObject == NULL){/*代表整个 Microsoft Excel 应用程序。*/_excelObject = new QAxObject("Excel.Application");if (!_excelObject){return -1;}}/*隐藏Excel窗口*/_excelObject->setProperty("Visible", false); /*返回一个表示所有打开的工作簿的**工作簿** 集合。 此为只读属性*/QAxObject * workbooks = _excelObject->querySubObject("WorkBooks");/*打开存在的Excel文件*///workbooks->dynamicCall("Open (const QString&)", "D:/123.xlsx");/*新建一个工作表。 新工作表将成为活动工作表。*/workbooks->dynamicCall("Add");/*workbooks必须指向活跃 WorkBook,否则保存时报错:QAxBase::dynamicCallHelper: SaveCopyAs(QString): No such property in  [unknown]  Candidates are:*/workbooks = _excelObject->querySubObject("ActiveWorkBook");  // ToDo .../*活动工作表*/_curWorkbook = _excelObject->querySubObject("ActiveWorkBook");/*第一个sheet*/_curWorkSheet = _curWorkbook->querySubObject("Worksheets(int)", 1);///< 当前sheet(实际就是第一个sheet)QList<QVariant> listXValues, listValues;QString cols_range;/* "B1:C20" */cols_range.sprintf("B%d:C%d", 1, 20);/*快速填充数据块, 填充B1到C20这一数据块*//*https://www.cnblogs.com/lifexy/p/10743316.html*/QAxObject *user_range = _curWorkSheet->querySubObject("Range(const QString&)", cols_range);QList<QList<QVariant> > datas;for (int i = 0; i<20; i++){QList<QVariant> rows;rows.append(i);rows.append(3 * i + 0.1);datas.append(rows);}QVariant var;castListListVariant2Variant(datas, var);user_range->setProperty("Value", var);/*设置单个单元格的内容,第5行,第1列填入字符串‘Hello’*/QAxObject *singleCell = _curWorkSheet->querySubObject("Cells(int,int)", 5, 1);singleCell->dynamicCall("SetValue(const QVariant&)", QVariant(QStringLiteral("Hello")));/*设置背景色为红色:http://blog.sina.com.cn/s/blog_a6fb6cc90101gv2p.html*/QAxObject* interior = singleCell->querySubObject("Interior");interior->setProperty("Color", QColor(0, 255, 0));   //设置单元格背景色(绿色)/*使用批量公式:https://github.com/muellerj/hexplorer/blob/master/src/excel.cpp*/const int average_use_cnt = 100;cols_range.sprintf("E%d:E%d", 1, 20);QAxObject *user_range_formular = _curWorkSheet->querySubObject("Range(const QString&)", cols_range);QList<QList<QVariant> > datas_formular;for (int i = 0; i<19; i++){QList<QVariant> rows;QString formular;//formular.sprintf("=RC[-2]*100");formular.sprintf("=AVERAGE(RC[-2]:R[1]C[-2])");rows.append(formular);datas_formular.append(rows);}QVariant var_formular;castListListVariant2Variant(datas_formular, var_formular);user_range_formular->setProperty("Value", var_formular);/*画折线图*/// 先选中一个空白的地方,不然后面的SeriesCollection会先将所有行都做个散点图。。。_usedRange = _curWorkSheet->querySubObject("UsedRange");QAxObject *clos = _usedRange->querySubObject("Columns");QAxObject *emptyCell = _curWorkSheet->querySubObject("Cells(int,int)", 1, clos->property("Count").toInt() + 3);emptyCell->dynamicCall("Select(void)");/*表达式。AddChart2(Style、 XlChartType、 Left、 Top、 Width、 Height、 NewLayout)*/QAxObject *shapes = _curWorkSheet->querySubObject("Shapes");shapes->dynamicCall("AddChart(int)", 74, 100, 100, 500, 800); //74:折线散点图,左 上 宽 高// 再将视野拖回到左上角区域QAxObject *range = _curWorkSheet->querySubObject("Range(QVariant)", "$A$1:$A$2");range->dynamicCall("Select(void)");int nbChart = shapes->property("Count").toInt();QAxObject *shape = shapes->querySubObject("Range(int)", nbChart);/*根据指定的系数缩放图形宽度。 对于图片和 OLE 对象,您可以说明是相对于原始大小还是相对于当前大小缩放形状。 图片和 OLE 对象以外的形状总是相对于当前宽度缩放。*///shape->dynamicCall("ScaleWidth(QVariant,QVariant)",2,0);shape->dynamicCall("Select(void)");QAxObject *chart = _curWorkbook->querySubObject("ActiveChart");QAxObject *seriesCollection = chart->querySubObject("SeriesCollection()");seriesCollection->dynamicCall("NewSeries (void)");int nb = seriesCollection->property("Count").toInt();QAxObject *series = chart->querySubObject("SeriesCollection(int)", nb);series->setProperty("Name", "Linear parameter");/*x轴最大最小值*/QAxObject* aixs_x = chart->querySubObject("Axes(int)", 1);aixs_x->setProperty("MinimumScale", 0);aixs_x->setProperty("MaximumScale", 25);/*y轴最大最小值*/QAxObject* aixs_y = chart->querySubObject("Axes(int)", 2);aixs_y->setProperty("MinimumScale", 0);aixs_y->setProperty("MaximumScale", 80);// 给图表添加数据//range->dynamicCall("Select(void)");cols_range.sprintf("B%d:B%d", 1, 20);/*B1:C20*/QAxObject * xvalues = _curWorkSheet->querySubObject("Range(const QString&)", cols_range);cols_range.sprintf("C%d:C%d", 1, 20);/*B1:C20*/QAxObject * yvalues = _curWorkSheet->querySubObject("Range(const QString&)", cols_range);series->setProperty("XValues", xvalues->asVariant());series->setProperty("Values", yvalues->asVariant());// 添加趋势线QAxObject *trendLines = series->querySubObject("Trendlines()");if (trendLines){trendLines->dynamicCall("Add()");int nbTrendLines = trendLines->property("Count").toInt();QAxObject *trendLine = series->querySubObject("Trendlines(int)", nbTrendLines);// 设定图标格式为 “散点图”,数字-4133来自 枚举变量 XlTrendlineType  : xlLogarithmic/*各种变量的值和属性名的关系:http://mugiseyebrows.ru/excel/Excel.Range.html#Cells*/trendLine->setProperty("Type", -4132);trendLine->setProperty("Name", "TrendLineName");trendLine->setProperty("DisplayEquation", true);/*显示公式,显示R2*/trendLine->setProperty("DisplayRSquared",true);/*获取公式*/QAxObject *dataLabel = trendLine->querySubObject("DataLabel");QString strFormula = dataLabel->property("Formula").toString();getFormulaCoeffcient_kx_plus_b(strFormula, out_k, out_b);out_formular = strFormula.toStdString();}/*将公式中的值自动填入,但是不能随着图表选择的数据范围动态刷新*/QAxObject *kvalue_Cell = _curWorkSheet->querySubObject("Cells(int,int)", 1, 7);QString formular;formular.sprintf("=INDEX(LINEST(R1C3:R20C3,R1C2:R20C2),1)");/*注意:Y值在左,X值在右,绝对位置*/kvalue_Cell->setProperty("Formula", formular);QAxObject *bvalue_Cell = _curWorkSheet->querySubObject("Cells(int,int)", 2, 7);formular.sprintf("=INDEX(LINEST(R1C3:R20C3,R1C2:R20C2),2)");/*注意:Y值在左,X值在右,绝对位置*/bvalue_Cell->setProperty("Formula", formular);/* ./ 会将文件保存在我的文档目录下面*/QString filepath = "./test.xlsx";/*文件名字转换,否则Excel一直卡住,QDir::toNativeSeparators*/workbooks->dynamicCall("SaveCopyAs(QString)", QDir::toNativeSeparators(filepath));/*在关闭Excel之前先调用这个不显示警告框,否则会弹出是否保存sheet1的对话框*/_excelObject->setProperty("DisplayAlerts", false);_excelObject->dynamicCall("Quit()");delete _excelObject;_excelObject = NULL;OleUninitialize();return 0;
}

CMakeLists

cmake_minimum_required (VERSION 2.6 FATAL_ERROR)project(QAxObject_Excel)
find_package (Qt5 REQUIRED Core Widgets AxContainer)ADD_DEFINITIONS (${QT_DEFINITIONS})
ADD_DEFINITIONS(-D _XKEYCHECK_H)
ADD_EXECUTABLE  (Demo main.cpp)set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT Demo)TARGET_LINK_LIBRARIES (Demo Qt5::Core Qt5::Widgets Qt5::AxContainer)
参考链接

简介的例子: Qt中使用QAxObject操作Excel
单元格详细操作: Qt之操作Excel
Excel vba文档:Excel VBA 参考
Excel 保存出错:Qt 使用QAxObject保存excel出错,使用双反斜线\路径分隔符
Excel COM 变量:The COM object is a QAxObject with the CLSID
Excel 自动拟合曲线:excel 自动获得拟合系数,自动引用,计算

QAxObject保存Excel表格相关推荐

  1. oracle中的表怎样保存,怎样保存excel 表格数据库中-如何将excel表格更新oracle数据库中数据...

    如何将excel表格更新oracle数据库中数据 这里以SQL SERVE2008为例.SQLSERVER2008有一个"数据导入导出功能",当然我们也可以打开数据库之后,在数据库 ...

  2. 浏览器批量采集网站标题 保存Excel表格

    有一批网址,不知道是什么网站,怎样才能快速获得网站标题呢?方法很简单,就是使用浏览器一个个地打开,记录下网站标题就可以了,关键是找一个具有自动完成功能的浏览器.具体步骤如下: 1.先把网址整理一下,保 ...

  3. 计算机excel没点保存,excel表格没保存怎么找回,excel表格没有保存

    在使用Windows 10工作时会遇到形形色色的问题,比如需要重装无线网卡驱动程序.那么如何进行操作呢?下面小编与你分享具体步骤和方法. 工具/材料 Windows 10操作系统 操作方法 01启动W ...

  4. QAxObject操作Excel表格

    1 pro CONFIG += qaxcontainer 2 封装qexcel.cpp qexcel.h文件 ,main.cpp用来测试 =====主要实现对工作表的操作,数据的插入删除读取操作,单元 ...

  5. Python中用OpenPyXL处理Excel表格

    更多内容,请访问我的 个人博客. 前言 用 Python 处理Excel表格的几个常规库: xlrd 用来读 xlwt 用来写 xlutils 用于做复制.筛选等针对文档文件的操作 这些库都不如 Op ...

  6. Jxl解析Excel表格数据

    /** * @file ExcelUtils.java * * @brief ExcelUtils.java相关函数 * * * @author * - Dec 28, 2011 xxxx * * @ ...

  7. matlab筛选表格数据导出,excel表格里怎么将筛选数据导出-Excel表格在进行筛选,我如何可以导出所有筛选出来......

    如何将EXCEL表格中筛选出来的数据一次性复制到另一... 使用数据透最方便下据为例: 步骤1:选择A1单元格,插入>>>数据透视表,再单击定"按钮,如下图 步骤2:勾选& ...

  8. Python爬虫项目:爬取JSON数据存储Excel表格与存储图片

    随着网络的迅速发展,万维网成为大量信息的载体,如何有效地提取并利用这些信息成为一个巨大的挑战.搜索引擎(Search Engine),例如传统的通用搜索引擎AltaVista,Yahoo!和Googl ...

  9. 用python爬取基金网信息数据,保存到表格,并做成四种简单可视化。(爬虫之路,永无止境!)

    用python爬取基金网信息数据,保存到表格,并做成四种简单可视化.(爬虫之路,永无止境!) 上次 2021-07-07写的用python爬取腾讯招聘网岗位信息保存到表格,并做成简单可视化. 有的人留 ...

最新文章

  1. HDU 3826 Squarefree number:题目解答源码
  2. RocketMQ : MQClientException: producerGroup can not equal DEFAULT_PRODUCER, please specify another
  3. 因子(factor)的研究
  4. python基础_collections系列
  5. PostgreSQL 10.0 preview 功能增强 - 增加access method CHECK接口amcheck
  6. java mysql备份_java调用mysql服务做备份与恢复
  7. mhdd测试hdd硬盘软件,硬盘检测工具mhdd
  8. Python-Cartopy制图学习02-中国2010年5月干旱情况空间制图
  9. windowsxp系统怎么装iis服务器,win xp系统安装IIS的详细步骤【图文】
  10. sublime text3 主题-Boxy Theme
  11. Win Server2003常见问题的解决然方案
  12. OIer__ZLY__OI计划
  13. LED发光二极管限流电阻的计算
  14. 20元一支的洗面奶,7天卖了上万,他们是如何做到的?
  15. Flash打造星火飘落效果
  16. 刚上岸就扫雷 祥生控股前债难还
  17. 新版电商运营学习路线图(全套视频笔记素材合集)
  18. ssm整合笔记(1)-curd
  19. 【智能优化算法】基于蜉蝣算法求解多目标优化问题附matlab代码
  20. 并网-低电压穿越与孤岛并存分析

热门文章

  1. xpanx原理解析 | 只要 3 秒!抖音视频无水印下载
  2. 金士顿固态硬盘不认盘修复_上海金士顿固态硬盘维修 上海台电固态硬盘不识别数据恢复中心...
  3. Android 渐变色背景样式
  4. mysql 批量查询
  5. Qt添加翻译文件无效或部分无效
  6. win10 屏幕切换鼠标手势桌面边缘快捷切换 ahk
  7. iOS开发系列--通讯录、蓝牙、内购、GameCenter、iCloud、Passbook系统服务开发汇总...
  8. 一个很简单的淘宝优惠券搜索助手 大家看看有没有用吧
  9. 2023年美赛C题Wordle预测问题三、四建模及Python代码详细讲解
  10. Android经典蓝牙相关知识