用MFC的手操作「真.Excel」

這篇文章提及的程式碼,最早是由 自動產生Excel-流浪小築 學來的,這個網站除了這個,還有很多相關的技術可以學唷!很棒的前輩。

如果把Excel的OLE加到MFC的Project也請參考那篇文章就可以了(請務必完全照做一次)。
之後對於xlsFile的了解會更有幫助。

Excel的程式控制,似乎是辦公室應用裡算是高階的應用。用C++幾乎就是天一般的高度呀(哈哈)畢竟語法細節太多,整個類別全部使用的話,複雜度又太恐怖了。
雖然網路上有一個包好的XLSLIB可以使用,但是它....不適合我,我就自己做了一個。

這是以操作Excel的概念去設計的類別。每一個函數都盡可能的簡單好用。
只是最後插入圖表的部份因為我個人沒有在使用的關係,所以沒有做概念上的最佳化。
個人建議使用Design Pattern的組合模式來實現。

這個類別有公佈在PTT的CandCpp版、Google code、Github中。
在ptt獲得網友Edison.Shin的支援,讓它的功能更豐富。在此完全公開其程式碼提供大家使用。

xlsFile.h

/*******************************************************************
 *                                                                 *
 * 此class由kx設計,並發佈初版                                        *
 * 二版則由Edison.Shih.提供函式,補足初版之不足                        *
 *                                                                 *
 * 由Edison.Shih.提供的函式補足,會做edisonx的記號                    *
 *                                                                 *
 * Class由 Visual C++ 6 開發                                        *
 * 適用於Microsoft Excel 2003 於 Microsoft Excel 2003 SP3 測試無誤   *
 * 測試平台 Microsoft Windows XP SP3                                *
 *                           2011/7/11                             *
 *******************************************************************/
#ifndef XLSFILE_H
#define XLSFILE_H

#include "excel.h"
#include <vector>

enum Boarder_Style
{
    BS_NONE    = 0,      //無框線
    BS_SOLIDLINE,        //一般線
    BS_BIGDASH,          //小間隔虛線- - - - - -有粗細
    BS_SMALLDASH,        //大間隔虛線- - - - - -無粗細
    BS_DOTDASH,          //虛線-.-.-.-.-.-.
    BS_DASHDOTDOT,       //虛線.-..-..-..-..-.
    BS_DOUBLSOLID = 9,   //雙線============(不受粗細改變)
    BS_SLASHDASH  = 13   //雙線-/-/-/-/-/-/(不受粗細改變)
};
enum Boarder_Weight    //(粗細)
{
    BA_HAITLINE = 1,     //比一般小(所以用虛線表示)
    BA_THIN,             //一般
    BA_MEDIUM,           //粗
    BA_THICK             //厚
};
enum Horizontal_Alignment
{
    HA_GENERAL = 1,
    HA_LEFT,           //edisonx
    HA_CENTER,
    HA_RIGHT,          //edisonx
    HA_FILL,           //重複至填滿    //edisonx
    HA_JUSTIFYPARA,    //段落重排(有留白邊,有自動斷行)
    HA_CENTERACROSS,   //跨欄置中(不合拼儲存格)
    HA_JUSTIFY,        //分散對齊(縮排)
};

enum Vertical_Alignment
{
    VA_TOP = 1,        //edisonx
    VA_CENTER,         //edisonx
    VA_BOTTOM,         //edisonx
    VA_JUSTIFYPARA,    //段落重排(有留白邊,有自動斷行)
    VA_JUSTIFY         //分散對齊
};

enum Histogram_Chart_Type
{
    CT_AREA = 0,       //區域
    CT_COLUMN,         //方柱
    CT_CONE,           //圓錐
    CT_CYLINDER,       //圓柱
    CT_PYRAMID         //金字塔
};

enum Stock_Type
{
    ST_HLC = 0,    //最高-最低-收盤
    ST_OHLC,       //開盤-最高-最低-收盤
    ST_VHLC,       //成交量-最高-最低-收盤
    ST_VOHLC       //成交量-開盤-最高-最低-收盤
};

class xlsFile
{
protected:
    COleVariant   VOptional, VTRUE, VFALSE;  
    _Application  objApp;
     Workbooks    objBooks;
    _Workbook     objBook;
     Sheets       objSheets;
    _Worksheet    objSheet,objSheetT;
    Range         range,col,row;
    Interior      cell;
    Font          font;
    COleException e;

    LPDISPATCH    lpDisp;
    ChartObjects  chartobjects;
    ChartObject   chartobject;
    _Chart        xlsChart;
    VARIANT       var;
    
    Shapes        shapes;

    char buf[200];  //暫存的字串
    char buf1[200];
    char buf2[200];
      
public:
    xlsFile();
    ~xlsFile();
    //回傳xlsFile* //開了檔案之後可以繼續選擇Sheet和命名
    xlsFile* New();
    xlsFile* Open(const char*);
    void SaveAs(const char*);
    void Save();
    
    void Quit();
    void SetVisible(bool);//設定視窗為看得見,並把控制權交給使用者
    //----------------------------------------------------
    //Sheet操作
    long SheetTotal();                     //取得 Sheet 個數
    void SetSheetName(short, const char*); //由SheetNumber    指定SheetName
    CString GetSheetName(short);           //由SheetNumber    取得SheetName
    
