一、加载
1、 在VC6.0里创建一个MFC工程
2、打开MFCClassWizard窗口(查看—>建立类向导),选择Automation,单击AddClass按钮,选择Froma type library...,弹出文件选择对话框,之后定位到C:\Program Files\MicrosoftOffice\OFFICE11\EXCEL.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表,并填充两个单元格的实例
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表格实例
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文件实例
1. book.SetSaved(TRUE);
4. 另存一个excel文件实例
1. book.SaveAs(COleVariant(m_filename),covOptional,
2. covOptional,covOptional,
3. long)0,
4. covOptional,covOptional,covOptional,
5. covOptional,covOptional); //与的不同,是个参数的,直接在后面加了两个covOptional成功了
5. 释放一个excel文件实例
经试验证实,不释放第二次使用excel时会中断,放在类的析构里面有时调用不到,主动调用最保险。(有没有AttachDispatch()过都要释放,否则报错)
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单元格
1. range=sheet.GetRange(COleVariant(IndexToString(row,col)),COleVariant(IndexToString(row,col)));
2. range.SetValue2(COleVariant(value));
7. 取出一个excel单元格
实现Variant数据类型转换为CString类,这个只是一个示例,转换较为简单。
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. 还有释放问题是最重要的问题:
首先变量必须全释放,无论当初是否绑定过;
其次,程序释放和程序关闭的顺序必须是
附录(操作类源码):
1. app.Quit();
2. app.ReleaseDispatch();
3. 如果顺如颠倒如下:
4. app.ReleaseDispatch();
5. app.Quit();
6. 出现的后果是程序关闭后,excel进程仍然运行,所以无法正常打开程序曾经打开excel表格。
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. "初始化Com失败!"));
29. return;
30. }
31.
32. //验证office文件是否可以正确运行
33.
34. if( !app.CreateDispatch(_T("Excel.Application")) )
35. {
36. "无法创建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. "文件不存在"));
84. return false;
85. }
86. //接口指针
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. 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. 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. 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. long(1)), COleVariant(long(1)))).pdispVal);
152. 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. 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. 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. "%c%c%d"),'A' + (col-1)/26-1,'A' + (col-1)%26,row);
244. }
245. else
246. {
247. "%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. "%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.