使用 VBA 将 Excel 数据导入 SQL 服务器 table

Import Excel data using VBA into a SQL Server table

这是我在 Sheet1 中的 VBA 脚本,其中包含导出和导入

Option Explicit

Private Sub cmdExport_Click()
On Error GoTo ErrExit

Dim cn_ADO As ADODB.Connection
Dim rs_ADO As ADODB.Recordset
Dim cmd_ADO As ADODB.Command

Dim SQLUser As String
Dim SQLPassword As String
Dim SQLServer As String
Dim DBName As String
Dim DbConn As String

Dim SQLQuery As String

Dim strStatus As String
Dim i As Integer
Dim j As Integer
Dim jOffset As Integer
Dim iStartRow As Integer
Dim iStep As Integer

Dim strCurrentValue As String
Dim strLastValue As String
Dim lColorIndex As Integer

iStep = 100
jOffset = 4
iStartRow = 8
i = iStartRow

SQLUser = "sa"
SQLPassword = "12345"
SQLServer = "DESKTOP-5877NMS\SQLEXPRESS"
DBName = "kpi"

DbConn = "Provider=SQLOLEDB.1;Persist Security Info=True;User ID=" & SQLUser & ";Password=" & SQLPassword & ";Initial Catalog=" & DBName & ";" & _
        "Data Source=" & SQLServer & ";Use Procedure for Prepare=1;Auto Translate=True;Packet Size=4096;" & _
        "Use Encryption for Data=False;Tag with column collation when possible=False"

Set cn_ADO = New ADODB.Connection
cn_ADO.Open DbConn

SQLQuery = "select "
SQLQuery = SQLQuery + "[ID], "
SQLQuery = SQLQuery + "[F2], "
SQLQuery = SQLQuery + "[2019], "
SQLQuery = SQLQuery + "[2020], "
SQLQuery = SQLQuery + "[Jan], "
SQLQuery = SQLQuery + "[Feb], "
SQLQuery = SQLQuery + "[Mar], "
SQLQuery = SQLQuery + "[Apr], "
SQLQuery = SQLQuery + "[May], "
SQLQuery = SQLQuery + "[Jun], "
SQLQuery = SQLQuery + "[Jul], "
SQLQuery = SQLQuery + "[Aug], "
SQLQuery = SQLQuery + "[Sep], "
SQLQuery = SQLQuery + "[Oct], "
SQLQuery = SQLQuery + "[Nov], "
SQLQuery = SQLQuery + "[Dec], "
SQLQuery = SQLQuery + "[2021], "
SQLQuery = SQLQuery + "[Tgt], "
SQLQuery = SQLQuery + "[UOM] "
SQLQuery = SQLQuery + "from "
SQLQuery = SQLQuery + "dbo.RAWDATA1 "

Application.Cursor = xlWait
Application.StatusBar = "Logging onto database..."

Set cmd_ADO = New ADODB.Command

cmd_ADO.CommandText = SQLQuery
cmd_ADO.ActiveConnection = cn_ADO
cmd_ADO.Execute
        
' Open the recordset.
Set rs_ADO = New ADODB.Recordset
Set rs_ADO.ActiveConnection = cn_ADO
rs_ADO.Open cmd_ADO

Range(Cells(i, 1), Cells(Rows.Count, jOffset + rs_ADO.Fields.Count)).Clear
Cells(1, 1).Select

Application.StatusBar = "Formatting columns..."
   
