Home
Search
 
What's New
Index
Books
Links
Q & A
Newsletter
Banners
 
Feedback
Tip Jar
 
C# Helper...
 
XML RSS Feed
Follow VBHelper on Twitter
 
 
 
MSDN Visual Basic Community
 
 
 
 
 
TitleCopy data from an Access database into an Excel spreadsheet
Description
KeywordsADO, Access, Excel, database
CategoriesDatabase, Office
 
Use ADO to open the database. Using Excel as a server, open the spreadsheet. Read the field names from the ADO Recordset and add them to the first row in the spreadsheet to make column headers. Read the values from the Recordset and add them to the spreadsheet.

To make things neater, use the Excel server to make the column headers bold. Then select the data and make the columns autofit. Finally, select the second row and freeze the pane above, making the column headers a non-scrolling region.

 
Private Sub cmdLoad_Click()
Dim excel_app As Object
Dim excel_sheet As Object
Dim row As Long
Dim conn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim statement As String
Dim col As Integer

    Screen.MousePointer = vbHourglass
    DoEvents

    ' Create the Excel application.
    Set excel_app = CreateObject("Excel.Application")

    ' Uncomment this line to make Excel visible.
'    excel_app.Visible = True

    ' Open the Excel spreadsheet.
    excel_app.Workbooks.Open FileName:=txtExcelFile.Text

    ' Check for later versions.
    If Val(excel_app.Application.Version) >= 8 Then
        ' Uncomment the following code to select
        ' a particular worksheet.
        ' excel_app.Sheets(2).Select
        Set excel_sheet = excel_app.ActiveSheet
    Else
        Set excel_sheet = excel_app
    End If

    ' Open the Access database.
    Set conn = New ADODB.Connection
    conn.ConnectionString = _
        "Provider=Microsoft.Jet.OLEDB.4.0;" & _
        "Data Source=" & txtAccessFile.Text & ";" & _
        "Persist Security Info=False"
    conn.Open

    ' Select the data.
    Set rs = conn.Execute( _
        "SELECT * FROM Books ORDER BY Title", , _
        adCmdText)

    ' Make the column headers.
    For col = 0 To rs.Fields.Count - 1
        excel_sheet.Cells(1, col + 1) = rs.Fields(col).Name
    Next col

    ' Get data from the database and insert
    ' it into the spreadsheet.
    row = 2
    Do While Not rs.EOF
        For col = 0 To rs.Fields.Count - 1
            excel_sheet.Cells(row, col + 1) = _
                rs.Fields(col).Value
        Next col

        row = row + 1
        rs.MoveNext
    Loop

    ' Make the columns autofit the data.
    excel_sheet.Range( _
        excel_sheet.Cells(1, 1), _
        excel_sheet.Cells(1, _
            rs.Fields.Count)).Columns.AutoFit

    ' Close the database.
    rs.Close
    Set rs = Nothing
    conn.Close
    Set conn = Nothing

    ' Make the header bold.
    excel_sheet.Rows(1).Font.Bold = True

    ' Freeze the header row so it doesn't scroll.
    excel_sheet.Rows(2).Select
    excel_app.ActiveWindow.FreezePanes = True

    ' Select the first cell.
    excel_sheet.Cells(1, 1).Select

    ' Comment the Close and Quit lines to keep
    ' Excel running so you can see it.

    ' Close the workbook saving changes.
    excel_app.ActiveWorkbook.Close True
    excel_app.Quit

    Set excel_sheet = Nothing
    Set excel_app = Nothing

    Screen.MousePointer = vbDefault
    MsgBox "Copied " & Format$(row - 2) & " values."
End Sub
 
Thanks to Kent Finkle for recommending that the row variable be declared as Long instead of Integer (because the maximum number of rows in an Excel worksheet is 65,536 and the maximum integer is 32,767). Of course if you have that many rows, this method will take a long time to execute.


Toby Bascom pointed out that this example will crash if the database contains OLE fields or GUIDs. He offers this solution:

You can use the OpenSchema method of the Connection object to first scrutinize the "DATA_TYPE" value of each of the columns in the Access table you are attempting to export and if the "DATA_TYPE" value is adLongVarBinary then *exclude* that column from the SELECT statement.

Then create the Excel file & sheet with this. You do not need ADOX and the Excel file does *not* need to exist; it will be created by Jet if it does not.

 
Dim cSource As String
cSource = App.Path & _
    IIf(Right$(App.Path, 1) <> "\", "\", "") & _
    "books.mdb"

Dim cTarget As String
cTarget = App.Path & _
    IIf(Right$(App.Path, 1) <> "\", "\", "") & _
    "Books.xls].[Table1]"

Dim oCon As ADODB.Connection
Set oCon = New ADODB.Connection
Dim cSQL As String

With oCon
    .ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;" _
        & _
        "Data Source=" & cSource & ";" & _
        "Persist Security Info=False"

    .Open

    cSQL = "SELECT " & _
        "[Title],[URL],[ISBN],[Picture],[Pages],[CD],[Year] " & _
        "" & _
        "INTO [Excel 8.0;Database=" & cTarget " " & _
        "FROM [Books]"

    .Execute cSQL
End With
 

Michael Yereniuk of Chickenlip Consulting Corp pointed out a better way to autofit the columns, using the number of fields in the recordset to determine the number of columns rather than hard coding in the number.

 
 
Copyright © 1997-2010 Rocky Mountain Computer Consulting, Inc.   All rights reserved.
  Updated