Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

VBA: Querying Access with Excel. Why so slow?

Tags:

excel

vba

jet

ado

I found this code online to query Access and input the data into excel (2003), but it is much slower than it should be:

Sub DataPull(SQLQuery, CellPaste)
Dim Con As New ADODB.Connection
Dim RST As New ADODB.Recordset
Dim DBlocation As String, DBName As String
Dim ContractingQuery As String

If SQLQuery = "" Then

Else
    DBName = Range("DBName")
    If Right(DBName, 4) <> ".mdb" Then DBName = DBName + ".mdb"

    DBlocation = ActiveWorkbook.Path
    If Right(DBlocation, 1) <> "\" Then DBlocation = DBlocation + "\"

    Con.ConnectionString = DBlocation + DBName
    Con.Provider = "Microsoft.Jet.OLEDB.4.0"
    Con.Open

    Set RST = Con.Execute(SQLQuery)
    Range(CellPaste).CopyFromRecordset RST

    Con.Close
End If

End Sub

The problem is that this code takes very long. If I open up Access and just run the query in there it takes about 1/10th the time. Is there anyway to speed this up? Or any reason this might be taking so long? All my queries are simple select queries with simple where statements and no joins. Even a select * from [test] query takes much longer than it should.

EDIT: I should specify that the line

Range(CellPaste).CopyFromRecordset RST

was the one taking a long time.

like image 1000
Dan Avatar asked Oct 15 '09 18:10

Dan


2 Answers

I'm no expert, but I run almost exactly the same code with good results. One difference is that I use the Command object as well as the Connection object. Where you

Set RST = Con.Execute(SQLQuery)

I

Dim cmd As ADODB.Command
Set cmd.ActiveConnection = con
cmd.CommandText = SQLQuery
Set RST = cmd.Execute

I don't know if or why that might help, but maybe it will? :-)

like image 121
Ryan Shannon Avatar answered Nov 01 '22 15:11

Ryan Shannon


I don't think you are comparing like-with-like.

In Access, when you view a Query's dataview what happens is:

  • an existing open connection is used (and kept open);
  • a recordset is partially filled with the first few rows only (and kept open);
  • the partial resultset is shown in a grid dedicated to the task and optimized for the native data access method Access employs (direct use of the Access Database Engine DLLs, probably).

In your VBA code:

  • a new connection is opened (then later closed and released);
  • the recordset is fully populated using all rows (then later closed and released);
  • the entire resultset is read into a Excel's generic UI using non-native data access components.

I think the most significant point there is that the dataview in Access doesn't fetch the entire resultset until you ask it to, usually by navigating to the last row in the resultset. ADO will always fetch all rows in the resultset.

Second most significant would be the time taken to read the fetched rows (assuming a full resultset) into the UI element and the fact Excel's isn't optimized for the job.

Opening, closing and releasing connections and recordsets should be insignificant but are still a factor.

I think you need to do some timings on each step of the process to find the bottleneck. When comparing to Access, ensure you are getting a full resultset e.g. check the number of rows returned.

like image 27
onedaywhen Avatar answered Nov 01 '22 14:11

onedaywhen