'Output Columns names
For j = 0 To rs_ADO.Fields.Count - 1
    Cells(i, j + jOffset).Value = rs_ADO.Fields(CLng(j)).Name
    Cells(i, j + jOffset).Font.Bold = True
    Cells(i, j + jOffset).Select
    
    With Selection.Interior
        If rs_ADO.Fields(CLng(j)).Name = "2019" Or _
                rs_ADO.Fields(CLng(j)).Name = "2020" Or _
                rs_ADO.Fields(CLng(j)).Name = "Jan" Or _
                rs_ADO.Fields(CLng(j)).Name = "Feb" Or _
                rs_ADO.Fields(CLng(j)).Name = "Mar" Or _
                rs_ADO.Fields(CLng(j)).Name = "Apr" Or _
                rs_ADO.Fields(CLng(j)).Name = "May" Or _
                rs_ADO.Fields(CLng(j)).Name = "Jun" Or _
                rs_ADO.Fields(CLng(j)).Name = "Jul" Or _
                rs_ADO.Fields(CLng(j)).Name = "Aug" Or _
                rs_ADO.Fields(CLng(j)).Name = "Sep" Or _
                rs_ADO.Fields(CLng(j)).Name = "Oct" Or _
                rs_ADO.Fields(CLng(j)).Name = "Nov" Or _
                rs_ADO.Fields(CLng(j)).Name = "Dec" Or _
                rs_ADO.Fields(CLng(j)).Name = "2021" Then
            .Pattern = xlSolid
            .PatternColorIndex = xlAutomatic
            .Color = 5296274
            .TintAndShade = 0
            .PatternTintAndShade = 0
        Else
            .Pattern = xlSolid
            .PatternColorIndex = xlAutomatic
            .Color = 15773696
            .TintAndShade = 0
            .PatternTintAndShade = 0
        End If
    End With
    
    
    Next j
    
DoEvents
Application.Wait (Now + TimeValue("0:00:01"))
Application.ScreenUpdating = False

strStatus = "Loading data..."
Application.StatusBar = strStatus

lColorIndex = xlNone
'dataset output
While Not rs_ADO.EOF
    i = i + 1
    
    strCurrentValue = rs_ADO.Fields(0).Value
            
    If strCurrentValue = strLastValue Then
        lColorIndex = lColorIndex
    Else
        lColorIndex = IIf(lColorIndex = xlNone, 15, xlNone)
    End If
            
    For j = 0 To rs_ADO.Fields.Count - 1
        Cells(i, j + jOffset).Interior.ColorIndex = lColorIndex
        If lColorIndex <> xlNone Then
            Cells(i, j + jOffset).Interior.Pattern = xlSolid
        End If
                    
        Cells(i, j + jOffset).Value = rs_ADO.Fields(j).Value
    Next j
    rs_ADO.MoveNext
    
    If i - iStartRow < iStep Then
        Application.StatusBar = strStatus & " record count: " & i - iStartRow
    Else
        'a Mod b ==>> a - (b * (a \ b))
        If (i - iStartRow) - (iStep * ((i - iStartRow) \ iStep)) = 0 Then
            Application.StatusBar = strStatus & " record count: " & i - iStartRow
            DoEvents
        End If
    End If
Wend

'Close ADO and recordset
rs_ADO.Close
Set cn_ADO = Nothing
Set cmd_ADO = Nothing
Set rs_ADO = Nothing

Application.StatusBar = "Total record count: " & i - iStartRow
Application.Cursor = xlDefault
Application.ScreenUpdating = True

Exit Sub

ErrExit:
        MsgBox "Error: " & Err & " " & Error(Err)
        Application.StatusBar = False
        Application.Cursor = xlDefault

        If Not cn_ADO Is Nothing Then
            Set cn_ADO = Nothing
        End If
        If Not cmd_ADO Is Nothing Then
            Set cmd_ADO = Nothing
        End If
        If Not rs_ADO Is Nothing Then
            Set rs_ADO = Nothing
        End If
End Sub


Private Sub cmdImport_Click()
On Error GoTo ErrExit

Dim cn_ADO As ADODB.Connection
Dim cmd_ADO As ADODB.Command
    
Dim SQLUser As String
Dim SQLPassword As String
Dim SQLServer As String
Dim DBName As String
Dim DbConn As String

Dim SQLQuery As String
Dim strWhere As String

'Dim strStatus As String
Dim i As Integer
'Dim j As Integer
Dim jOffset As Integer
Dim iStartRow As Integer
'Dim iStep As Integer

'Data Columns
Dim strID As String
Dim strF2 As String
Dim str2019 As String
Dim str2020 As String
Dim strJan As String
Dim strFeb As String
Dim strMar As String
Dim strApr As String
Dim strMay As String
Dim strJun As String
Dim strJul As String
Dim strAug As String
Dim strSep As String
Dim strOct As String
Dim strNov As String
Dim strDec As String
Dim str2021 As String
Dim strTgt As String
Dim strUOM As String


