VS2010对Excel操作---DLL向

最近公司有个项目要用到Excel的操作,于是自己就对VC中关于Excel的操作进行整理了下。而这里我是直接做成DLL方便他人调用的。

  1. 创建一个MFC Dll项目。

  2. 选择MFC扩展DLL。
  3. 在“类视图”---“添加类”---在MFC中选择“TypeLib中的MFC类”,按如图所示选择,并添加对应的类PS:由于我电脑上安装的是office2010,所以对应的Excel版本号是14.0,各位可以根据自己的情况选择。
  4. 删除这六个类的头文件中的第一句,如图,并将头文件添加到“stdafx.h"中
  5. 修改字符集,vs2010默认生成的是使用unicode字符集,这里我们把它修改为”使用多字节字符集“,这样能避免很多不必要的麻烦。
  6. 接下来进行编译,正常情况下会出现如下错误:这时候定位到警告处,在函数名之前加上下划线就OK了。如图:这样编译就没什么问题了。
  7. 接下就是直接添加导出函数来,这里我偷个懒直接到dllmain.cpp这个文件里面加了,大家可以根据自己的习惯来。
      1 extern "C" _declspec(dllexport) void ReadExcel(const CString& strPath,const CString& strFlag, const vector<CString>& vTarget,vector<CString>& vOutTarget)
      2 {
      3     CApplication _app;
      4     CWorkbook _book;
      5     CWorkbooks _books;
      6
      7     CWorksheet _sheet;
      8     CWorksheets _sheets;
      9     CRange _rang;
     10
     11     if (!_app.CreateDispatch(_T("Excel.Application")))
     12     {
     13         MessageBox(NULL,_T("Error!Creat Excel Application Server Faile!"),_T("Creat Excel Application Server"),MB_ICONERROR);
     14         exit(1);
     15     }
     16     _books = _app.get_Workbooks();
     17     _book = _books.Add(_variant_t(strPath));
     18
     19     _sheets = _book.get_Worksheets();
     20     _sheet = _sheets.get_Item(_variant_t("电力电缆井"));
     21
     22     //获取行列数
     23     CRange _usedRang;
     24     _usedRang.AttachDispatch(_sheet.get_UsedRange(),TRUE);
     25     _rang.AttachDispatch(_usedRang.get_Columns(),TRUE);
     26     long nColumn = _rang.get_Count();//列
     27     _rang.ReleaseDispatch();
     28     _rang.AttachDispatch(_usedRang.get_Rows(),TRUE);
     29     long nRow = _rang.get_Count();//行
     30     _rang.ReleaseDispatch();
     31     _usedRang.ReleaseDispatch();
     32     //遍历
     33     _rang.AttachDispatch(_sheet.get_Cells(),TRUE);//获取所有单元格
     34     CString str;
     35     long nCurRow = 0;
     36     long nCurColumn = 0;
     37     //获取关键字所在的行列号
     38     for (long i = 1; i <= nRow; ++i)
     39     {
     40         for (long j = 1; j <= nColumn; ++j)
     41         {
     42             CRange _currentRang;
     43             _currentRang.AttachDispatch(_rang.get_Item(COleVariant((long)i),COleVariant((long)j)).pdispVal,TRUE);
     44             COleVariant vResult = _currentRang.get_Value2();
     45
     46             if (VT_BSTR == vResult.vt)//字符串
     47             {
     48                 str = vResult.bstrVal;
     49             }
     50             else if (VT_INT==vResult.vt)
     51             {
     52                 str.Format(_T("%d"),vResult.pintVal);
     53             }
     54             else if (VT_R8==vResult.vt)//8字节数字
     55             {
     56                 str.Format(_T("%f"),vResult.dblVal);
     57             }
     58             else if (VT_DATE==vResult.vt)//时间格式
     59             {
     60                 SYSTEMTIME st;
     61                 VariantTimeToSystemTime(vResult.date,&st);
     62             }
     63             else if (VT_EMPTY==vResult.vt)//空单元格
     64             {
     65                 str = "(NULL)";
     66             }
     67             _currentRang.ReleaseDispatch();
     68             if (strFlag==str)//直接使用goto语句跳出双重循环
     69             {
     70                 nCurRow = i;
     71                 nCurColumn = j;
     72                 goto LOOPOUT;
     73             }
     74         }
     75     }
     76
     77 LOOPOUT:
     78     vector<long> vNTarget;//目标列所在的列号
     79     for (long i = 1;i <= nColumn;++i)
     80     {
     81         CRange _currentRang;
     82         _currentRang.AttachDispatch(_rang.get_Item(COleVariant((long)1),COleVariant((long)i)).pdispVal,TRUE);
     83         COleVariant vResult = _currentRang.get_Value2();
     84
     85         if (VT_BSTR == vResult.vt)//字符串
     86         {
     87             str = vResult.bstrVal;
     88         }
     89         else if (VT_INT==vResult.vt)
     90         {
     91             str.Format(_T("%d"),vResult.pintVal);
     92         }
     93         else if (VT_R8==vResult.vt)//8字节数字
     94         {
     95             str.Format(_T("%f"),vResult.dblVal);
     96         }
     97         else if (VT_DATE==vResult.vt)//时间格式
     98         {
     99             SYSTEMTIME st;
    100             VariantTimeToSystemTime(vResult.date,&st);
    101         }
    102         else if (VT_EMPTY==vResult.vt)//空单元格
    103         {
    104             str = "(NULL)";
    105         }
    106         _currentRang.ReleaseDispatch();
    107         //对取出来的str和目标str进行配对
    108         for (vector<CString>::size_type j = 0;j != vTarget.size(); ++j)
    109         {
    110             if (vTarget.at(j)==str)
    111             {
    112                 vNTarget.push_back(i);
    113                 break;
    114             }
    115         }
    116     }
    117     //接下来根据获取的行号nCurRow和列号vNTarget来读取指定内容
    118     for (vector<CString>::size_type i = 0; i != vTarget.size(); ++i)
    119     {
    120         CRange _currentRang;
    121         _currentRang.AttachDispatch(_rang.get_Item(COleVariant((long)nCurRow),COleVariant((long)vNTarget.at(i))).pdispVal,TRUE);
    122         COleVariant vResult = _currentRang.get_Value2();
    123
    124         if (VT_BSTR == vResult.vt)//字符串
    125         {
    126             str = vResult.bstrVal;
    127         }
    128         else if (VT_INT==vResult.vt)
    129         {
    130             str.Format(_T("%d"),vResult.pintVal);
    131         }
    132         else if (VT_R8==vResult.vt)//8字节数字
    133         {
    134             str.Format(_T("%f"),vResult.dblVal);
    135         }
    136         else if (VT_DATE==vResult.vt)//时间格式
    137         {
    138             SYSTEMTIME st;
    139             VariantTimeToSystemTime(vResult.date,&st);
    140         }
    141         else if (VT_EMPTY==vResult.vt)//空单元格
    142         {
    143             str = "(NULL)";
    144         }
    145         _currentRang.ReleaseDispatch();
    146         vOutTarget.push_back(str);
    147     }
    148
    149     _book.ReleaseDispatch();
    150     _books.ReleaseDispatch();
    151     _app.ReleaseDispatch();
    152     _app.Quit();
    153 }上述函数就是打开路径strPath的Excel文件,并通过标志符strFlag找到要读取的行,通过vTarget找到要读取的列,将读取的内容输出到vOutTarget中。这里我是默认表格的第一行就是存放的表头,大家可以根据自己的实际情况进行调整。
  8. 接下来再添加一个关于更新(即写某个单元格的函数)

      1 extern "C" _declspec(dllexport) void UpdateExcel(const CString& strPath,const CString& strFlag,const vector<CString>& vTarget,const vector<CString>& vInTarget)
      2 {
      3     CApplication _app;
      4     CWorkbook _book;
      5     CWorkbooks _books;
      6
      7     CWorksheet _sheet;
      8     CWorksheets _sheets;
      9     CRange _rang;
     10
     11     if (!_app.CreateDispatch(_T("Excel.Application")))
     12     {
     13         MessageBox(NULL,_T("Error!Creat Excel Application Server Faile!"),_T("Creat Excel Application Server"),MB_ICONERROR);
     14         exit(1);
     15     }
     16     _books = _app.get_Workbooks();
     17     _book = _books.Add(_variant_t(strPath));
     18
     19     _sheets = _book.get_Worksheets();
     20     _sheet = _sheets.get_Item(_variant_t("电力电缆井"));
     21
     22     //获取行列数
     23     CRange _usedRang;
     24     _usedRang.AttachDispatch(_sheet.get_UsedRange(),TRUE);
     25     _rang.AttachDispatch(_usedRang.get_Columns(),TRUE);
     26     long nColumn = _rang.get_Count();//列
     27     _rang.ReleaseDispatch();
     28     _rang.AttachDispatch(_usedRang.get_Rows(),TRUE);
     29     long nRow = _rang.get_Count();//行
     30     _rang.ReleaseDispatch();
     31     _usedRang.ReleaseDispatch();
     32     //遍历
     33     _rang.AttachDispatch(_sheet.get_Cells(),TRUE);//获取所有单元格
     34     CString str;
     35     long nCurRow = 0;
     36     long nCurColumn = 0;
     37     //获取关键字所在的行列号
     38     for (long i = 1; i <= nRow; ++i)
     39     {
     40         for (long j = 1; j <= nColumn; ++j)
     41         {
     42             CRange _currentRang;
     43             _currentRang.AttachDispatch(_rang.get_Item(COleVariant((long)i),COleVariant((long)j)).pdispVal,TRUE);
     44             COleVariant vResult = _currentRang.get_Value2();
     45
     46             if (VT_BSTR == vResult.vt)//字符串
     47             {
     48                 str = vResult.bstrVal;
     49             }
     50             else if (VT_INT==vResult.vt)
     51             {
     52                 str.Format(_T("%d"),vResult.pintVal);
     53             }
     54             else if (VT_R8==vResult.vt)//8字节数字
     55             {
     56                 str.Format(_T("%f"),vResult.dblVal);
     57             }
     58             else if (VT_DATE==vResult.vt)//时间格式
     59             {
     60                 SYSTEMTIME st;
     61                 VariantTimeToSystemTime(vResult.date,&st);
     62             }
     63             else if (VT_EMPTY==vResult.vt)//空单元格
     64             {
     65                 str = "(NULL)";
     66             }
     67             _currentRang.ReleaseDispatch();
     68             if (strFlag==str)//直接使用goto语句跳出双重循环
     69             {
     70                 nCurRow = i;
     71                 nCurColumn = j;
     72                 goto LOOPOUT;
     73             }
     74         }
     75     }
     76
     77 LOOPOUT:
     78     vector<long> vNTarget;//目标列所在的列号
     79     for (long i = 1;i <= nColumn;++i)
     80     {
     81         CRange _currentRang;
     82         _currentRang.AttachDispatch(_rang.get_Item(COleVariant((long)1),COleVariant((long)i)).pdispVal,TRUE);
     83         COleVariant vResult = _currentRang.get_Value2();
     84
     85         if (VT_BSTR == vResult.vt)//字符串
     86         {
     87             str = vResult.bstrVal;
     88         }
     89         else if (VT_INT==vResult.vt)
     90         {
     91             str.Format(_T("%d"),vResult.pintVal);
     92         }
     93         else if (VT_R8==vResult.vt)//8字节数字
     94         {
     95             str.Format(_T("%f"),vResult.dblVal);
     96         }
     97         else if (VT_DATE==vResult.vt)//时间格式
     98         {
     99             SYSTEMTIME st;
    100             VariantTimeToSystemTime(vResult.date,&st);
    101         }
    102         else if (VT_EMPTY==vResult.vt)//空单元格
    103         {
    104             str = "(NULL)";
    105         }
    106         _currentRang.ReleaseDispatch();
    107         //对取出来的str和目标str进行配对
    108         for (vector<CString>::size_type j = 0;j != vTarget.size(); ++j)
    109         {
    110             if (vTarget.at(j)==str)
    111             {
    112                 vNTarget.push_back(i);
    113                 break;
    114             }
    115         }
    116     }
    117     //更新指定的单元格
    118     for (vector<CString>::size_type i = 0; i != vInTarget.size(); ++i)
    119     {
    120         _rang.put_Item(COleVariant(nCurRow),COleVariant(vNTarget.at(i)),COleVariant(vInTarget.at(i)));
    121     }
    122     _book.ReleaseDispatch();
    123     _books.ReleaseDispatch();
    124     _app.ReleaseDispatch();
    125     _app.Quit();
    126 }参数的设置和上一个函数差不多。
  9. 接下来编译的时候,正常情况下会有一点小问题。这个问题如果你是基于对话框的MFC程序貌似是不会出现的,只有创建DLL或者ActiveX控件才会出现。这个问题也是烦恼了我好久,解决方法是先在文件头导入一个lib在编译,运气好的话就没什么问题了。运气不好还会出下如下问题。这个时候我们修改下项目属性把我标出来的选项改为否应该就没什么问题了。
  10. 最后编译完成通过。这样dll和lib就都生成好了,大家可以尽情的使用了。
  11. 差不多就这样了,至于其他的问题,比如如果直接创建的是基于对话框的MFc程序的话就更简单了。跟着步骤走就完事了。最后我是一个菜鸟,如果有什么问题也欢迎大家指教。
