VBA - working with data videos | Excel VBA Part 56.2 - Get Data from SQL Server with ADO Recordsets

Posted by Andrew Gould on 24 June 2019

This video shows you how to extract data from a SQL Server database using the ActiveX Data Objects (ADO) library for VBA and the Microsoft OLE DB Driver for SQL Server. You'll learn how to write a connection string to connect to a SQL Server databse and how to use a recordset to retrieve data. You'll learn how to populate the recordset using SQL Server tables, views, stored procedures and select statements and how to write the data you've retrieved into an Excel Worksheet.

You can download any files that you need to follow the video here.

You can increase the size of the video:

Full screen mode for YouTube

You can view the video in full screen mode as shown on the left, using the icon at the bottom right of the frame.

You can also increase the quality of the video:

Changing resolution

You can improve the resolution of the video using another icon at the bottom right of the frame. This will slow down the connection speed, but increase the display and sound quality. This icon only becomes visible when you start playing the video.

Finally, if nothing happens when you play the video, check that you're not using IE in compatibility view.

This page has 3 threads Add post
10 Oct 20 at 16:18

Hi Andrew, 

Awesome video and thank you. 

I think there are some bugs with the CopyFromRecordset property when using MySQL drivers. 

To be more specific, when I use this property then some of the fetched data come in a truncated version, say instead of Consumer Staples it is fetched as Consumer.

Having searched the web I found a property of the Recordset object as per below:

rs.CursorLocation = adUseClient

Indeed this addition provides me with a solution, but I quite do not get the reason why even when I read info in the link below. May I kindly ask you to elaborate on what this property does and its current value "adUseClient"?


Thank you

12 Oct 20 at 07:26

Hi! There's a pretty good description of some of the implications of using server-side or client-side cursors here https://stackoverflow.com/questions/56037800/difference-between-ado-client-side-vs-server-side-cursor-when-the-sql-server-dat

 I don't know MySQL well enough to explain why you see the results you do but I hope the link above gives you a little more information.

01 Nov 19 at 22:40

Hello Andrew, for some reason my code didn't work so I had to record it step by step. Here how it looks

Sub CostDataSQL()

    Dim i As Long
    Application.CutCopyMode = False

    With ActiveWorkbook.Connections("DATABASE").OLEDBConnection

        .BackgroundQuery = False
        .CommandType = xlCmdSql
        .connection = _
        "OLEDB;Provider=SQLOLEDB.1;Password=XXX;Persist Security Info=True;User ID=XXX;Data Source=MYSERVER;Use Procedure for Prepare=1;Auto Translate=True;Packet Size=4096;Use Encryption for Data=False;Tag with column collation when possible=False;Initial Catalog=DATABASE"

        .CommandText = Array( _
        "SELECT * FROM REPORT.dbo.PROJECTS as w WHERE w.""Project Number"" " & _
        "like '" & Lists.Range("C4").Value & "%' or w.""Project Number"" like '" & Lists.Range("C3").Value & "%' or w.""Project Number"" not like '" & Lists.Range("C9").Value & "%'" _

        .RefreshOnFileOpen = False
        .SavePassword = True
        .SourceConnectionFile = ""
        .SourceDataFile = ""
        .ServerCredentialsMethod = xlCredentialsMethodIntegrated
        .AlwaysUseConnectionFile = False

    End With

    With ActiveWorkbook.Connections("DATABASE")

        .Name = "DATABASE"
        .Description = ""

    End With

    Application.CutCopyMode = False

    With Test.ListObjects.Add(SourceType:=4, Source:=ActiveWorkbook. _
        Connections("DATABASE"), Destination:=Test.Range("$C$1")).TableObject

        .RowNumbers = False
        .PreserveFormatting = True
        .RefreshStyle = 1
        .AdjustColumnWidth = True
        .ListObject.DisplayName = "Table_DATABASE_Query"

    End With

End Sub

My questions would be:

1. Not sure what the difference is between OLEDB and ADODB, does it matter?

2. I have a VERY long SQL statement, so I tried to break it in lines and it didn't work (I have more than 25 lines). Is there a way for me to break it by variables? I tried it by looking at these websites, but it doesn't work for me


Thank you so much.

05 Nov 19 at 07:11

Hi Albert,

In VBA, ADODB is an object library which allows you to write code to connect to a database using several types of connection, of which OLEDB is one.  The code shown in the video uses the ADODB library to create a Connection object which establishes an OLEDB connection to a SQL Server database.  The technique you've used along with the macro recorder is quite different (I'm guessing you used Data > Get Data > From SQL Server Database from the Excel ribbon) and doesn't use the ADODB library at all.  It's up to you which technique you prefer!

The solutions shown in the links you provided are good so I'm not sure why your code still isn't working.  If your query is still too long you could try the technique shown in this video https://www.wiseowl.co.uk/vba-macros/videos/vba-ado-net-recordsets/ado-execute-sql-query-file/ which stores the query in a separate text file and has VBA read it.

I hope that helps!

30 Oct 19 at 22:02

Hello Andrew, I have an issue with my code, I'm trying to follow your code suggestion I appreciate if you can please help me.  I'm getting Run-Time error '-2147217900 (80040e14)'

[Microsoft] [ODBC SQL Server Driver] [SQL Server] An expression of non-boolean type specified in a context where a condition is expected near "number".

Ideally, my SQL contains SELECT within SELECT statement, i.e. several databases joined with "LEFT Outer join" with input parameters "WHERE project number is like 'P-10500%' or 'P-10600%'

But I tried to construct a code so that at least it can read the database. In Connection string should I put Schema name or I need to list database names if it is more than one database?  How can I construct a VBA code for it?

Here's my start code:

Sub GetDataFromSQLServer()

            Dim ws As Worksheet
            Dim f As ADODB.Field

            Dim i As Integer
            Dim myservername As String
            Dim mydatabase As String
            Dim myuserid As String
            Dim mypasswd As String
            Dim cn As ADODB.connection
            Dim rs As ADODB.Recordset 

          Set cn = New ADODB.connection   

          cn.ConnectionString = " Provider=MSDASQL.1;Persist Security Info=True;DRIVER=SQL Server; DATABASE: REPORT;SERVER=MYSERVER;UID=ALBERTAN;PWD=PW;APP=Microsoft Office 2016;WSID=XXX"


        Set rs = New ADODB.Recordset

        rs.ActiveConnection = cn
        rs.Source = "SELECT * FROM (SELECT * FROM REPORT 2 as a Left Outer Join Report 3 as b on a.costcode = b.costcode w WHERE w.Job Number like 'p-10500%' OR ‘P-10600%’”

            rs.CursorType = adOpenForwardOnly
            rs.LockType = adLockReadOnly


            Set ws = Worksheets.Add

           For Each f In ResultSet.Fields

                i = i + 1
                ws.Cells(1, i).Value = f.Name

            Next f  

            Range("A2").CopyFromRecordset ResultSet 
            Range("A1").CurrentRegion.WrapText = False


End Sub

01 Nov 19 at 13:58

Hi Albert, I believe the problem is in the WHERE clause.  Yours looks like this:

WHERE project number is like 'P-10500%' or 'P-10600%'

But it should look like this

WHERE [project number] like 'P-10500%' or [project number] like 'P-10600%'

When a column name contains a space it needs to be enclosed in square brackets.

When using a logical operator like AND or OR, you need to include a full logical test on each side of the operator.

I hope that helps!