'Trying to adjust my VBA Macro for inserting batches of rows into an SQL Server
I have already managed to program this VBA macro which takes as an input a range within an excel sheet, iterates over its columns and rows and then inserts the values with a SQL statement into a server database. But since some files which I need to insert into the database have over 90.000 rows I need to implement a batch insert inside my for loop, so that every iteration only takes a set number of rows for the insert procedure (like for example 500 rows at a time).
Below you find the code of the Macro which works just fine with smaller datasets:
Function RangeToInsert(rRng As Range) As String
Dim vaData As Variant
Dim i As Long, j As Long
Dim aReturn() As String
Dim aCols() As String
Dim aVals() As Variant
Const sINSERT As String = "INSERT INTO dbo.ExcelTest2"
Const sVAL As String = " VALUES "
'Read in data
vaData = rRng.Value
'Create arrays
ReDim aReturn(1 To UBound(vaData))
ReDim aCols(1 To UBound(vaData, 2))
ReDim aVals(1 To UBound(vaData, 2))
'Fill column name array from first row
For j = LBound(vaData, 2) To UBound(vaData, 2)
aCols(j) = "[" & vaData(1, j) & "]"
Next j
'Go through the rest of the rows
For i = LBound(vaData, 1) + 1 To UBound(vaData, 1)
'Fill a temporary array
For j = LBound(vaData, 2) To UBound(vaData, 2)
aVals(j) = "'" & vaData(i, j) & "'":
Next j
'Build the string into the main array
aReturn(i) = sINSERT & "(" & Join(aCols, ",") & ")" & sVAL & "(" & Join(aVals, ",") & ");"
Next i
RangeToInsert = Join(aReturn, vbNewLine)
End Function
Sub Test_Export()
Dim sConnString As String
Dim tbl As ListObject
Dim column_count, row_count As Integer
Dim Headers As Variant
sConnString = "Provider=X;Data Source=X;Initial Catalog = X;Integrated Security=SSPI"
Dim conn As ADODB.Connection
Dim rs As ADODB.Recordset
Set conn = New ADODB.Connection
Set rs = New ADODB.Recordset
conn.Open sConnString
conn.Execute ("use Salesreport")
conn.Execute ("truncate table dbo.ExcelTest2")
conn.Execute (RangeToInsert(ActiveSheet.Range("A1:AC5000")))
End Sub
For the batching I thought about adding an if clause along those lines:
If (i Mod 500) = 0 Then
aReturn(i) = sINSERT & "(" & Join(aCols, ",") & ")" & sVAL & "(" & Join(aVals, ",") & ");"
RangeToInsert = Join(aReturn, vbNewLine)
RangeToInsert = RangeToInsert As String
conn.Execute (RangeToInsert)
End If
But to be honest I am a little bit stuck right now on how I can actually implement this clause into the for loop while also making sure that still every row of the dataset gets inserted in the end. I would be really greatful for every hint or help.
Solution 1:[1]
This sounds like a weird design. Maybe you need to re-think your setup. You can certainly use VBA, like you are doing, or do a bulk insert into SQL Server, from a CSV. Here's a link with some info:
There are resize functions and offset functions that you may be able to leverage, but anytime you use 'select' things are going to run slow.
You can even save the XL file as a tab-delimited text file and do this...
BULK INSERT TableName
FROM 'C:\your_file_path.txt'
WITH
(
FIELDTERMINATOR = '\t',
ROWTERMINATOR = '\n'
)
GO
https://dbtut.com/index.php/2019/05/13/bulk-insert-in-sql-server/
Also, Python offers an easy way to chunk data and do multiple inserts.
https://towardsdatascience.com/loading-large-datasets-in-pandas-11bdddd36f7b
Although, maybe Python is outside the realm of feasibility for you. Just offering a couple ideas here.
Solution 2:[2]
You can have as many text fields as you want, you need to be in the shape text editor (hit F2 first so that text edit is opened, and then insert fields). Here is a video. Please note that this is not a programming question, probably should be closed here as offtopic.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | halfer |
| Solution 2 | Nikolay |
