如何在 Visual Basic .NET 中使用 ADO.NET 檢索和修改 Excel 工作簿中的記錄

本文討論如何使用 ADO.NET 檢索 Microsoft Excel 工作簿中的數據、修改現有工作簿中的數據或將數據添加至新的工作簿中。要通過 ADO.NET 訪問 Excel 工作簿,您可以使用 Jet OLE DB 提供程序;本文提供了您所需要的信息,以便您可以在 Excel 充當目標數據源時使用 Jet OLE DB 提供程序。

 

如何將 Jet OLE DB 提供程序與 Microsoft Excel 工作簿配合使用

Microsoft Jet 數據庫引擎可以通過可安裝的索引順序訪問方法 (ISAM) 驅動程序,訪問格式爲其他數據庫文件(例如 Excel 工作簿)的數據。要打開 Microsoft Jet 4.0 OLE DB 提供程序所支持的外部格式,請在連接的擴展屬性中指定數據庫類型。Jet OLE DB 提供程序對於 Microsoft Excel 工作簿支持下列數據庫類型:

Excel 3.0

Excel 4.0

Excel 5.0

Excel 8.0

注意:對於 Microsoft Excel 5.0 7.0 (95) 工作簿,請使用 Excel 5.0 源數據庫類型;對於 Microsoft Excel 8.0 (97)9.0 (2000) 10.0 (2002) 工作簿,請使用 Excel 8.0 源數據庫類型。本文中的示例使用的是格式爲 Excel 2000 Excel 2002 Excel 工作簿。

 

連接字符串

要使用 Jet OLE DB 提供程序訪問 Excel 工作簿,請使用具有下列語法的連接字符串:

Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:/Book1.xls;Extended Properties="Excel 8.0;HDR=YES;"

在連接字符串中,用 Data Source 參數指定工作簿的完整路徑和文件名。Extended Properties 參數可包含兩種屬性:一個屬性用於 ISAM 版本,一個屬性用於指示表是否包括標題。

使用 Excel 工作簿時,默認情況下,區域中的第一行是標題行(或字段名稱)。如果第一個區域不包含標題,您可以在連接字符串的擴展屬性中指定 HDR=NO。如果您在連接字符串中指定 HDR=NOJet OLE DB 提供程序將自動爲您命名字段(F1 表示第一個字段,F2 表示第二個字段,依此類推)。

 

數據類型

與傳統的數據庫不同,在 Excel 表中沒有指定列的數據類型的直接方式。而是,OLE DB 提供程序通過對一列中的八行進行掃描來猜測 該字段的數據類型。您可以通過爲連接字符串的擴展屬性中的 MAXSCANROWS 設置指定一個一 (1) 至十六 (16) 之間的值,來更改要掃描的行數。

 

表命名規則

您可以通過若干種方式引用 Excel 工作簿中的表(或區域):

使用工作表名稱後面跟一個美元符號(例如 [Sheet1$] [My Worksheet$])。以此方式引用的工作簿包括工作表的整個使用區域。

Select * from [Sheet1$]

使用帶有定義名稱的區域(例如 [MyNamedRange]):

Select * from [MyNamedRange]

使用帶有特定地址的區域(例如 [Sheet1$A1:B10]):

Select * from [Sheet1$A1:B10]

注意:工作表名稱後面帶美元符號表示該表存在。如果您要創建一個新表,如本文 創建新工作簿和表 一節中所討論的那樣,請不要使用美元符號。

 

如何將 Excel 工作簿用作 ADO.NET 數據源

檢索記錄

您可以使用 ADO.NET 中的兩種方法之一檢索數據庫中的記錄:使用 Dataset 或使用 DataReader

Dataset 是一個從數據源檢索到的記錄的緩存。Dataset 中的數據通常要比數據庫中的數據精簡得多。但是,您可以像使用實際數據一樣使用它,並且無須與實際數據庫連接。除了數據檢索之外,還可以使用 Dataset 在基礎數據庫上執行更新操作。

或者,您可以使用 DataReader 從數據庫中檢索只讀、只進數據流。當您使用 DataReader 程序時,由於內存中每次僅有一行,因此性能將增強,系統開銷將降低。如果您有大量數據需要檢索並且不希望更改基礎數據庫,則 DataReader 是比 Dataset 更好的選擇。

 

