1. 程式人生 > >用dumpcpp工具生成的excel.h/excel.cpp來操縱Excel

用dumpcpp工具生成的excel.h/excel.cpp來操縱Excel

//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兩種版本的儲存。