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. 工业相机和镜头说明与图像采集
  2. 计蒜客NOIP模拟赛(2) D2T2紫色百合
  3. github 修改fork的代码之后如何提交代码并pull request
  4. 基于 Zookeeper 的分布式锁实现
  5. Codeforces Round #201 (Div. 2)C,E
  6. 电路初级基本原理总结
  7. Atitit.印章文化 印章的起源历史与发展 v2 r99 .docx
  8. python如何输入整数求和_Python如何输入数字并求和
  9. 数据库作业8:SQL练习5 - SELECT(嵌套查询EXISTS、集合查询、基于派生表的查询)
  10. JAVA 实现《拳皇误闯冒险岛》游戏
  11. 绝对值表达式的最大值(Java)
  12. 香港电影中的演员:B字头(持续更新中)
  13. python使用QDA进行二次判别分析
  14. Maven - 8、大型Maven项目,快速按需任意构建
  15. 沪教版神奇的机器人分段_原创:四年级语文下册第2单元9神奇的机器人课件1沪教版.pptV5.1...
  16. 关于rem布局以及sprit雪碧图的移动端自适应
  17. C语言exit/atexit/_exit的区别
  18. 智能技术旨在改善视障人士的交通便利性
  19. 外观专利和著作权(版权)的区别 ?
  20. c语言实现数字竞猜游戏

热门文章

  1. Linux下提权常用小命令
  2. 福建食用菌产业博览会盛大开幕 谋定中国农民丰收节交易会
  3. 【期末复习】信息安全技术(含答案)
  4. 实验四 SQL语言的数据更新和视图
  5. 我的世界java皮肤展开图,我的世界情侣皮肤,我的世界皮肤展开图做图片
  6. linux内存96后无法连接,linux服务器因磁盘空间满导致oracle数据库无法连接问题探索...
  7. iOS开发系列--通讯录、蓝牙、内购、GameCenter、iCloud、Passbook系统服务开发汇总...
  8. 上海浦东新区:在不动产登记、政务服务领域应用电子合同、印章
  9. 字节跳动面试题+答案,全答对的 30K 以上!
  10. 树莓派驱动水星无线网卡(MW150UH)教程指南