簡體   English   中英

如何將訪問表中的數據寫入excel

[英]How do I write data from access tables to excel

我正在遍歷一個名為_TF_Tables的表,該表包含數據庫中需要為其創建 Excel 工作簿並填充該表中的數據的所有表的名稱。

當我逐行瀏覽腳本時,以下內容在調試模式下工作。 它創建一個空的 excel 文件,添加一個帶有表格名稱的新工作表,並使用表格名稱保存工作簿。

然后它查詢表中的所有數據並將其寫入新創建的 Excel 文件。

當我運行腳本時出現問題(不是在調試模式下)。 它在以下行給出錯誤:

adoConnnectionTF.Execute(strQuery)

錯誤

System.Runtime.InteropServices.COMException:'Microsoft Access 數據庫引擎找不到對象'TF_TT'。 確保對象存在並且正確拼寫其名稱和路徑名。 如果“TF_TT”不是本地對象,請檢查您的網絡

    Dim recordSetTables As Access.Dao.Recordset = dbTFFrom.OpenRecordset("_TF_Tables", Access.Dao.RecordsetTypeEnum.dbOpenDynaset)
    Dim Excel As Object
    Dim tempTableName As String
    Dim xlWorkSheet As Object
    Dim strQuery As String
    Do Until recordSetTables.EOF
        tempTableName = recordSetTables.Fields(0).Value

        Excel = CreateObject("Excel.Application")
        xlWorkSheet = Excel.workbooks.add
        xlWorkSheet.SaveAs("path\" & tempTableName & ".xlsx")
        xlWorkSheet = Nothing
        Excel.quit()
        Excel = Nothing

        strQuery = "SELECT * INTO [Excel 8.0;HDR=YES;DATABASE=path\" & tempTableName & ".xlsx].[" & tempTableName & "] FROM [" & tempTableName & "];"
        adoConnnectionTF.Execute(strQuery)

        recordSetTables.MoveNext()
    Loop
    recordSetTables.Close()
    recordSetTables = Nothing

strQuery 的輸出:
"SELECT * INTO [Excel 8.0;HDR=YES;DATABASE=path\TF_BLA.xlsx].[TF_BLA] FROM [TF_BLA];"

它會創建 1 個有時 2 個填充數據的 Excel 文件,但最終會出錯。 因為它不是一直為同一張桌子拋出的,所以很難理解

以上只是我將所需表格寫入 Excel 文件的嘗試。 替代解決方案也可以。

編輯 1
正如評論中所建議的,我將記錄集更改為 DAO(之前是 ADO),但是錯誤仍然存​​在。

編輯 2
正如評論中所建議的,將 Dim 語句置於循環之外,縮短了代碼並提供了strQuery的輸出

編輯 3 / 解決方案
我找到了解決方案。 以下從訪問文件中的表創建所需的 excel 文件

Dim dbTFFromAs Access.Dao.Database = workSpace.OpenDatabase(pathToTF)
Dim recordSetTables As Access.Dao.Recordset = dbTFFrom.OpenRecordset("_TF_Tables", Access.Dao.RecordsetTypeEnum.dbOpenDynaset)
Dim tempTableName As String
Dim strQuery As String
Do Until recordSetTables.EOF
   tempTableName = recordSetTables.Fields(0).Value

   strQuery = "SELECT * INTO [Excel 12.0 Xml;HDR=YES;DATABASE=\\DADI\MD\MDatabases\ExportedData\TT\" & tempTableName & ".xlsx].[" & tempTableName & "] FROM [" & tempTableName & "];"
   adoConnnectionTF.Execute(strQuery)
   recordSetTables.MoveNext()

Loop
recordSetTables.Close()
recordSetTables = Nothing 

下面展示了如何使用 OLE DB 從 Access 數據庫中讀取數據並使用 Excel Interop 將其插入 Excel 工作簿。 它已經過 Access 2016 和 Excel 2016 的測試。

先決條件

  • 已安裝 Microsoft Excel (>= 2007)

注意:您可以考慮使用以下 NuGet 包之一,而不是使用 Excel 互操作: DocumentFormat.OpenXml (另請參見:此處)、 ClosedXMLEPPlus 可能還有其他可用的。

添加參考

  • 在 VS 菜單中,單擊項目
  • 選擇添加參考...
  • 選擇COM
  • 選擇 Microsoft Excel xx.x 對象庫(例如:Microsoft Excel 16.0 對象庫)
  • 點擊確定

創建一個類(名稱:Helper.vb)

注意:檢查下面代碼中的“ToDo”項。 您需要將 Select 語句中的列名( SELECT tblName FROM _TF_TABLES order by tblName )替換為正確的列名。 此處定義的順序將決定工作表在 Excel 工作簿中的創建順序,以及工作表選項卡的順序。 此外,可能需要更改用於 Access 數據庫的連接字符串。 有關詳細信息,請參閱連接字符串

