【问题标题】:Importing Excel worksheet range to Ms Access Table将 Excel 工作表范围导入 Ms Access 表
【发布时间】:2018-07-25 02:38:34
【问题描述】:

下午好,

我创建了一个将数据上传到访问数据库的宏(都在我的桌面上)。问题是当我尝试扩大范围时不断出错。

我以为这很简单,但似乎我忽略了。

这是代码 - 基本上我想包含该列或将其设置为动态范围?你能帮忙吗?

Sub AccessCode()

    Application.ScreenUpdating = False

    Dim db As Database
    Dim rs As DAO.Recordset

    Set db = OpenDatabase("C:\Users\user\Desktop\Test Copy.accdb")
    Set rs = db.OpenRecordset("Fact Table", dbOpenTable)

    rs.AddNew
    rs.Fields("GUID") = Range("g2").Value
    rs.Fields("StageID") = Range("h2").Value
    rs.Fields("Sync Date") = Range("i2").Value
    rs.Fields("Forecast HP") = Range("j2").Value
    rs.Fields("Owner Id") = Range("k2").Value
    rs.Fields("Recent Modified Flag") = Range("L2").Value
    rs.Fields("Upload Date") = Range("M2").Value

    rs.Update
    rs.Close
    db.Close

    Application.ScreenUpdating = True
    MsgBox " Upload To PMO Database Successful."

End Sub

