Excel 到 SQL 表与 VB.net

Posted

技术标签:

【中文标题】Excel 到 SQL 表与 VB.net【英文标题】:Excel to SQL Table with VB.net 【发布时间】:2014-04-17 14:36:55 【问题描述】:

我已阅读其他用户关于此主题的所有文章和帖子,但我仍然陷入困境。

基本上我拥有的是一个带有本地 SQL 后端的 VB.net 程序。我创建了一个名为“consolDump”的表,我希望将 Excel 工作表导入其中。我觉得我很接近从其他有类似问题的人那里得到的帮助。澄清一下,我没有能力向我正在使用的机器添加软件(它受到 IT 的严格限制),也无权访问 SQL Server 导入实用程序。

这是我的代码。任何帮助,将不胜感激。

Imports System.Data.SqlClient
Public Class formImport

    Private Sub buttonConsolImport_Click(sender As Object, e As EventArgs) Handles buttonConsolImport.Click

        Dim MyConnection As System.Data.OleDb.OleDbConnection
        Dim DtSet As System.Data.DataSet
        Dim MyCommand As System.Data.OleDb.OleDbDataAdapter
        Dim fBrowse As New OpenFileDialog
        Dim fname As String

        Try
            With fBrowse
                .Filter = "Excel files(*.xls)|*.xls|All files (*.*)|*.*"
                .FilterIndex = 1
                .Title = "Import data from Excel file"

            End With
            If fBrowse.ShowDialog() = Windows.Forms.DialogResult.OK Then

                fname = fBrowse.FileName
                MyConnection = New System.Data.OleDb.OleDbConnection _
                    ("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & fname & ";" & "Extended Properties=""Excel 8.0;HDR=NO;IMEX=1""")
                MyCommand = New System.Data.OleDb.OleDbDataAdapter("A1, B1, C1, D1, E1, F1, G1, H1, I1, J1, k1, L1 from [consol_data$]", MyConnection)
                MyCommand.TableMappings.Add("Table", "consolDump")
                DtSet = New System.Data.DataSet
                MyCommand.Fill(DtSet)

                For Each Drr As DataRow In DtSet.Tables(0).Rows
                    Execute_Local("INSERT INTO consolDump(PO_Number, Consol_ID, Status, Contractor, UTAS_Owner, Description, Start_Date, End_Date, Total_Spend, ) VALUES ('" & Drr(0).ToString & "','" & Drr(1).ToString & "','" & Drr(2).ToString & "'),'" & Drr(3).ToString & "','" & Drr(4).ToString & "','" & Drr(5).ToString & "','" & Drr(6).ToString & "','" & Drr(7).ToString & "','" & Drr(8).ToString & "','" & Drr(9).ToString & "','" & Drr(10).ToString & "','" & Drr(11).ToString & "'")
                Next
                MsgBox("Success")
                MyConnection.Close()
            End If
        Catch ex As Exception
            MessageBox.Show(ex.ToString)
        End Try

    End Sub

好的,为了补充我的问题,我正在尝试使用此代码从 Excel 工作表中导入一个 csv 文件,它工作正常。

    'Converts consol data to csv file===========================
    Dim excelApplication As New Excel.Application
    Dim excelWrkBook As Excel.Workbook

    excelApplication.Visible = False
    excelApplication.DisplayAlerts = False
    excelWrkBook = excelApplication.Workbooks.Open("R:\PECOE-WLOX\QuEST\Torres\sqlProjects\consol_data.xls")
    excelWrkBook.SaveAs(Filename:="R:\PECOE-WLOX\QuEST\Torres\sqlProjects\consol_data.csv", FileFormat:=Microsoft.Office.Interop.Excel.XlFileFormat.xlCSV)

    excelWrkBook.Close()
    excelApplication.DisplayAlerts = True
    excelApplication.Quit()
    MessageBox.Show("Converted to CSV")
    '============================================================

现在我正在尝试将 csv 文件导入新数据表,但我收到一个奇怪的错误,提示“system.data.sql 是一个命名空间,不能用作表达式”。现在这可能是我的经验不足,因为我从另一个站点提取了代码,并且有几个人说他们可以正常工作。我已经修改它以适合我的数据。任何帮助,将不胜感激。该错误在“Dim cmd As New SqlClient.SqlCommand(Sql, connection)”上显示为语法错误。它将括号中的 Sql 突出显示为命名空间。

    Dim consolDump1 As New DataTable()

    consolDump1.Columns.Add("PO_Number")
    consolDump1.Columns.Add("Consol_ID")
    consolDump1.Columns.Add("Status")
    consolDump1.Columns.Add("Contractor")
    consolDump1.Columns.Add("UTAS_Owner")
    consolDump1.Columns.Add("Description")
    consolDump1.Columns.Add("Start_Date")
    consolDump1.Columns.Add("End_Date")
    consolDump1.Columns.Add("Total_Spend")
    consolDump1.Columns.Add("Job_Title")
    consolDump1.Columns.Add("Location")
    consolDump1.Columns.Add("Type")

    Dim parser As New FileIO.TextFieldParser("R:\PECOE-WLOX\QuEST\Torres\sqlProjects\consol_data.csv")

    parser.Delimiters = New String() "," ' fields are separated by comma
    parser.HasFieldsEnclosedInQuotes = True ' each of the values is enclosed with double quotes
    parser.TrimWhiteSpace = True

    parser.ReadLine()

    Do Until parser.EndOfData = True
        consolDump1.Rows.Add(parser.ReadFields())
    Loop

    Dim strSql As String = "INSERT INTO consolDump(PO_Number,Consol_ID,Status,Contractor,UTAS_Owner,Description,Start_Date,End_Date,Total_Spend,Job_Title,Location,Type) VALUES (@PO_Number,@Consol_ID,@Status,@Contractor,@UTAS_Owner,@Description,@Start_Date,@End_Date,@Total_Spend,@Job_Title,@Location,@Type)"
    Dim SqlconnectionString As String = "Data Source=(LocalDB)\v11.0;AttachDbFilename=|DataDirectory|\consolData.mdf;Integrated Security=True;Connect Timeout=30"

    Using connection As New SqlClient.SqlConnection(SqlconnectionString)
        Dim cmd As New SqlClient.SqlCommand(Sql, connection)

        ' create command objects and add parameters
        With cmd.Parameters
            .Add("@PO_Number", SqlDbType.VarChar, 15, "PO_Number")
            .Add("@Consol_ID", SqlDbType.BigInt, "Consol_ID")
            .Add("@Status", SqlDbType.Text, "Status")
            .Add("@Contractor", SqlDbType.Text, "Contractor")
            .Add("@UTAS_Owner", SqlDbType.Text, "UTAS_Owner")
            .Add("@Description", SqlDbType.Text, "Description")
            .Add("@Start_Date", SqlDbType.Date, "Start_Date")
            .Add("@End_Date", SqlDbType.Date, "End_Date")
            .Add("@Total_Spend", SqlDbType.Money, "Total_Spend")
            .Add("@Job_Title", SqlDbType.Text, "Job_Title")
            .Add("@Location", SqlDbType.Text, "Location")
            .Add("@Type", SqlDbType.Text, "Type")
        End With

        Dim adapter As New SqlClient.SqlDataAdapter()
        adapter.InsertCommand = cmd

        '--Update the original SQL table from the datatable
        Dim iRowsInserted As Int32 = adapter.Update(consolDump1)

    End Using

End Sub

【问题讨论】:

请澄清您的问题到底是什么。还包括您收到的所有(如果有)错误或其他消息。 我很抱歉。我在写我的原始帖子时被跟踪了。我需要导入一个 Excel 表并将该数据转储到名为 consolDump 的数据表中。 现在我在 For 循环中的“execute_local”上遇到语法错误。 【参考方案1】:

在你的 sql 查询的列列表末尾多了一个逗号:

End_Date、Total_Spend、)

你需要这个:

End_Date, Total_Spend)

此外,列列表有 9 个项目,但您的值列表有 12 个。您可能缺少几列吗?

最后,对于本节,个人使用的代码无关紧要,但是您使用字符串连接将 excel 数据放入查询中的做法被认为是不好的做法。如果您在产品代码中这样做,您将创建一个巨大的安全漏洞。相反,请了解参数化查询。

在后面的示例中,您可以这样定义 sql 字符串:

Dim strSql As String

但请尝试以这种方式包含在您的命令中:

Dim cmd As New SqlClient.SqlCommand(Sql, ...

你应该这样做:

Dim cmd As New SqlClient.SqlCommand(strSql, ...

另外,根据其他代码,如果这是一个 access 数据库,您应该仍然使用 System.Data.OleDb 命名空间中的 OleDbCommandOleDbConnection 对象。

我要做的是介于您的第一个样本和第二个样本之间:

Imports System.Data.SqlClient

Private Sub buttonConsolImport_Click(sender As Object, e As EventArgs) Handles buttonConsolImport.Click

    Dim fBrowse As New OpenFileDialog
    With fBrowse
        .Filter = "Excel files(*.xls)|*.xls|All files (*.*)|*.*"
        .FilterIndex = 1
        .Title = "Import data from Excel file"
    End With

    If fBrowse.ShowDialog() <> Windows.Forms.DialogResult.OK Then Exit Sub
    Dim fname As String = fBrowse.FileName

    Dim sql As String = "INSERT INTO consolDump(PO_Number,Consol_ID,[Status],Contractor,UTAS_Owner,Description,Start_Date,End_Date,Total_Spend,Job_Title,Location,Type) VALUES (@PO_Number,@Consol_ID,@Status,@Contractor,@UTAS_Owner,@Description,@Start_Date,@End_Date,@Total_Spend,@Job_Title,@Location,@Type)"

    Try 
        Dim parser As New FileIO.TextFieldParser(fname)
        parser.Delimiters = New String() "," ' fields are separated by comma
        parser.HasFieldsEnclosedInQuotes = True ' each of the values is enclosed with double quotes
        parser.TrimWhiteSpace = True

        parser.ReadLine() 'skip column headers

        Using cn As New SqlConnection("Data Source=(LocalDB)\v11.0;AttachDbFilename=|DataDirectory|\consolData.mdf;Integrated Security=True"), 
              cmd As New SqlCommand(sql, cn)

            With cmd.Parameters
                .Add("@PO_Number", SqlDbType.VarChar, 15)
                .Add("@Consol_ID", SqlDbType.BigInt)
                .Add("@Status", SqlDbType.Text) 'I doubt that "Text" is the right type for all of these
                .Add("@Contractor", SqlDbType.Text) 'If it is, you may want to examine your table schema
                .Add("@UTAS_Owner", SqlDbType.Text)
                .Add("@Description", SqlDbType.Text)
                .Add("@Start_Date", SqlDbType.Date)
                .Add("@End_Date", SqlDbType.Date)
                .Add("@Total_Spend", SqlDbType.Money)
                .Add("@Job_Title", SqlDbType.Text)
                .Add("@Location", SqlDbType.Text)
                .Add("@Type", SqlDbType.Text)
            End With

            cn.Open()
            Do Until parser.EndOfData = True
                Dim fields() As String = parser.ReadFields()
                For i As Integer = 0 To 11
                    cmd.Parameters(i).Value = fields(i)
                Next
                cmd.ExecuteNonQuery()
            Loop
        End Using
        MsgBox("Success")

    Catch ex As Exception
        MessageBox.Show(ex.ToString)
    End Try

End Sub

【讨论】:

谢谢。第一个包含计算错误的列的代码块和诸如此类的东西不再在项目中。 csv 转换后的所有内容现在都在那里。也就是说,在 cmd 中更改为“Dim cmd As New SqlClient.SqlCommand(strSql, ...”清除了语法错误,因此它现在运行。导入时抛出“未处理的 'System.InvalidCastException' 异常发生在Microsoft.VisualBasic.dll”。它不喜欢“状态”字段。它认为我正在尝试转换为整数。 哦,谢谢。我将花一些时间研究参数化查询以获取我自己的知识。对于这个项目,csv 导入应该足够了。它是一个程序的一部分,该程序将离线并在内部使用在严密保护的网络上,并且无法从外部访问,因此安全不是问题。 @CTTKDKing 我添加了一些代码。它经过了几次修改,所以如果您之前看到过,值得再看一遍。 添加了我在您的代码中遇到的错误的屏幕截图。否则它运行良好,没有错误,非常感谢您的帮助。 @CTTKDKing 你必须调试这个。我在没有测试的情况下直接在回复窗口中输入了我的答案,因为我没有你的测试材料。查看错误,这似乎是基本的调试问题。您应该能够单步调试 Visual Studio 中的代码以查看问题所在。

以上是关于Excel 到 SQL 表与 VB.net的主要内容,如果未能解决你的问题,请参考以下文章

使用 vba TransferSpreadsheet 将 Aaccess 表与 Excel 链接

sql如何将一个表与另外一张表相关联

想筛选出excel表格A表与B表内姓名与身份证号码相同的数据,那个啥函数不会用

MySQL表与数据向Oracle移植(使用Oracle SQL Developer工具)

如何将文件表与SQL Server中的现有表链接

如何设置SQL数据库表与表的关联关系?