zoukankan      html  css  js  c++  java
  • VC中操作excel表格

    操作系统是Microsoft XP,办公套装是Microsoft Office 2003,编程环境是Microsoft Visual Studio 6.0,一切都是Microsoft

     

    我最近要将数据库中的内容查询出来放到excel表格以便打印,所以上网找了这方面的内容,这里主要是抛砖引玉。

     

    从思路上来看,操作excel表格就是将其打开,然后写入/读出数据,然后关闭。

     

    首先创建一个程序(我的例子是一个MFC的单文档程序),在程序的入口处和出口处先作这样两个步骤来支持COM库:

     

    在程序入口处CXXXApp:: InitInstance()函数AfxEnableControlContainer();语句之后加入下面几行:

     

    if (CoInitialize(NULL) != 0)

     

    {

     

          AfxMessageBox(“初始化COM支持库失败!);

     

          exit(1);

     

    }

     

    假如这个条件不通过就不能运行起程序。

     

    在程序的出口处CXXXApp:: ExitInstance()函数return语句之前加入下面这句话:CoUninitialize();来释放COM支持库。

     

    这样对COM支持库的代码已经完成。

     

    下面要从Office的安装目录中找到对VC操作excel文件的动态库,在某些版本下这个文件是Excel8.olb或者Excel9.olb,在我的版本中是excel.exe这个exe也是动态库的形式,是微软公司主要的文件结果之一。选择vcView菜单里面的ClassWizad命令,会弹出一个对话框;然后点击Add Class…按钮选择From a type library,会弹出一个打开对话框,从这里打开Office安装目录下…\Office11\EXCEL.EXE文件,从里面选择几个要用到的类:_Application, Workbooks, _Wrokbook, Worksheets, _WorkSheet, Range,点击OK按钮。会在程序中生成一个excel.hexcel.cpp文件,这些文件中包含了刚才我们选择的几个类的代码。下面介绍一下这几个类:

     

    vc操纵excelexe动态库里面有好多个对象模型,就是刚才在创建过程中看到的那个列表,但是经常用到的有这么几个:_Application, Workbooks, _Wrokbook, Worksheets, _WorkSheet, RangeCharts_Chart,最后面的两个是用来操作图表的,我没有用到所以这里也就不记录了。

     

    _Application:这里的Application就是Excel本身,众所周知,一个Excel可以包含多个工作簿,每个工作簿又可以包含多个工作表,而每个工作表又可以包含多个区域或者图表,所以这里他们是树型的结构关系,而application最基本的一个功能就是找到它的子项工作簿。果然,我们在引入我们程序的Application类中看到了这样的成员函数:GetWorkbooks()。既然application就是excel,那么打开程序,退出程序,显示/隐藏程序这些基本的操作都可以在这个类的成员函数中找到,果不其然。

     

    Workbooks:这个对象是一个容器对象,它里面存放着所有打开的工作簿。因此,我们可以猜测它一定有添加,查找,打开/关闭工作簿的功能。(本程序中使用excel的一个xlt模板来生成一个xls文件就是使用了这个容器对象的添加功能。)

     

    _Workbook:这是一个工作簿,也就相当于一个xls文件。Excel可以同时打开多个工作簿,所以工作簿之间必定能够互相切换,每个工作簿可以关联工作表容器并获得工作表的索引。

     

    Worksheets:也是一个容器对象,和Workbooks类似。

     

    _Worksheet:这个就是我们看到的工作表,比如Sheet1sheet2等等。

     

    Rang:就是我们看到的能选中的方框的大小。而我们所要作的操作基本上是以区域为单位进行的。

     

     

     

    介绍完这些,就添加一个菜单,来响应操作excel的命令。

     

    然后下面附带这个函数的内容,注释还算可以吧,并且附上网上不知道谁写的但是转载极多的一个封装类。

     

    view plaincopy to clipboardprint?

    _Application _app;  

    _Workbook _workBook;  

    _Worksheet _workSheet;  

    Worksheets workSheets;  

    Workbooks workBooks;  

    Range range;  

    Range copyFrom;  

    Range copyTo;  

     

    if(!_app.CreateDispatch("Excel.Application", NULL))  

    {  

       MessageBox("创建Excel服务失败!", "信息提示", MB_OK);  

       return;  

    }  

    //利用模板建立新文档  

    workBooks.AttachDispatch(_app.GetWorkbooks());  

    _workBook.AttachDispatch(workBooks.Add(_variant_t("\"C:\\Documents and Settings\\模板.xlt\"")));//你可以自己创建一个模板,并自由设定目录  

    //得到worksheets  

    workSheets.AttachDispatch(_workBook.GetWorksheets()); 

    //得到workSheet  

    _workSheet.AttachDispatch(workSheets.GetItem(_variant_t("sheet1")));  

    //得到拷贝的母板  

    copyFrom.AttachDispatch(_workSheet.GetRange(_variant_t("A3"), _variant_t("Q6")));  

    copyTo.AttachDispatch(_workSheet.GetRange(_variant_t("A61"), _variant_t("A61")));  

    //得到全部的cells  

    range.AttachDispatch(_workSheet.GetCells());  

     

    ///////////////////////////////////////////////////////////////////////////////////////////////////  

    //上边是头  

     

    /* 

    中间要做的工作有这两项:设置数据和拷贝格式 

    设置数据就是将数据库中查询出来的数据写入表格,拷贝格式就是将表格拷贝到别的地方。 

    */ 

    //写入数据  

    range.SetItem(_variant_t((long)3), _variant_t((long)1), _variant_t("写入数据了"));  

    range.SetItem(_variant_t((long)5), _variant_t((long)1), _variant_t("重新写入数据了"));  

    //拷贝一段区域到另外的一段区域  

    copyFrom.Copy(_variant_t(copyTo));  

    range.SetItem(_variant_t((long)61), _variant_t((long)1), _variant_t("123"));  

     

    //显示excel表格  

       _app.SetVisible(TRUE);  

    //保存为文件  

    _app.SetDisplayAlerts(FALSE);  //隐藏弹出的对话框  

    _workSheet.SaveAs("d:\\Test.xls",vtMissing,vtMissing,vtMissing,vtMissing,  

       vtMissing,vtMissing,vtMissing,vtMissing,vtMissing);  

    _app.Quit();  

    //下边是尾  

    ///////////////////////////////////////////////////////////////////////////////////////////////////  

    copyFrom.ReleaseDispatch();  

    copyTo.ReleaseDispatch();  

    range.ReleaseDispatch();  

    _workSheet.ReleaseDispatch();  

    workSheets.ReleaseDispatch();  

    _workBook.ReleaseDispatch();  

    workSheets.ReleaseDispatch();  

    _app.ReleaseDispatch(); 

       _Application _app;

       _Workbook _workBook;

       _Worksheet _workSheet;

       Worksheets workSheets;

       Workbooks workBooks;

       Range range;

       Range copyFrom;

       Range copyTo;

       

       if(!_app.CreateDispatch("Excel.Application", NULL))

       {

          MessageBox("创建Excel服务失败!", "信息提示", MB_OK);

          return;

       }

       //利用模板建立新文档

       workBooks.AttachDispatch(_app.GetWorkbooks());

       _workBook.AttachDispatch(workBooks.Add(_variant_t("\"C:\\Documents and Settings\\模板.xlt\"")));//你可以自己创建一个模板,并自由设定目录

       //得到worksheets

       workSheets.AttachDispatch(_workBook.GetWorksheets());

       //得到workSheet

       _workSheet.AttachDispatch(workSheets.GetItem(_variant_t("sheet1")));

       //得到拷贝的母板

       copyFrom.AttachDispatch(_workSheet.GetRange(_variant_t("A3"), _variant_t("Q6")));

       copyTo.AttachDispatch(_workSheet.GetRange(_variant_t("A61"), _variant_t("A61")));

       //得到全部的cells

       range.AttachDispatch(_workSheet.GetCells());

       

       ///////////////////////////////////////////////////////////////////////////////////////////////////

       // 上边是头

       

       /*

       中间要做的工作有这两项:设置数据和拷贝格式

       设置数据就是将数据库中查询出来的数据写入表格,拷贝格式就是将表格拷贝到别的地方。

       */

       //写入数据

       range.SetItem(_variant_t((long)3), _variant_t((long)1), _variant_t("写入数据了"));

       range.SetItem(_variant_t((long)5), _variant_t((long)1), _variant_t("重新写入数据了"));

       //拷贝一段区域到另外的一段区域

       copyFrom.Copy(_variant_t(copyTo));

       range.SetItem(_variant_t((long)61), _variant_t((long)1), _variant_t("123"));

       

       //显示excel表格

          _app.SetVisible(TRUE);

       //保存为文件

       _app.SetDisplayAlerts(FALSE);   //隐藏弹出的对话框

       _workSheet.SaveAs("d:\\Test.xls",vtMissing,vtMissing,vtMissing,vtMissing,

          vtMissing,vtMissing,vtMissing,vtMissing,vtMissing);

       _app.Quit();

       //下边是尾

       ///////////////////////////////////////////////////////////////////////////////////////////////////

       copyFrom.ReleaseDispatch();

       copyTo.ReleaseDispatch();

       range.ReleaseDispatch();

       _workSheet.ReleaseDispatch();

       workSheets.ReleaseDispatch();

       _workBook.ReleaseDispatch();

       workSheets.ReleaseDispatch();

       _app.ReleaseDispatch();

     

     

     

    别人的代码:

     

     

    view plaincopy to clipboardprint?

    .h文件: 

    #include "comdef.h"  

    #include "excel.h"  

    class ExcelFile   

    {  

    public:  

    void ShowInExcel(bool bShow);  

    CString GetCell(int iRow, int iColumn);  

    int    GetCellInt(int iRow, int iColumn);  

    int GetRowCount();  

    int GetColumnCount();  

    bool LoadSheet(int iIndex);  

    CString GetSheetName(int iIndex);  

    static void InitExcel();  

    static void ReleaseExcel();  

    int GetSheetCount();  

    bool Open(CString FileName);  

    ExcelFile();  

    virtual ~ExcelFile();  

    protected:  

    private:  

    static _Application m_ExcelApp;  

     

    Workbooks   m_Books;   

    _Workbook   m_Book;   

    Worksheets  m_sheets;   

    _Worksheet  m_sheet;   

    Range       m_Rge;   

    };  

    .cpp文件:  

    ExcelFile::ExcelFile()  

    {  

    }  

    ExcelFile::~ExcelFile()  

    {  

    m_Rge.ReleaseDispatch();   

    m_sheet.ReleaseDispatch();   

    m_sheets.ReleaseDispatch();   

    m_Book.ReleaseDispatch();   

    m_Books.ReleaseDispatch();   

    }  

    void ExcelFile::InitExcel()  

    {  

    //创建Excel 2000服务器(启动Excel)   

    if (!m_ExcelApp.CreateDispatch("Excel.Application",NULL))   

    {   

    AfxMessageBox("创建Excel服务失败!");   

    exit(1);   

    }   

    }  

    void ExcelFile::ReleaseExcel()  

    {  

    m_ExcelApp.ReleaseDispatch();  

    }  

    bool ExcelFile::Open(CString FileName)  

    {  

    //打开excel文件  

    //利用模板文件建立新文档   

    m_Books.AttachDispatch(m_ExcelApp.GetWorkbooks(),true);   

    LPDISPATCH lpDis = NULL;  

    lpDis = m_Books.Add(_variant_t(FileName)); //如何判断文件是否打开?  

    if (lpDis)  

    {  

    m_Book.AttachDispatch(lpDis);   

    //得到Worksheets   

    m_sheets.AttachDispatch(m_Book.GetWorksheets(),true);   

    return true;  

    }  

    return false;  

    }  

    int ExcelFile::GetSheetCount()  

    {  

    return m_sheets.GetCount();  

    }  

    CString ExcelFile::GetSheetName(int iIndex)  

    {  

    _Worksheet sheet;  

    sheet.AttachDispatch(m_sheets.GetItem(_variant_t((long)iIndex)),true);  

    CString name = sheet.GetName();  

    sheet.ReleaseDispatch();  

    return name;  

    }  

    bool ExcelFile::LoadSheet(int iIndex)  

    {  

    LPDISPATCH lpDis = NULL;  

    m_Rge.ReleaseDispatch();  

    m_sheet.ReleaseDispatch();  

    lpDis = m_sheets.GetItem(_variant_t((long)iIndex));  

    if (lpDis)  

    {  

           m_sheet.AttachDispatch(lpDis,true);  

           m_Rge.AttachDispatch(m_sheet.GetCells(), true);  

           return true;  

    }  

    return false;  

    }  

    int ExcelFile::GetColumnCount()  

    {  

    Range range;  

    Range usedRange;  

    usedRange.AttachDispatch(m_sheet.GetUsedRange(), true);  

    range.AttachDispatch(usedRange.GetColumns(), true);  

    int count = range.GetCount();  

    usedRange.ReleaseDispatch();  

    range.ReleaseDispatch();  

    return count;  

    }  

    int ExcelFile::GetRowCount()  

    {  

    Range range;  

    Range usedRange;  

    usedRange.AttachDispatch(m_sheet.GetUsedRange(), true);  

    range.AttachDispatch(usedRange.GetRows(), true);  

    int count = range.GetCount();  

    usedRange.ReleaseDispatch();  

    range.ReleaseDispatch();  

    return count;  

    }  

    CString ExcelFile::GetCell(int iRow, int iColumn)  

    {  

    Range range;  

    range.AttachDispatch(m_Rge.GetItem (COleVariant((long)iRow),COleVariant((long)iColumn)).pdispVal, true);  

       COleVariant vResult =range.GetValue2();  

    CString str;  

    if(vResult.vt == VT_BSTR)      //字符串  

    {  

    str=vResult.bstrVal;  

    }  

    else if (vResult.vt==VT_INT)  

    {  

           str.Format("%d",vResult.pintVal);  

    }  

    else if (vResult.vt==VT_R8)    //8字节的数字   

    {  

    str.Format("%f",vResult.dblVal);  

    //str.Format("%.0f",vResult.dblVal);  

    //str.Format("%1f",vResult.fltVal);  

    }  

    else if(vResult.vt==VT_DATE)   //时间格式  

    {  

    SYSTEMTIME st;  

    VariantTimeToSystemTime(vResult.date, &st);  

    }  

    else if(vResult.vt==VT_EMPTY)  //单元格空的  

    {  

       str="(NULL)";  

    }   

    range.ReleaseDispatch();  

    return str;  

    }  

    int ExcelFile::GetCellInt(int iRow, int iColumn)  

    {  

    Range range;  

    range.AttachDispatch(m_Rge.GetItem(COleVariant((long)iRow),COleVariant((long)iColumn)).pdispVal, true);  

    COleVariant vResult =range.GetValue2();  

    int num;  

    num = (int)vResult.date;  

    range.ReleaseDispatch();  

    return num;  

    }  

    void ExcelFile::ShowInExcel(bool bShow)  

    {  

    m_ExcelApp.SetVisible(bShow);  

    } 

     

  • 相关阅读:
    异步FIFO总结
    异常检测参考
    Java数据库连接技术
    Eclipse Decompiler不生效解决办法
    mysql常用操作
    时间序列预测——Tensorflow.Keras.LSTM
    AR(I)MA时间序列建模过程——步骤和python代码
    MySQL优化实例
    MySQL性能优化经验
    高性能MySQL笔记 第6章 查询性能优化
  • 原文地址:https://www.cnblogs.com/jinsedemaitian/p/5589199.html
Copyright © 2011-2022 走看看