    xlsFile* SelectSheet(const char*);     //由SheetName      選擇Sheet
    xlsFile* SelectSheet(short);           //由SheetNumber    選擇Sheet
    void CopySheet(const char*);           //複製SheetName    指定插入Sheet的位置,並指定新Sheet名稱
    void CopySheet(short);                 //複製SheetNumber  指定插入Sheet的位置,並指定名稱
    void DelSheet(const char*);            //選SheetName      刪除Sheet
    void DelSheet(short);                  //選SheetNumber    刪除Sheet
    //-----------------------------------------------------
    //
    long GetHorztlStartCell(); // 起始行
    long GetVrticlStartCell(); // 起始列
    long GetHorztlTotalCell(); // 總行數
    long GetVrticlTotalCell(); // 總列數
    //-----------------------------------------------------
    //回傳xlsFile* 選了格子之後可以繼續下「讀」「寫」的成員函數
    //選一格
    xlsFile* SelectCell(const char* );
    xlsFile* SelectCell(const char* , int );
    xlsFile* SelectCell(char,int);
    xlsFile* SelectCell(char,char,int);
    //選一個範圍
    xlsFile* SelectCell(const char* , const char* );
    xlsFile* SelectCell(const char* , int ,const char* , int );
    xlsFile* SelectCell(char,int,char,int);
    xlsFile* SelectCell(char,char,int,char,char,int);
    //--------------------------------------------
    void ClearCell();                           //清除儲存格
    xlsFile* SetMergeCells(short vMerge = TRUE, //合併儲存格(通常會配跨欄置中)
                           bool isCenterAcross = true);
    //--------------------------------------------
    //對齊
    xlsFile* SetHorztlAlgmet(short);    //水平對齊
    xlsFile* SetVrticlAlgmet(short);    //垂直對齊
    xlsFile* SetTextAngle(short Angle); //方向-文字角度
    xlsFile* AutoNewLine(bool NewLine); //自動換行
    //---------------------------------------------
    //格線
    xlsFile* SetCellBorder(long BoarderStyle = 1, 
    int BoarderWeight = 2, long BoarderColor = 1);  //設定框線粗細和顏色
    //---------------------------------------
    //儲存格大小
    void AutoFitHight();           //自動調整列高
    void AutoFitWidth();           //自動調整欄寬
    xlsFile* SetCellHeight(float); //設定列高
    xlsFile* SetCellWidth(float);  //設定欄寬
    //---------------------------------------------
    //字
    xlsFile* SetFont(const char* fontType = "新細明體");  //設定字型(預設新細明體)
    xlsFile* SetFontBold(bool isBold = true);           //粗體
    xlsFile* SetFontStrkthrgh(bool isBold = true);      //刪除線
    xlsFile* SetFontSize(short fontSize = 12);          //設定字體大小(預設12pt)
    xlsFile* SetFontColor(short colorIndex = 1);        //字型顏色(預設黑色)
    //---------------------------------------------
    xlsFile* SetCellColor(short);//設定底色
    //---------------------------------------------
    //(17-32隱藏版也有收進來)
    //Microsoft Excel 的顏色排序是依
    //紅、橙、黃、綠、藍、靛、紫、灰(y),由深到淺(x)
    //不過絕對RGB並沒有規律的存在這個表裡
    short SelectColor(short x = 8, short y = 7);   //依excel介面的座標選擇顏色
    short SelectColor(const char ColorChar = 'W'); //快速版(黑D、白W、紅R、綠G、藍B、黃Y)
    //---------------------------------------------
    //設定資料進儲存格(存成字串)
    //一般版
    void SetCell(int);
    void SetCell(double);
    void SetCell(long);    
    void SetCell(const char* );    
    void SetCell(CString );    
    //自訂細部格式版
    void SetCell(const char*, int);
    void SetCell(const char*, double);
    void SetCell(const char*, long);
    //--------------------------------------------
    //取值
    int     GetCell2Int();
    CString GetCell2CStr();
    double  GetCell2Double();
    //--------------------------------------------
    //排序(依列排序)//edisonx
    void Sort(CString IndexCell1     , long DeCrement1,
              CString IndexCell2 = "", long DeCrement2 = 1,
              CString IndexCell3 = "", long DeCrement3 = 1);
    //--------------------------------------------

    //圖表皆由edisonx提供函數資料

    //儲存圖表圖片.bmp(.jpg亦可以)
    void SaveChart(CString FullBmpPathName);

    //圖表(三類型的函數在每次建立都要使用)
    //使用前必須選擇貼上Chart的儲存格範圍
    
    //選擇資料範圍
    xlsFile* SelectChartRange(const char* , const char* );    
    xlsFile* SelectChartRange(const char* , int ,const char* , int );
    xlsFile* SelectChartRange(char,int,char,int);    
    xlsFile* SelectChartRange(char,char,int,char,char,int);
    //設定Chart參數
    xlsFile* SetChart(short XaxisByToporLeft = 2, bool isLabelVisable = 1, 
    CString = "" , CString = "" , CString = "" );
    //區域、直方、方柱、圓柱、圓錐、金字塔
    void InsertHistogramChart(int shapeType = CT_COLUMN, 
                              bool is3D = 0, 
                              int isVrticlorHorztlorOther = 0, 
                              int isNone_Stack_Percent = 0);
    //其它(特殊圖表)   
    void InsertBubleChart    (bool is3D    = 0);                          //泡泡圖
    void InsertDoughnutChart (bool Explode = 0);                          //圓環圖
    void InsertSurfaceChart  (bool is3D    = 0, bool isWire         = 0); //曲面圖
    void InsertRadarChart    (bool isWire  = 0, bool isDot          = 1); //雷達圖
    void InsertPieChart      (bool Explode = 0, int  type2Dor3DorOf = 0); //圓餅圖
    void InsertLineChart     (bool isDot   = 1, bool is3D           = 0, 
                              int  isNone_Stack_Percent = 0);             //折線圖
    void InsertXYScatterChart(bool isDot, bool isLine, bool Smooth);      //離散圖
    void InsertStockChart    (int);                                       //股票圖
    //--------------------------------------------
    void InsertImage(const char* , float , float );  //插入圖片
    void InsertImage(const char* );                  //插入圖片(先選取範圍,圖檔必失真)
protected:
   void xlsFile::newChart();  //在Sheet新增圖表
//    防止任何運算
private:
    void operator+(const xlsFile&);
    void operator-(const xlsFile&);
    void operator*(const xlsFile&);
    void operator/(const xlsFile&);
    void operator%(const xlsFile&);
    void operator=(const xlsFile&);

    bool operator<(const xlsFile&);
    bool operator>(const xlsFile&);
    bool operator>=(const xlsFile&);
    bool operator<=(const xlsFile&);
    bool operator==(const xlsFile&);
    bool operator!=(const xlsFile&);
    bool operator&&(const xlsFile&);
    bool operator&(const xlsFile&);
    bool operator||(const xlsFile&);
    bool operator|(const xlsFile&);

    bool operator>>(const xlsFile&);
    bool operator<<(const xlsFile&);
};
#endif
//備用語法
    range.SetFormula(COleVariant("=RAND()*100000"));  //套公式
    range.setSetValue(COleVariant("Last Name"));      //輸入值
    range.SetNumberFormat(COleVariant("$0.00"));      //數字格式

    //插圖
    Shapes shapes = objSheet.GetShapes(); 
    range = objSheet.GetRange(COleVariant("J7"),COleVariant("R21")); 
  
    //range.AttachDispatch(pRange);
    shapes.AddPicture(
                    "c:\\CHILIN.bmp",                //LPCTSTR Filename
                    false,                           //long    LinkToFile
                    true,                            //long    SaveWithDocument
                    (float)range.GetLeft(  ).dblVal, //float   Left
                    (float)range.GetTop(   ).dblVal, //float   Top
                    (float)range.GetWidth( ).dblVal, //float   Width
                    (float)range.GetHeight().dblVal  //float   Height
    );
    range.Sort(
                key1,        //  key1
                DeCrement1,  // long Order1, [ 1(ascending order) or 2(descending order) ]
                key2,        // key2, 
                VOptional,   // type, [xlSortLabels, xlSortValues]
                DeCrement2,  // long Order2, [ 1(升冪) or 2( 降) ]
                key3,        // key3
                DeCrement3,  // long Order3, [ 1(升冪) or 2( 降) ]
                2,           // Header, [0,1 : 不含 title 2 : title (選取範圍)一起排
          //進階
                VOptional,   // OrderCustom [從1開始,自定義排序順序列表中之索引號,省略使用常規]
                _variant_t((short)TRUE),    // MatchCase [TRUE分大小寫排]
                1,           // Orientation : [排序方向, 1:按列, 2:按行)
                1,           // SortMethod : [1:按字符漢語拼音順序, 2:按字符筆畫數]
       //未知選項
                1,           // DataOption1 可選 0 與 1
                1,           // DataOption2 可選 0 與 1
                1            // DataOption3 可選 0 與 1
    );