添加和更新記錄

使用 ADO.NET,您可以通過三種方式之一在工作簿中插入和更新記錄:

直接運行一個命令,每次插入或更新一個記錄。爲此,您可以在自己的連接上創建一個 OLEDbCommand 對象,並將其 CommandText 屬性設置成一個插入記錄的有效命令

 

INSERT INTO [Sheet1$] (F1, F2) values ('111', 'ABC')

或一個可更新記錄的命令,

 

UPDATE [Sheet1$] SET F2 = 'XYZ' WHERE F1 = '111'

然後調用 ExecuteNonQuery 方法。

對使用 Excel 工作簿中的一個表/查詢填充的一個 DataSet 做一些更改,然後調用 DataAdapter Update 方法,以將這些更改從 DataSet 解析回工作簿。不過,要使用 Update 方法執行更新解析,您必須爲 DataAdapter InsertCommand 設置參數化命令:

INSERT INTO [Sheet1$] (F1, F2) values (?, ?)

併爲 UpdateCommand 設置參數化命令:

UPDATE [Sheet1$] SET F2 = ? WHERE F1 = ?

必須要用 INSERT UPDATE 的參數化命令,因爲 OleDbDataAdapter 不提供 Excel 工作簿的主鍵/索引信息;沒有主鍵/索引字段,CommandBuilder 就無法自動爲您生成命令。

如果 Jet OLE DB 提供程序能夠使用另外的數據源,請將該數據源中的數據導出到 Excel 工作簿中。可通過 Jet OLE DB 提供程序以這種方式使用的數據源包括:文本文件、Microsoft Access 數據庫,當然也包括其他 Excel 工作簿。使用單個 INSERT INTO 命令,您可以將其他表/查詢中的數據導出到您的工作簿中:

INSERT INTO [Sheet1$] IN 'C:/Book1.xls' 'Excel 8.0;' SELECT * FROM MyTable"

INSERT INTO 要求目標表(或工作表)已存在,並且數據已附加到目標表中。

您還可以使用 SELECT..INTO 將您的表/查詢導出到工作簿中:

SELECT * INTO [Excel 8.0;Database=C:/Book1.xls].[Sheet1] FROM [MyTable]

當您使用 SELECT..INTO 時,如果目標表或工作簿不存在,將爲您創建。如果在發出 SELECT..INTO 命令之前表已存在,您將收到錯誤信息。

本文的稍後的示例代碼 部分對這些在工作簿中添加和更新記錄的方法中的每一種都進行了說明。

 

刪除記錄

雖然 Jet OLE DB 提供程序允許您在 Excel 工作簿中插入和更新記錄,但是不允許進行 DELETE(刪除)操作。如果您嘗試對一個或多個記錄執行 DELETE 操作,您將收到以下錯誤信息:

Deleting data in a linked table is not supported by this ISAM.

這是將 Excel 工作簿作爲數據庫進行處理時所固有的限制。

 

創建工作簿和表

要在 Excel 工作簿中創建表,請運行 CREATE TABLE 命令:

CREATE TABLE Sheet1 (F1 char(255), F2 char(255))

當您運行此命令時,將使用您在命令中指定的表名稱創建新的工作表。如果不存在要連接的工作簿,也會創建該工作簿。

本文的 示例代碼 部分說明了如何使用 CREATE TABLE 命令創建新的工作簿和表。

 

分步操作

示例代碼

1、啓動一個新的 Visual Basic .NET Windows 應用程序項目

默認情況下會創建 Form1

2、向 Form1 添加六個 RadioButton(單選按鈕)控件和一個 Button(按鈕)控件。

3、選中所有單選按鈕控件,並將大小屬性設置爲 200,24

4、在視圖菜單上,單擊代碼。

5、在代碼模塊的開始處添加以下行

Imports System.Data.OleDb

6、將以下代碼插入到Form 類中:

Private m_sConn1 As String = "Provider=Microsoft.Jet.OLEDB.4.0;" & _

               "Data Source=C:/ExcelData1.xls;" & _

               "Extended Properties=""Excel 8.0;HDR=YES"""

