用dumpcpp工具生成的excel.h/excel.cpp来操纵Excel
2013-04-08 19:33
369 查看
上一篇:在Qt中用QAxObject来操作Excel
1.系统环境:Qt 4.7+MinGW、Win7、QtCreator、Excel 2007
2.生成excel.h、excel.cpp、office.h和office.cpp
dumpcpp ---- ActiveQt模块的命令行工具,可以导出Qt能识别的COM组件的接口。这个工具在Qt库的bin目录下可以找到。如果没有,也可以在Qt库\tools\activeqt\dumpcpp文件夹中找到源码,自己编译一下就有了。在命令行中进入某个目录,比如D:\,然后执行dumpcpp {00020813-0000-0000-C000-000000000046}就可以在D:\下生成excel.h和excel.cpp文件了。这两个文件中就包含了Qt导出的操纵Excel的类和申明。
如果找不到dumpcpp这个工具,可能是Qt库的bin目录没有加入到环境变量path中,或者bin目录下没有这个工具。如果dumpcpp提示 dumpcpp: type library '' not found 或者QAxBase::setControl: requested control {00020813-0000-0000-C000-000000000046} could not be instantiated,那么可以将 {00020813-0000-0000-C000-000000000046}改成Excel.Application或者{00024500-0000-0000-C000-000000000046}试试。如果还不行,就去注册表HKEY_LOCAL_MACHINE\SOFTWARE\Classes\TypeLib\中找吧。。。比如HKEY_LOCAL_MACHINE\SOFTWARE\Classes\TypeLib\{00020813-0000-0000-C000-000000000046}\1.6\0\win32下有个键值C:\Program
Files\Microsoft Office\Office12\EXCEL.EXE,那么 {00020813-0000-0000-C000-000000000046} 就是正确的CSSID了。
有了excel.h和excel.cpp还不行,加入到工程,编译后会发现其中很多类型不全,会出现诸如excel.h:26: 错误:use of enum 'MsoCalloutDropType' without previous declaration之类的很多错误。这是因为还需要office.h和office.cpp。同样用dumpcpp,执行dumpcpp
{2DF8D04C-5BFA-101B-BDE5-00AA0044DE52}就可得到office.h和office.cpp文件。这是Microsoft Office 12.0 Object Library,在注册表中位置是HKEY_LOCAL_MACHINE\SOFTWARE\Classes\TypeLib\{2DF8D04C-5BFA-101B-BDE5-00AA0044DE52}\2.4\0\win32。若提示找不到qpixmap类,则在excel.h的头文件中添加#include
<QtGui/qpixmap.h>。
将office.h和office.cpp也包含进工程,并在excel.h中添加#include"office.h"后再次编译,还是不行。会出现:office.h:1666: 警告:this decimal constant is unsigned only in ISO C90这样的错误。这是由编译器引起的。找到这个常数,在常数后面增加一个UL标识,或者ULL表示,如4294967295UL,这样就不会报警了。再次编译,会出现:
这样应该就可以正常编译了。
3.例子
我在QtCreator中新建了一个工程testExcel2作为测试之用。注意要在.pro文件中添加CONFIG += qaxcontainer。该工程中所有文件均为 uft8 格式。
在上例中,我测试了单元格的使用、函数的使用、图表的使用。还添加了Cells(int,int)函数,插入表格背景图片、中文输入无乱码,xls和xlsx两种版本的保存。
4.其他问题
运用过程中可能还会出现其他问题:
1)在Excel::Application *excel = new Excel::Application(this);这句出现undefined reference to `vtable for Excel::Application' 或 undefined reference to `Excel::Sheets::staticMetaObject'这样的错误。
解决办法:将外部引用的*.h文件在头文件中包含,不要包含在*.cpp中。在Office.h中包含<QMetaObject>。
2)出现QAxBase::setControl: requested control {00020813-0000-0000-C000-000000000046} could not be instantiated
QAxBase::qt_metacall: Object is not initialized, or initialization failed
QAxBase::qt_metacall: Object is not initialized, or initialization failed
QAxBase::qt_metacall: Object is not initialized, or initialization failed这样的错误
解决办法:在整个工程中查找 {00020813-0000-0000-C000-000000000046},将其替换为 Excel.Application
3)出现 'Excel::XlFileFormat' is not a class or namespace这样的错误
解决办法:xlFileFormat是枚举类型,如果要用其中的某个枚举值,直接写成 Excel::xlOpenXMLWorkbook,不要写成 Excel::XlFileFormat::xlOpenXMLWorkbook
5.样例图片
6.源码下载
百度网盘:
3个压缩包均在:http://pan.baidu.com/share/link?shareid=2465785956&uk=4128141257
新浪网盘(最近把网盘整理了一下,不知这个失效没):
1)testExcel2_仅包含修改后的excel,h、excel.cpp、office.h和office.cpp
2)testExcel2_包含所有源码,不包含Qt运行库
3)testExcel2_包含所有源码和Qt运行库
7.其他类
在Qt的天池项目里也有处理Excel文件的类,不过我还没用过。大家有兴趣可以看看。地址:http://www.qtcn.org/bbs/thread-htm-fid-105.html
1.系统环境:Qt 4.7+MinGW、Win7、QtCreator、Excel 2007
2.生成excel.h、excel.cpp、office.h和office.cpp
dumpcpp ---- ActiveQt模块的命令行工具,可以导出Qt能识别的COM组件的接口。这个工具在Qt库的bin目录下可以找到。如果没有,也可以在Qt库\tools\activeqt\dumpcpp文件夹中找到源码,自己编译一下就有了。在命令行中进入某个目录,比如D:\,然后执行dumpcpp {00020813-0000-0000-C000-000000000046}就可以在D:\下生成excel.h和excel.cpp文件了。这两个文件中就包含了Qt导出的操纵Excel的类和申明。
如果找不到dumpcpp这个工具,可能是Qt库的bin目录没有加入到环境变量path中,或者bin目录下没有这个工具。如果dumpcpp提示 dumpcpp: type library '' not found 或者QAxBase::setControl: requested control {00020813-0000-0000-C000-000000000046} could not be instantiated,那么可以将 {00020813-0000-0000-C000-000000000046}改成Excel.Application或者{00024500-0000-0000-C000-000000000046}试试。如果还不行,就去注册表HKEY_LOCAL_MACHINE\SOFTWARE\Classes\TypeLib\中找吧。。。比如HKEY_LOCAL_MACHINE\SOFTWARE\Classes\TypeLib\{00020813-0000-0000-C000-000000000046}\1.6\0\win32下有个键值C:\Program
Files\Microsoft Office\Office12\EXCEL.EXE,那么 {00020813-0000-0000-C000-000000000046} 就是正确的CSSID了。
有了excel.h和excel.cpp还不行,加入到工程,编译后会发现其中很多类型不全,会出现诸如excel.h:26: 错误:use of enum 'MsoCalloutDropType' without previous declaration之类的很多错误。这是因为还需要office.h和office.cpp。同样用dumpcpp,执行dumpcpp
{2DF8D04C-5BFA-101B-BDE5-00AA0044DE52}就可得到office.h和office.cpp文件。这是Microsoft Office 12.0 Object Library,在注册表中位置是HKEY_LOCAL_MACHINE\SOFTWARE\Classes\TypeLib\{2DF8D04C-5BFA-101B-BDE5-00AA0044DE52}\2.4\0\win32。若提示找不到qpixmap类,则在excel.h的头文件中添加#include
<QtGui/qpixmap.h>。
将office.h和office.cpp也包含进工程,并在excel.h中添加#include"office.h"后再次编译,还是不行。会出现:office.h:1666: 警告:this decimal constant is unsigned only in ISO C90这样的错误。这是由编译器引起的。找到这个常数,在常数后面增加一个UL标识,或者ULL表示,如4294967295UL,这样就不会报警了。再次编译,会出现:
In file included from ..\testExcel\/excel.h:20, from ..\testExcel\main.cpp:4: ..\testExcel\/office.h: In copy constructor 'Office::ChartColorFormat::ChartColorFormat(const Office::ChartColorFormat&)': ..\testExcel\/office.h:25460: note: synthesized method 'QAxObject::QAxObject(const QAxObject&)' first required here In file included from ..\..\Qt\4.7.2\include/QtCore/qmetatype.h:1, from ..\..\Qt\4.7.2\include/QtCore/../../src/corelib/kernel/qvariant.h:48, from ..\..\Qt\4.7.2\include/QtCore/qvariant.h:1, from ..\..\Qt\4.7.2\include/ActiveQt/../../src/activeqt/container/qaxbase.h:47, from ..\..\Qt\4.7.2\include/ActiveQt/qaxbase.h:1, from ..\..\Qt\4.7.2\include\ActiveQt/../../src/activeqt/container/qaxobject.h:44, from ..\..\Qt\4.7.2\include\ActiveQt/qaxobject.h:1, from ..\..\Qt\4.7.2\include\ActiveQt/QAxObject:1, from ..\testExcel\main.cpp:2: ..\..\Qt\4.7.2\include/QtCore/../../src/corelib/kernel/qmetatype.h: In function 'void* qMetaTypeConstructHelper(const T*) [with T = Office::ChartColorFormat]': ..\..\Qt\4.7.2\include/QtCore/../../src/corelib/kernel/qmetatype.h:142: note: synthesized method 'Office::ChartColorFormat::ChartColorFormat(const Office::ChartColorFormat&)' first required here mingw32-make[1]: *** [release/main.o] Error 1这样的错误。找到office.h的52460行,将函数inline Office::ChartColorFormat* ChartFillFormat::BackColor()和函数Office::ChartColorFormat* ChartFillFormat::ForeColor()中的前三行注释掉。例如:
inline Office::ChartColorFormat* ChartFillFormat::ForeColor() const { /* Office::ChartColorFormat* qax_pointer = 0; qRegisterMetaType("ChartColorFormat*", &qax_pointer); qRegisterMetaType("ChartColorFormat", qax_pointer);*/ QVariant qax_result = property("ForeColor"); if (!qax_result.constData()) return 0; Q_ASSERT(qax_result.isValid()); return *(Office::ChartColorFormat**)qax_result.constData(); }
这样应该就可以正常编译了。
3.例子
我在QtCreator中新建了一个工程testExcel2作为测试之用。注意要在.pro文件中添加CONFIG += qaxcontainer。该工程中所有文件均为 uft8 格式。
//testExcel2.pro #------------------------------------------------- # # Project created by QtCreator 2013-04-02T21:09:33 # #------------------------------------------------- QT += core gui greaterThan(QT_MAJOR_VERSION, 4): QT += widgets TARGET = testExcel2 TEMPLATE = app CONFIG += qaxcontainer SOURCES += main.cpp\ mainwindow.cpp \ office.cpp \ excel.cpp HEADERS += mainwindow.h \ excel.h \ office.h
//mainwindow.h #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QPushButton> #include "excel.h" #include <QAxObject> #include <QFileDialog> #include <QFileinfo> #include <QDir> #include <qmath.h> #include <QDebug> class MainWindow : public QPushButton { Q_OBJECT public: MainWindow(QWidget *parent = 0); ~MainWindow(); public slots: void click_pushbutton(); }; #endif // MAINWINDOW_H
//main.cpp #include "mainwindow.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); }
//mainwindow.cpp #include "mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QPushButton(parent) { connect(this,SIGNAL(clicked()),this,SLOT(click_pushbutton())); this->setText(tr("Push Me")); } MainWindow::~MainWindow() { } void MainWindow::click_pushbutton(){ Excel::Application *excel = new Excel::Application(this); excel->SetVisible(false);//不显示Excel窗体 excel->SetDisplayAlerts(false);//不显示警告 Excel::Workbooks *workbooks = excel->Workbooks();//工作簿集合 Excel::Workbook *workbook = workbooks->Add();//添加工作簿 Excel::Sheets *worksheets = workbook->Sheets();//工作表集合 //这里若写Excel::Worksheets *worksheets = workbook->Sheets(); //会出现cannot convert 'Excel::Sheets*' to 'Excel::Worksheets*' in initialization这样的错误 Excel::Worksheet* worksheet = new Excel::Worksheet(new Excel::_Worksheet(worksheets->Item(1)));//获取工作表 //这里若写Excel::Worksheet *worksheet = worksheets->Item(1); //会出现cannot convert 'IDispatch*' to 'Excel::Worksheet*' in initialization这样的错误 //因为worksheets->Item(1)返回的是IDispatch*类型。要将IDispatch*转换为Excel的对象,就得用上面的 //new的方法。若Excel空间中包含_XXXX这样的类(如Excel::_Worksheet),则生成XXXX对象 //(如Excel::Worksheet)时,就用new Excel::XXXX(new Excel_XXXX(IDispatch*));这样的方法,例如 //Excel::Worksheet* worksheet = new Excel::Worksheet(new Excel::_Worksheet(worksheets->Item(1))); //如果某对象XXXX没有_XXXX这样的类,那么将IDispatch*转换为该对象的指针时只用new XXXX(IDispatch*) //这样的方法就行了,例如下面的 //Excel::SeriesCollection *seriesCollection = new Excel::SeriesCollection(chart->SeriesCollection()); //因为源码是utf8格式的,所以这里用QString::fromUtf8(...),否则Excel中会出现乱码 worksheet->SetName(QString::fromUtf8("【测试】"));//设置中文表名 QString picpath = QFileDialog::getOpenFileName(this,tr("Open"),".",tr("picture file (*.jpg | *.png)")); if(!picpath.isEmpty()){ worksheet->SetBackgroundPicture(QDir::toNativeSeparators(picpath));//为工作表设置背景图片 //有关字体的Background属性,参见 //http://msdn.microsoft.com/en-us/library/office/bb220875(v=office.12).aspx worksheet->Cells()->Font()->SetBackground(Excel::xlBackgroundAutomatic);//设置背景图片和文字重叠时的显示效果 worksheet->Cells()->Font()->SetBold(false);//不要粗体 } Excel::Range *cell; Excel::Range *cells = worksheet->Cells();//获取工作表中的所有单元格 for(int i=0;i<10;i++){ cells->SetItem(i+1,i+1,(i+1)*(i+1));//设置第i+1行,第i+1列的单元格的值 QString range = QString('A'+i)+QString::number(i+1); cell = worksheet->Range(range);获取第i+1行,第i+1列的单元格 cell->Font()->SetItalic(true);//设置字体为斜体 cell->Font()->SetSize(25);//设置字号 cell->Font()->SetColor(QRgb("#FF0000")+i*30);//设置字体颜色,每次循环颜色都不同 } //测试中文输入 cells->SetItem(3,5,QString::fromUtf8("输入中文"));//在第3行,第5列的单元格中输入中文字符 //测试Excel的函数1 cells->SetItem(2,1,5); cell = worksheet->Range("A3");//获取A3单元格 cell->SetFormula("=sum(A1:A2)");//求取A1:A2单元格中值的和 //测试Excel的函数1 cells->SetItem(3,2,10); cells->SetItem(4,2,"=sum(B1:B3)");//求取B1:B3单元格中值的和 //以上两种方式说明用setFormula和setItem来设置函数,效果是一样的 //Qt的dumpcpp工具没有生成Cells(int,int)这种用法,所以用以下方法 //间接调用Cells(int,int)函数 QAxObject* range = worksheet->querySubObject("Cells(int,int)",4,6); cell = (Excel::Range*)range; cell->SetValue(QString::fromUtf8("因为dumcpp没有自动生成的函数Cells(int,int),故用querySubObject(\"Cells(int,int),\",4,6)的方式调用")); //由于Cells(int,int)十分常用,所以我在excel.h的Worksheet类中添加了Excel::Range* Worksheet::Cells(int,int)函数 //在excel.h中搜索class EXCEL_EXPORT Worksheet就可以找到Worksheet类 //然后在其中添加函数Cells(int rowIndex,int colIndex)即可。如: //inline Excel::Range* Cells(int rowIndex,int colIndex){ // QAxObject* range = this->querySubObject("Cells(int,int)",rowIndex,colIndex); // return (Excel::Range*)range; //} cell = worksheet->Cells(5,6); cell->SetValue(QString::fromUtf8("手动在类Excel::Worksheet中添加函数Cells(int,int)后,可直接调用")); //测试图表 //生成数据 Excel::Range* cellX; Excel::Range* cellY; double y; for(int x=0;x<37;x++){ y=sin(2*3.141592653/36*x); cellX = worksheet->Cells(x+1,12); cellY = worksheet->Cells(x+1,13); cellX->SetValue(x); cellY->SetValue(y); } Excel::Range *xValues = worksheet->Range("L1:L37"); Excel::Range *yValues = worksheet->Range("M1:M37"); //先选择一列,则待会儿在Chart中会创建一个Series,否则会创建多个Series xValues->Select(); //用workbook->Charts()->Add()添加一个图表工作表。由于返回的是IDispatch*类型 //所以需用如下方法,转为Excel::Chart*类型。这与前面获取Worksheet*时类似。 Excel::Chart *chart = new Excel::Chart(new Excel::_Chart(workbook->Charts()->Add())); chart->SetChartType(Excel::xlXYScatterSmooth);//设置图表类型为带点迹的平滑散点图 chart->SetName(QString::fromUtf8("【测试图表】"));//设置表名 //获取Series集合。由于chart->SeriesCollection()返回的是IDispatch*类型, //故用如下方法转换为Excel::SeriesCollection* Excel::SeriesCollection *seriesCollection = new Excel::SeriesCollection(chart->SeriesCollection()); Excel::Series *series = seriesCollection->Item(1);//获取第1条曲线 series->SetName(QString::fromUtf8("正弦")); series->SetXValues(xValues->asVariant());//设置横坐标 series->SetValues(yValues->asVariant());//设置对应的纵坐标 //在工作表内插入图表 //获取图表对象集合。同样,由于worksheet->ChartObjects()返回的是IDispatch*, //故要用new的方式来转换为Excel::ChartObjects* Excel::ChartObjects *chartObjects = new Excel::ChartObjects(worksheet->ChartObjects()); //添加图表,Left=800,Top=10,Height=500,Width=500,单位磅 Excel::ChartObject *chartObject = chartObjects->Add(800,10,500,500); Excel::Chart *innerChart = chartObject->Chart(); //使用xValues作为数据源,Excel::xlColumns表示每列都为一组数据,即1个Series innerChart->SetSourceData(xValues,Excel::xlColumns); innerChart->SetHasTitle(true);//显示标题 innerChart->SetChartType(Excel::xlXYScatterSmoothNoMarkers);//图表为不包含数据点的散点图 //获取散点图的系列(Series)集合 Excel::SeriesCollection *innerSeriesCollection = new Excel::SeriesCollection(innerChart->SeriesCollection()); //选取系列1,因为我只有1个系列,即一条曲线 Excel::Series *innerSeries = innerSeriesCollection->Item(1); innerSeries->SetName(QString::fromUtf8("正弦"));//设置系列名 innerSeries->SetXValues(xValues->asVariant());//设置横坐标 innerSeries->SetValues(yValues->asVariant());//设置对应的纵坐标 delete innerSeriesCollection;innerSeriesCollection=NULL; delete chartObjects;chartObjects=NULL; delete seriesCollection;seriesCollection=NULL; delete chart;chart=NULL; //QFileDialog::DontConfirmOverwrite表示如果遇到文件已存在,不提示,直接覆盖 QString filepath = QFileDialog::getSaveFileName(this,tr("Save"),".",tr("Microsoft Office 2007 (*.xlsx)\n" "Microsoft Office 2003 (*.xls)"),0,QFileDialog::DontConfirmOverwrite); //Excel::xlLocalSessionChanges表示遇到冲突时覆盖,且不提示 //SaveAs的详细用法参见http://msdn.microsoft.com/zh-cn/library/ff195820(v=office.15).aspx if(QFileInfo(filepath).suffix() == "xls"){ workbook->SaveAs(QDir::toNativeSeparators(filepath),Excel::xlExcel8,"","",false,false,Excel::xlNoChange,Excel::xlLocalSessionChanges); } else{ workbook->SaveAs(QDir::toNativeSeparators(filepath),Excel::xlOpenXMLWorkbook,"","",false,false,Excel::xlNoChange,Excel::xlLocalSessionChanges); } workbook->Close(); excel->Quit(); delete worksheet;worksheet=NULL; delete excel;excel=NULL; }
在上例中,我测试了单元格的使用、函数的使用、图表的使用。还添加了Cells(int,int)函数,插入表格背景图片、中文输入无乱码,xls和xlsx两种版本的保存。
4.其他问题
运用过程中可能还会出现其他问题:
1)在Excel::Application *excel = new Excel::Application(this);这句出现undefined reference to `vtable for Excel::Application' 或 undefined reference to `Excel::Sheets::staticMetaObject'这样的错误。
解决办法:将外部引用的*.h文件在头文件中包含,不要包含在*.cpp中。在Office.h中包含<QMetaObject>。
2)出现QAxBase::setControl: requested control {00020813-0000-0000-C000-000000000046} could not be instantiated
QAxBase::qt_metacall: Object is not initialized, or initialization failed
QAxBase::qt_metacall: Object is not initialized, or initialization failed
QAxBase::qt_metacall: Object is not initialized, or initialization failed这样的错误
解决办法:在整个工程中查找 {00020813-0000-0000-C000-000000000046},将其替换为 Excel.Application
3)出现 'Excel::XlFileFormat' is not a class or namespace这样的错误
解决办法:xlFileFormat是枚举类型,如果要用其中的某个枚举值,直接写成 Excel::xlOpenXMLWorkbook,不要写成 Excel::XlFileFormat::xlOpenXMLWorkbook
5.样例图片
6.源码下载
百度网盘:
3个压缩包均在:http://pan.baidu.com/share/link?shareid=2465785956&uk=4128141257
新浪网盘(最近把网盘整理了一下,不知这个失效没):
1)testExcel2_仅包含修改后的excel,h、excel.cpp、office.h和office.cpp
2)testExcel2_包含所有源码,不包含Qt运行库
3)testExcel2_包含所有源码和Qt运行库
7.其他类
在Qt的天池项目里也有处理Excel文件的类,不过我还没用过。大家有兴趣可以看看。地址:http://www.qtcn.org/bbs/thread-htm-fid-105.html
相关文章推荐
- 用groovy简化java反射编写一个基于行数据对象的自动生成excel文件对象的工具
- 基于Excel的QR二维码生成工具——原理及算法详解(之四)
- 基于Java的简单数据库设计生成工具(生成Excel文档)
- 如何禁用/启用dr.watson诊断工具 drwtsn32 / 如何在vista下生成转储文件dump
- 使用Dev-Cpp/MinGW来生成wxWidget SDL是一组包含若干媒体操作的工具库
- dump文件生成工具使用介绍
- 【C#附源码】数据库文档生成工具支持(Excel+Html)
- poi生成excel工具类
- 基于Excel的QR二维码生成工具——原理及算法详解(之七)
- 使用Java泛型和反射机制编写Excel文件生成和解析的通用工具类
- 导入导出封装工具类(二) jXLS Excel报表生成工具类
- gsoap工具生成soap.h.cpp文件遇到的问题
- 敏捷工具,使用Excel自动生成故事卡
- 导入导出封装工具类(二) jXLS Excel报表生成工具类
- NO.77 AR Tools-Arch3用国际化资源文件中英对照Excel生成工具
- AFS Tool Excel 宏编写的工具 批量生成Excel 文件
- 如何禁用/启用dr.watson诊断工具 drwtsn32 / 如何在vista下生成转储文件dump
- android的dmtracedump工具生成trace文件图片 'dot' 不是内部或外部命令,也不是可运行的程序 或批处理文件。
- java poi excel 生成表格的工具封装
- java生成excel和下载导出文件的工具类