xlsFile.cpp

簡化初始化動作

在細部操作裡,初始化設計實在是一件,不容易的事。
做太多,失去彈性,做太少,又增加函數之間的耦合力,容易讓人產生「誰知道要呼叫這個」的OS。在此,盡量設計的和Excel操作一樣,打開App這一步。而關掉也是設計對應的動作。
在construct有一個條件編譯的部份,是在debug模式中,盡快的顯示Excel,但是在release模式中,就把程式化的表格動作結束後,再顯示比較好。
xlsFile::xlsFile(): 
VOptional((long)DISP_E_PARAMNOTFOUND,VT_ERROR), VFALSE((short)FALSE), VTRUE((short)TRUE)
{
    ZeroMemory(buf,sizeof(buf));
    ZeroMemory(buf1,sizeof(buf1));
    ZeroMemory(buf2,sizeof(buf2));
    //Step 1.叫Excel應用程式
    if(!objApp.CreateDispatch("Excel.Application",&e))
    {
        CString str;
        str.Format("Excel CreateDispatch() failed w/err 0x%08lx", e.m_sc);
        AfxMessageBox(str, MB_SETFOREGROUND);
    }
#ifdef _DEBUG
    SetVisible(true);
#endif
};

xlsFile::~xlsFile()
{
    range.ReleaseDispatch();
    objSheet.ReleaseDispatch();
    objSheets.ReleaseDispatch();
    objBook.ReleaseDispatch();
    objBooks.ReleaseDispatch();
    objApp.ReleaseDispatch();
}

維持 開新檔案/開啟舊檔/存檔/另存新檔 的整體概念

概念描述
xlsFile* xlsFile::New()
{
    objBooks = objApp.GetWorkbooks();
    objBook = objBooks.Add(VOptional);    //開新檔案
    objSheets = objBook.GetWorksheets();
    return this;
}

xlsFile* xlsFile::Open(const char* path)
{
    objBooks = objApp.GetWorkbooks();
    objBook.AttachDispatch(objBooks.Add(_variant_t(path))); //開啟一個已存在的檔案
    objBook.Activate();
    objSheets = objBook.GetWorksheets();
    return this;
}

void xlsFile::SaveAs(const char* strTableName)
{
    ZeroMemory(buf,sizeof(buf));
    sprintf(buf, "%s", strTableName);
    objBook.SaveAs(
        COleVariant(buf),
        VOptional, VOptional, 
        VOptional, VOptional, 
        VOptional, 1,
        VOptional, VFALSE,
        VOptional, VOptional, VOptional); 
}

void xlsFile::Save()
{
    objBook.Save();
}

畫出視窗

就是把視窗畫出來,之後把控制權給使用者。
//SetVisible()
void xlsFile::SetVisible(bool a)
{
    objApp.SetVisible(a);    //顯示Excel檔
    objApp.SetUserControl(a);//使用者控制後,就不可以自動關閉
}

對Sheet的操作

其中,在選擇sheet時,常常會出現,程式碼指定選擇一個不存在的sheet,這時出錯了,只有一個空白的MessageBox(),出現了也不知道出了什麼事?哪裡出了問題,所以就在SelectSheet()時做try-catch的設計
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Sheet操作

//-------------------------
////取得 Sheet 個數
long xlsFile::SheetTotal()
{
    return objSheets.GetCount();//edisonx
}
//-------------------------
//由SheetIndex 指定SheetName
void xlsFile::SetSheetName(short SheetIndex, const char* SheetName)
{
    try
    {
        objSheet = objSheets.GetItem(COleVariant(SheetIndex));
        objSheet.SetName(SheetName);//設定sheet名稱
    }
    catch (...)
    {
        CString str;
        str.Format("設定第%d個Sheet的名字為%s出錯了!", SheetIndex, SheetName);
        AfxMessageBox(str);
    }
}
//-------------------------
//由SheetIndex 取得SheetName
CString xlsFile::GetSheetName(short SheetIndex)
{
    try
    {
        objSheet = objSheets.GetItem(COleVariant(SheetIndex));
    }
    catch (...)
    {
        CString str;
        str.Format("取得第%d個Sheet名字出錯了!", SheetIndex);
        AfxMessageBox(str);
    }
    return objSheet.GetName();//edisonx
}
//-------------------------
//選擇Sheet
//由SheetName
xlsFile* xlsFile::SelectSheet(const char* SheetName)
{
    try
    {
        objSheet = objSheets.GetItem(_variant_t(SheetName));
        objSheet.Activate();//edisonx
    }
    catch (...)
    {
        CString str;
        str.Format("選擇Sheet: %s出錯了!", SheetName);
         AfxMessageBox(str);
    }
    return this;
}
//由SheetIndex 
xlsFile* xlsFile::SelectSheet(short SheetIndex)
{
    try
    {
        objSheet = objSheets.GetItem(COleVariant(SheetIndex));
        objSheet.Activate();//edisonx
    }
    catch (...)
    {
        CString str;
        str.Format("選擇第%d個Sheet出錯了!", SheetIndex);
        AfxMessageBox(str);
    }
    return this;
}
//-------------------------
//複製SheetName 指定插入Sheet的位置,並指定新Sheet名稱
void xlsFile::CopySheet(const char* SheetName)
{
    objSheet.AttachDispatch(objSheets.GetItem(_variant_t(SheetName)),true);
    objSheet.Copy(vtMissing,_variant_t(objSheet));
}
//複製SheetIndex 指定插入Sheet的位置,並指定名稱
void xlsFile::CopySheet(short SheetIndex)
{
    objSheet.AttachDispatch(objSheets.GetItem(COleVariant(SheetIndex)));
    objSheet.Copy(vtMissing,_variant_t(objSheet));
}
//-------------------------
//刪除Sheet
//選SheetName 
void xlsFile::DelSheet(const char* SheetName)
{    
    objSheet = objSheets.GetItem(_variant_t(SheetName));
    objSheet.Delete();//edisonx
}
//選SheetIndex
void xlsFile::DelSheet(short SheetIndex)
{
    objSheet = objSheets.GetItem(COleVariant(SheetIndex));
    objSheet.Delete();//edisonx
}