时间: 2024-10-05 01:21:20

VS2010对Excel操作---DLL向的相关文章

Excel操作 Microsoft.Office.Interop.Excel.dll的使用

先说说题外话,前段时间近一个月,我一直在做单据导入功能,其中就涉及到Excel操作,接触Excel后发现他的api说明并不多,好在网上有很多朋友贴出了一些代码,我在不断的挫折中吸取了很多教训,现共享出来,给大家参考. 1. 最好在客户端使用,不要在B/S服务端使用,因为会受到IIS权限和占用内存影响,多人并发操作必然完蛋 2. 需要引入两个DLL,Microsoft.Office.Interop.Excel.dll和office.dll,在加上项目的时候,会报错“类型“Microsoft.Off

利用vs2010制作C语言 dll文件,并在其它程序中调用该dll文件

一.为什么需要dll 代码复用是提高软件开发 效率的重要途径.一般而言,只要某部分代码具有通用性,就可将它构造成相对独立的功能模块并在之后的项目中重复使用.比较常见的例子是各种应用程序框架, 如ATL.MFC等,它们都以源代码的形式发布.由于这种复用是“源码级别”的,源代码完全暴露给了程序员,因而称之为“白盒复用”.“白盒复用”的缺点 比较多,总结起来有4点. 暴露了源代码: 容易与程序员的“普通”代码发生命名冲突: 多份拷贝,造成存储浪费: 更新功能模块比较困难. 实际上,以上4点概括起来就是

