1.系統環境:Qt 4.7+MinGW、Win7、QtCreator、Excel 2007
2.生成excel.h、excel.cpp、office.h和office.cpp
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.例子
//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.其他問題
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這樣的錯誤