對儲存格(Cell)的操作

一般常見的cell操作,都在上面了
///////////////////////////////////////////////////////////////////////////////////////////
//Cell操作
//Cell計數計算
// 取得起始列
long xlsFile::GetHorztlStartCell()
{
    Range usedrange;
    usedrange.AttachDispatch(objSheet.GetUsedRange());
    return usedrange.GetColumn();
}
// 取得起始行
long xlsFile::GetVrticlStartCell()
{    
    Range usedrange;
    usedrange.AttachDispatch(objSheet.GetUsedRange());
    return usedrange.GetRow();
}
// 取得總列數
long xlsFile::GetHorztlTotalCell()
{
    Range usedrange;
    usedrange.AttachDispatch(objSheet.GetUsedRange());
    range.AttachDispatch(usedrange.GetColumns());
    return range.GetCount();
}
// 取得總行數
long xlsFile::GetVrticlTotalCell()
{
    Range usedrange;
    usedrange.AttachDispatch(objSheet.GetUsedRange());
    range.AttachDispatch(usedrange.GetRows());
    return range.GetCount();
}
//清除儲存格
void xlsFile::ClearCell()
{
    //先選取一個範圍的儲存格
    range.Clear();//edisonx
}
//合併儲存格
xlsFile* xlsFile::SetMergeCells(short vMerge, bool isCenterAcross)
{
    //先選取一個範圍的儲存格
    range.SetMergeCells(_variant_t(vMerge));
    if(isCenterAcross) SetHorztlAlgmet(HA_CENTERACROSS);
    return this;
}

選擇儲存格(Cell)

選擇格子的動作,就像是用滑鼠點選儲存格一樣直覺,分成兩種,點選格子和點選範圍
其中,和選擇sheet一樣,若出現了選擇了超過Z的格子(用迴圈控制,就可能會超過Z),就會出問題,也設計了try-catch來顯示出問題的格子在哪
//-------------------------
//Cell格式設定
//-------------------------
//選格子
//選一格
xlsFile* xlsFile::SelectCell(const char* x)
{
    try
    {
        range=objSheet.GetRange(COleVariant(x),COleVariant(x));
        ASSERT(range);
    }
    catch (...)
    {
        CString str;
        str.Format("選擇儲存格%s出錯了!", x);
        AfxMessageBox(str);
    }
    return this;
}

xlsFile* xlsFile::SelectCell(const char* x, int y)
{
    try
    {
        ZeroMemory(buf,sizeof(buf));
        sprintf(buf,"%s%d",x,y);
        range=objSheet.GetRange(COleVariant(buf),COleVariant(buf));
        ASSERT(range);
    }
    catch (...)
    {
        CString str;
        str.Format("選擇儲存格%s%d出錯了!", x, y);
        AfxMessageBox(str);
    }
    return this;
}
//小於Z
xlsFile* xlsFile::SelectCell(char x, int y)
{
    if (x >= 'A' && x <= 'Z')
    {
        ZeroMemory(buf,sizeof(buf));
        sprintf(buf,"%c%d",x,y);
        range=objSheet.GetRange(COleVariant(buf),COleVariant(buf));
        ASSERT(range);
    }
    else
    {
        CString str;
        str.Format("選擇儲存格%c%d出錯了!", x, y);
        AfxMessageBox(str);
        ASSERT(x >= 'A' && x <= 'Z');
    }
    return this;
}
//大於Z,開始選AA
xlsFile* xlsFile::SelectCell(char x1, char x2, int y)
{
    if ( (x1 >= 'A' && x1 <= 'Z') && (x2 >= 'A' && x2 <= 'Z'))
    {
        ZeroMemory(buf,sizeof(buf));
        sprintf(buf,"%c%c%d",x1,x2,y);
        range=objSheet.GetRange(COleVariant(buf),COleVariant(buf));
        ASSERT(range);
    }
    else
    {
        CString str;
        str.Format("選擇儲存格%c%c%d出錯了!", x1, x2, y);
        AfxMessageBox(str);
        ASSERT(x1 >= 'A' && x1 <= 'Z');
        ASSERT(x2 >= 'A' && x2 <= 'Z');
    }
    return this;
}
//-------------------------
//選範圍
xlsFile* xlsFile::SelectCell(const char* x1, const char* x2)
{
    try
    {
        range=objSheet.GetRange(COleVariant(x1),COleVariant(x2));
        ASSERT(range);
    }
    catch (...)
    {
        CString str;
        str.Format("選擇範圍,從%s到%s出錯了!", x1, x2);
        AfxMessageBox(str);
    }
    return this;
}

xlsFile* xlsFile::SelectCell(const char* x1, int y1, const char* x2, int y2)
{
    try
    {
        ZeroMemory(buf1,sizeof(buf1));
        ZeroMemory(buf2,sizeof(buf2));
        sprintf(buf1,"%s%d",x1,y1);
        sprintf(buf2,"%s%d",x2,y2);
        range=objSheet.GetRange(COleVariant(buf1),COleVariant(buf2));
        ASSERT(range);
    }
    catch (...)
    {
        CString str;
        str.Format("選擇範圍,從%s%d到%s%d的地方出錯了!", x1, y1, x2, y2);
        AfxMessageBox(str);
    }
    return this;
}
//小於Z
xlsFile* xlsFile::SelectCell(char x1, int y1, char x2, int y2)
{
    if (x1 >= 'A' && x1 <= 'Z')
    {
        ZeroMemory(buf1,sizeof(buf1));
        ZeroMemory(buf2,sizeof(buf2));
        sprintf(buf1,"%c%d",x1,y1);
        sprintf(buf2,"%c%d",x2,y2);
        range=objSheet.GetRange(COleVariant(buf1),COleVariant(buf2));
        ASSERT(range);
    }
    else
    {
        CString str;
        str.Format("選擇範圍,從%c%d到%c%d出錯了!", x1, y1, x2, y2);
        AfxMessageBox(str);
        ASSERT(x1 >= 'A' && x1 <= 'Z');
    }
    return this;
}
//大於Z,開始選AA
xlsFile* xlsFile::SelectCell(char xA1, char xB1, int y1, char xA2, char xB2, int y2)
{
    if ( (xA1 >= 'A' && xA2 <= 'Z') && (xB1 >= 'A' && xB2 <= 'Z') )
    {
        ZeroMemory(buf1,sizeof(buf1));
        ZeroMemory(buf2,sizeof(buf2));
        sprintf(buf1,"%c%c%d",xA1,xB1,y1);
        sprintf(buf2,"%c%c%d",xA2,xB2,y2);
        
        range=objSheet.GetRange(COleVariant(buf1),COleVariant(buf2));
        ASSERT(range);
    }
    else
    {
        CString str;
        str.Format("選擇範圍,從%c%c%d到%c%c%d出錯了!", xA1, xB1, y1, xA2, xB2, y2);
        AfxMessageBox(str);
        ASSERT(xA1 >= 'A' && xA2 <= 'Z');
        ASSERT(xB1 >= 'A' && xB2 <= 'Z');
    }
    return this;
}

