1. 單擊“添加引用”對話框的“COM”選項卡,找到“Microsoft Excel 11 Object Library”,按“確定”。
注意:Microsoft Excel 11 Object Library中Excel 11 的版本與安裝的OFFICE版本有關。
在編程之前還需要引入命名空間using Microsoft.Office.Interop.Excel;
注意:有的機器上需要用using Excel;我猜這也跟OFFICE版本有關;
這樣C#就可以正確識別Excel對象了。
大體過程是:
讀
Excel.Application app = new Excel.ApplicationClass()
Excel.Workbook wb = null;
Excel.Worksheet ws = null;
Excel.Range range = null;
string filepath = null;
wb = app.Workbooks.Open()
ws = (Excel.Worksheet)wb.Worksheet[sheetname];
range = (Excel.Range)ws.Cells[4,3];
string result = range.Value2.ToString();
寫
range.Value2 = "hello"
range.EntireColumn.AutoFit();
封裝代碼如下:
2. using System;
3. using System.Collections.Generic;
4. using System.Text;
5. using System.Reflection;
6. using Microsoft.Office.Core;
7. using Microsoft.Office.Interop.Excel;
8. using System.IO;
9.
10. namespace ExcelX.ExcelLib
11. {
12. /// <summary>
13. /// Excel 操作代理
14. /// </summary>
15. public class ExcelAgent
16. {
17. private ApplicationClass _app = null;
18. private _Workbook _wb = null;
19. private _Worksheet _ws = null;
20. private string _filePath = "";
21. private int _shIndex = 0; // 1 based index
22.
23. public event EventHandler ExcelExceptionOccured;
24.
25. /// <summary>
26. /// 當前Sheet
27. /// </summary>
28. public int SheetIndex { get { return this._shIndex; } }
29.
30. /// <summary>
31. /// 當前文件名
32. /// </summary>
33. public string FileName { get { return this._filePath; } }
34.
35. #region private operations
36. /// <summary>
37. /// 打開App
38. /// </summary>
39. private void OpenApp()
40. {
41. this._app = new ApplicationClass();
42. this._app.Visible = false;
43. }
44.
45. /// <summary>
46. /// 釋放資源
47. /// </summary>
48. /// <param name="o"></param>
49. private void ReleaseCom(object o)
50. {
51. try
52. {
53. System.Runtime.InteropServices.Marshal.ReleaseComObject(o);//強制釋放一個對象
54. }
55. catch { }
56. finally
57. {
58. o = null;
59. }
60. }
61.
62. /// <summary>
63. /// 檢查App
64. /// </summary>
65. private bool CheckApp()
66. {
67. if (this._app == null)
68. {
69. if (this.ExcelExceptionOccured != null)
70. {
71. this.ExcelExceptionOccured(this, new ErrorEventArgs(new Exception("Application對象未初始化")));
72. }
73. return false;
74. }
75.
76. return true;
77. }
78.
79. /// <summary>
80. /// 檢查Book
81. /// </summary>
82. private bool CheckWorkBook()
83. {
84. if (this._wb == null)
85. {
86. if (this.ExcelExceptionOccured != null)
87. {
88. this.ExcelExceptionOccured(this, new ErrorEventArgs(new Exception("Workbook對象未初始化")));
89. }
90.
91. return false;
92. }
93.
94. return true;
95. }
96.
97. /// <summary>
98. /// 檢查Sheet
99. /// </summary>
100. private bool CheckSheet()
101. {
102. if (this._ws == null)
103. {
104. if (this.ExcelExceptionOccured != null)
105. {
106. this.ExcelExceptionOccured(this, new ErrorEventArgs(new Exception("Worksheet對象未初始化")));
107. }
108.
109. return false;
110. }
111.
112. return true;
113. }
114. #endregion
115.
116. #region basic operation
117. /// <summary>
118. /// 打開文件
119. /// </summary>
120. /// <param name="filePath"></param>
121. public void Open(string filePath)
122. {
123. // Check Application
124. if (!this.CheckApp()) return;
125.
126. // Open workbook
127. this._filePath = filePath;
128. this._wb = this._app.Workbooks._Open(filePath, Missing.Value, Missing.Value, Missing.Value, Missing.Value
129. , Missing.Value, Missing.Value, Missing.Value, Missing.Value
130. , Missing.Value, Missing.Value, Missing.Value, Missing.Value);
131.
132. // set default sheet
133. this.SetCurrentSheet(1);
134. }
135.
136. /// <summary>
137. /// 自動打開Excel對象
138. /// </summary>
139. public ExcelAgent()
140. {
141. this.OpenApp();
142. }
143.
144. /// <summary>
145. /// 打開excel文件
146. /// </summary>
147. /// <param name="filePath"></param>
148. public ExcelAgent(string filePath)
149. {
150. this.OpenApp();
151. this.Open(filePath);
152. }
153.
154. /// <summary>
155. /// 保存當前文檔
156. /// </summary>
157. public void Save()
158. {
159. // check workbook
160. if (!this.CheckWorkBook()) return;
161.
162. // save the book
163. this._wb.Save();
164.
165. }
166.
167. /// <summary>
168. /// 另存當前文檔
169. /// </summary>
170. /// <param name="filePath"></param>
171. public void Save(string filePath)
172. {
173. // check workbook
174. if (!this.CheckWorkBook()) return;
175.
176. // save work book
177. this._filePath = filePath;
178. bool b = this._app.DisplayAlerts;
179. this._app.DisplayAlerts = false;
180.
181. // save work book
182. this._wb.SaveAs(this._filePath, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, XlSaveAsAccessMode.xlNoChange,
183. Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value);
184.
185. this._app.DisplayAlerts = b;
186. }
187.
188. /// <summary>
189. /// 關閉當前操作
190. /// </summary>
191. public void Close()
192. {
193. if (this._app == null) return;
194. if (this._wb != null)
195. {
196. this._wb.Close(false, Missing.Value, Missing.Value);
197. ReleaseCom(this._wb);
198. this._wb = null;
199. }
200. this._app.Quit();
201. ReleaseCom(this._app);
202. this._app = null;
203.
204. }
205.
206. /// <summary>
207. /// 設置當前工作Sheet(序號:從1記起)
208. /// </summary>
209. /// <param name="sheetIndex"></param>
210. public void SetCurrentSheet(int sheetIndex)
211. {
212. // check workbook
213. if (!this.CheckWorkBook()) return;
214.
215. // set sheet object
216. this._shIndex = sheetIndex;
217. this._ws = (_Worksheet)this._wb.Worksheets[sheetIndex];
218. }
219.
220. /// <summary>
221. /// 設置當前工作Sheet(序號:從1記起)
222. /// </summary>
223. /// <param name="sheetIndex"></param>
224. public void SetCurrentSheet(string SheetName)
225. {
226. // check workbook
227. if (!this.CheckWorkBook()) return;
228.
229. // set sheet object
230. this._ws = (_Worksheet)this._wb.Worksheets[SheetName];
231. this._shIndex = this._ws.Index;
232. }
233.
234. /// <summary>
235. /// 刪除一個工作表
236. /// </summary>
237. /// <param name="SheetName"></param>
238. public void DeleteSheet()
239. {
240. // check workbook
241. if (!this.CheckSheet()) return;
242.
243. this._ws.Delete();
244. }
245.
246. /// <summary>
247. /// 改名
248. /// </summary>
249. /// <param name="newName"></param>
250. public void RenameSheet(string newName)
251. {
252. // check workbook
253. if (!this.CheckSheet()) return;
254.
255. this._ws.Name = newName;
256. }
257.
258. /// <summary>
259. /// 創(chuàng)建Sheet
260. /// </summary>
261. /// <param name="newName"></param>
262. public void CreateSheet(string newName)
263. {
264. // check workbook
265. if (!this.CheckWorkBook()) return;
266.
267. this._wb.Worksheets.Add(Missing.Value, Missing.Value, Missing.Value, Missing.Value);
268. }
269.
270. /// <summary>
271. /// 獲取數(shù)量
272. /// </summary>
273. /// <returns></returns>
274. public int GetSheetCount()
275. {
276. // check workbook
277. if (!this.CheckWorkBook()) return -1;
278.
279. return this._wb.Worksheets.Count;
280. }
281. #endregion
282.
283. #region sheet operation
284. /// <summary>
285. /// 設置單元值
286. /// </summary>
287. /// <param name="x"></param>
288. /// <param name="y"></param>
289. /// <param name="value"></param>
290. public void SetCellValue(int x, int y, object value)
291. {
292. if (!this.CheckSheet()) return;
293. this._ws.Cells[x, y] = value;
294. }
295.
296. /// <summary>
297. /// 合并單元格
298. /// </summary>
299. /// <param name="x1"></param>
300. /// <param name="y1"></param>
301. /// <param name="x2"></param>
302. /// <param name="y2"></param>
303. public void UniteCells(int x1, int y1, int x2, int y2)
304. {
305. if (!this.CheckSheet()) return;
306. this._ws.get_Range(this._ws.Cells[x1, y1], this._ws.Cells[x2, y2]).Merge(Type.Missing);
307. }
308.
309. /// <summary>
310. /// 將內存中數(shù)據(jù)表格插入到Excel指定工作表的指定位置 為在使用模板時控制格式時使用一
311. /// </summary>
312. /// <param name="dt"></param>
313. /// <param name="startX"></param>
314. /// <param name="startY"></param>
315. public void InsertTable(System.Data.DataTable dt, int startX, int startY)
316. {
317. if (!this.CheckSheet()) return;
318.
319. for (int i = 0; i <= dt.Rows.Count - 1; i++)
320. {
321. for (int j = 0; j <= dt.Columns.Count - 1; j++)
322. {
323. this._ws.Cells[startX + i, j + startY] = dt.Rows[i][j].ToString();
324.
325. }
326.
327. }
328.
329. }
330.
331. /// <summary>
332. /// 獲取單元格值
333. /// </summary>
334. /// <param name="cellName"></param>
335. /// <returns></returns>
336. public object GetCellValue(string cellName)
337. {
338. if (!this.CheckSheet()) return null;
339.
340. Range range = this._ws.get_Range(cellName, Type.Missing);
341.
342. return range.Value2;
343. }
344.
345. /// <summary>
346. /// 獲取單元格值
347. /// </summary>
348. /// <param name="row"></param>
349. /// <param name="col"></param>
350. /// <returns></returns>
351. public object GetCellValue(int row, int col)
352. {
353. if (!this.CheckSheet()) return null;
354.
355. Range range = (Range)this._ws.Cells[row, col];
356.
357. return range.Value2;
358. }
359.
360. public string GetStringValue(string cellName)
361. {
362. object val = this.GetCellValue(cellName);
363. string result = "";
364.
365. if (val != null) result = val.ToString();
366.
367. return result;
368. }
369.
370. public string GetStringValue(int row, int col)
371. {
372. object val = this.GetCellValue(row, col);
373. string result = "";
374.
375. if (val != null) result = val.ToString();
376.
377. return result;
378. }
379.
380. public double GetDoubleValue(string cellName)
381. {
382. object val = this.GetCellValue(cellName);
383. string result = "";
384.
385. if (val != null) result = val.ToString();
386.
387. double number = 0d;
388. if (double.TryParse(result, out number))
389. {
390. number = double.Parse(result);
391. }
392. else
393. {
394. number = 0d;
395. }
396.
397. return number;
398. }
399.
400. public double GetDoubleValue(int row, int col)
401. {
402. object val = this.GetCellValue(row, col);
403. string result = "";
404.
405. if (val != null) result = val.ToString();
406.
407. double number = 0d;
408. if (double.TryParse(result, out number))
409. {
410. number = double.Parse(result);
411. }
412. else
413. {
414. number = 0d;
415. }
416.
417. return number;
418. }
419.
420. #endregion
421. }
422. }
要:本文介紹了Excel對象、C#中的受管代碼和非受管代碼,并介紹了COM組件在.NET環(huán)境中的使用。
關鍵詞:受管代碼;非受管代碼;Excel對象;動態(tài)連接庫
0 引言
Excel是微軟公司辦公自動化套件中的一個軟件,他主要是用來處理電子表格。Excel以其功能強大,界面友好等受到了許多用戶的歡迎。在設計應用系統(tǒng)時,對于不同的用戶,他們對于打印的需求是不一樣的,如果要使得程序中的打印功能適用于每一個用戶,可以想象程序設計是十分復雜的。由于Excel表格的功能強大,又由于幾乎每一臺機器都安裝了它,如果把程序處理的結果放到Excel表格中,這樣每一個用戶就可以根據(jù)自己的需要在Excel中定制自己的打印。這樣不僅使得程序設計簡單,而且又滿足了諸多用戶的要求,更加實用了。那么用Visual C#如何調用Excel,如何又把數(shù)據(jù)存放到Excel表格中?本文就來探討上述問題的解決辦法。
1 Excel對象
微軟的Excel對象模型包括了128個不同的對象,從矩形,文本框等簡單的對象到透視表,圖表等復雜的對象.下面我們簡單介紹一下其中最重要,也是用得最多的四個對象。
(1) Application對象。Application對象處于Excel對象層次結構的頂層,表示Excel自身的運行環(huán)境。 (2) Workbook對象。Workbook對象直接地處于Application對象的下層,表示一個Excel工作薄文件。
(3) Worksheet對象。Worksheet對象包含于Workbook對象,表示一個Excel工作表。
(4) Range對象。Range對象包含于Worksheet對象,表示Excel工作表中的一個或多個單元格。
2 C#中的受管代碼和非受管代碼
在.NET公用語言框架內運行的程序為受管代碼。受管代碼在程序中所有類型都受到嚴格檢查,沒有指針,對內存的管理完全由運行系統(tǒng)控制。受控狀態(tài)下,編寫程序更為容易,且更少出錯,我們可以花更多的時間在解決實際問題上而不是在計算機語言問題上。相對而言,那些在.NET框架外運行的程序為非受管代碼。比如:COM組件、ActiveX組件、Win32 API函數(shù)、指針運算等。C#編程中在某些特定情況下,需要運用非受管代碼,例如,要利用一個成熟的COM組件,或者調用一個API函數(shù),或者用指針去編寫實時/高效程序等。
3 Visual C#中調用Excel的COM組件
一個.NET組件事實上是一個.NET下的DLL,它包含的不僅是運行程序本身,更重要的是包含這個DLL的描述信息(Meta Data,即元數(shù)據(jù)),而一個COM組件是用其類庫(TLB)儲存其描述信息。這些COM組件都是非受管代碼,要在Visual C#中使用這些非受管代碼的COM組件,就必須把他們轉換成受管代碼的.NET組件。所以在用Visual C#調用Excel表格之前,必須完成從COM組件的非受管代碼到受管代碼的類庫的轉換。
3.1 將Excel的COM組件轉換為.NET組件
在項目中打開Add Reference對話框,選擇COM欄,之后在COM列表中找到“Microsoft Excel 9.0 Object Library”(Office 2000),然后將其加入到項目的References中即可。Visual C#.NET會自動產(chǎn)生相應的.NET組件文件,以后即可正常使用。
這個轉換形成.NET組件不能單獨使用,它不過是以前的COM組件的一個外層包裝,在.NET中可以通過這個外層包裝去發(fā)現(xiàn)原來的COM組件并調用其相應的界面函數(shù)。所以它必須與原來的COM組件一起起作用。
3.2 Visual C#打開Excel表格
事實上,在C#中使用一個經(jīng)轉換的COM組件和使用任何一個其它.NET組件完全一樣??梢杂胣ew關鍵字創(chuàng)建一個經(jīng)轉換的COM組件,然后再像使用任何一個其它C#對象一樣使用這個組件對象。
在轉換后的.NET組件中定義了一個命名空間Excel,在此命名空間中封裝了一個類Application,這個類和啟動Excel表格有非常重要的關系,在Visual C#中,只需要下列三行代碼就可以完成打開Excel表格的工作,具體如下:
Excel.Application excel = new Excel.Application ();//引用Excel對象
excel.Application.Workbooks.Add ( true );//引用Excel工作簿
excel.Visible = true ;//使Excel可視
但此時的Excel表格是一個空的表格,沒有任何內容,下面就來介紹如何往Excel表格中輸入數(shù)據(jù)。
3.3 往Excel表格中輸入數(shù)據(jù)
在命名空間"Excel"中,還定義了一個類"Cell",這個類所代表的就是Excel表格中的一個單元格。通過給"Cell"賦值,從而實現(xiàn)往Excel表格中輸入相應的數(shù)據(jù),下列代碼功能是打開Excel表格,并且往表格輸入一些數(shù)據(jù)。
Excel.Application excel = new Excel.Application () ;
excel.Application.Workbooks.Add ( true ) ;
excel.Cells[ 1 , 1 ] = "First Row First Column" ;
excel.Cells[ 1 , 2 ] = "First Row Second Column" ;
excel.Cells[ 2 , 1 ] = "Second Row First Column" ;
excel.Cells[ 2 , 2 ] = "Second Row Second Column" ;
excel.Visible = true ;
3.4 實例
下面實例在C#中連接Oracle數(shù)據(jù)庫(Name),從表(TableName)中讀取數(shù)據(jù),并寫入Excel.
string cnString="Provider=msdaora.1;Data source=Name; ";
cnString=cnString+"user id=UserName;password=Password";
try
{
OleDbConnection cn=new OleDbConnection (cnString);
cn.Open ();
try
{
string s="select * from Name.TableName";
OleDbCommand cmd=new OleDbCommand (s,cn);
OleDbDataReader dr=cmd.ExecuteReader ();
Excel.Application xlApp = new Excel.Application();
if(xlApp==null){MessageBox.Show ("Can’t open Excel!");return;}
xlApp.Application .Workbooks .Add (true);
int row=2,fieldcount;
fieldcount=dr.FieldCount ;
for(int col=0;col<fieldcount;col++) xlApp.Cells [1,col+1]=dr.GetName(col);
while (dr.Read ())
{
for(int col=0;col<fieldcount;col++)
xlApp.Cells [row,col+1]=dr.GetValue(col).ToString();
row++;
}
xlApp.Visible =true;
xlApp=null;
}
catch(Exception ex ){MessageBox.Show (ex.Message );}
finally {cn.Close();}
}
catch(Exception ex){MessageBox.Show (ex.Message );}
}
}
3.5安裝一個使用COM組件的.NET程序
如果要將這樣的程序安裝運行在另一臺機器上,那么除了安裝運行程序外,還做三件事。
首先,是安裝.NET運行系統(tǒng)。因為任何一個.NET程序都不能離開.NET運行系統(tǒng)去獨立運行。
其次,所調用的COM組件必須要安裝在目標機器上。本例中大多數(shù)目標機器上都裝有Microsoft Office的Excel,一般不會有這個問題。但如果是另一個用戶自定義的COM組件,那么這個COM組件在運行.NET程序之前必須先安裝好。
最后,轉換后的.NET組件DLL文件要安裝在目標機器上。因為.NET組件不需要在Windows Registry中注冊,所以最簡單的方法是將.NET組件DLL文件拷貝到運行程序目錄下。如果此.NET組件被多個.NET程序共享,可以將其安裝在.NET公用組件區(qū)中,從而可被任何一個.NET組件使用。只有當一個.NET組件參與了事務處理時,才需要將它注冊為一個COM+組件。因為.NET仍然用傳統(tǒng)的COM+機制來處理事務的提交、回滾等。
4 小結
通過以上討論,我們知道了在C#中,如何使用Excel的COM組件。需要注意的是,Excel對象包含的許多內容我們沒有介紹,在使用過程中需要我們不斷學習。也使我們了解了在C#中如何使用COM組件。
參考文獻:
[1] 劉洪成 C#高級編程 清華大學出版社 2003.7工作 187~200
C#中創(chuàng)建、打開、讀取、寫入、保存Excel的一般性代碼
首先,在引用的COM中找到Microsoft Excel 11.0 Object Library,添加。
using System;
using System.Reflection; // 引用這個才能使用Missing字段
using Excel;
namespace CExcel1
{
class Class1
{
[STAThread]
static void Main(string[] args)
{
//創(chuàng)建Application對象
Excel.Application xApp=new Excel.ApplicationClass();
xApp.Visible=true;
//得到WorkBook對象, 可以用兩種方式之一: 下面的是打開已有的文件
Excel.Workbook xBook=xApp.Workbooks._Open(@"D:/Sample.xls",
Missing.Value,Missing.Value,Missing.Value,Missing.Value
,Missing.Value,Missing.Value,Missing.Value,Missing.Value
,Missing.Value,Missing.Value,Missing.Value,Missing.Value);
//xBook=xApp.Workbooks.Add(Missing.Value);//新建文件的代碼
//指定要操作的Sheet,兩種方式:
Excel.Worksheet xSheet=(Excel.Worksheet)xBook.Sheets[1];
//Excel.Worksheet xSheet=(Excel.Worksheet)xApp.ActiveSheet;
//讀取數(shù)據(jù),通過Range對象
Excel.Range rng1=xSheet.get_Range("A1",Type.Missing);
Console.WriteLine(rng1.Value2);
//讀取,通過Range對象,但使用不同的接口得到Range
Excel.Range rng2=(Excel.Range)xSheet.Cells[3,1];
Console.WriteLine(rng2.Value2);
//寫入數(shù)據(jù)
Excel.Range rng3=xSheet.get_Range("C6",Missing.Value);
rng3.Value2="Hello";
rng3.Interior.ColorIndex=6; //設置Range的背景色
//保存方式一:保存WorkBook
xBook.SaveAs(@"D:/CData.xls",
Missing.Value,Missing.Value,Missing.Value,Missing.Value,Missing.Value,
Excel.XlSaveAsAccessMode.xlNoChange,Missing.Value,Missing.Value,Missing.Value,
Missing.Value,Missing.Value);
//保存方式二:保存WorkSheet
xSheet.SaveAs(@"D:/CData2.xls",
Missing.Value,Missing.Value,Missing.Value,Missing.Value,
Missing.Value,Missing.Value,Missing.Value,Missing.Value,Missing.Value);
//保存方式三
xBook.Save();
xSheet=null;
xBook=null;
xApp.Quit(); //這一句是非常重要的,否則Excel對象不能從內存中退出
xApp=null;
}
}
}
C#如何向EXCEL寫入數(shù)據(jù)
我按著微軟技術支持網(wǎng)上的方法寫入數(shù)據(jù):使用“自動化”功能逐單元格傳輸數(shù)據(jù),代碼如下:
// Start a new workbook in Excel.
m_objExcel = new Excel.Application();
m_objBooks = (Excel.Workbooks)m_objExcel.Workbooks;
m_objBook = (Excel._Workbook)(m_objBooks.Add(m_objOpt));
// Add data to cells in the first worksheet in the new workbook.
m_objSheets = (Excel.Sheets)m_objBook.Worksheets;
m_objSheet = (Excel._Worksheet)(m_objSheets.get_Item(1));
m_objRange = m_objSheet.get_Range("A1", m_objOpt);
m_objRange.Value = "Last Name";
m_objRange = m_objSheet.get_Range("B1", m_objOpt);
m_objRange.Value = "First Name";
m_objRange = m_objSheet.get_Range("A2", m_objOpt);
m_objRange.Value = "Doe";
m_objRange = m_objSheet.get_Range("B2", m_objOpt);
m_objRange.Value = "John";
// Apply bold to cells A1:B1.
m_objRange = m_objSheet.get_Range("A1", "B1");
m_objFont = m_objRange.Font;
m_objFont.Bold=true;
// Save the Workbook and quit Excel.
m_objBook.SaveAs(m_strSampleFolder + "Book1.xls", m_objOpt, m_objOpt,
m_objOpt, m_objOpt, m_objOpt, Excel.XlSaveAsAccessMode.xlNoChange,
m_objOpt, m_objOpt, m_objOpt, m_objOpt);
m_objBook.Close(false, m_objOpt, m_objOpt);
m_objExcel.Quit();
EXCEL表用c#來讀
using System; using System.IO; using System.Web; using System.Web.SessionState; using NickLee.Common.ExcelLite; namespace excel1 { /// <summary> /// excel 的摘要說明。 /// </summary> public class excel { public excel() { // // TODO: 在此處添加構造函數(shù)邏輯 // fileName = HttpContext.Current.Server.MapPath(".")+"//temp//"+g+".xls"; } private Guid g = Guid.NewGuid(); private string fileName; private ExcelFile ec =new ExcelFile(); /// <summary> /// 從model中復制模版到temp中 /// </summary> /// <param name="modelName">只需傳入模版的名字即可(注意是字符串)</param> public void copyModel(string modelName) { string MName = HttpContext.Current.Server.MapPath(".")+"//model//"+modelName; File.Copy(MName,fileName); } /// <summary> /// 設置EXCEL表中的字表個數(shù),字表在這個表中統(tǒng)一命名為“續(xù)表”+數(shù)字序號 /// </summary> /// <param name="sheetnum">設置字表的個數(shù)</param> public void setSheets(int sheetnum) { ec.LoadXls(fileName); ExcelWorksheet wsx =ec.Worksheets[0]; for (int y=0;y<sheetnum;y++) { int num = y+1; ec.Worksheets.AddCopy("續(xù)表"+num,wsx); } } /// <summary> /// 給EXCEL表的各個字段設置值 /// </summary> /// <param name="sheetnum">表的序號,注意表是以“0”開始的</param> /// <param name="x">對應于EXCEL的最左邊的數(shù)字列</param> /// <param name="y">對應于EXCEL的最上面的字母列</param> /// <param name="values">需要寫入的值</param> public void setValues(int sheetnum,int x,int y,string values) { ec.Worksheets[sheetnum].Cells[x,y].Value=values;; } /// <summary> /// 保存函數(shù),要是文件中有相同的文件就要刪除了,///然后重新寫入相同文件名的新EXCEL表 /// </summary> public void saveFile() { if(File.Exists(fileName)) { File.Delete(fileName); ec.SaveXls(fileName); } else { ec.SaveXls(fileName); } } /// <summary> /// 顯示的EXCEL表格 /// </summary> public void showFile() { HttpContext.Current.Response.Charset =System.Text.Encoding.Default.WebName; HttpContext.Current.Response.ContentType ="application/vnd.ms-excel"; HttpContext.Current.Response.ContentEncoding =System.Text.Encoding.UTF8; HttpContext.Current.Response.WriteFile(fileName); HttpContext.Current.Response.End(); } } }C#讀寫Excel文檔(---續(xù)C#讀寫Word文件)距離上次寫那篇《也說C#實現(xiàn)對Word文件讀寫》已經(jīng)一年多時間了,一直想小結一些C#讀寫Excel文件的相關技巧,畢竟Excel打印更為方便和實用,一個是Excel打印輸出編碼比Word文件打印數(shù)據(jù)簡單些,另一個是Excel本身對數(shù)據(jù)超強計算處理功能;趕巧最近項目又涉及Excel報表統(tǒng)計打印的問題,所以在把其中的一些技術記錄下來與大家一起分析討論,次篇主要涉及兩個方面內容:1、 讀寫Excel文件A、設計Excel模版B、打開一個目標文件并且讀取模版內容C、目標文件按格式寫入需要的數(shù)據(jù)D、保存并且輸出目標Excel文件2、 Excel對象資源釋放,這個在以前項目沒有注意徹底釋放使用到Excel對象,對客戶計算機資源造成一定浪費,此次得到徹底解決。下面是一個Excel打印輸出的Demo1、 創(chuàng)建一個叫DemoExcel的項目2、 引用COM,包括:Microsoft.Excel.x.0.Object.Library,Microsoft.Office.x.0.Object.Library建議安裝正版OFFICE,而且版本在11.0以上(Office2003以上),引用以上兩個Com后,在項目引用欄發(fā)現(xiàn)多了Excel、Microsoft.Office.Core,VBIDE三個 Library.3、 下面建立一些模擬的數(shù)據(jù),此處為街鎮(zhèn)信息
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Microsoft.Office.Interop.Excel;
using Microsoft.Office.Core;
using System.IO;
using System.Reflection;namespace DemoExcel
{
public partial class Form1 : Form
{
private object missing = Missing.Value;
private Microsoft.Office.Interop.Excel.Application ExcelRS;
private Microsoft.Office.Interop.Excel.Workbook RSbook;
private Microsoft.Office.Interop.Excel.Worksheet RSsheet;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
// TODO: 這行代碼將數(shù)據(jù)加載到表“dataSet1.STREET”中。您可以根據(jù)需要移動或移除它。
this.sTREETTableAdapter.Fill(this.dataSet1.STREET);
}
private void button1_Click(object sender, EventArgs e)
{
string OutFilePath = System.Windows.Forms.Application.StartupPath + @" emp.xls";
string TemplateFilePath = System.Windows.Forms.Application.StartupPath + @"模版.xls";
PrintInit(TemplateFilePath,OutFilePath);
}
//Excle輸出前初始化
/// <summary>
///
/// </summary>
/// <returns></returns>
public bool PrintInit(string templetFile, string outputFile)
{
try
{
if (templetFile == null)
{
MessageBox.Show("Excel模板文件路徑不能為空!");
return false;
}
if (outputFile == null)
{
MessageBox.Show("輸出Excel文件路徑不能為空!");
return false;
}
//把模版文件templetFile拷貝到目輸出文件outputFile中,并且目標文件可以改寫
System.IO.File.Copy(templetFile, outputFile, true);
if (this.ExcelRS != null)
ExcelRS = null;
//實例化ExcelRS對象
ExcelRS = new Microsoft.Office.Interop.Excel.ApplicationClass();
//打開目標文件outputFile
RSbook = ExcelRS.Workbooks.Open(outputFile, missing, missing, missing, missing, missing,
missing, missing, missing, missing, missing, missing, missing, missing, missing);
//設置第一個工作溥
RSsheet = (Microsoft.Office.Interop.Excel.Worksheet)RSbook.Sheets.get_Item(1);
//激活當前工作溥
RSsheet.Activate();
在當前工作溥寫入內容
for (int i = 0; i < this.dataGridView1.RowCount; i++)
{
RSsheet.Cells[3 + i, 1] = this.dataGridView1[0, i].Value.ToString();
RSsheet.Cells[3 + i, 2] = this.dataGridView1[1, i].Value.ToString();
RSsheet.Cells[3 + i, 3] = this.dataGridView1[2, i].Value.ToString();
}
//保存目標文件
RSbook.Save();
//設置DisplayAlerts
ExcelRS.DisplayAlerts = false;
ExcelRS.Visible = true;
//ExcelRS.DisplayAlerts = true;
//釋放對象
RSsheet = null;
RSbook = null;
ExcelRS = null;
//釋放內存
GcCollect();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
return false;
}
return true;
}
public void GcCollect()
{
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
}特別說明:
a、引用Microsoft.Office.Interop.Excel;using Microsoft.Office.Core;
b、(關鍵)在程序中特別釋放Excel資源的時候既要設置對象為null,又要強制回收內存,這樣才能徹底回收資源。
c、引用的Office組建版本是個敏感問題,不同版本之間有細微差別,需要分別處理。
第二種方法:
1. 單擊“添加引用”對話框的“COM”選項卡,找到“Microsoft Excel 11 Object Library”,按“確定”。
注意:Microsoft Excel 11 Object Library中Excel 11 的版本與安裝的OFFICE版本有關。
在編程之前還需要引入命名空間using Microsoft.Office.Interop.Excel;
注意:有的機器上需要用using Excel;我猜這也跟OFFICE版本有關;
這樣C#就可以正確識別Excel對象了。
大體過程是:
讀
Excel.Application app = new Excel.ApplicationClass()
Excel.Workbook wb = null;
Excel.Worksheet ws = null;
Excel.Range range = null;
string filepath = null;
wb = app.Workbooks.Open()
ws = (Excel.Worksheet)wb.Worksheet[sheetname];
range = (Excel.Range)ws.Cells[4,3];
string result = range.Value2.ToString();
寫
range.Value2 = "hello"
range.EntireColumn.AutoFit();
封裝代碼如下:
2. using System;
3. using System.Collections.Generic;
4. using System.Text;
5. using System.Reflection;
6. using Microsoft.Office.Core;
7. using Microsoft.Office.Interop.Excel;
8. using System.IO;
9.
10. namespace ExcelX.ExcelLib
11. {
12. /// <summary>
13. /// Excel 操作代理
14. /// </summary>
15. public class ExcelAgent
16. {
17. private ApplicationClass _app = null;
18. private _Workbook _wb = null;
19. private _Worksheet _ws = null;
20. private string _filePath = "";
21. private int _shIndex = 0; // 1 based index
22.
23. public event EventHandler ExcelExceptionOccured;
24.
25. /// <summary>
26. /// 當前Sheet
27. /// </summary>
28. public int SheetIndex { get { return this._shIndex; } }
29.
30. /// <summary>
31. /// 當前文件名
32. /// </summary>
33. public string FileName { get { return this._filePath; } }
34.
35. #region private operations
36. /// <summary>
37. /// 打開App
38. /// </summary>
39. private void OpenApp()
40. {
41. this._app = new ApplicationClass();
42. this._app.Visible = false;
43. }
44.
45. /// <summary>
46. /// 釋放資源
47. /// </summary>
48. /// <param name="o"></param>
49. private void ReleaseCom(object o)
50. {
51. try
52. {
53. System.Runtime.InteropServices.Marshal.ReleaseComObject(o);//強制釋放一個對象
54. }
55. catch { }
56. finally
57. {
58. o = null;
59. }
60. }
61.
62. /// <summary>
63. /// 檢查App
64. /// </summary>
65. private bool CheckApp()
66. {
67. if (this._app == null)
68. {
69. if (this.ExcelExceptionOccured != null)
70. {
71. this.ExcelExceptionOccured(this, new ErrorEventArgs(new Exception("Application對象未初始化")));
72. }
73. return false;
74. }
75.
76. return true;
77. }
78.
79. /// <summary>
80. /// 檢查Book
81. /// </summary>
82. private bool CheckWorkBook()
83. {
84. if (this._wb == null)
85. {
86. if (this.ExcelExceptionOccured != null)
87. {
88. this.ExcelExceptionOccured(this, new ErrorEventArgs(new Exception("Workbook對象未初始化")));
89. }
90.
91. return false;
92. }
93.
94. return true;
95. }
96.
97. /// <summary>
98. /// 檢查Sheet
99. /// </summary>
100. private bool CheckSheet()
101. {
102. if (this._ws == null)
103. {
104. if (this.ExcelExceptionOccured != null)
105. {
106. this.ExcelExceptionOccured(this, new ErrorEventArgs(new Exception("Worksheet對象未初始化")));
107. }
108.
109. return false;
110. }
111.
112. return true;
113. }
114. #endregion
115.
116. #region basic operation
117. /// <summary>
118. /// 打開文件
119. /// </summary>
120. /// <param name="filePath"></param>
121. public void Open(string filePath)
122. {
123. // Check Application
124. if (!this.CheckApp()) return;
125.
126. // Open workbook
127. this._filePath = filePath;
128. this._wb = this._app.Workbooks._Open(filePath, Missing.Value, Missing.Value, Missing.Value, Missing.Value
129. , Missing.Value, Missing.Value, Missing.Value, Missing.Value
130. , Missing.Value, Missing.Value, Missing.Value, Missing.Value);
131.
132. // set default sheet
133. this.SetCurrentSheet(1);
134. }
135.
136. /// <summary>
137. /// 自動打開Excel對象
138. /// </summary>
139. public ExcelAgent()
140. {
141. this.OpenApp();
142. }
143.
144. /// <summary>
145. /// 打開excel文件
146. /// </summary>
147. /// <param name="filePath"></param>
148. public ExcelAgent(string filePath)
149. {
150. this.OpenApp();
151. this.Open(filePath);
152. }
153.
154. /// <summary>
155. /// 保存當前文檔
156. /// </summary>
157. public void Save()
158. {
159. // check workbook
160. if (!this.CheckWorkBook()) return;
161.
162. // save the book
163. this._wb.Save();
164.
165. }
166.
167. /// <summary>
168. /// 另存當前文檔
169. /// </summary>
170. /// <param name="filePath"></param>
171. public void Save(string filePath)
172. {
173. // check workbook
174. if (!this.CheckWorkBook()) return;
175.
176. // save work book
177. this._filePath = filePath;
178. bool b = this._app.DisplayAlerts;
179. this._app.DisplayAlerts = false;
180.
181. // save work book
182. this._wb.SaveAs(this._filePath, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, XlSaveAsAccessMode.xlNoChange,
183. Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value);
184.
185. this._app.DisplayAlerts = b;
186. }
187.
188. /// <summary>
189. /// 關閉當前操作
190. /// </summary>
191. public void Close()
192. {
193. if (this._app == null) return;
194. if (this._wb != null)
195. {
196. this._wb.Close(false, Missing.Value, Missing.Value);
197. ReleaseCom(this._wb);
198. this._wb = null;
199. }
200. this._app.Quit();
201. ReleaseCom(this._app);
202. this._app = null;
203.
204. }
205.
206. /// <summary>
207. /// 設置當前工作Sheet(序號:從1記起)
208. /// </summary>
209. /// <param name="sheetIndex"></param>
210. public void SetCurrentSheet(int sheetIndex)
211. {
212. // check workbook
213. if (!this.CheckWorkBook()) return;
214.
215. // set sheet object
216. this._shIndex = sheetIndex;
217. this._ws = (_Worksheet)this._wb.Worksheets[sheetIndex];
218. }
219.
220. /// <summary>
221. /// 設置當前工作Sheet(序號:從1記起)
222. /// </summary>
223. /// <param name="sheetIndex"></param>
224. public void SetCurrentSheet(string SheetName)
225. {
226. // check workbook
227. if (!this.CheckWorkBook()) return;
228.
229. // set sheet object
230. this._ws = (_Worksheet)this._wb.Worksheets[SheetName];
231. this._shIndex = this._ws.Index;
232. }
233.
234. /// <summary>
235. /// 刪除一個工作表
236. /// </summary>
237. /// <param name="SheetName"></param>
238. public void DeleteSheet()
239. {
240. // check workbook
241. if (!this.CheckSheet()) return;
242.
243. this._ws.Delete();
244. }
245.
246. /// <summary>
247. /// 改名
248. /// </summary>
249. /// <param name="newName"></param>
250. public void RenameSheet(string newName)
251. {
252. // check workbook
253. if (!this.CheckSheet()) return;
254.
255. this._ws.Name = newName;
256. }
257.
258. /// <summary>
259. /// 創(chuàng)建Sheet
260. /// </summary>
261. /// <param name="newName"></param>
262. public void CreateSheet(string newName)
263. {
264. // check workbook
265. if (!this.CheckWorkBook()) return;
266.
267. this._wb.Worksheets.Add(Missing.Value, Missing.Value, Missing.Value, Missing.Value);
268. }
269.
270. /// <summary>
271. /// 獲取數(shù)量
272. /// </summary>
273. /// <returns></returns>
274. public int GetSheetCount()
275. {
276. // check workbook
277. if (!this.CheckWorkBook()) return -1;
278.
279. return this._wb.Worksheets.Count;
280. }
281. #endregion
282.
283. #region sheet operation
284. /// <summary>
285. /// 設置單元值
286. /// </summary>
287. /// <param name="x"></param>
288. /// <param name="y"></param>
289. /// <param name="value"></param>
290. public void SetCellValue(int x, int y, object value)
291. {
292. if (!this.CheckSheet()) return;
293. this._ws.Cells[x, y] = value;
294. }
295.
296. /// <summary>
297. /// 合并單元格
298. /// </summary>
299. /// <param name="x1"></param>
300. /// <param name="y1"></param>
301. /// <param name="x2"></param>
302. /// <param name="y2"></param>
303. public void UniteCells(int x1, int y1, int x2, int y2)
304. {
305. if (!this.CheckSheet()) return;
306. this._ws.get_Range(this._ws.Cells[x1, y1], this._ws.Cells[x2, y2]).Merge(Type.Missing);
307. }
308.
309. /// <summary>
310. /// 將內存中數(shù)據(jù)表格插入到Excel指定工作表的指定位置 為在使用模板時控制格式時使用一
311. /// </summary>
312. /// <param name="dt"></param>
313. /// <param name="startX"></param>
314. /// <param name="startY"></param>
315. public void InsertTable(System.Data.DataTable dt, int startX, int startY)
316. {
317. if (!this.CheckSheet()) return;
318.
319. for (int i = 0; i <= dt.Rows.Count - 1; i++)
320. {
321. for (int j = 0; j <= dt.Columns.Count - 1; j++)
322. {
323. this._ws.Cells[startX + i, j + startY] = dt.Rows[i][j].ToString();
324.
325. }
326.
327. }
328.
329. }
330.
331. /// <summary>
332. /// 獲取單元格值
333. /// </summary>
334. /// <param name="cellName"></param>
335. /// <returns></returns>
336. public object GetCellValue(string cellName)
337. {
338. if (!this.CheckSheet()) return null;
339.
340. Range range = this._ws.get_Range(cellName, Type.Missing);
341.
342. return range.Value2;
343. }
344.
345. /// <summary>
346. /// 獲取單元格值
347. /// </summary>
348. /// <param name="row"></param>
349. /// <param name="col"></param>
350. /// <returns></returns>
351. public object GetCellValue(int row, int col)
352. {
353. if (!this.CheckSheet()) return null;
354.
355. Range range = (Range)this._ws.Cells[row, col];
356.
357. return range.Value2;
358. }
359.
360. public string GetStringValue(string cellName)
361. {
362. object val = this.GetCellValue(cellName);
363. string result = "";
364.
365. if (val != null) result = val.ToString();
366.
367. return result;
368. }
369.
370. public string GetStringValue(int row, int col)
371. {
372. object val = this.GetCellValue(row, col);
373. string result = "";
374.
375. if (val != null) result = val.ToString();
376.
377. return result;
378. }
379.
380. public double GetDoubleValue(string cellName)
381. {
382. object val = this.GetCellValue(cellName);
383. string result = "";
384.
385. if (val != null) result = val.ToString();
386.
387. double number = 0d;
388. if (double.TryParse(result, out number))
389. {
390. number = double.Parse(result);
391. }
392. else
393. {
394. number = 0d;
395. }
396.
397. return number;
398. }
399.
400. public double GetDoubleValue(int row, int col)
401. {
402. object val = this.GetCellValue(row, col);
403. string result = "";
404.
405. if (val != null) result = val.ToString();
406.
407. double number = 0d;
408. if (double.TryParse(result, out number))
409. {
410. number = double.Parse(result);
411. }
412. else
413. {
414. number = 0d;
415. }
416.
417. return number;
418. }
419.
420. #endregion
421. }
422. }