Private m_sConn2 As String = "Provider=Microsoft.Jet.OLEDB.4.0;" & _

               "Data Source=C:/ExcelData2.xls;" & _

               "Extended Properties=""Excel 8.0;HDR=YES"""

Private m_sNorthwind = _

      "C:/Program Files/Microsoft Office/Office10/Samples/Northwind.mdb"

Private m_sAction As String

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

      RadioButton1.Text = "Create_Workbook"

      RadioButton2.Text = "Retrieve_Records"

      RadioButton3.Text = "Add_Records"

      RadioButton4.Text = "Update_Records"

      RadioButton5.Text = "Update_Individual_Cells"

      RadioButton6.Text = "Use_External_Source"

      Button1.Text = "Go!"

End Sub

Private Sub RadioButtons_Click(ByVal sender As Object, ByVal e As System.EventArgs) _

      Handles RadioButton1.Click, RadioButton2.Click, RadioButton3.Click, _

      RadioButton4.Click, RadioButton5.Click, RadioButton6.Click

      m_sAction = sender.Text'Store the text for the selected radio button

End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

      Try

         ' Call the associated routine to add/update/modify the workbook.

         Select Case m_sAction

            Case "Create_Workbook" : Create_Workbook()

            Case "Retrieve_Records" : Retrieve_Records()

            Case "Add_Records" : Add_Records()

            Case "Update_Records" : Update_Records()

            Case "Update_Individual_Cells" : Update_Individual_Cells()

            Case "Use_External_Source" : Use_External_Source()

         End Select

      Catch ex As OleDbException

         Dim er As OleDbError

         For Each er In ex.Errors

            MsgBox(er.Message)

         Next

      Catch ex2 As System.InvalidOperationException

         MsgBox(ex2.Message)

      End Try

 

End Sub

Public Sub Create_Workbook()

      ' If the workbooks already exist, prompt to delete.

      Dim answer As MsgBoxResult

      If Dir("C:/ExcelData1.xls") <> "" Or Dir("C:/ExcelData2.xls") <> "" Then

          answer = MsgBox("Delete existing workbooks (C:/ExcelData1.xls and " & _

                   "C:/ExcelData2.xls)?", MsgBoxStyle.YesNo)

          If answer = MsgBoxResult.Yes Then

              If Dir("C:/ExcelData1.xls") <> "" Then Kill("C:/ExcelData1.xls")

              If Dir("C:/ExcelData2.xls") <> "" Then Kill("C:/ExcelData2.xls")

          Else

              Exit Sub

          End If

      End If

'==========================================================================

      ' Create a workbook with a table named EmployeeData. The table has 3

      ' fields: ID (char 255), Name (char 255) and Birthdate (date). 

'==========================================================================

      Dim conn As New OleDbConnection()

      conn.ConnectionString = m_sConn1

      conn.Open()

      Dim cmd1 As New OleDbCommand()

      cmd1.Connection = conn

      cmd1.CommandText = "CREATE TABLE EmployeeData (Id char(255), Name char(255), BirthDate date)"

      cmd1.ExecuteNonQuery()

      cmd1.CommandText = "INSERT INTO EmployeeData (Id, Name, BirthDate) values ('AAA', 'Andrew', '12/4/1955')"

      cmd1.ExecuteNonQuery()

      conn.Close()

'==========================================================================

      ' Create a workbook with a table named InventoryData. The table has 3

      ' fields: Product (char 255), Qty (float) and Price (currency).

'==========================================================================

      conn.ConnectionString = m_sConn2

      conn.Open()

      Dim cmd2 As New OleDbCommand()

      cmd2.Connection = conn

      cmd2.CommandText = "CREATE TABLE InventoryData (Product char(255), Qty float, Price currency)"

      cmd2.ExecuteNonQuery()

      cmd2.CommandText = "INSERT INTO InventoryData (Product, Qty, Price) values ('Cola', 200, 1.35)"

      cmd2.ExecuteNonQuery()

      cmd2.CommandText = "INSERT INTO InventoryData (Product, Qty, Price) values ('Chips', 550, 0.89)"

      cmd2.ExecuteNonQuery()

      conn.Close()

      ' NOTE: You can ALTER and DROP tables in a similar fashion.