靠左/靠右/靠上/靠下/置中 旋轉/文字自動換行

保持與Excel操作介面相同的思考方式,其參數在.h檔中,有列舉成文字,不需使用數字做辨識,可提高可讀性。
//-------------------------
//對齊方式
//水平對齊
xlsFile* xlsFile::SetHorztlAlgmet(short position)
{
    range.SetHorizontalAlignment(COleVariant(position));
    return this;
}
//垂直對齊
xlsFile* xlsFile::SetVrticlAlgmet(short position)
{
    range.SetVerticalAlignment(COleVariant(position));
    return this;
}
//對齊方式的方向幾度(+90~-90)
xlsFile* xlsFile::SetTextAngle(short Angle)
{
    range.SetOrientation(COleVariant(Angle)); 
    return this;
}
//設定文字自動換行
xlsFile* xlsFile::AutoNewLine(bool NewLine)
{
    if(NewLine)    range.SetWrapText(VTRUE);
    else           range.SetWrapText(VFALSE);
    return this;
}

設定框線粗細、框線顏色

用同一個介面來設定框線和框線顏色,對於造一個表格來說,是方便的事,若有需要,也可以將它拆開兩個各別處理。但是因為沒有遇到這樣的需求,所以就沒有設計這樣的介面。
//設定框線粗細、框線顏色
xlsFile* xlsFile::SetCellBorder(long BoarderStyle, int BoarderWeight, long BoarderColor)
{
    range.BorderAround(_variant_t(BoarderStyle), BoarderWeight, BoarderColor,_variant_t((long)RGB(0,0,0)));
    return this;
}

自動欄寬、列高

在Excel中,只要對著調整格線的地方點兩下,即可適動調整適當欄寬和列高。
Excel預設的介面,原本無法一個函數搞定,要先選取整排,再調整。包起來的設計,比較直覺。
//設定欄寬列高
//自動調整列高
void xlsFile::AutoFitWidth()
{
    col = range.GetEntireColumn();    //選取某個範圍的一整排
    col.AutoFit();                    //自動調整一整排的欄寬
}
//自動調整欄寬
void xlsFile::AutoFitHight()
{
    row = range.GetEntireRow();        //選取某個範圍的一整排
    row.AutoFit();                    //自動調整一整排的列高
}
//設定列高
xlsFile* xlsFile::SetCellHeight(float height)
{
    range.SetRowHeight(_variant_t(height));
    return this;
}
//設定欄寬
xlsFile* xlsFile::SetCellWidth(float height)
{
    range.SetColumnWidth(_variant_t(height));
    return this;
}

儲存格字型的操作

字型的顏色、粗體、字型大小...在工作列上的那一排常用的功能,都建上來了。
顏色對照,參考.....參考文件!XDDD
//設定字型
xlsFile* xlsFile::SetFont(const char* fontType)
{
    font = range.GetFont();
    font.SetName(_variant_t(fontType));//原本是韓文字型
    return this;
}
//粗體
xlsFile* xlsFile::SetFontBold(bool isBold)
{
    font = range.GetFont();
    if (isBold)    font.SetBold(VTRUE);//粗體
    else           font.SetBold(VFALSE);
    return this;
}
//刪除線
xlsFile* xlsFile::SetFontStrkthrgh(bool isStrike)
{
    font = range.GetFont();
    if (isStrike)    font.SetStrikethrough(VTRUE);    //edisonx
    else             font.SetStrikethrough(VFALSE);    //edisonx
    return this;
}
//字型大小
xlsFile* xlsFile::SetFontSize(short fontSize)
{
    font = range.GetFont();
    font.SetSize(_variant_t(fontSize));//字型大小pt
    return this;
}
//字型顏色
xlsFile* xlsFile::SetFontColor(short colorIndex)
{
    font = range.GetFont();
    font.SetColorIndex(_variant_t(colorIndex)); //字色(預設黑色)
    return this;
}

填滿色彩

在填滿色彩時,設計了使用座標的方式做操作,此是使用Excel視窗軟體介面上的調色盤的位置為準。
除此之外,還有快速選色介面,不過只有幾個純色支援此介面。
//設定底色
xlsFile* xlsFile::SetCellColor(short colorIndex)
{
    cell = range.GetInterior();                   //取得選取範圍,設定儲存格的記憶體位址
    cell.SetColorIndex(_variant_t(colorIndex));   //設定底色(查表)
    //cell.SetColor(_variant_t(colorIndex));
    return this;
}
//選擇顏色(適合字色和底色)依excel介面的座標選擇顏色
short xlsFile::SelectColor(short x, short y)
{
//Microsoft Excel 的顏色排序是依
//紅、橙、黃、綠、藍、靛、紫、灰(y)
//由深到淺(x)
    switch(x)
    {
    case 1:
             if(y == 1) return 1;
        else if(y == 2) return 9;
        else if(y == 3) return 3;
        else if(y == 4) return 7;
        else if(y == 5) return 38;

        else if(y == 6) return 17;
        else if(y == 7) return 38;
        break;
    case 2:
             if(y == 1) return 53;
        else if(y == 2) return 46;
        else if(y == 3) return 45;
        else if(y == 4) return 44;
        else if(y == 5) return 40;
        
        else if(y == 6) return 18;
        else if(y == 7) return 26;
        break;
    case 3:
             if(y == 1) return 52;
        else if(y == 2) return 12;
        else if(y == 3) return 43;
        else if(y == 4) return  6;
        else if(y == 5) return 36;
        
        else if(y == 6) return 19;
        else if(y == 7) return 27;
        break;
    case 4:
             if(y == 1) return 51;
        else if(y == 2) return 10;
        else if(y == 3) return 50;
        else if(y == 4) return  4;
        else if(y == 5) return 35;
        
        else if(y == 6) return 20;
        else if(y == 7) return 28;
        break;
    case 5:
             if(y == 1) return 49;
        else if(y == 2) return 14;
        else if(y == 3) return 42;
        else if(y == 4) return  8;
        else if(y == 5) return 34;
        
        else if(y == 6) return 21;
        else if(y == 7) return 29;
        break;
    case 6:
             if(y == 1) return 11;
        else if(y == 2) return  5;
        else if(y == 3) return 41;
        else if(y == 4) return 33;
        else if(y == 5) return 37;
        
        else if(y == 6) return 22;
        else if(y == 7) return 30;
        break;
    case 7:
             if(y == 1) return 55;
        else if(y == 2) return 47;
        else if(y == 3) return 13;
        else if(y == 4) return 54;
        else if(y == 5) return 39;
        
        else if(y == 6) return 23;
        else if(y == 7) return 31;
        break;
    case 8:
             if(y == 1) return 56;
        else if(y == 2) return 16;
        else if(y == 3) return 48;
        else if(y == 4) return 15;
        else if(y == 5) return  2;
        
        else if(y == 6) return 24;
        else if(y == 7) return 32;
        break;
    }
    return 2;//預設白色
}
short xlsFile::SelectColor(const char ColorChar)
{
    switch(ColorChar)
    {
    //黑色
    case 'D':
    case 'd':
        return 1;
        break;
    //白色
    case 'W':
    case 'w':
        return 2;
        break;
    //紅色
    case 'R':
    case 'r':
        return 3;
        break;
    //綠色
    case 'G':
    case 'g':
        return 4;
        break;
    //藍色
    case 'B':
    case 'b':
        return 5;
        break;
    //黃色
    case 'Y':
    case 'y':
        return 6;
        break;    }
    return 2;//預設白色
}

