C#操作Excel (轉)

首先的一步就是使用Tlbimp這個工具將Excel9.0的對象庫文件Excel8.olb轉換成爲dll,這樣才能做爲.Net平臺Assembly來使用:)操作如下:

TlbImp Excel9.olb Excel.dll 

只要有了這個Excel.dll,現在我們就能使用Excel的各種操作函數了。 
下面就讓我們具體看看C#是如何使用這些東東吧。 

1. 創建一個新Excel的Application: 

Application exc 
= new Application();
if (exc == null) {
Console.WriteLine(
"ERROR: EXCEL couldn"t be started");
return 0;
}

2. 讓這個工程可見: 

exc.set_Visible(
0true); 

3. 獲取WorkBooks集合: 

Workbooks workbooks 
= exc.Workbooks; 

4. 加入新的WorkBook: 

_Workbook workbook 
= workbooks.Add(XlWBATemplate.xlWBATWorksheet, 0); 

5. 獲取WorkSheets集合: 

_Worksheet worksheet 
= (_Worksheet) sheets.get_Item(1);
if (worksheet == null) {
Console.WriteLine (
"ERROR in worksheet == null");
}

6. 給單元格設置變量: 

Range range1 
= worksheet.get_Range("C1", Missing.Value);
if (range1 == null) {
Console.WriteLine (
"ERROR: range == null");
}
const int nCells = 1;
Object[] args1 
= new Object[1];
args1[
0= nCells;
range1.GetType().InvokeMember(
"Value", BindingFlags.SetProperty, null, range1, args1);

例程: 

using System;
using System.Reflection; 
using System.Runtime.InteropServices; 
using Excel;

class Excel {
public static int Main() {
Application exc 
= new Application();
if (exc == null) {
Console.WriteLine(
"ERROR: EXCEL couldn"t be started!");
return 0;
}

exc.set_Visible(
0true); 
Workbooks workbooks 
= exc.Workbooks;
_Workbook workbook 
= workbooks.Add(XlWBATemplate.xlWBATWorksheet, 0); 
Sheets sheets 
= workbook.Worksheets;

_Worksheet worksheet 
= (_Worksheet) sheets.get_Item(1);
if (worksheet == null) {
Console.WriteLine (
"ERROR: worksheet == null");
}

Range range1 
= worksheet.get_Range("C1", Missing.Value);
if (range1 == null) {
Console.WriteLine (
"ERROR: range == null");
}
const int nCells = 1;
Object[] args1 
= new Object[1];
args1[
0= nCells;
range1.GetType().InvokeMember(
"Value", BindingFlags.SetProperty, null,range1, args1);
return 100;
}
}

現在我們來看看如何使用數組,他有些類似於設置單元格。僅僅需要的改變只是args2[
0= array2; 
const int nCell = 5;
Range range2 
= worksheet.get_Range("A1""E1");
int[] array2 = new int [nCell];
for (int i=0; i < array2.GetLength(0); i++) {
array2[i] 
= i+1;
}
Object[] args2 
= new Object[1];
args2[
0= array2;
range2.GetType().InvokeMember(
"Value", BindingFlags.SetProperty, null, range2, args2);

  大家需要了解Tlbimp這個工具的使用啊:)這個東東很有用,可以將普通Win32程序移植到.Net下面來:) 



Excel表格文檔由於其簡單易用,普遍應用於不少單位或部門,因而在編寫應用程序過程中,有時會需要對Excel文檔進行操作,最簡單的情況通常有兩種:(
1)需要獲取文檔中一些單元格的值;(2)將文檔導入至數據庫。

 

1).在操作Excel文檔之前,需要添加對Excel對象庫的引用:

引用—COM—Microsoft Excel 
11.0 Object Library(版本號可能不同)

 

2).以下代碼示意打開一個已有的Excel文檔的第一個sheet頁,獲取單元格“B1”的內容,並判斷其值是否爲“my”:


        
private void Operate(string pFileName)
        {
            Excel.Application app = new Excel.Application();//打開一個Excel應用

            if (app == null)
            {
                return
;
            }

            Workbooks wbs =
 app.Workbooks;
            _Workbook wb = wbs.Add(pFileName);//打開一個現有的工作薄

            Sheets shs = wb.Sheets;
            _Worksheet sh = (_Worksheet)shs.get_Item(1);//選擇第一個Sheet頁

            if (sh == null)
            {
                return
;
            }

            Range r = sh.get_Range("B1"
, Missing.Value);
            if (System.Convert.ToString(r.Value2).Trim().Equals("my"
))
            {
                //Do Something.

            }
        }


 

3).不少人在打開Excel應用後,對如何在使用完成後釋放它大感頭痛,在網上我找到一種方法,經過實驗證明是OK的:

        
private void ReleaseCOM(object pObj)
        {
            
try
            {
                System.Runtime.InteropServices.Marshal.ReleaseComObject(pObj);
            }
            
catch
            {
                
throw new Exception("釋放資源時發生錯誤!");
            }
            
finally
            {
                pObj 
= null;
            }
        }

有了該方法,則只要在步驟2)代碼之後添加以下代碼,就可以完成對資源的釋放:


        
private void Operate(string pFileName)
        { 
……
//釋放資源
            ReleaseCOM(sh);
            ReleaseCOM(shs);
            ReleaseCOM(wb);
            ReleaseCOM(wbs);
            app.Quit();
            ReleaseCOM(app);
        }