End Sub

Public Sub Retrieve_Records()

      '==========================================================

      'Use a DataReader to read data from the EmployeeData table.

      '==========================================================

      Dim conn1 As New System.Data.OleDb.OleDbConnection(m_sConn1)

      conn1.Open()

      Dim cmd1 As New System.Data.OleDb.OleDbCommand("Select * From [EmployeeData$]", conn1)

      Dim rdr As OleDbDataReader = cmd1.ExecuteReader

      Debug.WriteLine(vbCrLf & "EmployeeData:" & vbCrLf & "=============")

      Do While rdr.Read()

         Debug.WriteLine(System.String.Format("{0,-10}{1, -15}{2}", _

            rdr.GetString(0), rdr.GetString(1), _

            rdr.GetDateTime(2).ToString("d")))

      Loop

      rdr.Close()

      conn1.Close()

      '========================================================

      'Use a DataSet to read data from the InventoryData table.

      '========================================================

      Dim conn2 As New OleDbConnection(m_sConn2)

      Dim da As New OleDbDataAdapter("Select * From [InventoryData$]", conn2)

      Dim ds As DataSet = New DataSet()

      da.Fill(ds)

      Debug.WriteLine(vbCrLf & "InventoryData:" & vbCrLf & "==============")

      Dim dr As DataRow

      For Each dr In ds.Tables(0).Rows'Show results in output window

         Debug.WriteLine(System.String.Format("{0,-15}{1, -6}{2}", _

            dr("Product"), dr("Qty"), dr("Price")))

      Next

      conn2.Close()

End Sub

Public Sub Add_Records()

'==========================================================================

      ' Run an INSERT INTO command to add new records to the workbook.

'==========================================================================

      Dim conn1 As New System.Data.OleDb.OleDbConnection(m_sConn1)

      conn1.Open()

      Dim cmd As New System.Data.OleDb.OleDbCommand()

      cmd.Connection = conn1

      cmd.CommandText = "INSERT INTO [EmployeeData$] (ID, Name, BirthDate) values ('CCC', 'Charlie', '10/14/48')"

      cmd.ExecuteNonQuery()

      cmd.CommandText = "INSERT INTO [EmployeeData$] (ID, Name, BirthDate) values ('DDD', 'Deloris', '7/19/98')"

      cmd.ExecuteNonQuery()

      conn1.Close()

      '====================================================================

      'Use the InsertCommand object to add new records to the InventoryData

      'table.

      '====================================================================

      Dim conn2 As New OleDbConnection(m_sConn2)

      Dim da As New OleDbDataAdapter("Select * From [InventoryData$]", conn2)

      Dim ds As DataSet = New DataSet()

      da.Fill(ds, "MyExcelTable")

      ' Generate the InsertCommand and add the parameters for the command.

      da.InsertCommand = New OleDbCommand( _

         "INSERT INTO [InventoryData$] (Product, Qty, Price) VALUES (?, ?, ?)", conn2)

      da.InsertCommand.Parameters.Add("@Product", OleDbType.VarChar, 255, "Product")

      da.InsertCommand.Parameters.Add("@Qty", OleDbType.Double).SourceColumn = "Qty"

      da.InsertCommand.Parameters.Add("@Price", OleDbType.Currency).SourceColumn = "Price"

      ' Add two new records to the dataset.

      Dim dr As DataRow

      dr = ds.Tables(0).NewRow

      dr("Product") = "Bread" : dr("Qty") = 390 : dr("Price") = 1.89 : ds.Tables(0).Rows.Add(dr)

      dr = ds.Tables(0).NewRow

      dr("Product") = "Milk" : dr("Qty") = 99 : dr("Price") = 2.59 : ds.Tables(0).Rows.Add(dr)

      ' Apply the dataset changes to the actual data source (the workbook).

      da.Update(ds, "MyExcelTable")

      conn2.Close()

End Sub

Public Sub Update_Records()

'==========================================================================

      ' Run an UPDATE command to change a record in the EmployeeData

      ' table.

