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

- 选择MFC扩展DLL。

- 在“类视图”---“添加类”---在MFC中选择“TypeLib中的MFC类”,按如图所示选择,并添加对应的类
PS:由于我电脑上安装的是office2010,所以对应的Excel版本号是14.0,各位可以根据自己的情况选择。 - 删除这六个类的头文件中的第一句,如图,并将头文件添加到“stdafx.h"中


- 修改字符集,vs2010默认生成的是使用unicode字符集,这里我们把它修改为”使用多字节字符集“,这样能避免很多不必要的麻烦。

- 接下来进行编译,正常情况下会出现如下错误:
这时候定位到警告处,在函数名之前加上下划线就OK了。如图:
这样编译就没什么问题了。 接下就是直接添加导出函数来,这里我偷个懒直接到dllmain.cpp这个文件里面加了,大家可以根据自己的习惯来。
extern "C" _declspec(dllexport) void ReadExcel(const CString& strPath,const CString& strFlag, const vector<CString>& vTarget,vector<CString>& vOutTarget)
{
CApplication _app;
CWorkbook _book;
CWorkbooks _books; CWorksheet _sheet;
CWorksheets _sheets;
CRange _rang; if (!_app.CreateDispatch(_T("Excel.Application")))
{
MessageBox(NULL,_T("Error!Creat Excel Application Server Faile!"),_T("Creat Excel Application Server"),MB_ICONERROR);
exit();
}
_books = _app.get_Workbooks();
_book = _books.Add(_variant_t(strPath)); _sheets = _book.get_Worksheets();
_sheet = _sheets.get_Item(_variant_t("电力电缆井")); //获取行列数
CRange _usedRang;
_usedRang.AttachDispatch(_sheet.get_UsedRange(),TRUE);
_rang.AttachDispatch(_usedRang.get_Columns(),TRUE);
long nColumn = _rang.get_Count();//列
_rang.ReleaseDispatch();
_rang.AttachDispatch(_usedRang.get_Rows(),TRUE);
long nRow = _rang.get_Count();//行
_rang.ReleaseDispatch();
_usedRang.ReleaseDispatch();
//遍历
_rang.AttachDispatch(_sheet.get_Cells(),TRUE);//获取所有单元格
CString str;
long nCurRow = ;
long nCurColumn = ;
//获取关键字所在的行列号
for (long i = ; i <= nRow; ++i)
{
for (long j = ; j <= nColumn; ++j)
{
CRange _currentRang;
_currentRang.AttachDispatch(_rang.get_Item(COleVariant((long)i),COleVariant((long)j)).pdispVal,TRUE);
COleVariant vResult = _currentRang.get_Value2(); if (VT_BSTR == vResult.vt)//字符串
{
str = vResult.bstrVal;
}
else if (VT_INT==vResult.vt)
{
str.Format(_T("%d"),vResult.pintVal);
}
else if (VT_R8==vResult.vt)//8字节数字
{
str.Format(_T("%f"),vResult.dblVal);
}
else if (VT_DATE==vResult.vt)//时间格式
{
SYSTEMTIME st;
VariantTimeToSystemTime(vResult.date,&st);
}
else if (VT_EMPTY==vResult.vt)//空单元格
{
str = "(NULL)";
}
_currentRang.ReleaseDispatch();
if (strFlag==str)//直接使用goto语句跳出双重循环
{
nCurRow = i;
nCurColumn = j;
goto LOOPOUT;
}
}
} LOOPOUT:
vector<long> vNTarget;//目标列所在的列号
for (long i = ;i <= nColumn;++i)
{
CRange _currentRang;
_currentRang.AttachDispatch(_rang.get_Item(COleVariant((long)),COleVariant((long)i)).pdispVal,TRUE);
COleVariant vResult = _currentRang.get_Value2(); if (VT_BSTR == vResult.vt)//字符串
{
str = vResult.bstrVal;
}
else if (VT_INT==vResult.vt)
{
str.Format(_T("%d"),vResult.pintVal);
}
else if (VT_R8==vResult.vt)//8字节数字
{
str.Format(_T("%f"),vResult.dblVal);
}
else if (VT_DATE==vResult.vt)//时间格式
{
SYSTEMTIME st;
VariantTimeToSystemTime(vResult.date,&st);
}
else if (VT_EMPTY==vResult.vt)//空单元格
{
str = "(NULL)";
}
_currentRang.ReleaseDispatch();
//对取出来的str和目标str进行配对
for (vector<CString>::size_type j = ;j != vTarget.size(); ++j)
{
if (vTarget.at(j)==str)
{
vNTarget.push_back(i);
break;
}
}
}
//接下来根据获取的行号nCurRow和列号vNTarget来读取指定内容
for (vector<CString>::size_type i = ; i != vTarget.size(); ++i)
{
CRange _currentRang;
_currentRang.AttachDispatch(_rang.get_Item(COleVariant((long)nCurRow),COleVariant((long)vNTarget.at(i))).pdispVal,TRUE);
COleVariant vResult = _currentRang.get_Value2(); if (VT_BSTR == vResult.vt)//字符串
{
str = vResult.bstrVal;
}
else if (VT_INT==vResult.vt)
{
str.Format(_T("%d"),vResult.pintVal);
}
else if (VT_R8==vResult.vt)//8字节数字
{
str.Format(_T("%f"),vResult.dblVal);
}
else if (VT_DATE==vResult.vt)//时间格式
{
SYSTEMTIME st;
VariantTimeToSystemTime(vResult.date,&st);
}
else if (VT_EMPTY==vResult.vt)//空单元格
{
str = "(NULL)";
}
_currentRang.ReleaseDispatch();
vOutTarget.push_back(str);
} _book.ReleaseDispatch();
_books.ReleaseDispatch();
151 _app.Quit();_app.ReleaseDispatch();
}
上述函数就是打开路径strPath的Excel文件,并通过标志符strFlag找到要读取的行,通过vTarget找到要读取的列,将读取的内容输出到vOutTarget中。这里我是默认表格的第一行就是存放的表头,大家可以根据自己的实际情况进行调整。- 接下来再添加一个关于更新(即写某个单元格的函数)
extern "C" _declspec(dllexport) void UpdateExcel(const CString& strPath,const CString& strFlag,const vector<CString>& vTarget,const vector<CString>& vInTarget)
{
CApplication _app;
CWorkbook _book;
CWorkbooks _books; CWorksheet _sheet;
CWorksheets _sheets;
CRange _rang; if (!_app.CreateDispatch(_T("Excel.Application")))
{
MessageBox(NULL,_T("Error!Creat Excel Application Server Faile!"),_T("Creat Excel Application Server"),MB_ICONERROR);
exit();
}
_books = _app.get_Workbooks();
_book = _books.Add(_variant_t(strPath)); _sheets = _book.get_Worksheets();
_sheet = _sheets.get_Item(_variant_t("电力电缆井")); //获取行列数
CRange _usedRang;
_usedRang.AttachDispatch(_sheet.get_UsedRange(),TRUE);
_rang.AttachDispatch(_usedRang.get_Columns(),TRUE);
long nColumn = _rang.get_Count();//列
_rang.ReleaseDispatch();
_rang.AttachDispatch(_usedRang.get_Rows(),TRUE);
long nRow = _rang.get_Count();//行
_rang.ReleaseDispatch();
_usedRang.ReleaseDispatch();
//遍历
_rang.AttachDispatch(_sheet.get_Cells(),TRUE);//获取所有单元格
CString str;
long nCurRow = ;
long nCurColumn = ;
//获取关键字所在的行列号
for (long i = ; i <= nRow; ++i)
{
for (long j = ; j <= nColumn; ++j)
{
CRange _currentRang;
_currentRang.AttachDispatch(_rang.get_Item(COleVariant((long)i),COleVariant((long)j)).pdispVal,TRUE);
COleVariant vResult = _currentRang.get_Value2(); if (VT_BSTR == vResult.vt)//字符串
{
str = vResult.bstrVal;
}
else if (VT_INT==vResult.vt)
{
str.Format(_T("%d"),vResult.pintVal);
}
else if (VT_R8==vResult.vt)//8字节数字
{
str.Format(_T("%f"),vResult.dblVal);
}
else if (VT_DATE==vResult.vt)//时间格式
{
SYSTEMTIME st;
VariantTimeToSystemTime(vResult.date,&st);
}
else if (VT_EMPTY==vResult.vt)//空单元格
{
str = "(NULL)";
}
_currentRang.ReleaseDispatch();
if (strFlag==str)//直接使用goto语句跳出双重循环
{
nCurRow = i;
nCurColumn = j;
goto LOOPOUT;
}
}
} LOOPOUT:
vector<long> vNTarget;//目标列所在的列号
for (long i = ;i <= nColumn;++i)
{
CRange _currentRang;
_currentRang.AttachDispatch(_rang.get_Item(COleVariant((long)),COleVariant((long)i)).pdispVal,TRUE);
COleVariant vResult = _currentRang.get_Value2(); if (VT_BSTR == vResult.vt)//字符串
{
str = vResult.bstrVal;
}
else if (VT_INT==vResult.vt)
{
str.Format(_T("%d"),vResult.pintVal);
}
else if (VT_R8==vResult.vt)//8字节数字
{
str.Format(_T("%f"),vResult.dblVal);
}
else if (VT_DATE==vResult.vt)//时间格式
{
SYSTEMTIME st;
VariantTimeToSystemTime(vResult.date,&st);
}
else if (VT_EMPTY==vResult.vt)//空单元格
{
str = "(NULL)";
}
_currentRang.ReleaseDispatch();
//对取出来的str和目标str进行配对
for (vector<CString>::size_type j = ;j != vTarget.size(); ++j)
{
if (vTarget.at(j)==str)
{
vNTarget.push_back(i);
break;
}
}
}
//更新指定的单元格
for (vector<CString>::size_type i = ; i != vInTarget.size(); ++i)
{
_rang.put_Item(COleVariant(nCurRow),COleVariant(vNTarget.at(i)),COleVariant(vInTarget.at(i)));
}_book.SaveCopyAs(COleVariant(strPath));
_book.put_Saved(TRUE);
_app.put_Visible(FALSE);
_book.ReleaseDispatch();
_books.ReleaseDispatch(); _app.Quit()
_app.ReleaseDispatch();}
参数的设置和上一个函数差不多。 - 接下来编译的时候,正常情况下会有一点小问题。这个问题如果你是基于对话框的MFC程序貌似是不会出现的,只有创建DLL或者ActiveX控件才会出现。
这个问题也是烦恼了我好久,解决方法是先在文件头导入一个lib
在编译,运气好的话就没什么问题了。运气不好还会出下如下问题。
这个时候我们修改下项目属性
把我标出来的选项改为否应该就没什么问题了。 - 最后编译完成通过。这样dll和lib就都生成好了,大家可以尽情的使用了。
- 差不多就这样了,至于其他的问题,比如如果直接创建的是基于对话框的MFc程序的话就更简单了。跟着步骤走就完事了。最后我是一个菜鸟,如果有什么问题也欢迎大家指教。
VS2010对Excel操作---DLL向的更多相关文章
- Excel操作 Microsoft.Office.Interop.Excel.dll的使用
----转载: http://www.cnblogs.com/lanjun/archive/2012/06/17/2552920.html 先说说题外话,前段时间近一个月,我一直在做单据导入功能,其中 ...
- MFC -- Excel操作简介(基于VS2010)
一.添加与 Excel 操作相关的头文件 项目 -> 类向导,在右上方有一个下拉栏,选择其中的 类型库中的MFC类(T),即可看到下图所示界面,选择“文件”选项,然后在下方的位置选项中添加本地文 ...
- Npoi导入导出Excel操作
之前公司的一个物流商系统需要实现对订单的批量导入和导出,翻阅了一些资料,最后考虑使用NPOI实现这个需求. 在winform上面实现excel操作:http://www.cnblogs.com/Cal ...
- Excel 操作类
转载:http://www.cnblogs.com/fellowcheng/archive/2010/08/21/1805158.html ExcelHelper(Excel2007) Code hi ...
- VS2010 EXCEL2010 表格操作的编程实现
参考: http://blog.csdn.net/wxfy1977/article/details/3847450(另外一种实现方式,数据库方式) http://blog.csdn.net/evkj2 ...
- C#封装的VSTO Excel操作类
自己在用的Excel操作类,因为经常在工作中要操作Excel文件,可是使用vba实现起来实在是不方便,而且编写也很困难,拼接一个字符串都看的眼花. 这个时候C#出现了,发现使用C#来操作Excel非常 ...
- Excel报表开发(本节主要讲述导出到Excel操作)
一.Excel导入到GridView以及数据库操作比较简单,这儿不做过多讲解,需要注意的有二点: 1.设置IMEX=1将强制混合数据转换为文本. 2.解决Excel驱动程序默认读取8行:将" ...
- Delphi Excel 操作大全
Delphi Excel 操作大全 (一) 使用动态创建的方法首先创建 Excel 对象,使用ComObj:var ExcelApp: Variant;ExcelApp := CreateOleObj ...
- VS2010 C++环境下DLL和LIB文件目录及名称修改
VS2010 C++环境下DLL和LIB文件目录及名称修改 转自:http://blog.csdn.net/archielau/article/details/8507581 DLL工程,Debug版 ...
随机推荐
- HDU 2546 饭卡
http://acm.hdu.edu.cn/showproblem.php?pid=2546 呆呆. 饭卡 Time Limit: 5000/1000 MS (Java/Others) Memo ...
- Bash字符串的处理
# 定义几个变量用于测试目的 FILE_NAME="/usr/local/app/world.txt" TIME_NOW="`date +"%Y%m%d%H%M ...
- HDOJ/HDU 2140 Michael Scofield's letter(字符转换~)
Problem Description I believe many people are the fans of prison break. How clever Michael is!! In o ...
- HTC仅限拨打紧急电话
问题描述: 我手上有台 HTC One V 没碰没撞,突然打不出电话,信号上显示一个叉,屏幕上显示“仅限拨打紧急电话” 解决办法:经百度,原来很多HTC机子都有这种情况,幸好不是硬件坏了,只需按以下步 ...
- 研磨设计模式解析及python代码实现——(一)简单工厂模式
最近在学设计模式,正巧书之前学了些python,但用的还不是很成熟.<研磨设计模式>书上只给了java代码,本着以练手为目标,我照着书上打了一遍java代码,在仔细体会其思想后,将其写成了 ...
- PC-全国的 DNS服务商
我们请选第2个.然后根据自己的省市来填写..我复制了下版主给的网站 北京:202.96.199.133 202.96.0.133 202.106.0.20 202.106.148.1 202.97.1 ...
- BFS+状态压缩 hdu-1885-Key Task
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1885 题目意思: 给一个矩阵,给一个起点多个终点,有些点有墙不能通过,有些点的位置有门,需要拿到相应 ...
- CSS 列表 你知道吗
CSS 列表属性允许你放置.改变列表项标志,或者将图像作为列表项标志.CSS 列表从某种意义上讲,不是描述性的文本的任何内容都可以认为是列表.人口普查.太阳系.家谱.参观菜单,甚至你的所有朋友都可以表 ...
- mysql添加用户权限
MySQL性能调优my.cnf详解 //登录MYSQLmysql -u root -p//创建用户insert into mysql.user(Host,User,Password) values(‘ ...
- [D3] 7. Quantitative Scales
# Quantitative Scales var colorScale = d3.scale.quantile() .domain([d3.max(dataset) / 4, d3.max(data ...