Insert into Access Select from Excel from within A

2020-07-22 18:46发布

I have an Access 2010 database with all tables linked to SQL Server 2014 tables. I have an Excel 2010 (.xlsx) file (though it starts as a .csv, and I could leave it that way), that I need to import into a SQL Server table via VBA code. I know that there are import tools available to do this, however, I have 20+ XLS files per month to import, and would rather have an automated method of doing this.

All my VBA code resides in the Access database, and all the examples of VBA code I've been able to find are for pushing data from Excel (i.e. the code is in Excel) not pulling from Access (i.e. the code is in Access).

I would prefer to do it with a single INSERT INTO AccessTable SELECT FROM ExcelRange query instead of reading Excel row by row, and I need to do some transformation on the Excel data before it's inserted.

What I have so far:

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

As you can see, I've tried a few different options to get things working. This seems to work the best except that I am now getting:

Run-time error '-2147467259 (80004005)':
The Database has been placed in a state by user 'Admin' on machine 'MINIT-EGHJSAU' that prevents it from being opened or locked.

The machine name indicated is my machine. Since the code is running from within Access on my machine, it seems logical that I would have had the database open.

I'm not tied to doing it this way, so any fixes or alternate suggestions are welcome.

3条回答
够拽才男人
2楼-- · 2020-07-22 19:17

You will find several ways to move data from Excel to SQL Server in the links below.

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

Obviously, you run those from Excel. Also, consider looping through files using SQL Server (opposite from what is described above).

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

This script assumes your files have a date in the name of the file. Hopefully your Excel files have some kind of pattern in the name of the file, and you can leverage that.

查看更多
狗以群分
3楼-- · 2020-07-22 19:27

You don't need to create a New ADODB.Connection which connects to the database you currently have open in your Access session. Your Con object variable can simply reference CurrentProject.Connection ...

Set Con = CurrentProject.Connection

However, you don't really even need that object variable. Just use the Execute method directly from CurrentProject.Connection ...

CurrentProject.Connection.Execute SQLString

That is simpler than what you have now, but I'm not certain it will eliminate the "state ... that prevents it from being opened or locked" complaint.

Since you said "alternate suggestions are welcome", consider DAO instead of ADO for this. And do not include parentheses around the field expression list in the SELECT piece of your INSERT query (regardless of whether you choose ADO or 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
查看更多
在下西门庆
4楼-- · 2020-07-22 19:35

I find it is easier to do (and debug!) this by actually linking or importing the table from Excel. Then you can use it like any other table.

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"
查看更多
登录 后发表回答