Imports System.Data.OleDb
Imports Excel = Microsoft.Office.Interop.Excel

Public Class Helper
    Private _connectionStringACE As String = String.Empty
    Private _connectionStringAceJet As String = String.Empty
    Private _connectionStringJet As String = String.Empty

    Public Sub New(filename As String)
        'ToDo: replace with connection string for the version that you're using
        'set value
        _connectionStringACE = String.Format("Provider = Microsoft.ACE.OLEDB.12.0; Data Source = {0};Persist Security Info=False;", filename)
        _connectionStringAceJet = String.Format("Provider = Microsoft.ACE.OLEDB.12.0; Data Source = {0};Jet OLEDB:Database Password=''", filename)
        _connectionStringJet = String.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};User Id=admin;Password=;", filename)
    End Sub

    Public Sub New(filename As String, password As String)
        'ToDo: replace with connection string for the version that you're using
        'set value
        _connectionStringAceJet = String.Format("Provider = Microsoft.ACE.OLEDB.12.0; Data Source = {0};Jet OLEDB:Database Password={1}", filename, password)
        _connectionStringJet = String.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};User Id=admin;Password={1};", filename, password)
    End Sub

    Public Function AccessGetTables() As DataTable
        'get all Access tables including system tables

        Dim dt As DataTable = New DataTable()

        Using con As OleDbConnection = New OleDbConnection(_connectionStringAceJet)
            'open
            con.Open()

            'get Access tables
            dt = con.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, Nothing)

            Return dt
        End Using
    End Function

    Private Function AccessGetDataFromSpecifiedTable(sqlText As String) As DataTable
        'get data from Access database

        Dim dt As DataTable = New DataTable()

        Debug.WriteLine($"sqlText: {sqlText}")

        Using con As OleDbConnection = New OleDbConnection(_connectionStringAceJet)
            'open
            con.Open()

            Using da As OleDbDataAdapter = New OleDbDataAdapter(sqlText, con)
                'get data
                da.Fill(dt)

                Return dt
            End Using
        End Using
    End Function

    Public Function AccessGetUserTables() As List(Of String)
        'get list of tables that were user created

        Dim userTables As List(Of String) = New List(Of String)

        'get Access tables
        Dim dt As DataTable = AccessGetTables()

        If dt IsNot Nothing AndAlso dt.Rows.Count > 0 Then
            For Each row As DataRow In dt.Rows
                'Debug.WriteLine($"{row("TABLE_NAME"),-25} {row("TABLE_TYPE"),25}")
                If row("TABLE_TYPE") IsNot DBNull.Value AndAlso row("TABLE_TYPE") IsNot Nothing AndAlso row("TABLE_TYPE").ToString() = "TABLE" Then
                    'add
                    userTables.Add(row("TABLE_NAME").ToString())
                End If
            Next
        End If

        Return userTables
    End Function

    Public Function ExcelCreateWorkbook(filename As String) As String
        Dim oMissing As Object = System.Reflection.Missing.Value

        Dim excelApp As Excel.Application = Nothing
        Dim excelWorkbook As Excel.Workbook = Nothing
        Dim excelWorksheet As Excel.Worksheet = Nothing

        Try
            'get data from _TF_TABLES
            'ToDo: replace 'tblName' with correct column name(s)
            Dim dtTfTables As DataTable = AccessGetDataFromSpecifiedTable("SELECT tblName FROM _TF_TABLES order by tblName")

            'if no data was found, throw an exception
            'ToDo: if desired, return an error message instead
            If dtTfTables Is Nothing OrElse dtTfTables.Rows.Count = 0 Then
                Throw New Exception("Error: No data was found.")
            End If

            'create New instance
            excelApp = New Excel.Application()

            'set Excel visability
            excelApp.Visible = True

            'suppress displaying alerts (such as prompting to overwrite existing file)
            excelApp.DisplayAlerts = False

            'disable user control while modifying the Excel Workbook
            'to prevent user interference
            'only necessary if Excel application Visibility property = true
            'excelApp.UserControl = False

            'add workbook
            excelWorkbook = excelApp.Workbooks.Add()

            'used to keep track of previous Worksheet
            Dim previousWorksheet As Excel.Worksheet = Nothing

            If excelWorkbook IsNot Nothing AndAlso excelWorkbook.Sheets.Count > 0 Then
                'set value
                previousWorksheet = CType(excelWorkbook.Sheets("Sheet1"), Excel.Worksheet)
            End If

            'loop for each table name found in _TF_TABLES
            For Each rowTf As DataRow In dtTfTables.Rows
                If rowTf(0) IsNot Nothing AndAlso rowTf(0) IsNot DBNull.Value Then
                    'add a worksheet And set the value to the New worksheet
                    excelWorksheet = CType(excelWorkbook.Sheets.Add(After:=previousWorksheet), Excel.Worksheet)

                    'set name
                    excelWorksheet.Name = rowTf(0).ToString()

                    'get data from specified table
                    Dim dt As DataTable = AccessGetDataFromSpecifiedTable($"SELECT * FROM {rowTf(0).ToString()}")

                    If dt IsNot Nothing AndAlso dt.Rows.Count > 0 Then
                        Debug.WriteLine($"Adding column headers for table: {rowTf(0).ToString()}")

                        'add column headers
                        For colIndex As Integer = 0 To dt.Columns.Count - 1
                            'indices are 1-based in Excel; A1 = Cells(1,1)
                            excelWorksheet.Cells(1, colIndex + 1) = dt.Columns(colIndex).ColumnName
                        Next

                        Debug.WriteLine($"Adding data for table: {rowTf(0).ToString()}")

                        Dim rowNum As Integer = 1
                        For Each rowDt As DataRow In dt.Rows
                            'increment
                            rowNum += 1

                            For colIndex As Integer = 0 To dt.Columns.Count - 1
                                Debug.WriteLine($"    rowNum: {rowNum}; colNum: {colIndex + 1}")

                                'indices are 1-based in Excel; A1 = Cells(1,1)
                                excelWorksheet.Cells(rowNum, colIndex + 1) = rowDt(colIndex)
                            Next
                        Next
                    End If

                    'set value
                    previousWorksheet = excelWorksheet
                End If
            Next

            If excelWorkbook IsNot Nothing AndAlso excelWorkbook.Sheets.Count > 0 Then
                excelWorksheet = CType(excelWorkbook.Sheets("Sheet1"), Excel.Worksheet)

                'delete existing worksheet
                excelWorksheet.Delete()
            End If

            If excelApp IsNot Nothing AndAlso excelWorkbook IsNot Nothing Then
                'save Workbook - if file exists, overwrite it
                excelWorkbook.SaveAs(filename, System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value, Excel.XlSaveAsAccessMode.xlNoChange, System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value)
            End If

        Catch ex As Exception
            Debug.WriteLine("Error (ExcelCreateWorkbook): " & ex.Message)
            Throw ex
        Finally
            If excelWorkbook IsNot Nothing Then
                excelWorkbook.Close()

                'release resource
                System.Runtime.InteropServices.Marshal.FinalReleaseComObject(excelWorkbook)
                excelWorkbook = Nothing
            End If

            If excelWorksheet IsNot Nothing Then
                'release resource
                System.Runtime.InteropServices.Marshal.FinalReleaseComObject(excelWorksheet)
                excelWorksheet = Nothing
            End If

            If excelApp IsNot Nothing Then
                excelApp.Quit()

                'release all resources
                System.Runtime.InteropServices.Marshal.FinalReleaseComObject(excelApp)
            End If
        End Try

        Return $"Created Excel Workbook: '{filename}'"
    End Function