Cell填值

支援格種常用的儲存格格式,但是不支援時間格式。使用上要小心
//SetCell()
void xlsFile::SetCell(int Data)
{
    ZeroMemory(buf,sizeof(buf));
    sprintf(buf,"%d",Data);
    range.SetItem(_variant_t((long)1),_variant_t((long)1),_variant_t(buf));
}

void xlsFile::SetCell(long Data)
{
    ZeroMemory(buf,sizeof(buf));
    sprintf(buf,"%d",Data);
    range.SetItem(_variant_t((long)1),_variant_t((long)1),_variant_t(buf));
}

void xlsFile::SetCell(double Data)
{
    ZeroMemory(buf,sizeof(buf));
    sprintf(buf,"%f",Data);
    range.SetItem(_variant_t((long)1),_variant_t((long)1),_variant_t(buf));
}

void xlsFile::SetCell(const char* Data)
{
    ZeroMemory(buf,sizeof(buf));
    strcpy(buf,Data);
    //sprintf(buf,"%s",Data);
    range.SetItem(_variant_t((long)1),_variant_t((long)1),_variant_t(buf));
}

void xlsFile::SetCell(CString Data)
{
    ZeroMemory(buf,sizeof(buf));
    sprintf(buf,"%s",Data);
    range.SetItem(_variant_t((long)1),_variant_t((long)1),_variant_t(buf));
}

void xlsFile::SetCell(const char* Format, int Data)
{
    ZeroMemory(buf,sizeof(buf));
    sprintf(buf,Format,Data);
    range.SetItem(_variant_t((long)1),_variant_t((long)1),_variant_t(buf));
}

void xlsFile::SetCell(const char* Format, double Data)
{
    ZeroMemory(buf,sizeof(buf));
    sprintf(buf,Format,Data);
    range.SetItem(_variant_t((long)1),_variant_t((long)1),_variant_t(buf));
}

void xlsFile::SetCell(const char* Format, long Data)
{
    ZeroMemory(buf,sizeof(buf));
    sprintf(buf,Format,Data);
    range.SetItem(_variant_t((long)1),_variant_t((long)1),_variant_t(buf));
}
//-------------------------
CString xlsFile::GetCell2CStr()
{
    return (char*)_bstr_t(range.GetItem(_variant_t((long)1), _variant_t((long)1)));
}
int xlsFile::GetCell2Int()
{
    COleVariant vResult = range.GetValue2();   //edisonx 
    vResult.ChangeType(VT_INT);                //edisonx 
    return vResult.intVal;                     //edisonx 
}
double xlsFile::GetCell2Double()
{
    COleVariant vResult = range.GetValue2();  //edisonx 
    vResult.ChangeType(VT_R8);                //edisonx 
    return vResult.dblVal;                    //edisonx 
}

排序演算法

排序演算法有分主要順序和次要順序的設定,可以順序填值,也可以填完值再排序。
//排序
void xlsFile::Sort(CString IndexCell1, long DeCrement1, CString IndexCell2, long DeCrement2, CString IndexCell3, long DeCrement3)
{
    VARIANT key1, key2, key3;

    V_VT(&key1) = VT_DISPATCH;
    V_DISPATCH(&key1)=objSheet.GetRange(COleVariant(IndexCell1),COleVariant(IndexCell1));

    if(IndexCell2.IsEmpty())
    {
        range.Sort( key1, DeCrement1, VOptional, VOptional, 1, VOptional, 1, 2,//一般選項
                    VOptional, _variant_t((short)TRUE),//進階 
                    1, 1, 1, 1, 1);//未知選項//edisonx
    }
    else
    {
        V_VT(&key2) = VT_DISPATCH;
        V_DISPATCH(&key2)=objSheet.GetRange(COleVariant(IndexCell2),COleVariant(IndexCell2));
        
        if(IndexCell3.IsEmpty())
        {
            range.Sort( key1, DeCrement1, key2,    VOptional, DeCrement2, VOptional, 1, 2,
                        VOptional, _variant_t((short)TRUE),                                //進階 
                        1, 1, 1, 1, 1);                                                    //未知選項//edisonx
        }
        else
        {
            V_VT(&key3) = VT_DISPATCH;
            V_DISPATCH(&key3)=objSheet.GetRange(COleVariant(IndexCell3),COleVariant(IndexCell3));
            
            range.Sort( key1, DeCrement1, key2, VOptional, DeCrement2, key3, DeCrement3, 2, //一般選項
                        VOptional, _variant_t((short)TRUE),                                 //進階 
                        1, 1, 1, 1, 1);                                                     //未知選項//edisonx
        }
    }
}

其它

在其它,就將不常用的圖表/圖的新增與設定的操作放在這。
這裡的設計就比較不費心思,使用上也許會有種種困擾。小心使用!
void xlsFile::newChart()
{
    //在Sheet新增圖表
    lpDisp = objSheet.ChartObjects(VOptional);
    chartobjects.AttachDispatch(lpDisp);    
    chartobject = chartobjects.Add(
                                (float)range.GetLeft(  ).dblVal,
                                (float)range.GetTop(   ).dblVal, 
                                (float)range.GetWidth( ).dblVal, 
                                (float)range.GetHeight().dblVal  );    //圖表符合儲存格範圍的大小
    xlsChart.AttachDispatch(chartobject.GetChart());    //資料來源(範圍left, top預設為 比較Item和Group)
}
///////////////////////////////////////////////////////////////////////////////////////////
//圖表操作
//儲存圖表
//edisonx
void xlsFile::SaveChart(CString FullBmpPathName)
{
    xlsChart.Export(LPCTSTR(FullBmpPathName),VOptional,VOptional);
}
//選擇表格資料的範圍
xlsFile* xlsFile::SelectChartRange(const char* x1,const char* x2)
{
    newChart();

    lpDisp = objSheet.GetRange(COleVariant(x1),COleVariant(x2));
    range.AttachDispatch(lpDisp);
    
    return this;
}