'iStep = 100
jOffset = 4
iStartRow = 9
i = iStartRow

SQLUser = "sa"
SQLPassword = "12345"
SQLServer = "DESKTOP-5877NMS\SQLEXPRESS"
DBName = "kpi"

DbConn = "Provider=SQLOLEDB.1;Persist Security Info=True;User ID=" & SQLUser & ";Password=" & SQLPassword & ";Initial Catalog=" & DBName & ";" & _
        "Data Source=" & SQLServer & ";Use Procedure for Prepare=1;Auto Translate=True;Packet Size=4096;" & _
        "Use Encryption for Data=False;Tag with column collation when possible=False"

Set cn_ADO = New ADODB.Connection
cn_ADO.Open DbConn

Set cmd_ADO = New ADODB.Command

While Cells(i, jOffset).Value <> ""
    strID = Cells(i, 0 + jOffset).Value
    strF2 = Cells(i, 1 + jOffset).Value
    str2019 = Cells(i, 2 + jOffset).Value
    str2020 = Cells(i, 3 + jOffset).Value
    strJan = Cells(i, 4 + jOffset).Value
    strFeb = Cells(i, 5 + jOffset).Value
    strMar = Cells(i, 6 + jOffset).Value
    strApr = Cells(i, 7 + jOffset).Value
    strMay = Cells(i, 8 + jOffset).Value
    strJun = Cells(i, 9 + jOffset).Value
    strJul = Cells(i, 10 + jOffset).Value
    strAug = Cells(i, 11 + jOffset).Value
    strSep = Cells(i, 12 + jOffset).Value
    strOct = Cells(i, 13 + jOffset).Value
    strNov = Cells(i, 14 + jOffset).Value
    strDec = Cells(i, 15 + jOffset).Value
    str2021 = Cells(i, 16 + jOffset).Value
    strTgt = Cells(i, 17 + jOffset).Value
    strUOM = Cells(i, 18 + jOffset).Value

    strWhere = "ID = " & strID
    
    SQLQuery = "update dbo.RAWDATA1 " & _
                "set " & _
                "[2019] = '" & str2019 & "', " & _
                "[2020] = '" & str2020 & "', " & _
                "Jan = '" & strJan & "', " & _
                "Feb = '" & strFeb & "', " & _
                "Mar = '" & strMar & "', " & _
                "Apr = '" & strApr & "', " & _
                "May = '" & strMay & "', " & _
                "Jun = '" & strJun & "', " & _
                "Jul = '" & strJul & "', " & _
                "Aug = '" & strAug & "', " & _
                "Sep = '" & strSep & "', " & _
                "Oct = '" & strOct & "', " & _
                "Nov = '" & strNov & "', " & _
                "Dec = '" & strDec & "', " & _
                "[2021] = '" & str2021 & "' " & _
                "where " & strWhere



    cmd_ADO.CommandText = SQLQuery
    cmd_ADO.ActiveConnection = cn_ADO
    cmd_ADO.Execute
    
    i = i + 1
Wend

Set cmd_ADO = Nothing
Set cn_ADO = Nothing

Exit Sub

ErrExit:
        MsgBox "Error: " & Err & " " & Error(Err)
        Application.StatusBar = False
        Application.Cursor = xlDefault

        If Not cn_ADO Is Nothing Then
            Set cn_ADO = Nothing
        End If
        If Not cmd_ADO Is Nothing Then
            Set cmd_ADO = Nothing
        End If
End Sub

这是我的

SQL Table

Excel Data

Export SQL to Excel 完美运行,但是对于 Import Excel to SQL 当我按下 Import 按钮时它显示错误

-2147217913 error converting data type varchar to numeric

我是 VBA 和 SQL 的新手。

将SQL的末尾改为

 "[2021] = " & IIF(Len(str2021) = O, "Null",str2021) & _ ' no single quotes
 " where " & strWhere ' note added leading space

谢谢你们帮助我。我已经尝试按照 CDP1802 给出的评论和答案中所述更改 SQL 。它工作得很好。但是我尝试将所有值更改为 nvarchar(max) 除了 Id 并且它完美无误地工作。