【问题标题】:Insert into Access Select from Excel from within Access VBA插入 Access 从 Access VBA 中的 Excel 中选择
【发布时间】:2016-02-27 01:50:12
【问题描述】:

我有一个 Access 2010 数据库,其中所有表都链接到 SQL Server 2014 表。我有一个 Excel 2010 (.xlsx) 文件(虽然它以 .csv 开头,我可以保留它),我需要通过 VBA 代码将其导入 SQL Server 表。我知道可以使用导入工具来执行此操作,但是,我每月要导入 20 多个 XLS 文件,并且希望有一种自动化的方法来执行此操作。

我所有的 VBA 代码都驻留在 Access 数据库中,而我能够找到的所有 VBA 代码示例都是 推送 Excel 中的数据(即代码在 Excel 中)而不是 从 Access 中提取(即代码在 Access 中)。

我宁愿使用单个 INSERT INTO AccessTable SELECT FROM ExcelRange 查询而不是逐行读取 Excel,而且我需要在插入 Excel 数据之前对其进行一些转换。

到目前为止我所拥有的:

Private Sub TransferData(ByVal Company As String, ByVal Address As String, ByVal XLName As String)

Dim Con As ADODB.Connection
Dim SQLString As String

  SQLString = "INSERT INTO SatSurvey " & _
              "(ClinicID, Method, CollectionDate, Duration, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q10, Q11, Q12, Q13, Q14, Q15, Q16, Q17, Q18, Q19, Q20, Q21, Q22, Physician, Nurse, MedAst) " & _
              "SELECT " & _
              "('clinic name', IDFormat, IDendDate, IDtime, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q10, Q11, Q12, Q13, Q14, Q15, Q16, Q17, Q18, Q19, Q20, Q21, Q22, NZ(Q9s1,1), NZ(Q9s2,1), NZ(Q9s3,1)) " & _
              "  FROM [Excel 12.0;HDR=Yes;Database=" & XLName & "]." & Address

  Set Con = New ADODB.Connection
'  Con.ConnectionString = "Datasource=" & CurrentProject.Connection
  Con.ConnectionString = CurrentProject.Connection

'  Con.Properties(9).Value = "Extended Properties='Excel 12.0 Xml;HDR=YES';"
'  Con.Provider = "Microsoft.ACE.OLEDB.12.0;Extended Properties='Excel 12.0 Xml;HDR=YES';"

  Con.Open

  Con.Execute SQLString

End Sub

如您所见,我尝试了几种不同的方法来让事情正常进行。这似乎是我现在得到的最好的 except

运行时错误“-2147467259 (80004005)”:
数据库已被计算机“MINIT-EGHJSAU”上的用户“管理员”置于阻止其打开或锁定的状态。

指示的机器名称是 my 机器。由于代码是在我机器上的 Access 中运行的,因此我应该打开数据库似乎是合乎逻辑的。

我不喜欢这样做,所以欢迎任何修复或替代建议。

【问题讨论】:

  • 收到“状态”消息后,保存代码更改,运行压缩和修复,然后再次尝试运行代码。
  • 你真的应该参数化这些插入。按照编码,这很容易受到 sql 注入的影响。
  • 你看过 SSIS 吗?它是为处理这类事情而设计的。
  • @SeanLange - 我很欣赏 SQL 注入问题。但是,参数将来自数据库本身作为配置项。我们中只有 2 人可以设置参数,所以little Bobby Drop Tables 不太可能会过来。
  • 如果您对这些参数感到满意,那么这对我来说肯定不是问题。 :)

标签: vba ms-access ms-access-2010 excel-2010


【解决方案1】:

您不需要创建一个New ADODB.Connection 来连接到您当前在 Access 会话中打开的数据库。您的 Con 对象变量可以简单地引用 CurrentProject.Connection ...

Set Con = CurrentProject.Connection

然而,你甚至不需要那个对象变量。只需直接从CurrentProject.Connection 使用Execute 方法...

CurrentProject.Connection.Execute SQLString

这比你现在拥有的要简单,但我不确定它会消除 “阻止它被打开或锁定的状态......” 投诉。

既然您说“欢迎提出其他建议”,请考虑使用 DAO 而不是 ADO。并且不要在INSERT 查询的SELECT 部分的字段表达式列表周围包含括号(无论您选择ADO 还是DAO)。

Private Sub TransferData(ByVal Company As String, ByVal Address As String, ByVal XLName As String)
    Dim SQLString As String

    SQLString = "INSERT INTO SatSurvey " & _
                "(ClinicID, Method) " & _
                "SELECT '<location>', IDFormat " & _
                " FROM [Excel 12.0;HDR=Yes;Database=" & XLName & "]." & Address
    Debug.Print SQLString
    CurrentDb.Execute SQLString, dbFailOnError
End Sub

【讨论】:

  • 赢家,赢家,吃鸡! CurrentDb.Execute 成功了。非常感谢 HansUp!
【解决方案2】:

您可以在下面的链接中找到几种将数据从 Excel 移动到 SQL Server 的方法。

http://www.excel-sql-server.com/excel-import-to-sql-server-using-distributed-queries.htm

http://www.excel-sql-server.com/excel-sql-server-import-export-using-vba.htm#Excel%20Data%20Export%20to%20SQL%20Server%20Test%20Code

显然,您从 Excel 运行这些。另外,考虑使用 SQL Server 循环文件(与上面描述的相反)。

DECLARE @intFlag INT
SET @intFlag = 1
WHILE (@intFlag <=10000)
BEGIN

PRINT @intFlag


declare @fullpath1 varchar(1000)
select @fullpath1 = '''\\FTP\your_path' + convert(varchar, getdate()- @intFlag , 112) + '_your_file.txt'''
declare @cmd1 nvarchar(1000)
select @cmd1 = 'bulk insert [dbo].[your_table] from ' + @fullpath1 + ' with (FIELDTERMINATOR = ''\t'', FIRSTROW = 2, ROWTERMINATOR=''0x0a'')'
exec (@cmd1)


SET @intFlag = @intFlag + 1

END
GO

此脚本假定您的文件在文件名中有一个日期。希望您的 Excel 文件在文件名中有某种模式,您可以利用它。

【讨论】:

  • 哇。这看起来真的很有用ryguy,谢谢!我正在使用 HansUp 的建议,特别是因为我需要修改来自 Excel 的数据,但对于直接导入数据肯定会很方便。
【解决方案3】:

我发现通过从 Excel 中实际链接或导入表格更容易做到(和调试!)。然后你就可以像使用任何其他表格一样使用它了。

DoCmd.TransferSpreadsheet acLink, acSpreadsheetTypeExcel12Xml, "TempImport", XLName, True
' If the range is needed, linking doesn't work. Use import instead.
DoCmd.TransferSpreadsheet acImport, acSpreadsheetTypeExcel12Xml, "TempImport", XLName, True, Address

SQLString = "INSERT INTO SatSurvey ... SELECT ... FROM TempImport"
CurrentDb.Execute SQLString

' Clean up temp table
DoCmd.DeleteObject acTable, "TempImport"

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-06
    相关资源
    最近更新 更多