I have a 4D database from which I need to periodically pull data using Excel and VBA. For now, the machine that I intend to run this on is similar to a Mac mini (Late 2014) on OS 10.13.6 and Excel for Mac 2011. I know, it is old, but it is what I have to work with for now.
Actually, I've been doing this for years now and it works fine to use a QueryTable if I only need to pull the data one time (or a small number of times). There is a REST interface on the database side. Now though, I need to query the database somewhere in the range of 1500 or 2000 times each time I run this macro. The results of each query have to be individually written to the spreadsheet and it runs very slowly. I think it would work much faster if I could append the results of the queries to an array, and just write the array to the spreadsheet in one block. However, QueryTables apparently must write the results to a specified range, so I'm forced to do ~2000 individual writes. It takes a little over 5 minutes each time and needs to be run a few times a day.
I can't just write it in SQL or the Mac equivalent of ADO, because I do not have the ability to change my source or its REST interface right now. I don't know SQL or ADO in any case, although I could probably learn them if it made the difference, but as I understand, it won't.
It does run considerably faster on an M1 Mac mini (about 1.5 minute run time), so the slowness can't be blamed on the network speed or the database server.
Just for fun, I compared writing a 2000 line array in one block versus writing it one line at a time. In my experiment, the block copy was at least 25 times faster.
Is there another VBA function that can be used to get data from an external source and append it to an array? Or can the functionality of QueryTables be built from scratch in VBA such that I can write it to an array instead of a range?
FWIW: Here is the sub I currently use to get data. It works, but is just slow for this application.
Public Sub REST_FillCellsWithDataFrom4D(strStartCell As String, _
strServerIPAddress As String, _
strServerPort As String, _
strUserName As String, _
strUserPassword As String, _
strCallType As String, _
strTableName As String, _
strFieldNamesList As String, _
strSearchFieldsList As String, _
strSortFieldsList As String)
Dim strURL As String
strURL = "URL;http://" & strServerIPAddress & ":" & strServerPort & "/" & strCallType
strURL = strURL & "/table=" & strTableName
strURL = strURL & "&fieldnames=" & strFieldNamesList
strURL = strURL & "&searchfields=" & strSearchFieldsList
strURL = strURL & "&sortfields=" & strSortFieldsList
Worksheets("TablesAndFields").Range("A99") = strURL
With ActiveSheet.QueryTables.Add(Connection:=strURL, Destination:=Range(strStartCell))
.PostText = "user=" & strUserName & ";password=" & strUserPassword
.RefreshStyle = xlOverwriteCells
.SaveData = True
.BackgroundQuery = False
.Refresh
.Delete
End With
End Sub