Word Excel 操作总结

1.与office无关使用 Aspose.Cells.dll,Aspose.Words.dll 2.使用Microsoft.Office.Interop.Excel Microsoft.Office.Interop.Word 3.打开文件 WORD: object oMissing = Missing.Value;_Application app = new Application();_Document currentDoc = null;app.Visible = false;current

C#EXCEL 操作类--C#DataToExcel帮助类

using System; using System.Diagnostics; //using Excel; namespace DotNet.Utilities {     /// <summary>     /// 操作EXCEL导出数据报表的类     /// </summary>     public class DataToExcel     {         public DataToExcel()         {         }           #reg

Excel 操作类

转载:http://www.cnblogs.com/fellowcheng/archive/2010/08/21/1805158.html ExcelHelper(Excel2007) Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ -->using System; using System.Collections.Generic; using Sys

使用VS2010命令提示窗口操作程序集强命名

说明:文中示例均以将文件置于D盘根目录(D:\)下为例. 一.查看程序集是否具有强命名 sn -T d:\LicBase.dll 若有则会显示PublicKeyToken值,反之不会. 二.给无强命名程序集添加强命名 1.创建密钥对,并将其存储在 d:\LicBase.snk 中 sn -k d:\LicBase.snk 2.反编译目标程序集 ildasm d:\LicBase.dll /out=d:\LicBase.il 3.重新编译,附带强命名参数 ilasm d:\LicBase.il /

python excel操作及网络编程

python excel操作 一:excel获取值操作 1.导入模块 import xlrd 2.打开Excel文件读取数据 data = xlrd.open_workbook('excelFile.xls') 3.使用技巧 获取一个工作表 table = data.sheets()[0]          #通过索引顺序获取 table = data.sheet_by_index(0) #通过索引顺序获取 table = data.sheet_by_name(u'Sheet1')#通过名称获取

EXCEL 操作

1.为几万行数据加序号 先在A1,A2分别输入1,2,选中A1:A2,双击A2右下角那个小方块. 数据有多少行就会自动填充多少行(要求:B列数据连续) 2.统计一列中单元格的值等于某个值的单元格的个数 =COUNTIF(A1:A10,123) 计算列A1至A10单元格中的值等于123的单元格的个数 EXCEL 操作,布布扣,bubuko.com

C#Excel操作

1.添加对Microsoft.Office.Interop.Excel程序集引用 2.创建Excel应用对象 Microsoft.Office.Interop.Excel.Application excelApp = new Microsoft.Office.Interop.Excel.Application(); 3.Excel操作