xlsFile* xlsFile::SelectChartRange(const char* x1, int y1, const char* x2, int y2)
{
    newChart();    

    ZeroMemory(buf1,sizeof(buf1));
    ZeroMemory(buf2,sizeof(buf2));
    sprintf(buf1,"%s%d",x1,y1);
    sprintf(buf2,"%s%d",x2,y2);

    lpDisp = objSheet.GetRange(COleVariant(buf1),COleVariant(buf2));
    range.AttachDispatch(lpDisp);
    return this;
}
//小於Z
xlsFile* xlsFile::SelectChartRange(char x1, int y1, char x2, int y2)
{
    newChart();

    ZeroMemory(buf1,sizeof(buf1));
    ZeroMemory(buf2,sizeof(buf2));
    //發現了這個問題,但是忘記了是不是故意這樣寫的!
    //是x1, y1; x2, y2?
    sprintf(buf1,"%c%d",x1,y2);
    sprintf(buf2,"%c%d",x1,y2);

    lpDisp = objSheet.GetRange(COleVariant(buf1),COleVariant(buf2));
    range.AttachDispatch(lpDisp);
    return this;
}
//大於Z,開始選AA
xlsFile* xlsFile::SelectChartRange(char xA1, char xB1, int y1, char xA2, char xB2, int y2)
{
    newChart();
    ZeroMemory(buf1,sizeof(buf1));
    ZeroMemory(buf2,sizeof(buf2));
    sprintf(buf1,"%c%c%d",xA1,xB1,y1);
    sprintf(buf2,"%c%c%d",xA2,xB2,y2);    
    lpDisp = objSheet.GetRange(COleVariant(buf1),COleVariant(buf2));
    range.AttachDispatch(lpDisp);
    return this;
}
// 設定表格參數(預設會顯示立體直方圖)
xlsFile* xlsFile::SetChart(short XaxisByToporLeft, bool isLabelVisable, CString TitleString, CString XaxisTitle, CString YaxisTitle) 
{    
    var.vt = VT_DISPATCH;
    var.pdispVal = lpDisp;

    short LabelVisable(FALSE);
    LabelVisable = (isLabelVisable) ? (short)TRUE : (short)FALSE ;
        
    xlsChart.ChartWizard(
        var,                                   // const VARIANT& Source.
        COleVariant((short)11),                // const VARIANT& fix please, Gallery: 3d Column. 1 or 11 是否轉動3D(3D類適用, 1轉,11不轉)
        COleVariant((short)1),                 // const VARIANT& fix please, Format, use default
        COleVariant(XaxisByToporLeft),         // const VARIANT& PlotBy: 1.X  2.Y 圖表的x軸要使用 表格的1:X-top還是2:Y-left
        COleVariant((short)1),                 // const VARIANT& Category Labels fix please 不當軸的那個資料,從第幾個格子開始算(比較群組資料數量)
        COleVariant((short)1),                 // const VARIANT& Series Labels. Start X, 不當軸的那個資料,資料名稱要用幾排格子(更改名字)
        COleVariant(LabelVisable),             // const VARIANT& HasLegend. 是否要顯示群組資料標籤
        //以下可不填
        _variant_t(COleVariant(TitleString)),  // const VARITNT& Title
        _variant_t(COleVariant(XaxisTitle)),   // const VARIANT& CategoryTitle
        _variant_t(COleVariant(YaxisTitle)),   // const VARIANT& ValueTitle
        VOptional                              // const VARIANT& ExtraTitle
        );
    return this;
}
//插入圖表
void xlsFile::InsertHistogramChart(int shapeType, bool is3D, 
                                   int isVrticl_Horztl_Other, 
                                   int isNone_Stack_Percent )
{
    long ChartType = 51;
    if (shapeType == 0)//Area
    {
        if(!is3D)   //2D
        {
                 if (isNone_Stack_Percent == 0) ChartType = 1;  //無堆疊
            else if (isNone_Stack_Percent == 1) ChartType = 77; //有堆疊
            else if (isNone_Stack_Percent == 2) ChartType = 76; //有百分比
        }
        else        //3D
        {
                 if (isNone_Stack_Percent == 0) ChartType = -4098; //無堆疊
            else if (isNone_Stack_Percent == 1) ChartType = 78;    //有堆疊
            else if (isNone_Stack_Percent == 2) ChartType = 79;    //百分比
        }
    } 
    else if (shapeType == 1)//直方圖
    {
        if(isVrticl_Horztl_Other == 0)//直的
        {
            if(!is3D)   //2D
            {
                     if (isNone_Stack_Percent == 0) ChartType = 51; //無堆疊
                else if (isNone_Stack_Percent == 1) ChartType = 52; //有堆疊
                else if (isNone_Stack_Percent == 2) ChartType = 53; //有百分比
            }
            else        //3D
            {
                     if (isNone_Stack_Percent == 0) ChartType = 54; //無堆疊
                else if (isNone_Stack_Percent == 1) ChartType = 55; //有堆疊
                else if (isNone_Stack_Percent == 2) ChartType = 56; //百分比
            }
        }
        else if(isVrticl_Horztl_Other == 1)//橫的
        {
            if(!is3D)   //2D
            {
                     if (isNone_Stack_Percent == 0) ChartType = 57;
                else if (isNone_Stack_Percent == 1) ChartType = 58;
                else if (isNone_Stack_Percent == 2) ChartType = 59;
            }
            else        //3D
            {
                     if (isNone_Stack_Percent == 0) ChartType = 60;
                else if (isNone_Stack_Percent == 1) ChartType = 61;
                else if (isNone_Stack_Percent == 2) ChartType = 62;
            }
        }
        else                                        ChartType = -4100;    //平面 必3D
    }
    else if (shapeType == 2)//CONE
    {
        if(isVrticl_Horztl_Other == 0)//直的
        {
                 if (isNone_Stack_Percent == 0) ChartType = 92;  //無堆疊
            else if (isNone_Stack_Percent == 1) ChartType = 93;  //有堆疊
            else if (isNone_Stack_Percent == 2) ChartType = 94;  //百分比
        }
        else if(isVrticl_Horztl_Other == 1)//橫的
        {
                 if (isNone_Stack_Percent == 0) ChartType = 95;  //無堆疊
            else if (isNone_Stack_Percent == 1) ChartType = 96;  //有堆疊
            else if (isNone_Stack_Percent == 2) ChartType = 97;  //百分比
        }
        else                                    ChartType = 98;  //平面 必3D
    }
    else if (shapeType == 3)
    {
        if(isVrticl_Horztl_Other == 0)//直的
        {
                 if (isNone_Stack_Percent == 0) ChartType =  99;  //無堆疊
            else if (isNone_Stack_Percent == 1) ChartType = 100;  //有堆疊
            else if (isNone_Stack_Percent == 2) ChartType = 101;  //百分比
        }
        else if(isVrticl_Horztl_Other == 1)//橫的
        {
                  if(isNone_Stack_Percent == 0) ChartType = 102;  //無堆疊
            else if (isNone_Stack_Percent == 1) ChartType = 103;  //有堆疊
            else if (isNone_Stack_Percent == 2) ChartType = 104;  //百分比
        }
        else                    ChartType = 105;//平面 必3D
    }
    else if (shapeType == 4)
    {
        if(isVrticl_Horztl_Other == 0)//直的
        {
                 if (isNone_Stack_Percent == 0) ChartType = 106;  //無堆疊
            else if (isNone_Stack_Percent == 1) ChartType = 107;  //有堆疊
            else if (isNone_Stack_Percent == 2) ChartType = 108;  //百分比
        }
        else if(isVrticl_Horztl_Other == 1)//橫的
        {
                 if (isNone_Stack_Percent == 0) ChartType = 109;  //無堆疊
            else if (isNone_Stack_Percent == 1) ChartType = 110;  //有堆疊
            else if (isNone_Stack_Percent == 2) ChartType = 111;  //百分比
        }
        else                                    ChartType = 112;  //平面 必3D
    }
    xlsChart.SetChartType((long)ChartType);
}
///////////////////////////////////////////////////////////////
//泡泡
void xlsFile::InsertBubleChart(bool is3D)
{
    long ChartType = 51;

    if(is3D)    ChartType = 15;
    else        ChartType = 87;

    xlsChart.SetChartType((long)ChartType);
}
//圓環
void xlsFile::InsertDoughnutChart(bool Explode)
{
    long ChartType = 51;
    
    if(!Explode)    ChartType = -4120;
    else            ChartType = 80;

    xlsChart.SetChartType((long)ChartType);

}
//曲面
void xlsFile::InsertSurfaceChart(bool is3D, bool isWire)
{
    long ChartType = 51;
    
    if (is3D)
    {
        if (!isWire)    ChartType = 83;
        else            ChartType = 84;
    } 
    else
    {
        if (!isWire)    ChartType = 85;
        else            ChartType = 86;
    }

    xlsChart.SetChartType((long)ChartType);
}
//雷達
void xlsFile::InsertRadarChart(bool isWire, bool isDot)
{
    long ChartType = 51;
    
    if (isWire)
    {
        if (!isDot) ChartType = -4151;
        else        ChartType = 81;
    } 
    else            ChartType = 82;

    xlsChart.SetChartType((long)ChartType);
}
//圓餅
void xlsFile::InsertPieChart(bool Explode, int type2Dor3DorOf)
{
    long ChartType = 51;

    if(!Explode)
    {
             if (type2Dor3DorOf == 0)        ChartType = 5;
        else if (type2Dor3DorOf == 1)        ChartType = -1402;
        else if (type2Dor3DorOf == 2)        ChartType = 68;
    }
    else
    {
             if (type2Dor3DorOf == 0)        ChartType = 69;
        else if (type2Dor3DorOf == 1)        ChartType = 70;
        else if (type2Dor3DorOf == 2)        ChartType = 71;
    }
    
    xlsChart.SetChartType(ChartType);
}