'==========================================================================

      Dim conn1 As New System.Data.OleDb.OleDbConnection(m_sConn1)

      conn1.Open()

      Dim cmd As New System.Data.OleDb.OleDbCommand()

      cmd.Connection = conn1

      cmd.CommandText = "UPDATE [EmployeeData$] " & _

                    "SET NAME = 'Aaron', BirthDate = '5/4/1975' WHERE ID = 'AAA'"

      cmd.ExecuteNonQuery()

      conn1.Close()

      '====================================================================

      ' Use the UpdateCommand object to modify records in the InventoryData

      ' table.

      '====================================================================

      Dim conn2 As New OleDbConnection(m_sConn2)

      Dim da As New OleDbDataAdapter("Select * From [InventoryData$]", conn2)

      Dim ds As DataSet = New DataSet()

      da.Fill(ds, "MyInventoryTable")

      ' Generate the UpdateCommand and add the parameters for the command.

      da.UpdateCommand = New OleDbCommand( _

         "UPDATE [InventoryData$] SET Qty = ?, Price=? WHERE Product = ?", conn2)

      da.UpdateCommand.Parameters.Add("@Qty", OleDbType.Numeric).SourceColumn = "Qty"

      da.UpdateCommand.Parameters.Add("@Price", OleDbType.Currency).SourceColumn = "Price"

      da.UpdateCommand.Parameters.Add("@Product", OleDbType.VarChar, 255, "Product")

      ' Update the first two records.

      ds.Tables(0).Rows(0)("Qty") = 1000

      ds.Tables(0).Rows(0)("Price") = 10.1

      ds.Tables(0).Rows(1)("Qty") = 2000

      ds.Tables(0).Rows(1)("Price") = 20.2

      ' Apply the dataset changes to the actual data source (the workbook).

      da.Update(ds, "MyInventoryTable")

      conn2.Close()

End Sub

Public Sub Update_Individual_Cells()

'==========================================================================

      ' Update individual cells on the EmployeeData worksheet;

      ' specifically, cells F3, G3, and I4 are modified.

'==========================================================================

      ' NOTE: The connection string indicates that the table does *NOT*

      ' have a header row.

      Dim conn As New System.Data.OleDb.OleDbConnection(m_sConn1.Replace("HDR=YES", "HDR=NO"))

      conn.Open()

      Dim cmd As New System.Data.OleDb.OleDbCommand()

      cmd.Connection = conn

      cmd.CommandText = "UPDATE [EmployeeData$F3:G3] SET F1 = 'Cell F3', F2 = 'Cell G3'"

      cmd.ExecuteNonQuery()

      cmd.CommandText = "UPDATE [EmployeeData$I4:I4] SET F1 = 'Cell I4'"

      cmd.ExecuteNonQuery()

      conn.Close()

End Sub