4).基於Excel中的函數可以編輯出相當複雜的公式,有時候在處理Excel文檔時,希望使用Excel中的公式,以下結合FREQUENCY,MATCH函數對B列計算distinct count,將其寫入B100單元格(假定有數據的行不超過100行):


        
string  count = sh.UsedRange.Rows.Count.ToString();
        Range r 
= sh.get_Range("B100",Missing.Value);
        r.Formula 
= "=SUM(IF(FREQUENCY(MATCH(B1:B" + count + ",B1:B" + count + ",0),MATCH(B1:B" + count + ",B1:B" + count + ",0))>0,1))";
        Console.WriteLine(System.Convert.ToString(r.Value2));


5).從Excel導入數據,可以先使用ODBC,以select查詢時使用“[sheet頁名稱$]”作爲“表名”,將數據以datatable形式載入到內存中,之後的事就比較簡單了,可以根據datatable逐行構造insert語句,然後插入到目標數據庫中:


        
private DataTable LoadExcel(string pPath)
        {
            
string connString = "Driver={Driver do Microsoft Excel(*.xls)};DriverId=790;SafeTransactions=0;ReadOnly=1;MaxScanRows=16;Threads=3;MaxBufferSize=2048;UserCommitSync=Yes;FIL=excel 8.0;PageTimeout=5;";
            connString 
+= "DBQ=" + pPath;
            OdbcConnection conn 
= new OdbcConnection(connString);
            OdbcCommand cmd 
= new OdbcCommand();
            cmd.Connection 
= conn;
            
//獲取Excel中第一個Sheet名稱,作爲查詢時的表名
            string sheetName = this.GetExcelSheetName(pPath);
            
string sql = "select * from [" + sheetName.Replace('.''#'+ "$]";
            cmd.CommandText 
= sql;
            OdbcDataAdapter da 
= new OdbcDataAdapter(cmd);
            DataSet ds 
= new DataSet();
            
try
            {                
                da.Fill(ds);
                
return ds.Tables[0];
            }
            
catch (Exception x)
            {
                ds 
= null;
                
throw new Exception("從Excel文件中獲取數據時發生錯誤!");
            }
            
finally
            {
                cmd.Dispose();
                cmd 
= null;
                da.Dispose();
                da 
= null;
                
if (conn.State == ConnectionState.Open)
                {
                    conn.Close();
                }
                conn 
= null;
            }
        }

        
private string GetExcelSheetName(string pPath)
        {
            
//打開一個Excel應用
            Excel.Application app = new Excel.Application();
            
if (app == null)
            {
                
throw new Exception("打開Excel應用時發生錯誤!");
            }
            Excel.Workbooks wbs 
= app.Workbooks;
            
//打開一個現有的工作薄
            Excel._Workbook wb = wbs.Add(pPath);
            Excel.Sheets shs 
= wb.Sheets;
            
//選擇第一個Sheet頁
            Excel._Worksheet sh = (Excel._Worksheet)shs.get_Item(1);
            
string sheetName = sh.Name;

            ReleaseCOM(sh);
            ReleaseCOM(shs);
            ReleaseCOM(wb);
            ReleaseCOM(wbs);
            app.Quit();
            ReleaseCOM(app);
            
return sheetName;
        }

(“
string sql = "select * from [" + sheetName.Replace('.''#'+ "$]";”如果sheet頁名稱中含有“.”,則要將其替換爲“#”,具體原因,沒研究出來-_-。另外貼一張界面截圖:)




6).關於從Excel導入數據,網上應該有很多例子,這裏補充一個關於數據導入時的效率問題。最初在從Excel導入數據到MySql中時,當文件達到50000行時,逐行導入花了10餘分鐘的時間。大量執行插入操作,逐條執行很慢原因可能在於:

(
1)每執行一條插入語句,客戶端需要與服務器交互一次,這要有代價;

(
2)一些數據庫對每一條插入操作都執行事務,這也要有代價

所以在大量執行插入操作時,應該儘量先多個insert語句拼接好,例如每次拼接好200個insert語句,然後再一次執行它,這樣可以大幅提高效率。

最近因爲需要學習了一下使用C#操作Excel表格,現在把我使用C#如何定製表格的過程提供給需要的兄弟: 
/*從數據庫提取數據*/ 
string strconn="packet size=4096;user id=sa;data source=localhost;persist security info=True;initial catalog=Database;password=sa"
SqlConnection sqlconn
=new SqlConnection(strconn); 
sqlconn.Open(); 
SqlDataAdapter sqldataAdapter
=new SqlDataAdapter("Select * from [數據表]",sqlconn); 
DataSet myds
=new DataSet(); 
sqldataAdapter.Fill(myds); 
/*在Execl中建立“成果表”的格式表格*/ 
Excel.ApplicationClass excel
=new Excel.ApplicationClass(); 
excel.Application.Workbooks.Add(
true); 
excel.Cells[
1,1= "單元名稱" ; 
excel.Cells[
1,2]="指標及其描述、特徵值和權重"
excel.Cells[
1,23]="屬性"
excel.Cells[
2,2]="D"
excel.Cells[
2,5]="R"
excel.Cells[
2,8]="A"
excel.Cells[
2,11]="S"
excel.Cells[
2,14]="T"
excel.Cells[
2,17]="I"
excel.Cells[
2,20]="C"
excel.Cells[
2,23]="結果"
excel.Cells[
2,24]="等級"
excel.Cells[
3,2]="描述"
excel.Cells[
3,3]="特徵值"
excel.Cells[
3,4]="權重"
excel.Cells[
3,5]="描述"
excel.Cells[
3,6]="特徵值"
excel.Cells[
3,7]="權重"
excel.Cells[
3,8]="描述"
excel.Cells[
3,9]="特徵值"
excel.Cells[
3,10]="權重"
excel.Cells[
3,11]="描述"
excel.Cells[
3,12]="特徵值"
excel.Cells[
3,13]="權重"
excel.Cells[
3,14]="描述"
excel.Cells[
3,15]="特徵值"
excel.Cells[
3,16]="權重"
excel.Cells[
3,17]="描述"
excel.Cells[
3,18]="特徵值"
excel.Cells[
3,19]="權重"
excel.Cells[
3,20]="描述"
excel.Cells[
3,21]="特徵值"
excel.Cells[
3,22]="權重"

excel.get_Range(excel.Cells[ 
1 , 1 ],excel.Cells[ 3 ,1 ]).MergeCells=true
excel.get_Range(excel.Cells[ 
1 , 2 ],excel.Cells[ 1 ,22 ]).MergeCells=true
excel.get_Range(excel.Cells[ 
1 , 23 ],excel.Cells[ 1 ,24 ]).MergeCells=true
excel.get_Range(excel.Cells[ 
2 , 2 ],excel.Cells[ 2 ,4 ]).MergeCells=true
excel.get_Range(excel.Cells[ 
2 , 5 ],excel.Cells[ 2 ,7 ]).MergeCells=true
excel.get_Range(excel.Cells[ 
2 , 8],excel.Cells[ 2 ,10 ]).MergeCells=true
excel.get_Range(excel.Cells[ 
2 ,11 ],excel.Cells[ 2 ,13 ]).MergeCells=true
excel.get_Range(excel.Cells[ 
2 , 14 ],excel.Cells[ 2 ,16 ]).MergeCells=true
excel.get_Range(excel.Cells[ 
2 , 17 ],excel.Cells[ 2 ,19 ]).MergeCells=true
excel.get_Range(excel.Cells[ 
2 , 20 ],excel.Cells[ 2 ,22 ]).MergeCells=true
excel.get_Range(excel.Cells[ 
2 , 23 ],excel.Cells[ 3 ,23 ]).MergeCells=true
excel.get_Range(excel.Cells[ 
2 , 24 ],excel.Cells[ 3 ,24 ]).MergeCells=true

/*往Excel格式表格中寫入數據*/ 
int waterdataRows=myds.Tables[0].Rows.Count; 
int waterdataCols=myds.Tables[0].Columns.Count; 
for(int i=1;i<=waterdataRows;i++

excel.Cells[i
+3,1]=myds.Tables[0].Rows[i-1].ItemArray.GetValue(0); 
for(int j=1;j<=7;j++

excel.Cells[i
+3,3*j]=myds.Tables[0].Rows[i-1].ItemArray.GetValue(j); 
excel.Cells[i
+3,3*j+1]=WW[j-1]; 

excel.Cells[i
+3,23]=ds.Tables[0].Rows[i-1].ItemArray.GetValue(1); 
excel.Cells[i
+3,24]=ds.Tables[0].Rows[i-1].ItemArray.GetValue(3); 

excel.Visible
=false
excel.DisplayAlerts
=false
//Excel.WorksheetClass worksheet=(Excel.WorksheetClass)excel.ActiveSheet; 
excel.Save(); 
excel.Application.Workbooks.Close(); 
excel.Application.Quit(); 
excel.Quit(); 
System.Runtime.InteropServices.Marshal.ReleaseComObject (excel); 
KillProcess(
"EXCEL.EXE"); 
GC.Collect();
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章