如何动态读取Excel工作表而不指定工作表的名称

时间:2016-04-08 19:19:11

标签: vb.net excel vba excel-vba

Dim MyConnection As System.Data.OleDb.OleDbConnection
        Dim DtSet As System.Data.DataSet
        Dim MyCommand As System.Data.OleDb.OleDbDataAdapter
        Dim filePath = GlobalVariable.savedPath + GlobalVariable.excelFileName

        'Code to Use an Oledb Connection to get data from the Excel File
        MyConnection = New System.Data.OleDb.OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & filePath & ";Extended Properties='Excel 12.0 Xml;HDR=YES;';")
        'Code to Read the Sheet Selected from the Excel Spread Sheet'
        MyCommand = New System.Data.OleDb.OleDbDataAdapter("select * from [Sheet1$]", MyConnection)
        '-- Extra Code Not Needed which Maps the tables as Columns from the Spreadsheet
        'MyCommand.TableMappings.Add("Table", "Net-informations.com")
        DtSet = New System.Data.DataSet
        MyCommand.Fill(DtSet)
        'Populates GridView with the excel Spreadsheet
        GridView1.DataSource = DtSet.Tables(0)
        'Code Below needed to show the excel to GridView
        GridView1.DataBind()
        MyConnection.Close()

此代码基本上在网格视图中使用select * from Sheet1$显示excel文件。但是,我希望数据源中的任何文件都能动态显示excel表。

1 个答案:

答案 0 :(得分:1)

以下将通过OleDb从特定的Excel文件中收集工作表名称,不幸的是,在获取工作表时对a-z进行排序,而不像Excel自动化,您可以通过顺序位置收集工作表名称。

接下来,正如我相信你知道但无论如何都要说的那样,工作表的第一行可以是列名或数据,并且取决于需要为正确的连接字符串设置连接字符串(如图所示)在代码中)但没有真正的方法来确定这一点,通常是“你知道它”或“客户决定”。

首先,支持类(取自this code sample

Imports System.Data.OleDb
Public Class Connections
    Public Sub New()
    End Sub
    ''' <summary>
    ''' Create a connection where first row contains column names
    ''' </summary>
    ''' <param name="FileName"></param>
    ''' <param name="IMEX"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <System.Diagnostics.DebuggerStepThrough()> _
    Public Function HeaderConnectionString(ByVal FileName As String, Optional ByVal IMEX As Integer = 1) As String
        Dim Builder As New OleDbConnectionStringBuilder
        If IO.Path.GetExtension(FileName).ToUpper = ".XLS" Then
            Builder.Provider = "Microsoft.Jet.OLEDB.4.0"
            Builder.Add("Extended Properties", String.Format("Excel 8.0;IMEX={0};HDR=Yes;", IMEX))
        Else
            Builder.Provider = "Microsoft.ACE.OLEDB.12.0"
            Builder.Add("Extended Properties", String.Format("Excel 12.0;IMEX={0};HDR=Yes;", IMEX))
        End If

        Builder.DataSource = FileName

        Return Builder.ToString

    End Function
    ''' <summary>
    ''' Create a connection where first row contains data
    ''' </summary>
    ''' <param name="FileName"></param>
    ''' <param name="IMEX"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <System.Diagnostics.DebuggerStepThrough()> _
    Public Function NoHeaderConnectionString(ByVal FileName As String, Optional ByVal IMEX As Integer = 1) As String
        Dim Builder As New OleDbConnectionStringBuilder
        If IO.Path.GetExtension(FileName).ToUpper = ".XLS" Then
            Builder.Provider = "Microsoft.Jet.OLEDB.4.0"
            Builder.Add("Extended Properties", String.Format("Excel 8.0;IMEX={0};HDR=No;", IMEX))
        Else
            Builder.Provider = "Microsoft.ACE.OLEDB.12.0"
            Builder.Add("Extended Properties", String.Format("Excel 12.0;IMEX={0};HDR=No;", IMEX))
        End If

        Builder.DataSource = FileName

        Return Builder.ToString

    End Function
End Class

另一个支持类

Imports System.Data.OleDb

Public Class Utility
    Public Sub New()
    End Sub
    ''' <summary>
    ''' Returns a list of sheet names from Excel or table names from Access
    ''' </summary>
    ''' <param name="ConnectionString"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function SheetNames(ByVal ConnectionString As String) As List(Of SheetNameData)
        Dim Names As New List(Of SheetNameData)

        Using cn As New OleDbConnection(ConnectionString)
            cn.Open()
            Dim dt As DataTable = New DataTable With {.TableName = "AvailableSheetsTables"}
            dt = cn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, New Object() {Nothing, Nothing, Nothing, "TABLE"})
            cn.Close()

            Names =
                (
                    From F In dt.Rows.Cast(Of DataRow)()
                    Select New SheetNameData With
                           {
                               .DisplayName = F.Field(Of String)("TABLE_NAME").Replace("$", ""),
                               .ActualName = F.Field(Of String)("TABLE_NAME")
                           }
                ).ToList

        End Using

        Return Names
    End Function
End Class
Public Class SheetNameData
    Public Sub New()

    End Sub
    Public Property DisplayName As String
    Public Property ActualName As String

End Class

首先要注意的是文件名和路径是硬编码的,没有检查是否存在,因为整个回复是一个样本,保持手头的任务。在按钮点击事件中,我们得到了工作表名称,这当然可以在另一个事件中完成,例如形式负荷。工作表名称放在强类型列表中,选择第一个工作表(如果不确定是否有工作表,则将使用断言)。我打开第一行的工作表作为数据,如果你的列有标题我也包含了一个连接方法。 DataTable使用已使用的行和列加载,DataTable成为DataGridView的DataSource。

Public Class Form1
    Private FileName As String = IO.Path.Combine(
        AppDomain.CurrentDomain.BaseDirectory, "PeopleData.xlsx")
    Private Connection As Connections = New Connections
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim Utils = New Utility

        Dim SheetsList As List(Of SheetNameData) = Utils.SheetNames(
            Connection.NoHeaderConnectionString(IO.Path.GetFileName(FileName)))

        Dim dt As New DataTable
        Dim ConnectionString As String = Connection.NoHeaderConnectionString(FileName)

        Using cn As New OleDb.OleDbConnection With {.ConnectionString = ConnectionString}
            Using cmd As New OleDb.OleDbCommand(
                String.Format("SELECT * FROM [{0}]",
                              SheetsList.FirstOrDefault.ActualName),
                          cn)
                cn.Open()
                dt.Load(cmd.ExecuteReader)
            End Using
        End Using

        DataGridView1.DataSource = dt

    End Sub
End Class

结束备注,如果您需要特定的工作表,而不是随机工作表,则必须打开每张工作表,检查预期的数据,例如如果第一行有字段/列名称读取第一行并使用连接字符串对无标题进行有效,则在找到正确的表单后,使用带有标题集的连接字符串加载它。

希望这会有所帮助: - )