用dumpcpp工具生成的excel.h/excel.cpp來操縱Excel
阿新 • • 發佈:2019-01-25
//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兩種版本的儲存。