void xlsFile::InsertLineChart(bool isDot, bool is3D, int isNone_Stack_Percent)
{
    long ChartType = 51;
    
    if(!is3D)//3D
    {
        if(!isDot)
        {
                 if (isNone_Stack_Percent == 0) ChartType =  4;  //無堆疊
            else if (isNone_Stack_Percent == 1) ChartType = 63;  //有堆疊
            else if (isNone_Stack_Percent == 2) ChartType = 64;  //有百分比
        }
        else
        {
                 if (isNone_Stack_Percent == 0) ChartType = 65;  //無堆疊
            else if (isNone_Stack_Percent == 1) ChartType = 66;  //有堆疊
            else if (isNone_Stack_Percent == 2) ChartType = 67;  //有百分比
        }
    }
    else                                        ChartType = -4101;  //3D

    xlsChart.SetChartType((long)ChartType);
}
//離散圖
void xlsFile::InsertXYScatterChart(bool isDot, bool isLine, bool Smooth)
{
    long ChartType = 51;
    if(!isLine)          ChartType = -4169;  //3D
    else
    {
        if(Smooth)
        {
            if(isDot)    ChartType = 72;
            else         ChartType = 73;
        }
        else
        {
            if(isDot)    ChartType = 74;
            else         ChartType = 75;
        }
    }
    xlsChart.SetChartType((long)ChartType);
}

//股票圖
void xlsFile::InsertStockChart(int StockType)
{
    long ChartType = 51;
    
         if (StockType == 0)    ChartType = 88;
    else if (StockType == 1)    ChartType = 89;
    else if (StockType == 2)    ChartType = 90;
    else if (StockType == 3)    ChartType = 91;

    xlsChart.SetChartType((long)ChartType);
}
//--------------------------------------------
//--------------------------------------------
//插入圖(從檔案)
void xlsFile::InsertImage(const char* FileNamePath, float Width, float Height)
{
    shapes = objSheet.GetShapes(); 
    shapes.AddPicture(
        FileNamePath,                   //LPCTSTR Filename
        false,                          //long LinkToFile
        true,                           //long SaveWithDocument
        (float)range.GetLeft().dblVal,  //float Left
        (float)range.GetTop().dblVal,   //float Top
        Width,                          //float Width
        Height                          //float Height
    );
}

void xlsFile::InsertImage(const char* FileNamePath)
{
    shapes = objSheet.GetShapes(); 
    shapes.AddPicture(
        FileNamePath,                   //LPCTSTR Filename
        false,                          //long LinkToFile
        true,                           //long SaveWithDocument
        (float)range.GetLeft().dblVal,  //float Left
        (float)range.GetTop().dblVal,   //float Top
        (float)range.GetWidth().dblVal, //float Width
        (float)range.GetHeight().dblVal //float Height
    );
}

沒有留言:

張貼留言

(什麼是留言欄訊息?)