Public Sub Use_External_Source()

      ' Open a connection to the sample Northwind Access database.

      Dim conn As New System.Data.OleDb.OleDbConnection( _

            "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & m_sNorthwind & ";")

      conn.Open()

      Dim cmd As New System.Data.OleDb.OleDbCommand()

      cmd.Connection = conn

'=======================================================================

      ' Run an INSERT..INTO command on the Northwind database to append

      ' the records from a table/query to an existing table in the Excel

      ' workbook.

'=======================================================================

      cmd.CommandText = "INSERT INTO [EmployeeData$] IN 'C:/ExcelData1.xls' 'Excel 8.0;'" & _

         "SELECT EmployeeID AS ID, FirstName AS Name, BirthDate FROM Employees"

      cmd.ExecuteNonQuery()

'==========================================================================

      ' Run a SELECT..INTO command on the Northwind database to insert

      ' all the records from a table/query into a new sheet in the Excel

      ' workbook.

'==========================================================================

      cmd.CommandText = "SELECT * INTO [Excel 8.0;Database=C:/ExcelData2.xls].[ProductSales]" & _

                      "FROM [Product Sales for 1997]"

      cmd.ExecuteNonQuery()

      conn.Close()

End Sub

如果需要,可爲代碼中的 m_sNorthwind 成員修改指向 Access 示例數據庫 Northwind 的路徑。

試運行

1、在視圖菜單上,指向其他窗口,然後單擊輸出以顯示輸出窗口。

2、按 F5 鍵生成並運行程序。

3、單擊 Create_Workbook,然後單擊 Go(執行。下同)。Create_Workbook 過程將運行 CREATE TABLE 命令以創建兩個新的工作簿:C:/ExcelData1.xls C:/ExcelData2.xlsExcelData1.xls 包含一個名爲 EmployeeData 的工作表(表),ExcelData2.xls 包含一個名爲 InventoryData 的工作表(表)。這兩個表都填入了記錄。

注意:請在此測試的每個其餘步驟中,在 Excel 中打開工作簿以檢查結果。或者,單擊 Retrieve_Records 以在 Visual Studio .NET 的輸出窗口中查看錶內容。

4、單擊 Retrieve_Records,然後單擊 GoRetrieve_Records 過程將從表中提取記錄並將它們顯示在輸出窗口中,輸出的記錄類似於下面的內容:

EmployeeData:

=============

AAA       Andrew         12/4/1955

InventoryData:

==============

Cola           200   1.35

Chips          550   0.89

單擊 Add_Records,然後單擊 GoAdd_Records 例程將向每個表添加兩條記錄:

EmployeeData:

=============

AAA       Andrew         12/4/1955

CCC       Charlie        10/14/1948

DDD       Deloris        7/19/1998

InventoryData:

==============

Cola           200   1.35

Chips          550   0.89

Bread          390   1.89

Milk           99    2.59

單擊 Update_Records,然後單擊 GoUpdate_Records 例程在每一個工作簿中更新兩條記錄:

EmployeeData:

=============

AAA       Aaron          5/4/1975

CCC       Charlie        10/14/1948

DDD       Deloris        7/19/1998

InventoryData:

==============

Cola           1000  10.1

Chips          2000  20.2

Bread          390   1.89

Milk           99    2.59

 

5、單擊 Update_Individual_Cells,然後單擊 GoUpdate_Individual_Cells 例程修改 ExcelData1.xls EmployeeData 工作表上的特定單元格;具體就是單元格 F3G3 I4 將被更新。

6、單擊 Use_External_Source,然後單擊 Go。當您使用 INSERT..INTO 命令時,Use_External_Source 例程將 Northwind 表“Employees”中的記錄追加到 ExcelData1.xls 中的 EmployeeData 工作表中。並且,Use_External_Source 使用 SELECT..INTO 命令在 ExcelData2.xls 中創建一個包含 Northwind 表“Products”中的所有記錄的新表(或工作表)。

注意:如果您單擊 Use_External_Source 多次,Employees 列表將被追加多次,原因是主鍵未被識別或實施。

單元格格式設置

如果您要使用 ADO.NET 在現有工作簿中添加或更新記錄,可以將單元格格式應用到該工作簿,以將該格式應用於新的或已更新的記錄。當您更新工作簿中的現有記錄(或行)時,將保留單元格格式設置。當您在工作簿中插入新的記錄(或行)時,新記錄將繼承上一行的格式設置。

以下過程說明了如何通過示例代碼在工作簿中使用格式設置:

1)        F5 生成並運行該示例。

2)        Form1 上,單擊 Create_Workbook,然後單擊 Go

3)        啓動 Microsoft Excel 並打開 C:/ExcelData1.xls

4)        對單元格 A2 應用粗體樣式。

5)        對單元格 B2 應用斜體和下劃線樣式,並居中對齊。

6)        對單元格 C2 應用長日期格式。

7)        保存並關閉 C:/ExcelData1.xls

8)        Form1 上,單擊 Add_Records,然後單擊 Go

9)        Excel 中打開 C:/ExcelData1.xls,可以看到兩個新行繼承了第一行的格式設置。

 

 

限制

下面是 Jet OLE DB 提供程序關於 Excel 數據源的一些限制:

您不能使用 ADO.NET 在單元格中插入公式。

Jet OLE DB 提供程序無法爲 Excel 工作簿中的表提供主鍵/索引信息。因此,您不能使用

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章