如何使用自動化將資料從 ADO 記錄集傳輸至 Excel

摘要

您可以自動化 Excel,將 ADO 記錄集的內容傳輸至 Microsoft Excel 工作表。 您可以使用的方法取決於您要自動化的 Excel 版本。 Excel 97、Excel 2000 和 Excel 2002 具有 CopyFromRecordset 方法,可用來將記錄集傳送到某個範圍。 Excel 2000 和 2002 中的 CopyFromRecordset 可用來複製 DAO 或 ADO 記錄集。 不過,Excel 97 中的 CopyFromRecordset 僅支援 DAO 記錄集。 若要將 ADO 記錄集傳送至 Excel 97,您可以從記錄集建立陣列,然後在範圍中填入該陣列的內容。

本文討論這兩種方法。 顯示的範例程式碼說明如何將 ADO 記錄集傳送至 Excel 97、Excel 2000、Excel 2002、Excel 2003 或 Excel 2007。

其他相關資訊

以下提供的程式碼範例示範如何使用 Microsoft Visual Basic 的自動化,將 ADO 記錄集複製到 Microsoft Excel 工作表。 程式碼會先檢查 Excel 的版本。 如果偵測到 Excel 2000 或 2002,則會使用 CopyFromRecordset 方法,因為它很有效率,而且需要較少的程式碼。 不過,如果偵測到 Excel 97 或更早版本,則會先使用 ADO 記錄集物件的 GetRows 方法將記錄集複製到陣列。 然後轉譯陣列,讓記錄位於資料列) 中的第一個維度 (,而欄位則位於資料行) 中的第二個維度 (。 然後,陣列會透過將陣列指派給儲存格範圍,複製到 Excel 工作表。 (陣列會以一個步驟複製,而不是在 worksheet.) 中的每個儲存格中執行迴圈

程式碼範例會使用隨附于 Microsoft Office 的 Northwind 範例資料庫。 如果您在安裝 Microsoft Office 時選取預設資料夾,資料庫位於:

\Program Files\Microsoft Office\Office\Samples\Northwind.mdb

如果 Northwind 資料庫位於您電腦上不同的資料夾中,您需要在下列程式碼中編輯資料庫的路徑。

如果您的系統上未安裝 Northwind 資料庫,您可以使用 Microsoft Office 安裝程式的 [新增/移除] 選項來安裝範例資料庫。

注意 當您安裝 2007 Microsoft Office 時,不會安裝 Northwind 資料庫。 若要取得 Northwind 2007,請造訪下列 Microsoft 網站:

Office 模 & 板主題

建立範例的步驟

  1. 啟動 Visual Basic 並建立新的標準 EXE 專案。 根據預設,會建立 Form1。

  2. 將 CommandButton 新增至 Form1。

  3. 按一下 [專案] 功能表中的 [參考]。 新增 Microsoft ActiveX Data Objects 2.1 程式庫的參考。

  4. 將下列程式碼貼到 Form1 的程式碼區段中:

    Private Sub Command1_Click()
        Dim cnt As New ADODB.Connection
        Dim rst As New ADODB.Recordset
    
    Dim xlApp As Object
        Dim xlWb As Object
        Dim xlWs As Object
    
    Dim recArray As Variant
    
    Dim strDB As String
        Dim fldCount As Integer
        Dim recCount As Long
        Dim iCol As Integer
        Dim iRow As Integer
    
    ' Set the string to the path of your Northwind database
        strDB ="c:\program files\Microsoft office\office11\samples\Northwind.mdb"
    
    ' Open connection to the database
        cnt.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
            "Data Source=" & strDB & ";"
    
    ''When using the Access 2007 Northwind database
        ''comment the previous code and uncomment the following code.
        'cnt.Open "Provider=Microsoft.ACE.OLEDB.12.0;" & _
        '    "Data Source=" & strDB & ";"
    
    ' Open recordset based on Orders table
        rst.Open "Select * From Orders", cnt
    
    ' Create an instance of Excel and add a workbook
        Set xlApp = CreateObject("Excel.Application")
        Set xlWb = xlApp.Workbooks.Add
        Set xlWs = xlWb.Worksheets("Sheet1")
    
    ' Display Excel and give user control of Excel's lifetime
        xlApp.Visible = True
        xlApp.UserControl = True
    
    ' Copy field names to the first row of the worksheet
        fldCount = rst.Fields.Count
        For iCol = 1 To fldCount
            xlWs.Cells(1, iCol).Value = rst.Fields(iCol - 1).Name
        Next
    
    ' Check version of Excel
        If Val(Mid(xlApp.Version, 1, InStr(1, xlApp.Version, ".") - 1)) > 8 Then
            'EXCEL 2000,2002,2003, or 2007: Use CopyFromRecordset
    
    ' Copy the recordset to the worksheet, starting in cell A2
            xlWs.Cells(2, 1).CopyFromRecordset rst
            'Note: CopyFromRecordset will fail if the recordset
            'contains an OLE object field or array data such
            'as hierarchical recordsets
    
    Else
            'EXCEL 97 or earlier: Use GetRows then copy array to Excel
    
    ' Copy recordset to an array
            recArray = rst.GetRows
            'Note: GetRows returns a 0-based array where the first
            'dimension contains fields and the second dimension
            'contains records. We will transpose this array so that
            'the first dimension contains records, allowing the
            'data to appears properly when copied to Excel
    
    ' Determine number of records
    
    recCount = UBound(recArray, 2) + 1 '+ 1 since 0-based array
    
    ' Check the array for contents that are not valid when
            ' copying the array to an Excel worksheet
            For iCol = 0 To fldCount - 1
                For iRow = 0 To recCount - 1
                    ' Take care of Date fields
                    If IsDate(recArray(iCol, iRow)) Then
                        recArray(iCol, iRow) = Format(recArray(iCol, iRow))
                    ' Take care of OLE object fields or array fields
                    ElseIf IsArray(recArray(iCol, iRow)) Then
                        recArray(iCol, iRow) = "Array Field"
                    End If
                Next iRow 'next record
            Next iCol 'next field
    
    ' Transpose and Copy the array to the worksheet,
            ' starting in cell A2
            xlWs.Cells(2, 1).Resize(recCount, fldCount).Value = _
                TransposeDim(recArray)
        End If
    
    ' Auto-fit the column widths and row heights
        xlApp.Selection.CurrentRegion.Columns.AutoFit
        xlApp.Selection.CurrentRegion.Rows.AutoFit
    
    ' Close ADO objects
        rst.Close
        cnt.Close
        Set rst = Nothing
        Set cnt = Nothing
    
    ' Release Excel references
        Set xlWs = Nothing
        Set xlWb = Nothing
    
    Set xlApp = Nothing
    
    End Sub
    
    Function TransposeDim(v As Variant) As Variant
    ' Custom Function to Transpose a 0-based array (v)
    
    Dim X As Long, Y As Long, Xupper As Long, Yupper As Long
        Dim tempArray As Variant
    
    Xupper = UBound(v, 2)
        Yupper = UBound(v, 1)
    
    ReDim tempArray(Xupper, Yupper)
        For X = 0 To Xupper
            For Y = 0 To Yupper
                tempArray(X, Y) = v(Y, X)
            Next Y
        Next X
    
    TransposeDim = tempArray
    
    End Function
    
    
  5. 按 F5 鍵以執行專案。 Form1 隨即出現。

  6. 按一下 Form1 上的 CommandButton,並注意 Orders 資料表的內容會顯示在 Excel 的新活頁簿中。

使用 CopyFromRecordset

為了提高效率和效能,CopyFromRecordset 是慣用的方法。 由於 Excel 97 僅支援具有 CopyFromRecordset 的 DAO 記錄集,因此如果您嘗試將 ADO 記錄集傳遞至具有 Excel 97 的 CopyFromRecordset,您會收到下列錯誤:

執行階段錯誤 430:類別不支援自動化,或不支援預期的介面。 在程式碼範例中,您可以藉由檢查 Excel 的版本來避免此錯誤,這樣您就不會針對 97 版使用 CopyFromRecordset。

注意 使用 CopyFromRecordset 時,您應該注意您使用的 ADO 或 DAO 記錄集不能包含 OLE 物件欄位或陣列資料,例如階層式記錄集。 如果您在記錄集中包含任一類型的欄位,CopyFromRecordset 方法會失敗,並出現下列錯誤:

執行階段錯誤 -2147467259:物件範圍的方法 CopyFromRecordset 失敗。

使用 GetRows

如果偵測到 Excel 97,請使用 ADO 記錄集的 GetRows 方法,將記錄集複製到陣列中。 如果您將 GetRows 傳回的陣列指派給工作表中的儲存格範圍,則資料會跨越資料行,而不是沿著資料列往下移動。 例如,如果記錄集有兩個欄位和 10 個數據列,則陣列會顯示為兩個數據列和 10 個數據行。 因此,您必須先使用 TransposeDim () 函式轉置陣列,再將陣列指派給儲存格範圍。 將陣列指派給儲存格範圍時,有一些限制需要注意:

將陣列指派給 Excel Range 物件時,適用下列限制:

  • 陣列不能包含 OLE 物件欄位或陣列資料,例如階層式記錄集。 請注意,程式碼範例會檢查此條件並顯示「陣列欄位」,讓使用者知道欄位無法顯示在 Excel 中。

  • 陣列不能包含具有 1900 年之前日期的日期欄位。 (請參閱 Microsoft 知識庫文章連結的一節。) 請注意,程式碼範例會將日期欄位格式化為變體字串,以避免發生此潛在問題。

請注意,將陣列複製到 Excel 工作表之前,使用 TransposeDim () 函式來轉置陣列。 您可以修改範例程式碼,將陣列指派給儲存格,以使用 Excel 的 Transpose 函式,而不是建立自己的函式來轉置陣列,如下所示:

   xlWs.Cells(2, 1).Resize(recCount, fldCount).Value = _
      xlApp.WorksheetFunction.Transpose(recArray)

如果您決定使用 Excel 的 Transpose 方法,而不是 TransposeDim () 函式來轉置陣列,您應該注意 Transpose 方法的下列限制:

  • 陣列不能包含大於 255 個字元的專案。
  • 陣列不能包含 Null 值。
  • 陣列中的元素數目不能超過 5461。

如果您將陣列複製到 Excel 工作表時未考慮上述限制,可能會發生下列其中一個執行階段錯誤:

執行階段錯誤 13:類型不符

執行階段錯誤 5:不正確程式

呼叫或引數執行階段錯誤 1004:應用程式定義或物件定義錯誤

參考

如需有關將陣列傳遞至各種 Excel 版本限制的其他資訊,請按一下下列文章編號以檢視 Microsoft 知識庫中的文章:

177991 XL:使用自動化將陣列傳遞至 Excel 的限制

247412 資訊:從 Visual Basic 將資料傳輸至 Excel 的方法