End Class

用法(創建 Excel 工作簿)

Private _helper As Helper = Nothing
          ...

Private Sub btnCreateExcelWorkbook_Click(sender As Object, e As EventArgs) Handles btnCreateExcelWorkbook.Click
    Using ofd As OpenFileDialog = New OpenFileDialog()
        ofd.Filter = "Access Files (*.accdb)|*.accdb|All Files (*.*)|*.*"
        ofd.Title = "Choose Access Filename"

        If ofd.ShowDialog() = DialogResult.OK Then
            Using sfd As SaveFileDialog = New SaveFileDialog()
                sfd.Filter = "Excel File (*.xlsx)|*.xlsx|All Files (*.*)|*.*"
                sfd.FileName = "Test_TFTables.xlsx"
                sfd.Title = "Choose Excel Filename"

                If sfd.ShowDialog() = DialogResult.OK Then
                    'create new instance
                    _helper = New Helper(ofd.FileName)

                    'create Excel file
                    Dim result As String = _helper.ExcelCreateWorkbook(sfd.FileName)
                    Debug.WriteLine($"{result}")
                End If
            End Using
        End If
    End Using
End Sub

用法(從 Access 獲取表名)

Private _helper As Helper = Nothing
          ...

Private Sub btnGetAccessTables_Click(sender As Object, e As EventArgs) Handles btnGetAccessTables.Click
    Using ofd As OpenFileDialog = New OpenFileDialog()
        ofd.Filter = "Access Files (*.accdb)|*.accdb|All Files (*.*)|*.*"
        ofd.Title = "Choose Access Filename"

        If ofd.ShowDialog() = DialogResult.OK Then
            'create new instance
            _helper = New Helper(ofd.FileName)

            Dim userTables As List(Of String) = _helper.AccessGetUserTables()

            For Each tbl In userTables
                Debug.WriteLine(tbl)
            Next
        End If
    End Using
End Sub

這是用於測試的 Access 表定義(和一些數據):

_TF_TABLES

在此處輸入圖像描述

在此處輸入圖像描述


表 123

在此處輸入圖像描述

在此處輸入圖像描述


表 456

在此處輸入圖像描述

在此處輸入圖像描述


表 789

在此處輸入圖像描述


資源

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM