zoukankan      html  css  js  c++  java
  • 使用MFC操作EXCEL文件

    一、加载

    1、 在VC6.0里创建一个MFC工程

    2、打开MFCClassWizard窗口(查看—>建立类向导),选择Automation,单击AddClass按钮,选择Froma type library...,弹出文件选择对话框,之后定位到C:Program FilesMicrosoftOfficeOFFICE11EXCEL.EXE,在生成类中添加所有的对象(其实添加需要的即可,为了简便,不出错保留了冗余),如下图。

     

     
     


    3、返回编辑器,查看工程文件,可发现多了EXCEL.9H及EXCEL9.CPP两个文件,拷贝出来,放在VS2005需要使用excel的工程文件中。

    4. 打开stdafx.h头文件确保包含如下头文件:

    #include <afxdisp.h>(这个一般有了)

    #include "excel.h" (手动添加这个即可)

    5. 打开TestExcel.cpp文件,修改CTestExcelApp::InitInstance(),加入如下代码:

    if(!AfxOleInit() ){

    AfxMessageBox("初始化Ole出错!");

    return FALSE;

    }

    为保证编译时不产生重复定义错误(可以验证一下是否成功加载,没有也能正常执行),我编译时出现了很多“类重复定义”异常,打开excel.h文件,在文件开始位置加入如下代码:

    #if !defined _HEAD_FILE_EXCEL9_

    #define _HEAD_FILE_EXCEL9_

    相应的,在文件末尾加入:

    #endif

    成功

    Excel接口

    导入类

    头文件

    说明

    _Application

    CApplicaton

    Application.h

    Excel应用程序。

    Workbooks

    CWorkbooks

    Workbooks.h

    工作簿的容器,里面包括了Excel应用程序打开的所有工作簿。

    _Workbook

    CWorkbook

    Workbook.h

    单个工作簿。

    Worksheets

    CWorksheets

    Worksheets.h

    单个工作簿中的Sheet表格的容器,包括该工作簿中的所有Sheet。

    _Worksheet

    CWorksheet

    Worksheet.h

    单个Sheet表格。

    Range

    CRange

    Range.h

    一定数量的单元格,可对单元格进行单个或多个单元格进行操作。

    在MSDN中,很少有excel方面的资料,但是在http://msdn.microsoft.com/zh-cn/ms348103.aspx中可以找到C#控制EXCEL方面的说明

     

    二、操作EXCEL文件

    1. 新建一个excel表,并填充两个单元格的实例

     

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. void CTestExcelDlg::OnButton1()  
    2. {  
    3. //Workbooks—>Workbook —>Worksheets—>Worksheet —>Range  
    4. _Application app;       //Excel应用程序接口  
    5. Workbooks books;        //工作薄集合  
    6. _Workbook book;     //工作薄  
    7. Worksheets sheets;      //工作表集合  
    8. _Worksheet sheet;       //工作表  
    9. Range range;            //Excel中针对单元格的操作都应先获取其对应的Range对象  
    10. Font font;  
    11. Range cols;  
    12. /* 
    13. COleVariant类为VARIANT数据类型的包装,在自动化程序中,通常都使用 
    14. VARIANT数据类型进行参数传递。故下列程序中,函数参数都是通过COleVariant 
    15. 类来转换了的。 
    16. */  
    17. //covOptional 可选参数的VARIANT类型  
    18. COleVariant covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);  
    19. if( !app.CreateDispatch("Excel.Application") ){  
    20. this->MessageBox("无法创建Excel应用!");  
    21. return;  
    22. }  
    23. //获取工作薄集合  
    24. books=app.GetWorkbooks();  
    25. //添加一个工作薄  
    26. book=books.Add(covOptional);  
    27. //获取工作表集合  
    28. sheets=book.GetSheets();  
    29. //获取第一个工作表  
    30. sheet=sheets.GetItem(COleVariant((short)1));  
    31. //选择工作表中A1:A1单元格区域  
    32. range=sheet.GetRange(COleVariant("A1"),COleVariant("A1"));  
    33. //设置A1=HELLO EXCEL!"  
    34. range.SetValue(COleVariant("HELLO EXCEL!"));  
    35. //调整格式,设置粗体  
    36. font=range.GetFont();  
    37. font.SetBold(COleVariant((short)TRUE));  
    38. //选择A2单元格,插入一个公式"=RAND()*100000",并设置A2数字格式为货币形  
    39. 式  
    40. range=sheet.GetRange(COleVariant("A2"),COleVariant("A2"));  
    41. range.SetFormula(COleVariant("=RAND()*100000"));  
    42. range.SetNumberFormat(COleVariant("$0.00"));  
    43. //选择A:A列,设置宽度为自动适应  
    44. cols=range.GetEntireColumn();  
    45. cols.AutoFit();  
    46. //显示Excel表格,并设置状态为用户可控制  
    47. app.SetVisible(TRUE);  
    48. app.SetUserControl(TRUE);  

    2. 打开一个已有的excel表格实例

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. CString strPath;   
    2. strPath += "C:\template.xlt"; // 模板的路径   
    3. CFileFind filefind;   
    4. if( !filefind.FindFile( strPath ) )   
    5. {   
    6. AfxMessageBox( "没有找到模版文档,请其查找" );   
    7.     return;  
    8. }   
    9. LPDISPATCH lpDisp;  //接口指针  
    10. books=app.GetWorkbooks();  
    11. lpDisp = books.Open(m_filepath,  
    12.     covOptional, covOptional, covOptional, covOptional,  
    13.     covOptional, covOptional, covOptional, covOptional,  
    14.     covOptional, covOptional, covOptional, covOptional,  
    15.     covOptional, covOptional  
    16.     );                  //与的不同,是个参数的,直接在后面加了两个covOptional成功了  
    17. book.AttachDispatch(lpDisp);  

    3. 保存一个excel文件实例

     

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. book.SetSaved(TRUE);  

    4. 另存一个excel文件实例

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. book.SaveAs(COleVariant(m_filename),covOptional,  
    2.     covOptional,covOptional,  
    3.     covOptional,covOptional,(long)0,  
    4. covOptional,covOptional,covOptional,  
    5. covOptional,covOptional); //与的不同,是个参数的,直接在后面加了两个covOptional成功了  

    5. 释放一个excel文件实例

    经试验证实,不释放第二次使用excel时会中断,放在类的析构里面有时调用不到,主动调用最保险。(有没有AttachDispatch()过都要释放,否则报错)

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. //释放对象(相当重要!)   
    2. Rang.ReleaseDispatch();   
    3. sheet.ReleaseDispatch();   
    4. sheets.ReleaseDispatch();   
    5. book.ReleaseDispatch();   
    6. books.ReleaseDispatch();   
    7. //退出程序   
    8. app.Quit();  
    9. //m_ExlApp一定要释放,否则程序结束后还会有一个Excel进程驻留在内存中,而且程序重复运行的时候会出错   
    10. app.ReleaseDispatch();   

    6. 修改一个excel单元格

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. range=sheet.GetRange(COleVariant(IndexToString(row,col)),COleVariant(IndexToString(row,col)));  
    2. range.SetValue2(COleVariant(value));  

    7. 取出一个excel单元格

    实现Variant数据类型转换为CString类,这个只是一个示例,转换较为简单。

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. range=sheet.GetRange(COleVariant(IndexToString(row,col)),COleVariant(IndexToString(row,col)));  
    2. COleVariant rValue;  
    3. rValue=COleVariant(range.GetValue2());  
    4. rValue.ChangeType(VT_BSTR);  
    5. return CString(rValue.bstrVal);  

    8. 还有释放问题是最重要的问题:

       首先变量必须全释放,无论当初是否绑定过;

       其次,程序释放和程序关闭的顺序必须是

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. app.Quit();  
    2. app.ReleaseDispatch();  
    3. 如果顺如颠倒如下:  
    4. app.ReleaseDispatch();  
    5. app.Quit();  
    6. 出现的后果是程序关闭后,excel进程仍然运行,所以无法正常打开程序曾经打开excel表格。  

    附录(操作类源码):

     

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
      1. #include "../Stdafx.h"  
      2. #include "OptExcel.h"  
      3. #include "excel.h"  
      4. #include "comdef.h"  
      5.          
      6.   
      7. _Application app;  
      8. Workbooks books;  
      9. _Workbook book;  
      10. Worksheets sheets;  
      11. _Worksheet sheet;  
      12. Range range;  
      13. Range cell;  
      14. Font font;  
      15.   
      16. COleVariant covOptional((long)DISP_E_PARAMNOTFOUND, VT_ERROR);  
      17.   
      18.   
      19. ////////////////////////////////////////////////////////////////////////  
      20. ///Function:    COptExcel  
      21. ///Description: 初始化函数,初始化中附加excel应用程序  
      22. ///Call:        app.CreateDispatch(_T("Excel.Application")  
      23. ////////////////////////////////////////////////////////////////////////  
      24. COptExcel::COptExcel(void)  
      25. {  
      26.     if (::CoInitialize( NULL ) == E_INVALIDARG)   
      27.     {   
      28.         AfxMessageBox(_T("初始化Com失败!"));   
      29.         return;  
      30.     }  
      31.   
      32.     //验证office文件是否可以正确运行  
      33.   
      34.     if( !app.CreateDispatch(_T("Excel.Application")) )  
      35.     {  
      36.         AfxMessageBox(_T("无法创建Excel应用!"));  
      37.         return;  
      38.     }  
      39.     //在程序执行文件路径名中,剪掉执行文件名,得到程序路径,追加模板文件名,得到模板完整路径  
      40.       
      41.   
      42. }  
      43.   
      44.   
      45. ////////////////////////////////////////////////////////////////////////  
      46. ///Function:    ~COptExcel  
      47. ///Description: 析构函数,释放对象,非常重要,不全部释放,占用内存,下  
      48. ///             一次使用此类时会中断  
      49. ///Call:        ReleaseDispatch()  
      50. ////////////////////////////////////////////////////////////////////////  
      51. COptExcel::~COptExcel(void)  
      52. {  
      53.       
      54.   
      55.       
      56.     books.ReleaseDispatch();  
      57.     book.ReleaseDispatch();  
      58.     sheets.ReleaseDispatch();  
      59.     sheet.ReleaseDispatch();  
      60.     range.ReleaseDispatch();  
      61.     font.ReleaseDispatch();  
      62.     cell.ReleaseDispatch();  
      63.   
      64.     app.Quit();  
      65.   
      66.     app.ReleaseDispatch();  
      67.     ::CoUninitialize();  
      68. }  
      69.   
      70.   
      71. ////////////////////////////////////////////////////////////////////////  
      72. ///Function:    OpenExcelBook  
      73. ///Description: 打开表名为filename的文件,注意,文件路径非自动生成,以后  
      74. ///             考虑从下处理方法  
      75. ///Call:        GetAppPath()  
      76. ///Input:       CString filename 文件名  
      77. ////////////////////////////////////////////////////////////////////////  
      78. bool COptExcel::OpenExcelBook(CString filename)  
      79. {  
      80.     CFileFind filefind;   
      81.     if( !filefind.FindFile(filename) )   
      82.     {   
      83.         AfxMessageBox(_T("文件不存在"));  
      84.         return false;  
      85.     }  
      86.     LPDISPATCH lpDisp; //接口指针  
      87.     books=app.GetWorkbooks();  
      88.     lpDisp = books.Open(filename,  
      89.         covOptional, covOptional, covOptional, covOptional,  
      90.         covOptional, covOptional, covOptional, covOptional,  
      91.         covOptional, covOptional, covOptional, covOptional,  
      92.         covOptional, covOptional  
      93.         );                                      //与office 2000的不同,是个参数的,直接在后面加了两个covOptional成功了  
      94.     book.AttachDispatch(lpDisp);  
      95.     sheets=book.GetSheets();  
      96.     sheet=sheets.GetItem(COleVariant((short)1));        //与的不同,是个参数的,直接在后面加了两个covOptional成功了  
      97.     return true;  
      98. }  
      99. void COptExcel::NewExcelBook()  
      100. {  
      101.     books=app.GetWorkbooks();  
      102.     book=books.Add(covOptional);  
      103.     sheets=book.GetSheets();  
      104.     sheet=sheets.GetItem(COleVariant((short)1));        //与的不同,是个参数的,直接在后面加了两个covOptional成功了  
      105. }  
      106.   
      107. ////////////////////////////////////////////////////////////////////////  
      108. ///Function:    OpenExcelApp  
      109. ///Description: 打开应用程序(要注意以后如何识别用户要打开的是哪个文件)  
      110. ////////////////////////////////////////////////////////////////////////  
      111. void COptExcel::OpenExcelApp(void)  
      112. {  
      113.     app.SetVisible(TRUE);  
      114.     app.SetUserControl(TRUE);  
      115. }  
      116.   
      117. ////////////////////////////////////////////////////////////////////////  
      118. ///Function:    SaveExcel  
      119. ///Description: 用于打开数据文件,续存数据后直接保存  
      120. ////////////////////////////////////////////////////////////////////////  
      121. void COptExcel::SaveExcel(void)  
      122. {  
      123.     book.SetSaved(TRUE);  
      124. }  
      125.   
      126. ////////////////////////////////////////////////////////////////////////  
      127. ///Function:    SaveAsExcel  
      128. ///Description: 保存excel文件  
      129. ////////////////////////////////////////////////////////////////////////  
      130. void COptExcel::SaveAsExcel(CString filename)  
      131. {  
      132.     book.SaveAs(COleVariant(filename),covOptional,  
      133.     covOptional,covOptional,  
      134.     covOptional,covOptional,(long)0,covOptional,covOptional,covOptional,  
      135.     covOptional,covOptional);                     
      136. }  
      137.   
      138.   
      139. ////////////////////////////////////////////////////////////////////////  
      140. ///Function:    SetCellValue  
      141. ///Description: 修改单元格内的值  
      142. ///Call:        IndexToString() 从(x,y)坐标形式转化为“A1”格式字符串  
      143. ///Input:       int row 单元格所在行  
      144. ///             int col 单元格所在列  
      145. ///             int Align       对齐方式默认为居中  
      146. ////////////////////////////////////////////////////////////////////////  
      147. void COptExcel::SetCellValue(int row, int col,int Align)  
      148. {  
      149.     range=sheet.GetRange(COleVariant(IndexToString(row,col)),COleVariant(IndexToString(row,col)));  
      150.     range.SetValue2(COleVariant(value));  
      151.     cell.AttachDispatch((range.GetItem (COleVariant(long(1)), COleVariant(long(1)))).pdispVal);  
      152.     cell.SetHorizontalAlignment(COleVariant((short)Align));  
      153. }  
      154.   
      155. ////////////////////////////////////////////////////////////////////////  
      156. ///Function:    GetCellValue  
      157. ///Description: 得到的单元格中的值  
      158. ///Call:        IndexToString() 从(x,y)坐标形式转化为“A1”格式字符串  
      159. ///Input:       int row 单元格所在行  
      160. ///             int col 单元格所在列  
      161. ///Return:      CString 单元格中的值  
      162. ////////////////////////////////////////////////////////////////////////  
      163. CString COptExcel::GetCellValue(int row, int col)  
      164. {  
      165.     range=sheet.GetRange(COleVariant(IndexToString(row,col)),COleVariant(IndexToString(row,col)));  
      166.     COleVariant rValue;  
      167.     rValue=COleVariant(range.GetValue2());  
      168.     rValue.ChangeType(VT_BSTR);  
      169.     return CString(rValue.bstrVal);  
      170. }  
      171. ////////////////////////////////////////////////////////////////////////  
      172. ///Function:    SetRowHeight  
      173. ///Description: 设置行高  
      174. ///Call:        IndexToString() 从(x,y)坐标形式转化为“A1”格式字符串  
      175. ///Input:       int row 单元格所在行  
      176. ////////////////////////////////////////////////////////////////////////  
      177. void COptExcel::SetRowHeight(int row, CString height)  
      178. {  
      179.     int col = 1;  
      180.     range=sheet.GetRange(COleVariant(IndexToString(row,col)),COleVariant(IndexToString(row,col)));  
      181.     range.SetRowHeight(COleVariant(height));  
      182. }  
      183. ////////////////////////////////////////////////////////////////////////  
      184. ///Function:    SetColumnWidth  
      185. ///Description: 设置列宽  
      186. ///Call:        IndexToString() 从(x,y)坐标形式转化为“A1”格式字符串  
      187. ///Input:       int col 要设置列宽的列  
      188. ///             CString 宽值  
      189. ////////////////////////////////////////////////////////////////////////  
      190. void COptExcel::SetColumnWidth(int col,CString width)  
      191. {  
      192.     int row = 1;  
      193.     range=sheet.GetRange(COleVariant(IndexToString(row,col)),COleVariant(IndexToString(row,col)));  
      194.     range.SetColumnWidth(COleVariant(width));  
      195. }  
      196.   
      197. ////////////////////////////////////////////////////////////////////////  
      198. ///Function:    SetRowHeight  
      199. ///Description: 设置行高  
      200. ///Call:        IndexToString() 从(x,y)坐标形式转化为“A1”格式字符串  
      201. ///Input:       int row 单元格所在行  
      202. ////////////////////////////////////////////////////////////////////////  
      203. CString COptExcel::GetColumnWidth(int col)  
      204. {  
      205.     int row = 1;  
      206.     range=sheet.GetRange(COleVariant(IndexToString(row,col)),COleVariant(IndexToString(row,col)));  
      207.     VARIANT width = range.GetColumnWidth();  
      208.     CString strwidth;  
      209.     strwidth.Format(CString((LPCSTR)(_bstr_t)(_variant_t)width));  
      210.     return strwidth;  
      211. }  
      212.   
      213. ////////////////////////////////////////////////////////////////////////  
      214. ///Function:    GetRowHeight  
      215. ///Description: 设置行高  
      216. ///Call:        IndexToString() 从(x,y)坐标形式转化为“A1”格式字符串  
      217. ///Input:       int row 要设置行高的行  
      218. ///             CString 宽值  
      219. ////////////////////////////////////////////////////////////////////////  
      220. CString COptExcel::GetRowHeight(int row)  
      221. {  
      222.     int col = 1;  
      223.     range=sheet.GetRange(COleVariant(IndexToString(row,col)),COleVariant(IndexToString(row,col)));  
      224.     VARIANT height = range.GetRowHeight();  
      225.     CString strheight;  
      226.     strheight.Format(CString((LPCSTR)(_bstr_t)(_variant_t)height));  
      227.     return strheight;  
      228. }  
      229.   
      230.   
      231. ////////////////////////////////////////////////////////////////////////  
      232. ///Function:    IndexToString  
      233. ///Description: 得到的单元格在EXCEL中的定位名称字符串  
      234. ///Input:       int row 单元格所在行  
      235. ///             int col 单元格所在列  
      236. ///Return:      CString 单元格在EXCEL中的定位名称字符串  
      237. ////////////////////////////////////////////////////////////////////////  
      238. CString COptExcel::IndexToString( int row, int col )   
      239. {   
      240.     CString strResult;  
      241.     if( col > 26 )   
      242.     {   
      243.         strResult.Format(_T("%c%c%d"),'A' + (col-1)/26-1,'A' + (col-1)%26,row);  
      244.     }   
      245.     else   
      246.     {   
      247.         strResult.Format(_T("%c%d"), 'A' + (col-1)%26,row);  
      248.     }   
      249.     return strResult;  
      250. }   
      251.   
      252. ////////////////////////////////////////////////////////////////////////  
      253. ///Function:    LastLineIndex  
      254. ///Description: 得到表格总第一个空行的索引  
      255. ///Return:      int 空行的索引号  
      256. ////////////////////////////////////////////////////////////////////////  
      257. int COptExcel::LastLineIndex()   
      258. {   
      259.     int i,j,flag=0;  
      260.     CString str;  
      261.     for(i=1;;i++)  
      262.     {  
      263.         flag = 0;  
      264.         //粗略统计,认为前列都没有数据即为空行  
      265.         for(j=1;j<=5;j++)  
      266.         {  
      267.             str.Format(_T("%s"),this->GetCellValue(i,j).Trim());  
      268.             if(str.Compare(_T(""))!=0)  
      269.             {  
      270.                 flag = 1;  
      271.                 break;  
      272.             }  
      273.               
      274.         }  
      275.         if(flag==0)  
      276.             return i;  
      277.           
      278.     }  
      279. }  
      280.    
  • 相关阅读:
    微信卡券领用中的问题
    abp的开发20180425
    typescript 接口的新认识
    Jquery构建Form表单Post提交数据的简单方法
    EF使用时异常:对一个或多个实体的验证失败。有关详细信息
    VS快捷键简单记录
    比较和排序 IComparable And IComparer
    wpf全局异常
    MailBee的简单使用
    json数据的获取(网络摘抄)
  • 原文地址:https://www.cnblogs.com/huhewei/p/6216986.html
Copyright © 2011-2022 走看看