【问题讨论】:

    标签: excel ms-access vba


    【解决方案1】:

    只是想我会添加一个替代@Erik von Asmuth 的出色答案。我在一个真实的项目中使用这样的东西。对于导入动态范围来说,它更健壮一些。

    Public Sub ImportFromWorksheet(sht As Worksheet)
    
        Dim strFile As String, strCon As String
    
        strFile = sht.Parent.FullName
    
        strCon = "Excel 12.0;HDR=Yes;Database=" & strFile
    
        Dim strSql As String, sqlTransferFromExcel As String
    
        Dim row As Long
        row = sht.Range("A3").End(xlDown).row
        Dim rng As Range
    
        sqlTransferFromExcel = " Insert into YourTable( " & _
                    " [GUID] " & _
                    " ,StageID " & _
                    " ,[sync Date] " & _
                    " ,[etc...] " & _
                    " ) " & _
                    " SELECT [GUID] " & _
                    " ,StageID " & _
                    " ,[sync Date] " & _
                     " ,[etc...] " & _
                    " FROM [{{connString}}].[{{sheetName}}$G2:M{{lastRow}}]"
    
        sqlTransferFromExcel = Replace(sqlTransferFromExcel, "{{lastRow}}", row)
        sqlTransferFromExcel = Replace(sqlTransferFromExcel, "{{connString}}", strCon)
        sqlTransferFromExcel = Replace(sqlTransferFromExcel, "{{sheetName}}", sht.Name)
    
        CurrentDb.Execute sqlTransferFromExcel
    
    End Sub
    

    【讨论】:

    • 这当然是更好的包装,功能齐全的解决方案,但是ADODB.ConnectionADODB.Recordset 是什么?此外,您假设第 1 行包含标题(它可能应该,但尚未指定)
    • @ErikvonAsmuth 啊,你说的太对了。我以前以不同的方式使用它。我想我没有完全清理它。你对列标题是正确的。我猜你可以修改strCon 字符串/让它成为一个输入参数。
    • 看起来很棒!但这会从访问中导入?我正在尝试(并且到目前为止失败)从 excel 到访问来做到这一点
    • @SIRO1 如果您使用 db. 而不是 CurrentDb,您可以从 Excel 运行它
    【解决方案2】:

    您可以使用查询而不是遍历记录集:

    Sub AccessCode()
        Application.ScreenUpdating = False
        Dim db As Database
        Dim rs As DAO.Recordset
    
        Set db = OpenDatabase("C:\Users\user\Desktop\Test Copy.accdb")
        db.Execute "INSERT INTO [Fact Table] ([GUID], [StageID], etc) " & _
        "SELECT * FROM [SheetName$G:M] " & _
        "IN """ & ActiveWorkbook.FullName & """'Excel 12.0 Macro;HDR=No;'"
    End Sub
    

    这有很多优点,例如通常更快,因为您不必遍历所有字段。

    如果您从 Access 而不是 Excel 触发导入,您甚至不需要 VBA 来执行查询。

    【讨论】:

    • FROM 子句应具有 Excel 工作表名称,范围为 SheetName$[G:M]。我第一次看到IN 与 Excel 工作簿一起使用。但是对于双引号/单引号组合,我会使用FROM [Excel 12.0 Xml;HDR=No;Database=C:\Path\To\Workbook.xlsx].[SheetName$G:M]。但将此添加到我的笔记中。
    • 是的,报价组合有点奇怪。我采用它是为了避免 Access 在 SQL 中将两个单引号转换为文字双引号,并且没有 lot 的引号来解释这一点。非 IN 子句语法更加清晰(我对它不太熟悉)。仅当有多个工作表时才需要指定工作表名称,但这是一个很好的补充。我已经编辑了我的答案。
    • 感谢您的回复!同意访问触发器会更容易,但我正在为不想使用仅访问 Excel 工作表的人开发这个。我现在收到错误 3127 - 我的表名是正确的,但它说有一个未知字段 - 我遗漏了什么明显的东西?
    • 您是否已将etc 替换为所有其他字段?这是et cetera的缩写
    • 是的,肯定有 - “插入 [Fact Table] ([GUID],[StageID],[EDB Sync Date],[Forecast HP],[Owner Id],[Recent Modified Flag], [上传日期]) " & _ "SELECT * FROM [EDITS$G:M] " & _ "IN """ & ActiveWorkbook.FullName & """'Excel 12.0 Macro;HDR=No;'" - 我已经尝试使用下划线,感叹号认为这是愚蠢的。上面有什么突出的问题吗?空格会导致问题吗?
    【解决方案3】:

    rs 部分更改为此:

    With rs
        .addnew
        !GUID = Range("g2").Value
        !StageID = Range("h2").Value
        '...etc
        .Update
    End With
    

    MSDN source

    使用 AddNew 方法在记录集命名的 Recordset 对象中创建和添加一条新记录。此方法将字段设置为默认值,如果未指定默认值,则将字段设置为 Null(为表类型 Recordset 指定的默认值)。

    修改新记录后,使用 Update 方法保存更改并将记录添加到 Recordset。在您使用 Update 方法之前,数据库中不会发生任何更改。

    编辑: 当您使用上面的代码更改 rs 部分时,您的代码应该是这样的:

    Sub AccessCode()
    
        Application.ScreenUpdating = False
    
        Dim db As Database
        Dim rs As DAO.Recordset
    
        Set db = OpenDatabase("C:\Users\user\Desktop\Test Copy.accdb")
        Set rs = db.OpenRecordset("Fact Table", dbOpenTable)
        
        With rs
            .addnew
            !GUID = Range("g2").Value
            !StageID = Range("h2").Value
            '...etc
            .Update
            .Close
        End With
    
        Application.ScreenUpdating = True
        MsgBox " Upload To PMO Database Successful."
    
    End Sub
    

    【讨论】:

    • 我收到“编译错误 - 预期以结尾” 我还需要包含所有 G 列 - 以上似乎不起作用
    • @SIRO1 - 编译错误是 VBA 中最好的错误。 (没有讽刺意味 - 它们是调试中最容易和最快的解决方案)。试一试,你可能在最后错过了End With 之类的。
    • 啊是结束了是问题 - 这让我回到设置仍然是大问题的范围?有什么想法吗?感谢您的意见!
    • @SIRO1 - 您是否尝试过 Edit 下的代码?它仍然会抛出错误吗?
    • !GUID = Range("G:G").Value 我认为这会起作用,但它没有
    猜你喜欢
    • 2018-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-09
    • 1970-01-01
    • 2011-11-16
    • 2018-01-18
    • 1970-01-01
    相关资源
    最近更新 更多