已經創建了Excel.Application對象,並打開了工作薄,現在可以遍歷工作表和單元格來獲取數據了。並不是所有的單元格都有數據,大部分都是空的,因此XmlDocument來保存取得的數據是個不錯的主意,還可以將XmlDocuemnt作爲ScriptMethod的結果返回到客戶端瀏覽器,使用JavaScript來生成表格,表現結果。根據我的經驗,即使在服務端創建表格,也只消耗Excel操作的數百分之一的時間(實際數據:Excel操作耗時22.3秒,生成表格0.06秒,差距巨大)。
可以通過以下方式遍歷工作表:
- sheets = workbook.Sheets;
- for (int i = 1; i <= sheets.Count; i++) // 注意Excel的對象數組訪問是以1爲起始滴!
- {
- Excel.Worksheet sheet = (Excel.Worksheet)sheets.get_Item(i);// 獲取工作表對象
- ......
- releaseComObject(sheet); // 釋放COM對象
- sheet = null;
- }
Excel的表格範圍從A-IV列共256列,65536行,而且很多單元格是空的,完全遍歷會消耗很多時間,因此,我們應該限定一個範圍:
- Excel.Range range = sheet.get_Range("A1", "Z128"); // 範圍爲A1到Z128,注意Excel.Range對象會產生引用計數
- Excel.Range rowRange = range.Rows; // 行對象,帶"s",會產生引用計數
- Excel.Range colRange = range.Columns; // 列對象,也會產生引用計數
- object[,] data = (object[,])range.get_Value(Type.Missing); // 一次性獲取範圍內的所有數據,注意,獲取的是值!
- for (int r = rowRange.Count; r >= 1; r--) // 使用倒序遍歷行
- {
- for ( int c = 1; c <= colRange.Count; c++ ) // 順序訪問列
- {
- if ( data[r, c] != null ) // 如果[r,c]位置的單元格沒有數據,則值爲null,這可以檢測空單元格
- {
- Excel.Range cell = (Excel.Range)range.get_Item(r, c);
- ......
- releaseComObject(cell); // 釋放引用
- cell = null;
- }
- }
- }
在Excel 2003中,通過cell.Value屬性訪問值域,在Excel 2007中,則爲cell.Value2。
對於以倒序的方式遍歷行的方式的解釋: 假設我們的XML格式如下: <WORKSHEET NAME="SheetXXX"> <ROW> <CELL>XXXXXXX</CELL> </ROW> </WORKSHEET> 由於Excel工作表數據集中在頭部,後面基本是空的,填充XML時先生成CELL元素,插入到ROW元素中,再將ROW插入到WORKSHEET元素中。當以倒序遍歷行時,如果行爲空,不包括單元格數據,則ROW的ChildNodes.Count爲0,如果這時WORKSHEET的ChildNodes爲空,表示不包含行數據,則不需要將ROW插入到WORKSHEET中。這種情況直到遇到第一個包含數據單元格的行後改變。這時,行會添加到WORKSHEET的ChildNodes中。通過這種方式,可以跳過尾部沒有數據的行,又不會略過夾在有數據的行中間的空行。
插入行元素的示例代碼如下:
- if (row_elem.ChildNodes.Count > 0 || sheet_elem.ChildNodes.Count > 0) // 有行數據或空行則插入
- {
- sheet_elem.InsertBefore(row_elem, sheet_elem.FirstChild);
- }