Excel макросы для sql

Представьте себе ситуацию, Вы получили целевую выборку из одной базы данных, но для полноты картины, как всегда, нужны дополнительные данные. Проблема может быть в том, что нужная информация хранится в другой базе данных и возможности создать на ней свою таблицу нет, подключиться используя link тоже нельзя, да и количество элементов, по которым нужно получить данные, несколько больше, чем допустимое на данном источнике. Вот и получается, что возможность написать SQL запрос и получить нужные данные есть, но написать придется не один запрос, а потом потратить время на объединение полученных данных.

Выйти из подобной ситуации поможет Excel.

Уверен, что ни для кого не секрет, что MS Excel имеет встроенный модуль VBA и надстройки, позволяющие подключаться к внешним источникам данных, то есть по сути является мощным инструментом для аналитики, а значит идеально подходит для решения подобных задач.

Для того чтобы обойти проблему, нам потребуется таблица с целевой выборкой, в которой содержатся идентификаторы, по которым можно достаточно корректно получить недостающую информацию (это может быть уникальный идентификатор, назовем его ID, или набор из данных, находящихся в разных столбцах), ПК с установленным MS Excel, и доступом к БД с недостающей информацией и, конечно, желание получить ту самую информацию.

Создаем в MS Excel книгу, на листе которой размещаем таблицу с идентификаторами, по которым будем в дальнейшем формировать запрос (если у нас есть уникальный идентификатор, для обеспечения максимальной скорости обработки таблицу лучше представить в виде одного столбца), сохраняем книгу в формате *.xlsm, после чего приступаем к созданию макроса.

Через меню «Разработчик» открываем встроенный VBA редактор и начинаем творить.

Sub job_sql() — Пусть наш макрос называется job_sql.

Пропишем переменные для подключения к БД, записи данных и запроса:

Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim sql As String

Опишем параметры подключения:

sql = «Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=True;Data Source=Storoge.company.ru Storoge.»

Объявим процедуру свойства, для присвоения значения:

Set cn = New ADODB.Connection
cn.Provider = » SQLOLEDB.1″
cn.ConnectionString = sql
cn.ConnectionTimeout = 0
cn.Open

Вот теперь можно приступать непосредственно к делу.

Организуем цикл:

For i = 2 To 1000

Как вы уже поняли конечное значение i=1000 здесь только для примера, а в реальности конечное значение соответствует количеству строк в Вашей таблице. В целях унификации можно использовать автоматический способ подсчета количества строк, например, вот такую конструкцию:

Dim LastRow As Long
LastRow = ActiveSheet.UsedRange.Row — 1 + ActiveSheet.UsedRange.Rows.Count

Тогда открытие цикла будет выглядеть так:

For i = 2 To LastRow

Как я уже говорил выше MS Excel является мощным инструментом для аналитики, и возможности Excel VBA не заканчиваются на простом переборе значений или комбинаций значений. При наличии известных Вам закономерностей можно ограничить объем выгружаемой из БД информации путем добавления в макрос простых условий, например:

If Cells(i, 2) = «Ваше условие» Then

Итак, мы определились с объемом и условиями выборки, организовали подключение к БД и готовы формировать запрос. Предположим, что нам нужно получить информацию о размере ежемесячного платежа [Ежемесячный платеж] из таблицы [payments].[refinans_credit], но только по тем случаям, когда размер ежемесячного платежа больше 0

sql = «select [Ежемесячный платеж] from [PAYMENTS].[refinans_credit] » & _
«where [Ежемесячный платеж]>0 and [Номер заявки] ='» & Cells(i, 1) & «‘ «

Если значений для формирования запроса несколько, соответственно прописываем их в запросе:

«where [Ежемесячный платеж]>0 and [Номер заявки] = ‘» & Cells(i, 1) & «‘ » & _
» and [Дата платежа]='» & Cells(i, 2) & «‘»

В целях самоконтроля я обычно записываю сформированный макросом запрос, чтобы иметь возможность проверить его корректность и работоспособность, для этого добавим вот такую строчку:

Cells(i, 3) = sql

в третьем столбце записываются запросы.

Выполняем SQL запрос:

Set rs = cn.Execute(sql)

А чтобы хоть как-то наблюдать за выполнением макроса выведем изменение i в статус-бар

Application.StatusBar = «Execute script …» & i
Application.ScreenUpdating = False

Теперь нам нужно записать полученные результаты. Для этого будем использовать оператор Do While:

j = 0
Do While Not rs.EOF
For ii = 0 To rs.Fields.Count — 1
Cells(i, 4 + j + ii) = rs.Fields(0 + ii) ‘& «;»

Указываем ячейки для вставки полученных данных (4 в примере это номер столбца с которого начинаем запись результатов)

Next ii
j = j + rs.Fields.Count
s.MoveNext
Loop
rs.Close
End If

— закрываем цикл If, если вводили дополнительные условия

Next i
cn.Close
Application.StatusBar = «Готово»
End Sub

— закрываем макрос.

В дополнение хочу отметить, что данный макрос позволяет обращаться как к БД на MS SQL так и к БД Oracle, разница будет только в параметрах подключения и собственно в синтаксисе SQL запроса.

В приведенном примере для авторизации при подключении к БД используется доменная аутентификация.

А как быть если для аутентификации необходимо ввести логин и пароль? Ничего невозможного нет. Изменим часть макроса, которая отвечает за подключение к БД следующим образом:

sql = «Provider= SQLOLEDB.1;Password=********;User ID=********;Data Source= Storoge.company.ru Storoge;APP=SFM»

Но в этом случае при использовании макроса возникает риск компрометации Ваших учетных данных. Поэтому лучше программно удалять учетные данные после выполнения макроса. Разместим поля для ввода пароля и логина на листе и изменим макрос следующим образом:

sql = «Provider= SQLOLEDB.1;Password=» & Sheets(«Лист аутентификации»).TextBox1.Value & «;User ID=» & Sheets(«Лист аутентификации «).TextBox2.Value & «;Data Source= Storoge.company.ru Storoge;APP=SFM»

Место для расположения текстовых полей не принципиально, можно расположить их на листе с таблицей в первых строках, но мне удобней размещать поля на отдельном листе. Чтобы введенные учетные данные не сохранялись вместе с результатом выполнения макроса в конце исполняемого кода дописываем:

Sheets(«Выгрузка»).TextBox1.Value = «« Sheets(»Выгрузка«).TextBox2.Value = »»

То есть просто присваиваем текстовым полям пустые значения, таким образом после выполнения макроса поля для ввода пароля и логина окажутся пустыми.

Вот такое вполне жизнеспособное решение, позволяющее сократить трудозатраты при получении и обработке данных, я использую. Надеюсь мой опыт применения SQL запросов в Excel будет полезен и вам в решении текущих задач.

UPDATE 21.10.15 Добавил «обратный» макрос — VBA в SQL и макрос для доступа к строке запроса SQL

Некоторое время назад я прошел несколько курсов по SQL. И мне было очень интересно — какую часть из мощного инструмента под названием T-SQL можно применять без использования SQL-Server (не дают мне сервачек под мои нужды, хнык-хнык).

Итак… Начнем с простого — подключение через Query Table в VBA. Можно записать через макрорекордер — для этого нужно создать подключение через Microsoft Query.

Microsoft Query

Выбираем Excel Files, указываем путь к файлу (пытаясь при этом не ругать разработчиков за интерфейс из 90х годов), фильтруем как-угодно поля. Нам сейчас это не важно — главное получить код, который дальше можно будет корректировать.

Должно получится что-то вроде этого:

Sub Макрос1()
    With ActiveSheet.ListObjects.Add(SourceType:=0, Source:=Array(Array( _
        "ODBC;DSN=Excel Files;DBQ=D:DropboxExcelтест excel_SQL-2015.xlsx;DefaultDir=D:DropboxExcel;DriverId=1046;MaxBufferSize=2048;Page" _
        ), Array("Timeout=5;")), Destination:=Range("$A$1")).QueryTable
        .CommandType = 0
        .CommandText = Array( _
        "SELECT Продажи.F2, Продажи.F3" & Chr(13) & "FROM `D:DropboxExcelтест excel_SQL-2015.xlsx`.Продажи Продажи" _
        )
        .RowNumbers = False
        .FillAdjacentFormulas = False
        .PreserveFormatting = True
        .RefreshOnFileOpen = False
        .BackgroundQuery = True
        .RefreshStyle = xlInsertDeleteCells
        .SavePassword = False
        .SaveData = True
        .AdjustColumnWidth = True
        .RefreshPeriod = 0
        .PreserveColumnInfo = True
        .ListObject.DisplayName = "Таблица_Запрос_из_Excel_Files"
        .Refresh BackgroundQuery:=False
    End With
End Sub

Строчка .CommandText = «SELECT…» — отвечает за SQL запрос. Если хотя бы немного почитать поисковую выдачу google по запросу QueryTable можно упростить код до следующего:

Sub CopyFromRecordset_To_Range()
  
  DBPath = "C:InputData.xlsx"
  sconnect = "Provider=MSDASQL.1;DSN=Excel Files;DBQ=" & DBPath & ";HDR=Yes';"
  Conn.Open sconnect
  sSQLSting = "SELECT * FROM [Sheet1$]"

  rs.Open sSQLSting, Conn
  Set QT1 = ActiveSheet.QueryTables.Add(rs, Range("A1"))
  QT1.Refresh

  rs.Close
  Conn.Close

End Sub

Теперь начинаем копаться глубже — какого уровня запросы можно строить из VBA. Самые-самые базовые, основные конструкции — все работает, все ок.

Заполнение нового столбца одинаковым значением

SELECT  'YTikhonov', * 
FROM    [Sheet1$]

Переименование столбцов

SELECT  [Advertiser] AS 'Рекламодатель', [Quantity] AS 'Количество'
FROM    [Sheet1$]

Фильтрация записей

SELECT  * 
FROM    [Sheet1$]
WHERE   [Year] = 2014

Сортировка

SELECT   * 
FROM     [Sheet1$]
ORDER BY [Advertiser] DESC

Агрегация записей

SELECT   [Advertiser], Sum([Cost]) 
FROM     [Sheet1$]
GROUP BY [Advertiser]

Работа с датой

Дату можно впрямую через конструкцию

[SomeDateField] = {ts '2015-01-01 00:00:00'}

Но я люблю отталкиваться от текущей даты. За пару текущая дата-время отвечает функция SYSDATETIME() и она может вернуть в том числе текущий день. Для этого нужна еще одна функция  — CONVERT(type,value)

SELECT CONVERT(date,SYSDATETIME())

С функцией DATEFROMPARTS строка запроса в Excel почему-то не дружит, поэтому придется использовать костыли функцию DATEADD:

DATEADD(minute, 59, DATEADD(hour, 23, DATEADD(month, MONTH(SYSDATETIME())+1, DATEADD(year, YEAR(SYSDATETIME()) - 1900, 0))))-1

Эта строчка в любой день октября 2015 вернет значение — 30.11.15 23:59

А теперь — немного best practice!

Объединение + Агрегация + Join + Подзапросы. И самое интересное — подключение к нескольким источникам:

SELECT [Year], O.Numbers, SCost, SVolume, SQuantity FROM
 (
  SELECT [Year], Month, SUM([Cost RUB]) AS SCost, SUM(Volume) AS SVolume, SUM(Quantity) AS SQuantity FROM
   (
     SELECT Advertiser, 2013 as [Year], Month, [Cost RUB], Quantity, Volume
     FROM [N:GKRadioМаркетингСлужебный2013.xlsb].[Мониторинг$]
      UNION
     SELECT Advertiser, 2014 as [Year], Month, [Cost RUB], Quantity, Volume
     FROM [N:GKRadioМаркетингСлужебный2014.xlsb].[Мониторинг$]
       UNION
     SELECT Advertiser, 2015 as [Year], Month, [Cost RUB], Quantity, Volume
     FROM [N:GKRadioМаркетингСлужебный2015.xlsb].[Мониторинг$]
   )
   WHERE [Advertiser] = 'METRO GROUP'
   GROUP BY [Year], Month
 ) as T INNER JOIN [C:testMonth.xlsb].[Test$] AS O
ON T.[Month] = O.[Month]

Одна проблема — если осуществлять такого вида запрос для соединения нескольких Excel-файлов, он будет выполняться достаточно медленно. У меня вышло порядка 2 минут. Но не стоит думать что это бесполезно — если подобные запросы выполнять при подключении к SQL-серверу, то время обработки будет 1-2 секунды (само собой, все зависит от сложности запроса, базы, и прочие прочие факторы).

Бонусы

Формировать более-менее сложный запрос SQL вручную в VBA мягко говоря неудобно.  Поэтому я написал мини-макрос, который берет информацию из буфера обмена, и возвращает туда строчки для вставки в VBE.

'работа с буфером обмена http://excelvba.ru/code/clipboard
Private Function ClipboardText() ' чтение из буфера обмена
    With GetObject("New:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")
        .GetFromClipboard
        ClipboardText = .GetText
    End With
End Function
 
Private Sub SetClipboardText(ByVal txt$) ' запись в буфер обмена
    With GetObject("New:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")
        .SetText txt$
        .PutInClipboard
    End With
End Sub

Public Sub SQL_String_To_VBA()
  
    Dim sInput As String, sOut As String
    Dim ArrInput, i As Integer
    
    Dim cIdent As Integer: cIdent = 1 'Count of tabs
    Dim sVar As String: sVar = "strSQL" 'Name of variable
      
    sInput = ClipboardText()
    
    ArrInput = Split(sInput, Chr(13))
    
    For i = LBound(ArrInput) To UBound(ArrInput)
        sOut = sOut & sVar & " = " & sVar & " & " & Chr(34)
        sOut = sOut & String(cIdent, Chr(9))
        sOut = sOut & Replace(ArrInput(i), Chr(10), "")
        sOut = sOut & Chr(34) & "& chr(10)" & Chr(10)
    Next i
    
    SetClipboardText (sOut)

End Sub

Public Sub VBA_String_To_SQL()
 
    Dim sInput As String, sOut As String
    Dim ArrInput, i As Integer, sTemp
 
    sInput = ClipboardText()
 
    ArrInput = Split(sInput, Chr(10))
 
    For i = LBound(ArrInput) To UBound(ArrInput)
      sTemp = Replace(ArrInput(i), "& chr(10)", "")
      If Right(sTemp, 1) = " " Then sTemp = Left(sTemp, Len(sTemp) - 1)
      If Right(sTemp, 1) = Chr(34) Then sTemp = Left(sTemp, Len(sTemp) - 1)
 
      If Len(sTemp) > 0 Then
        sTemp = Right(sTemp, Len(sTemp) - InStr(1, sTemp, Chr(34)))
        sOut = sOut & Chr(10) & sTemp
      End If
    Next i
 
    SetClipboardText (sOut)

End Sub

Сами запросы просто и удобно создавать, например, используя Notepad++. Создали многострочный запрос SQL, копируете его в буфер обмена, запускаете макрос и вуаля — в буфере обмена строчки кода, готовые для вставки в ваши макросы. При желании вы можете настроить название переменной и количество табуляций.

И еще один небольшой бонус. Если у вас есть отчет по менеджерам/руководителям, построенный на запросах, то вам наверняка потребуется получать доступ к строке запроса через VBA. Сделать это можно через замечательную команду .CommandText — работает на чтение и запись. Мне для формирования отчета на 25 человек очень пригодился.

Public Sub ReplaceCommandText()
 
Dim con As WorkbookConnection
Dim sTemp As String
 
  For Each con In ActiveWorkbook.Connections
    sTemp = con.ODBCConnection.CommandText
    con.ODBCConnection.CommandText = sTemp
    con.Refresh
  Next con
 
End Sub

PS Ссылка с ответом на вопрос — как вставить данные из Excel в SQL
https://www.simple-talk.com/sql/t-sql-programming/questions-about-using-tsql-to-import-excel-data-you-were-too-shy-to-ask/

Приятного использования!

Содержание

  1. SQL запрос из Excel VBA
  2. Выполнять SQL-запросы к файлам Excel
  3. Откройте SQL-подключение к файлу Excel
  4. Откройте SQL-подключение к файлу Excel, защищенному паролем
  5. Чтение содержимого электронной таблицы Excel
  6. Удалить данные из строки Excel
  7. Получить данные Excel, кроме определенной строки
  8. Как сформировать SQL запросы в Excel?
  9. Формируем SQL запросы в Excel
  10. 11.09.2020 Лесин Александр, г. Воронеж

SQL запрос из Excel VBA

SQL расшифровывается как Structured Query Language (структурированный язык запросов) и является языком, который используется для получения информации из баз данных (таких как Access , SQL Server from Microsoft , Oracle , Sybase , SAP и других). Вы также можете получать данные из интернета, текстовых файлов или других Excel или CSV файлов.

Итак, нам нужно соединение с базой данных (переменная varConn в макросе ниже) и SQL запрос (переменная varSQL ), чтобы автоматизировать получение данных из базы для отчета. В примере ниже есть SQL запрос , который получает данные с малой базы данных в Access.

Нажмите скачать базу данных Access . Для корректного соединения база данных должна быть в папке «Мои документы«. Файл Access будет выглядеть:

Давайте напишем свой макрос, который будет осуществлять SQL запрос .

Меню Сервис — Макрос — Редактор Visual Basic , вставьте новый модуль (меню Insert — Module ) и скопируйте туда текст макроса:

Нажимаем сохранить и возвращаемся к Excel . Выбираем в меню Вид — Макросы (Alt + F8) название нашего макроса » SQLQuery_1 «.

Источник

Выполнять SQL-запросы к файлам Excel

Хотя действия Excel могут обрабатывать большинство сценариев автоматизации Excel, запросы SQL могут более эффективно извлекать значительные объемы данных Excel и работать с ними.

Предположим, поток должен изменить только те реестры Excel, которые содержат определенное значение. Чтобы реализовать эту функциональность без SQL-запросов, вам потребуются циклы, условные выражения и несколько действий Excel.

Вы также можете реализовать эту функциональность с помощью SQL-запросов, используя только два действия: Открыть SQL-подключение и Выполнять инструкции SQL.

Откройте SQL-подключение к файлу Excel

Перед запуском SQL-запроса вы должны открыть подключение с файлом Excel, к которому вы хотите получить доступ.

Чтобы установить подключение, создайте новую переменную с именем %Excel_File_Path% и инициализируйте его, указав путь к файлу Excel. При желании вы можете пропустить этот шаг и использовать жестко заданный путь к файлу позже в потоке.

Теперь разверните действие Открыть SQL-подключение и заполните следующую строку подключения в его свойствах.

Provider=Microsoft.ACE.OLEDB.12.0;Data Source=%Excel_File_Path%;Extended Properties=»Excel 12.0 Xml;HDR=YES»;

Для успешного использования представленной строки подключения вам необходимо скачать и установить Распространяемый пакет ядра СУБД Microsoft Access 2010.

Откройте SQL-подключение к файлу Excel, защищенному паролем

Другой подход требуется в сценариях, где вы запускаете SQL-запросы к файлам Excel, защищенным паролем. Действие Открыть SQL-подключение не может подключиться к файлам Excel, защищенным паролем, поэтому вам необходимо снять защиту.

Для этого запустите файл Excel с помощью действие Запустить Excel. Файл защищен паролем, поэтому введите соответствующий пароль в поле Пароль.

Затем разверните соответствующие действия автоматизации пользовательского интерфейса и перейдите к Файл>Информация>Защита книги>Зашифровать паролем. Дополнительные сведения об автоматизации пользовательского интерфейса и о том, как использовать соответствующие действия можно найти в Автоматизировать классические приложения.

После выбора Зашифровать паролем заполните пустую строку во всплывающем диалоговом окне, используя действие Заполнить текстовое поле в окне. Чтобы заполнить пустую строку, используйте следующее выражение: %»»%.

Чтобы нажать на ОК в диалоговом окне и применить изменения, разверните действие Нажать кнопку в окне.

Наконец, разверните действие Закрыть Excel, чтобы сохранить незащищенную книгу как новый файл Excel.

После сохранения файла следуйте инструкциям в Открытие SQL-подключения к файлу Excel, чтобы открыть к нему подключение.

Когда работа с файлом Excel будут завершена, используйте действие Удалить файлы для удаления незащищенной копии файла Excel.

Чтение содержимого электронной таблицы Excel

Хотя действие Считать с листа Excel может считывать содержимое листа Excel, циклы могут занять значительное время для итерации полученных данных.

Более эффективный способ получения определенных значений из электронных таблиц — это рассматривать файлы Excel как базы данных и выполнять на них SQL-запросы. Этот подход быстрее и увеличивает производительность потока.

Чтобы получить все содержимое электронной таблицы, вы можете использовать следующий SQL-запрос в действие Выполнить инструкцию SQL.

Чтобы применить этот SQL-запрос в ваших потоках, замените заполнитель SHEET именем электронной таблицы, к которой вы хотите получить доступ.

Чтобы получить строки, содержащие определенное значение в определенном столбце, используйте следующий запрос SQL:

Чтобы применить этот SQL-запрос в ваших потоках, замените:

  • SHEET с именем электронной таблицы, к которой вы хотите получить доступ.
  • COLUMN NAME столбцом, содержащим значение, которое вы хотите найти. Столбцы в первой строке листа Excel идентифицируются как имена столбцов таблицы.
  • VALUE со значением, которое вы хотите найти.

Удалить данные из строки Excel

Хотя Excel не поддерживает SQL-запрос DELETE, вы можете использовать запрос UPDATE, чтобы установить для всех ячеек определенной строки значение NULL.

Точнее, вы можете использовать следующий SQL-запрос:

При разработке потока вы должны заменить заполнитель SHEET именем электронной таблицы, к которой вы хотите получить доступ.

Заполнители COLUMN1 а также COLUMN2 представляют имена всех столбцов для обработки. В этом примере два столбца, но в реальном сценарии количество столбцов может быть другим. Столбцы в первой строке листа Excel идентифицируются как имена столбцов таблицы.

Часть запроса [COLUMN1]=’VALUE’определяет строку, которую вы хотите обновить. В вашем потоке используйте имя столбца и значение в зависимости от того, какая комбинация однозначно описывает строки.

Получить данные Excel, кроме определенной строки

В некоторых сценариях может потребоваться получить все содержимое электронной таблицы Excel, кроме определенной строки.

Удобный способ добиться этого результата — установить для значений нежелательной строки значение NULL, а затем получить все значения, кроме нулевых.

Чтобы изменить значения определенной строки в электронной таблице, вы можете использовать SQL-запрос UPDATE, представленный в Удалить данные из строки Excel:

Затем выполните следующий SQL-запрос, чтобы получить все строки электронной таблицы, не содержащие значений NULL:

Заполнители COLUMN1 а также COLUMN2 представляют имена всех столбцов для обработки. В этом примере два столбца, но в реальной таблице количество столбцов может быть другим. Все столбцы в первой строке листа Excel идентифицируются как имена столбцов таблицы.

Источник

Как сформировать SQL запросы в Excel?

Представьте себе ситуацию, Вы получили целевую выборку из одной базы данных, но для полноты картины, как всегда, нужны дополнительные данные. Проблема может быть в том, что нужная информация хранится в другой базе данных и возможности создать на ней свою таблицу нет, подключиться используя link тоже нельзя, да и количество элементов, по которым нужно получить данные, несколько больше, чем допустимое на данном источнике. Вот и получается, что возможность написать SQL запрос и получить нужные данные есть, но написать придется не один запрос, а потом потратить время на объединение полученных данных.

Выйти из подобной ситуации поможет Excel.

Уверен, что ни для кого не секрет, что MS Excel имеет встроенный модуль VBA и надстройки, позволяющие подключаться к внешним источникам данных, то есть по сути является мощным инструментом для аналитики, а значит идеально подходит для решения подобных задач.

Для того чтобы обойти проблему, нам потребуется таблица с целевой выборкой, в которой содержатся идентификаторы, по которым можно достаточно корректно получить недостающую информацию (это может быть уникальный идентификатор, назовем его ID, или набор из данных, находящихся в разных столбцах), ПК с установленным MS Excel, и доступом к БД с недостающей информацией и, конечно, желание получить ту самую информацию.

Создаем в MS Excel книгу, на листе которой размещаем таблицу с идентификаторами, по которым будем в дальнейшем формировать запрос (если у нас есть уникальный идентификатор, для обеспечения максимальной скорости обработки таблицу лучше представить в виде одного столбца), сохраняем книгу в формате *.xlsm, после чего приступаем к созданию макроса.

Через меню «Разработчик» открываем встроенный VBA редактор и начинаем творить.

Sub job_sql() — Пусть наш макрос называется job_sql.

Пропишем переменные для подключения к БД, записи данных и запроса:

Опишем параметры подключения:

Объявим процедуру свойства, для присвоения значения:

Вот теперь можно приступать непосредственно к делу.

Как вы уже поняли конечное значение i=1000 здесь только для примера, а в реальности конечное значение соответствует количеству строк в Вашей таблице. В целях унификации можно использовать автоматический способ подсчета количества строк, например, вот такую конструкцию:

Тогда открытие цикла будет выглядеть так:

Как я уже говорил выше MS Excel является мощным инструментом для аналитики, и возможности Excel VBA не заканчиваются на простом переборе значений или комбинаций значений. При наличии известных Вам закономерностей можно ограничить объем выгружаемой из БД информации путем добавления в макрос простых условий, например:

Итак, мы определились с объемом и условиями выборки, организовали подключение к БД и готовы формировать запрос. Предположим, что нам нужно получить информацию о размере ежемесячного платежа [Ежемесячный платеж] из таблицы [payments].[refinans_credit], но только по тем случаям, когда размер ежемесячного платежа больше 0

Если значений для формирования запроса несколько, соответственно прописываем их в запросе:

В целях самоконтроля я обычно записываю сформированный макросом запрос, чтобы иметь возможность проверить его корректность и работоспособность, для этого добавим вот такую строчку:

Источник

Формируем SQL запросы в Excel

11.09.2020 Лесин Александр, г. Воронеж

Время прочтения: 5 мин.

Наша работа неразрывно связана с получением и анализом информации из разных источников. Представьте себе ситуацию, Вы получили целевую выборку из одной базы данных, но для полноты картины, как всегда, нужны дополнительные данные. Проблема может быть в том, что нужная информация хранится в другой базе данных и возможности создать на ней свою таблицу нет, подключиться используя link тоже нельзя, да и количество элементов, по которым нужно получить данные, несколько больше, чем допустимое на данном источнике. Вот и получается, что возможность написать SQL запрос и получить нужные данные есть, но написать придется не один запрос, а потом потратить время на объединение полученных данных.

Выйти из подобной ситуации поможет Excel.

Уверен, что ни для кого не секрет, что MS Excel имеет встроенный модуль VBA и надстройки, позволяющие подключаться к внешним источникам данных, то есть по сути является мощным инструментом для аналитики, а значит идеально подходит для решения подобных задач.

Для того чтобы обойти проблему, нам потребуется таблица с целевой выборкой, в которой содержатся идентификаторы, по которым можно достаточно корректно получить недостающую информацию (это может быть уникальный идентификатор, назовем его ID, или набор из данных, находящихся в разных столбцах), ПК с установленным MS Excel, и доступом к БД с недостающей информацией и, конечно, желание получить ту самую информацию.

Создаем в MS Excel книгу, на листе которой размещаем таблицу с идентификаторами, по которым будем в дальнейшем формировать запрос (если у нас есть уникальный идентификатор, для обеспечения максимальной скорости обработки таблицу лучше представить в виде одного столбца), сохраняем книгу в формате *.xlsm, после чего приступаем к созданию макроса.

Через меню «Разработчик» открываем встроенный VBA редактор и начинаем творить.

Sub job_sql() — Пусть наш макрос называется job_sql.

Пропишем переменные для подключения к БД, записи данных и запроса:

Опишем параметры подключения:

Объявим процедуру свойства, для присвоения значения:

Вот теперь можно приступать непосредственно к делу.

Как вы уже поняли конечное значение i=1000 здесь только для примера, а в реальности конечное значение соответствует количеству строк в Вашей таблице. В целях унификации можно использовать автоматический способ подсчета количества строк, например, вот такую конструкцию:

Тогда открытие цикла будет выглядеть так:

Как я уже говорил выше MS Excel является мощным инструментом для аналитики, и возможности Excel VBA не заканчиваются на простом переборе значений или комбинаций значений. При наличии известных Вам закономерностей можно ограничить объем выгружаемой из БД информации путем добавления в макрос простых условий, например:

Итак, мы определились с объемом и условиями выборки, организовали подключение к БД и готовы формировать запрос. Предположим, что нам нужно получить информацию о размере ежемесячного платежа [Ежемесячный платеж] из таблицы [PAYMENTS].[refinans_credit], но только по тем случаям, когда размер ежемесячного платежа больше 0

Если значений для формирования запроса несколько, соответственно прописываем их в запросе:

В целях самоконтроля я обычно записываю сформированный макросом запрос, чтобы иметь возможность проверить его корректность и работоспособность, для этого добавим вот такую строчку:

в третьем столбце записываются запросы.

Выполняем SQL запрос:

А чтобы хоть как-то наблюдать за выполнением макроса выведем изменение i в статус-бар

Теперь нам нужно записать полученные результаты. Для этого будем использовать оператор Do While:

Указываем ячейки для вставки полученных данных (4 в примере это номер столбца с которого начинаем запись результатов)

— закрываем цикл If, если вводили дополнительные условия

В дополнение хочу отметить, что данный макрос позволяет обращаться как к БД на MS SQL так и к БД Oracle, разница будет только в параметрах подключения и собственно в синтаксисе SQL запроса.

В приведенном примере для авторизации при подключении к БД используется доменная аутентификация.

А как быть если для аутентификации необходимо ввести логин и пароль? Ничего невозможного нет. Изменим часть макроса, которая отвечает за подключение к БД следующим образом:

Но в этом случае при использовании макроса возникает риск компрометации Ваших учетных данных. Поэтому лучше программно удалять учетные данные после выполнения макроса. Разместим поля для ввода пароля и логина на листе и изменим макрос следующим образом:

Место для расположения текстовых полей не принципиально, можно расположить их на листе с таблицей в первых строках, но мне удобней размещать поля на отдельном листе. Чтобы введенные учетные данные не сохранялись вместе с результатом выполнения макроса в конце исполняемого кода дописываем:

То есть просто присваиваем текстовым полям пустые значения, таким образом после выполнения макроса поля для ввода пароля и логина окажутся пустыми.

Вот такое вполне жизнеспособное решение, позволяющее сократить трудозатраты при получении и обработке данных, я использую. Надеюсь мой опыт применения SQL запросов в Excel будет полезен и вам в решении текущих задач.

Источник

Время прочтения: 5 мин.

Наша работа неразрывно связана с получением и анализом информации из разных источников. Представьте себе ситуацию, Вы получили целевую выборку из одной базы данных, но для полноты картины, как всегда, нужны дополнительные данные. Проблема может быть в том, что нужная информация хранится в другой базе данных и возможности создать на ней свою таблицу нет, подключиться используя link тоже нельзя, да и количество элементов, по которым нужно получить данные, несколько больше, чем допустимое на данном источнике. Вот и получается, что возможность написать SQL запрос и получить нужные данные есть, но написать придется не один запрос, а потом потратить время на объединение полученных данных.

Выйти из подобной ситуации поможет Excel.

Уверен, что ни для кого не секрет, что MS Excel имеет встроенный модуль VBA и надстройки, позволяющие подключаться к внешним источникам данных, то есть по сути является мощным инструментом для аналитики, а значит идеально подходит для решения подобных задач.

Для того чтобы обойти проблему, нам потребуется таблица с целевой выборкой, в которой содержатся идентификаторы, по которым можно достаточно корректно получить недостающую информацию (это может быть уникальный идентификатор, назовем его ID, или набор из данных, находящихся в разных столбцах), ПК с установленным MS Excel, и доступом к БД с недостающей информацией и, конечно, желание получить ту самую информацию.

Создаем в MS Excel книгу, на листе которой размещаем таблицу с идентификаторами, по которым будем в дальнейшем формировать запрос (если у нас есть уникальный идентификатор, для обеспечения максимальной скорости обработки таблицу лучше представить в виде одного столбца), сохраняем книгу в формате *.xlsm, после чего приступаем к созданию макроса.

Через меню «Разработчик» открываем встроенный VBA редактор и начинаем творить.

Sub job_sql()  — Пусть наш макрос называется job_sql.

Пропишем переменные для подключения к БД, записи данных и запроса:

Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim sql As String

Опишем параметры подключения:

sql = "Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=True;Data Source=Storoge.company.ru Storoge." 

Объявим процедуру свойства, для присвоения значения:

Set cn = New ADODB.Connection
    cn.Provider = " SQLOLEDB.1"
    cn.ConnectionString = sql
    cn.ConnectionTimeout = 0
    cn.Open

Вот теперь можно приступать непосредственно к делу.

Организуем цикл:

For i = 2 To 1000 

Как вы уже поняли конечное значение i=1000 здесь только для примера, а в реальности конечное значение соответствует количеству строк в Вашей таблице. В целях унификации можно использовать автоматический способ подсчета количества строк, например, вот такую конструкцию:

Dim LastRow As Long
LastRow = ActiveSheet.UsedRange.Row - 1 + ActiveSheet.UsedRange.Rows.Count

Тогда открытие цикла будет выглядеть так:

For i = 2 To LastRow

Как я уже говорил выше MS Excel является мощным инструментом для аналитики, и возможности Excel VBA не заканчиваются на простом переборе значений или комбинаций значений. При наличии известных Вам закономерностей можно ограничить объем выгружаемой из БД информации путем добавления в макрос простых условий, например:

If Cells(i, 2) = "Ваше условие" Then

Итак, мы определились с объемом и условиями выборки, организовали подключение к БД и готовы формировать запрос. Предположим, что нам нужно получить информацию о размере ежемесячного платежа [Ежемесячный платеж] из таблицы [PAYMENTS].[refinans_credit], но только по тем случаям, когда размер ежемесячного платежа больше 0

sql = "select [Ежемесячный платеж] from [PAYMENTS].[refinans_credit] " & _
"where [Ежемесячный платеж]>0 and [Номер заявки] ='" & Cells(i, 1) & "' "

Если значений для формирования запроса несколько, соответственно прописываем их в запросе:

"where [Ежемесячный платеж]>0 and [Номер заявки] = '" & Cells(i, 1) & "' " & _
" and [Дата платежа]='" & Cells(i, 2) & "'"

В целях самоконтроля я обычно записываю сформированный макросом запрос, чтобы иметь возможность проверить его корректность и работоспособность, для этого добавим вот такую строчку:

Cells(i, 3) = sql

в третьем столбце записываются запросы.

Выполняем SQL запрос:

Set rs = cn.Execute(sql)

А чтобы хоть как-то наблюдать за выполнением макроса выведем изменение i в статус-бар

Application.StatusBar = "Execute script ..." & i
Application.ScreenUpdating = False

Теперь нам нужно записать полученные результаты. Для этого будем использовать оператор Do While:

j = 0
Do While Not rs.EOF
For ii = 0 To rs.Fields.Count - 1
Cells(i, 4 + j + ii) = rs.Fields(0 + ii) '& ";" 

Указываем ячейки для вставки полученных данных (4 в примере это номер столбца с которого начинаем запись результатов)

Next ii
j = j + rs.Fields.Count
s.MoveNext
Loop
rs.Close
End If 

— закрываем цикл If, если вводили дополнительные условия

Next i
cn.Close
Application.StatusBar = "Готово"
End Sub 

— закрываем макрос.

В дополнение хочу отметить, что данный макрос позволяет обращаться как к БД на MS SQL так и к БД Oracle, разница будет только в параметрах подключения и собственно в синтаксисе SQL запроса.

В приведенном примере для авторизации при подключении к БД используется доменная аутентификация.

А как быть если для аутентификации необходимо ввести логин и пароль? Ничего невозможного нет. Изменим часть макроса, которая отвечает за подключение к БД следующим образом:

sql = "Provider= SQLOLEDB.1;Password=********;User ID=********;Data Source= Storoge.company.ru Storoge;APP=SFM"

Но в этом случае при использовании макроса возникает риск компрометации Ваших учетных данных. Поэтому лучше программно удалять учетные данные после выполнения макроса. Разместим поля для ввода пароля и логина на листе и изменим макрос следующим образом:

sql = "Provider= SQLOLEDB.1;Password=" & Sheets("Лист аутентификации").TextBox1.Value & ";User ID=" & Sheets("Лист аутентификации ").TextBox2.Value & ";Data Source= Storoge.company.ru Storoge;APP=SFM"

Место для расположения текстовых полей не принципиально, можно расположить их на листе с таблицей в первых строках, но мне удобней размещать поля на отдельном листе. Чтобы введенные учетные данные не сохранялись вместе с результатом выполнения макроса в конце исполняемого кода дописываем:

Sheets("Выгрузка").TextBox1.Value = ""
Sheets("Выгрузка").TextBox2.Value = ""

То есть просто присваиваем текстовым полям пустые значения, таким образом после выполнения макроса поля для ввода пароля и логина окажутся пустыми.

Вот такое вполне жизнеспособное решение, позволяющее сократить трудозатраты при получении и обработке данных, я использую. Надеюсь мой опыт применения SQL запросов в Excel будет полезен и вам в решении текущих задач.

Learn how to easily run a plain SQL query with Visual Basic for Applications on your Excel Spreadsheet.

In the last days, I received an unusual request from a friend that is working on something curious because of an assignment of the University. For this assignment, it’s necessary to find the answer or data as response of a query. Instead of a database, we are going to query plain data from an excel spreadsheet (yeah, just as it sounds). For example, for this article, we are going to use the following Sheet in Excel Plus 2016:

Excel Spreadsheet Run SQL Query

The goal of this task is to write raw SQL Queries against the available data in the spreadsheet to find the answer of the following questions:

  • Which users live in Boston.
  • Which users are boys and live in Boston.
  • Which users were born in 2012.
  • Which users were born in 2010 and were ranked in place #1.

Of course, finding such information as a regular user is quite easy and simple using filters and so, however the assignment requires to do the queries using SQL and Visual Basic for the job. In this article, I will explain you from scratch how to use Microsoft Visual Basic for Applications to develop your own macros and run some SQL queries against plain data in your excel spreadsheets.

1. Launch Microsoft Visual Basic For Applications

In order to launch the window of Visual Basic to run some code on your spreadsheets, you will need to enable the Developer tab on the excel Ribbon. You can do this easily opening the Excel options (File > Options) and searching for the Customize Ribbon tab, in this Tab you need to check the Developer checkbox to enable it in your regular interface:

Excel Ribbon Developer Tab

Click on Ok and now you should be able to find the Developer tab on your excel ribbon. In this tab, launch the Visual Basic window:

Visual Basic Ribbon Developer Excel

In this new interface you will be able to run your VB code.

2. Building connection

In the Visual Basic window, open the code window of your sheet and let’s type some code! According to your needs you may create a custom macro and assign them to the action of buttons or other kind of stuff. In this example, we are going to work with plain code and will run them independently to test them. You need to understand how to connect to the workbook data source that will be handled with the following code:

Dim connection As Object
    
'--- Connect to the current datasource of the Excel file
Set connection = CreateObject("ADODB.Connection")
With connection
    .Provider = "Microsoft.ACE.OLEDB.12.0"
    .ConnectionString = "Data Source=" & ThisWorkbook.Path & "" & ThisWorkbook.Name & ";" & _
    "Extended Properties=""Excel 12.0 Xml;HDR=NO"";"
    .Open
End With

The connection properties are described as follows:

  • Provider: we will use the Microsoft Access Database Engine 2010 (Microsoft.ACE.OLEDB.12.0)
  • ConnectionString: we will use the current excel file as the database.
  • HDR=Yes;: indicates that the first row contains the column names, not data. HDR=No; indicates the opposite.

You will use this connection to run the SQL.

3. Printing whole table data

The following example, will use the mentioned logic to connect to the current spreadsheet and will query the range A1:E6 (selecting the whole table in the example excel) and will print every row in the immediate window:

Sub MyMethod()
    '--- Declare Variables to store the connection, the result and the SQL query
    Dim connection As Object, result As Object, sql As String, recordCount As Integer
    
    '--- Connect to the current datasource of the Excel file
    Set connection = CreateObject("ADODB.Connection")
    With connection
        .Provider = "Microsoft.ACE.OLEDB.12.0"
        .ConnectionString = "Data Source=" & ThisWorkbook.Path & "" & ThisWorkbook.Name & ";" & _
        "Extended Properties=""Excel 12.0 Xml;HDR=YES"";"
        .Open
    End With
    
    '--- Write the SQL Query. In this case, we are going to select manually the data range
    '--- To print the whole information of the table
    sql = "SELECT * FROM [Sheet1$A1:E6]"
    
    '--- Run the SQL query
    Set result = connection.Execute(sql)
    
    '--- Fetch information
    Do
        ' Print the information of every column of the result
        Debug.Print result(0); ";" & result(1) & ";" & result(2) & ";" & result(3) & ";" & result(4)
        
        result.MoveNext
        recordCount = recordCount + 1
    Loop Until result.EOF
    
    '--- Print the amount of results
    Debug.Print vbNewLine & recordCount & " results found."
End Sub

Note that we are using HDR so the query will use the first row of data as the column headers, so the result will be the following one:

Excel Spreadsheet Result Query

4. Query by columns

Now that you are able to connect to the worksheet, you may now customize the SQL to fit your needs. It is necessary to explain you the most basic thing you need to know about querying some data in your excel file. The range needs to specify the Sheet Name and the regular excel range (e.g. A1:Z1) and the whole data should be selected, not individual columns. You may filter by individual columns using regular SQL statements as WHERE, AND, OR, etc.

Depending if  you use HDR (first row contains the column names), the query syntax will change:

HDR=YES

If you have HDR enabled (in the extended properties of the connection), you may query through the column name, considering that you selected the appropriate range:

SELECT * FROM [Sheet1$A1:E6] WHERE [city] = 'Boston'

HDR=NO

If you don’t use HDR, the nomenclature of the columns will follow the F1, F2, F3, …, FN pattern:

Query Columns Excel VBA

The following query would work perfectly if you don’t have HDR enabled (note that the range changes):

SELECT * FROM [Sheet1$A2:E6] WHERE [F5] = 'Boston'

In both cases, the output will be the same in the immediate window:

Jacob;1;boy;2010;Boston
Ethan;2;boy;2010;Boston
Michael;3;boy;2010;Boston

3 results found.

5. Answering questions

The SQL that should solve the initial questions will be the following ones (with HDR disabled):

Which users live in Boston.

SELECT * FROM [Sheet1$A2:E6] WHERE [F5] = 'Boston'

Which users are boys and live in Boston.

SELECT * FROM [Sheet1$A2:E6] WHERE [F5] = 'Boston' and [F3] = 'boy'

Which users were born in 2012.

SELECT * FROM [Sheet1$A2:E6] WHERE [F4] = 2012

Which users were born in 2010 and were ranked in place #1.

SELECT * FROM [Sheet1$A2:E6] WHERE [F2] = 1 AND [F4] = 2010

Happy coding ❤️!

I am fairly new to SQL and VBA. I have written a SQL query that I would like to be able to call and run from a VBA sub in an excel workbook and then bring the query results into the workbook. I have found some subs online (stackoverflow and other places) that claim to do this but I am having trouble understanding them as they contain no explanation. For example, here is a sub that I found online:

Sub ConnectSqlServer()

    Dim conn As ADODB.Connection
    Dim rs As ADODB.Recordset
    Dim sConnString As String

    ' Create the connection string.
    sConnString = "Provider=SQLOLEDB;Data Source=INSTANCESQLEXPRESS;" & _
                  "Initial Catalog=MyDatabaseName;" & _
                  "Integrated Security=SSPI;"

    ' Create the Connection and Recordset objects.
    Set conn = New ADODB.Connection
    Set rs = New ADODB.Recordset

    ' Open the connection and execute.
    conn.Open sConnString
    Set rs = conn.Execute("SELECT * FROM Table1;")

    ' Check we have data.
    If Not rs.EOF Then
        ' Transfer result.
        Sheets(1).Range("A1").CopyFromRecordset rs
    ' Close the recordset
        rs.Close
    Else
        MsgBox "Error: No records returned.", vbCritical
    End If

    ' Clean up
    If CBool(conn.State And adStateOpen) Then conn.Close
    Set conn = Nothing
    Set rs = Nothing

End Sub

First of all, would this work? Second, what do I need to replace in the sub (it looks like provider, data source, initial catalog, etc) and where do I find the info to replace them with?

I hope this question is not too confusing and I appreciate your help!

Wahyu Kristianto's user avatar

asked Dec 9, 2014 at 17:37

Sam's user avatar

10

Below is code that I currently use to pull data from a MS SQL Server 2008 into VBA. You need to make sure you have the proper ADODB reference [VBA Editor->Tools->References] and make sure you have Microsoft ActiveX Data Objects 2.8 Library checked, which is the second from the bottom row that is checked (I’m using Excel 2010 on Windows 7; you might have a slightly different ActiveX version, but it will still begin with Microsoft ActiveX):

References required for SQL

Sub Module for Connecting to MS SQL with Remote Host & Username/Password

Sub Download_Standard_BOM()
'Initializes variables
Dim cnn As New ADODB.Connection
Dim rst As New ADODB.Recordset
Dim ConnectionString As String
Dim StrQuery As String

'Setup the connection string for accessing MS SQL database
   'Make sure to change:
       '1: PASSWORD
       '2: USERNAME
       '3: REMOTE_IP_ADDRESS
       '4: DATABASE
    ConnectionString = "Provider=SQLOLEDB.1;Password=PASSWORD;Persist Security Info=True;User ID=USERNAME;Data Source=REMOTE_IP_ADDRESS;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"

    'Opens connection to the database
    cnn.Open ConnectionString
    'Timeout error in seconds for executing the entire query; this will run for 15 minutes before VBA timesout, but your database might timeout before this value
    cnn.CommandTimeout = 900

    'This is your actual MS SQL query that you need to run; you should check this query first using a more robust SQL editor (such as HeidiSQL) to ensure your query is valid
    StrQuery = "SELECT TOP 10 * FROM tbl_table"

    'Performs the actual query
    rst.Open StrQuery, cnn
    'Dumps all the results from the StrQuery into cell A2 of the first sheet in the active workbook
    Sheets(1).Range("A2").CopyFromRecordset rst
End Sub

djv's user avatar

djv

14.6k7 gold badges50 silver badges72 bronze badges

answered Dec 9, 2014 at 18:25

Michael's user avatar

MichaelMichael

2,1381 gold badge21 silver badges26 bronze badges

5

Skip to content

ADO in Excel VBA – Connecting to database using SQL

Home » Excel VBA » ADO in Excel VBA – Connecting to database using SQL

  • adodb.connection vba

ADO Excel VBA – SQL Connecting to Database Example Macros helps to connect the different data sources from Excel VBA. Select, Delete,Update Records set.

In this Section:

  • What is ADO?
  • What is Database?
  • What is SQL?
  • adodb.connection VBA Reference
  • Practical Learning: Using ADO and SQL with VBA
  • Example File

What is ADO?

ADO Stands for ActiveX Data Objects, is Microsoft’s Client-Server technology to access the data between Client and Server.  ADO can’t access the data source directly, it will take help of OLE DB Provider to communicate with the data source.  Most of the times OLE DB providers are specific to a particular Data Source Type. However, we have an OLE DB provider for ODBC, it is a general purpose provider with help of this ADO can access any Data source which can understand ODBC.
ADO in Excel VBA - Connecting to a database using SQL -example-1

What is Database?

Database (DB) is a collection of information organized in such a way that a computer program can easily understand and read the data. And the Database Management System (DBMS) are designed to understand and interact with other computer applications to perform the different operations on the data. MySQL, Microsoft SQL Server, Microsoft Access, Oracle, and IBM DB2 are some of the well know DBMS.

Generally the information stored in the data in the form of tables, and a table is designed with set of records (rows) and fields (columns).

You can use Microsoft Excel to store some data, where an Excel workbook will act as a data source, worksheet will be a table and the rows and the columns of the worksheet will be records and the fields of the table.

What is SQL?

SQL Stands for Structured Query Language, ADO use SQL commands to communicate with the databases. Following are the most commonly used SQL commands to deal with the databases:

SELECT command used to retrieve the data from a data source
INSERT command used to insert the records to a data source
UPDATE command used to modify the existing records of the data source
DELETE command used to delete the records from a data source

adodb.connection VBA Reference

adodb.connection VBA Reference helps as to refer ADO in Excel VBA. We can use ADO in Excel VBA to connect the data base and perform data manipulating operations. We need add ‘Microsoft Activex Data Objects Library’ from References to reference the ADO in VBA. Here is the adodb.connection VBA Reference screen-shot.

adodb.connection VBA Reference

ADO in Excel VBA – Practical Learning: Using ADO and SQL with VBA

To retrieve the data from any data source into Excel using ADO:
1. We have to Open the connection to the Data Source
2. We need to run the required SQL command
3. We have to copy the resulted record set into our worksheet
4. We have to close the record set and connection

We will  consider the Excel workbook as data source and we will connect to the worksheet (table) to retrieve the data. In this example we will get the data from Sheet1 to Sheet2 using ADO.

Assuming you have an excel workbook with the following data in Sheet1, as shown below.

EmpID EmpName EmpSalary

1

Jo

22000

2

Kelly

28000

3

Ravi

30000

ADO in Excel VBA - Connecting to a database using SQL -example-2

Step 1:Add reference for Microsoft Activex Data Objects Library

ADO in Excel VBA - Connecting to a database using SQL -example-3
1. Go to VBE (Alt+F11) and Select References.. from Tools Menu.
2. Then select ” Microsoft Activex Data Objects Library” from the list.
3. And Create sub procedure to write the code:

Sub sbADOExample()
'We will write the code here 
End Sub
Step 2: Create the Connection String with Provider and Data Source options
Dim sSQLQry As String
Dim ReturnArray

Dim Conn As New ADODB.Connection
Dim mrs As New ADODB.Recordset

Dim DBPath As String, sconnect As String


DBPath = ThisWorkbook.FullName 'Refering the sameworkbook as Data Source

'You can provide the full path of your external file as shown below
'DBPath ="C:InputData.xlsx"

sconnect = "Provider=MSDASQL.1;DSN=Excel Files;DBQ=" & DBPath & ";HDR=Yes';"
'If any issue with MSDASQL Provider, Try the Microsoft.Jet.OLEDB:
'sconnect = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & DBPath _
    & ";Extended Properties=""Excel 8.0;HDR=Yes;IMEX=1"";"

Step 3: Open the Connection to data source
Conn.Open sconnect
Step 4: Create SQL Command String
      sSQLSting = "SELECT * From [Sheet1$]" ' Your SQL Statement (Table Name= Sheet Name=[Sheet1$]) 
Step 5: Get the records by Opening this Query with in the Connected data source
       mrs.Open sSQLSting, Conn
Step 6: Copy the reords into our worksheet
        Sheet2.Range("A2").CopyFromRecordset mrs
Step 7: Close the Record Set and Connection
           'Close Recordset
            mrs.Close

          'Close Connection
           Conn.Close
So, the final program should look like this:
Sub sbADOExample()
Dim sSQLQry As String
Dim ReturnArray

Dim Conn As New ADODB.Connection
Dim mrs As New ADODB.Recordset

Dim DBPath As String, sconnect As String



DBPath = ThisWorkbook.FullName

'You can provide the full path of your external file as shown below
'DBPath ="C:InputData.xlsx"

sconnect = "Provider=MSDASQL.1;DSN=Excel Files;DBQ=" & DBPath & ";HDR=Yes';"

'If any issue with MSDASQL Provider, Try the Microsoft.Jet.OLEDB:
'sconnect = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & DBPath _
    & ";Extended Properties=""Excel 8.0;HDR=Yes;IMEX=1"";"

Conn.Open sconnect
    
    sSQLSting = "SELECT * From [Sheet1$]" ' Your SQL Statement (Table Name= Sheet Name=[Sheet1$])
    
    mrs.Open sSQLSting, Conn
        '=>Load the Data into an array
        'ReturnArray = mrs.GetRows
                ''OR''
        '=>Paste the data into a sheet
        Sheet2.Range("A2").CopyFromRecordset mrs
    'Close Recordset
    mrs.Close

'Close Connection
Conn.Close

End Sub

Example File

You can download the example files here and explore it. Getting Data Using ADO (Using MSDASQL Provider)

Getting Data Using ADO (Using MSDASQL Provider)

Download the Example File: ANALYSIS TABS – Getting Data Using ADO (Using Microsoft.Jet.OLEDB Provider)

Getting Data Using ADO (Using Microsoft.Jet.OLEDB Provider)

Effortlessly Manage Your Projects and Resources
120+ Professional Project Management Templates!

A Powerful & Multi-purpose Templates for project management. Now seamlessly manage your projects, tasks, meetings, presentations, teams, customers, stakeholders and time. This page describes all the amazing new features and options that come with our premium templates.

Save Up to 85% LIMITED TIME OFFER
Excel VBA Project Management Templates
All-in-One Pack
120+ Project Management Templates
Essential Pack
50+ Project Management Templates

Excel Pack
50+ Excel PM Templates

PowerPoint Pack
50+ Excel PM Templates

MS Word Pack
25+ Word PM Templates

Ultimate Project Management Template

Ultimate Resource Management Template

Project Portfolio Management Templates

Related Posts

VBA Reference

Effortlessly
Manage Your Projects

120+ Project Management Templates

Seamlessly manage your projects with our powerful & multi-purpose templates for project management.

120+ PM Templates Includes:

134 Comments

  1. Vandana
    August 7, 2013 at 4:49 PM — Reply
  2. lisa Pereira
    February 12, 2014 at 7:33 AM — Reply

    HI,
    Nice one.. I am trying to pull multiple values from one parameter in excel, for example. I need to pull the parameter from Range(“a2”) separated by commas,
    how can I do this?

  3. PNRao
    February 25, 2014 at 11:58 PM — Reply

    Hi Lisa,

    Assuming you have data at A1 as “1st,2nd,3rd,4th” and you want to separate it.

    You can use Split function to separate the values. Please see the following code.

    fullText=Range(“A1″).Value ‘i.e; fullText=”1,2,3,4″
    arraySplitValues=Split(fullText,”,”)

    Now your array contains the comma delimited values:
    arraySplitValues(0) contains 1st
    arraySplitValues(1) contains 2nd
    arraySplitValues(2) contains 3rd
    arraySplitValues(3) contains 4th

    You can print the values at any Range like:
    Range(“B1”)=arraySplitValues(3)

    or you can loop the entire array to print all values:

    For iCntr=0 to ubound(arraySplitValues,1)
    Cells(iCntr+1,2)=arraySplitValues(iCntr) ‘ this will print all the values in the B Column
    Next

    Please explain your question in more detailed,so that I can help you in better way.

    Thanks-PNRao!

  4. Hi – great article! 2 questions:
    1. Do you have to install the ActiveX Object library 2.8 on every machine that uses this Excel file? I ask because I need to set up multiple files for multiple users who could benefit from this functinality (ADODB + SQL queries vs. Linked spreadsheets).
    2. Do you know how to create an auto-install program for these MS library features? I ask because I don’t prefer to guide every user through the installation procedure.

    Thanks again!
    Stephen

  5. PNRao
    March 24, 2014 at 11:13 PM — Reply

    Hi Stephen,
    Thanks for your comments! Please see my answers below:
    1.You do not required to install ActiveX Object library in every machine, by default it is installed when user have installed in MS Office.
    2.I think the above information answers this question too…

    To help you in understanding clearly: ActiveX Object Library is .DLL file which is installed with your office installation. You need to this reference this in your code, to use the ADO functionality in Excel VBA.

    When you successfully write any code using ADO by referring ActiveX Object Library in your workbook. You can send the file to any one, it should work automatically in any system.

    Hope this helps.
    Thanks-PNRao!

  6. Lisa Pereira
    June 18, 2014 at 5:00 AM — Reply

    Hi PN,
    You are awesome , i love this site.have used your ideas and has helped me a lot. love it..
    What i needed to know was that having pulled the record set into sheet :-
    1) I want to use the values listed in rows in column A
    2) transpose them into a cell and use these values to pull another query record-set with the IN statement.
    is there a way to do this in one connection only or open another connection.?
    let me know if this is possible.
    Regards..
    lisa

  7. PNRao
    June 19, 2014 at 12:11 AM — Reply

    Hi Lisa,
    How are you doing! Thanks for your feedback!
    Yes, this can be done. Here is an example case:
    To explain this, I have entered some data in ADO sheet of the example file (available at end of the article)
    Step1: Entered 1 at Range A2, 2 at Range A3
    The I concatenate these values at C1 using the below formul
    -> =A2&”,”&A3
    i.e; Now you can see ‘1,2’ at C1, I want to pass this in my SQL IN Operator, So – I changed the SQL Query string as follows:

    Step2: sSQLSting = “SELECT * From [DataSheet$] where Quarter IN (” & Range(“C1”) & “);”
    i.e; it will form the query as ‘SELECT * From [DataSheet$] where Quarter IN (1,2);’

    Step3: Now executed and got the required values in the ADO sheet.

    Hope this helps!
    Thanks-PNRao!

  8. Jon McNeil
    July 1, 2014 at 9:58 PM — Reply

    Thanks PN,

    This is working nicely. The only thing that I cannot appear to fix is that when one user has the source file open (from which the data comes from) the other user, who is using the destination file (where the data is pulled to), opens a read-only source file when they run the macro. Is there a way round this?
    The source file is only supposed to be viewed by one person whereas the destination file is for multiple users

    Thanks in advance,

    Jon

  9. Shubhangi
    July 1, 2014 at 11:24 PM — Reply

    I used this code to connect to MS Access 2007 database but am getting a runtime error and an application error when I try to open the same. I used DSN as MS Access Database and Provider as Microsoft.ACE.OLEDB.12.0.
    Please help.

  10. PNRao
    July 2, 2014 at 3:35 PM — Reply
  11. Noz
    July 3, 2014 at 3:24 PM — Reply

    This is very well explained, if this had been available when I was first learning it would have save me loads of time. Do you have something similar on how to insert into SQL tables from excel?

  12. PNRao
    July 4, 2014 at 12:48 AM — Reply

    Hi Noz, Thanks for your comments!

    Yes, you can write insert query, you can download the example file and change the query string as follows:
    sSQLSting = “INSERT INTO [DataSheet$](Quarter, Sales) Values(2,5000)”

    and comment the below line, as insert query will not return any values.
    ‘ActiveSheet.Range(“A2”).CopyFromRecordset mrs

    Now your ADO procedure should look like this:

    Sub sbADO()
    Dim sSQLQry As String
    Dim ReturnArray

    Dim Conn As New ADODB.Connection
    Dim mrs As New ADODB.Recordset

    Dim DBPath As String, sconnect As String

    DBPath = ThisWorkbook.FullName

    'You can provide the full path of your external file as shown below
    'DBPath ="C:InputData.xlsx"

    sconnect = "Provider=MSDASQL.1;DSN=Excel Files;DBQ=" & DBPath & ";HDR=Yes';"

    Conn.Open sconnect
    'sSQLSting = "SELECT * From [DataSheet$]" ' Your SQL Statemnt (Table Name= Sheet Name=[DataSheet$])
    sSQLSting = "INSERT INTO [DataSheet$](Quarter, Sales) Values(2,5000)"
    mrs.Open sSQLSting, Conn
    '=>Load the Data into an array
    'ReturnArray = mrs.GetRows
    ''OR''
    '=>Paste the data into a sheet
    'ActiveSheet.Range("A2").CopyFromRecordset mrs
    'Close Recordset
    mrs.Close

    'Close Connection
    Conn.Close

    End Sub

  13. Jaishree Ramani
    July 10, 2014 at 8:08 PM — Reply

    hello, this really helps when you have a simple query.. would you be kind enough to provide an example for a parameter query (multiple) i.e for dates say selct* from table data between fromDate and toDate?

  14. PNRao
    July 11, 2014 at 1:29 AM — Reply

    Hi,
    Sure, you change the query to suits your requirement.
    For example:
    I have changed the query sting from sSQLSting = “SELECT * From [DataSheet$]” to sSQLSting = “SELECT * From [DataSheet$] Where Quarter Between 2 And 4” in the example file. And now it will pull the data if the quarter is between 2 and 4.

    For your requirement, sSQLSting will be something like below:

    sSQLSting = “SELECT * From [DataSheet$] Where YOUR_Date_Varibale Between ‘LowerDate’ And ‘UpperDate’”

    If Dates creates any problems, try to use date values.

    Hope this helps-Thanks-PNRao!

  15. Jaishree Ramani
    July 11, 2014 at 6:57 PM — Reply

    Hi Sir,
    that works but I am having issue with the parameters dates as my query below
    “O.DELIVERY_DATE BETWEEN :”From date” AND :”To Date” ) . how do i setup the parameters in vba to ensure that the record-set only pulls data in ‘DD-MMM-YYYY’ format. right now i have the dates converted to text(“dd-mmm-yyyy”) but when the data is returned its shows up in ‘mm/ddd/yyyy’ .

    note :i have the user to input the dates..

  16. PNRao
    July 12, 2014 at 1:05 PM — Reply

    Hi,
    You can create the query string use as shown below:

    FromDate = 1 / 1 / 2010
    ToDate = 12 / 30 / 2012
    sSQLSting = “SELECT * From [DataSheet$] Where O.DELIVERY_DATE Between ” & FromDate & ” And ” & ToDate

    And your excel, default date format is ‘mm/ddd/yyyy’, you can format the dates using either sql or VBA.

    In VBA it is like this: Format(YourDate,”mm-dd-yyyy”)

    Thanks-PNRao!

  17. Jaishree Ramani
    July 14, 2014 at 8:21 PM — Reply

    Hi Sir,
    my code is
    userInput (“Pls type FromDate”) ,FromDate
    userInput (“Pls type ToDate”) ,ToDate
    FromDate = format(FromDate,”dd-mmm-yyyy”)
    ToDate = format(ToDate,”dd-mmm-yyyy”)

    “select…
    …..”AND O276054.DELIVERY_DATE BETWEEN ” & FromDate & ” And ” & ToDate & _ ”

    i tried that but i keep getting error ‘saying missing expression..’
    what am i doing wrong??

  18. PNRao
    July 15, 2014 at 10:56 AM — Reply

    Hi,
    I could not find any issue in the code. As per the Error message, something wrong with the query string. Could you please provide me the complete query string.

    Or you can try this: You can use Debug.Print YourstrQery, now look into the Immediate Window to see the resulted query.

    You can send me the file with some dummy data to our email id: info@analysistabs.com

    Thanks-PNRao!

  19. Nigel
    July 18, 2014 at 7:29 PM — Reply

    Hello, very good site .. quick question do you have an example for record-sets and Pivot tables or cross-tabs.?
    i have an issue which I am trying to merge two query’s into one record-set and Pivot them into a cross report?
    something similar to what Discoverer does. but I am trying to combine aggregate data points with Detail data points into one sheet without errors..(that’s why the two query s)

    please direct in a right direction if this is doable???

  20. PNRao
    July 20, 2014 at 12:31 AM — Reply

    Hi Nigel,

    Please look into the example below:


    'Add reference for Microsoft Activex Data Objects Library

    Sub sbADO()
    Dim sSQLQry As String
    Dim ReturnArray

    Dim Conn As New ADODB.Connection
    Dim mrs As New ADODB.Recordset

    Dim DBPath As String, sconnect As String

    DBPath = ThisWorkbook.FullName

    'You can provide the full path of your external file as shown below
    'DBPath ="C:InputData.xlsx"

    sconnect = "Provider=MSDASQL.1;DSN=Excel Files;DBQ=" & DBPath & ";HDR=Yes';"

    Conn.Open sconnect
    sSQLSting = "SELECT * From [DataSheet$]"

    '***********> You can change this query as per your requirement (Join / Union)

    mrs.Open sSQLSting, Conn

    'Set record set as a pivot table data source
    Set objPivotCache = ActiveWorkbook.PivotCaches.Add( _
    SourceType:=xlExternal)
    Set objPivotCache.Recordset = mrs
    With objPivotCache
    .CreatePivotTable TableDestination:=Range("G20"), _
    TableName:="MyPivotTable1"
    End With

    'Close Recordset
    mrs.Close

    'Close Connection
    Conn.Close

    End Sub

    Hope this helps! Thanks-PNRao!

  21. Gavrav
    July 24, 2014 at 1:59 PM — Reply

    Hi,
    I would like to automate my daily process by using VBA and macro actually my doubt is there any solution for instead of copying and pasting the query statement to SSMS 2005 which is stored in excel.So by making that statements as link or by clicking some command buttons to pass that query to SSMS and thus the statement should be executed automatically by using ODBC conn or OLEDB data sources. Is it Possible ???

  22. PNRao
    July 24, 2014 at 2:53 PM — Reply

    Hi Gavrav,

    Yes – we can do this. You can simply record a macro and fetch the data using tools in Data menu tab.

    Thanks-PNRao!

  23. Ricky Dobriyal
    July 26, 2014 at 9:39 PM — Reply

    Hi All,
    I am very glad that I visited this website and would like thank you for giving such valuable info.
    I have one question in VBA while using ADO and database as excel how we can use where condition and other query on excel sheet like below example of this website.

    sconnect = “Provider=MSDASQL.1;DSN=Excel Files;DBQ=” & DBPath & “;HDR=Yes’;”

    Conn.Open sconnect
    sSQLSting = “SELECT * From [DataSheet$] WHERE ” ‘ Your SQL Statemnt (Table Name= Sheet Name=[DataSheet$])

    mrs.Open sSQLSting, Conn
    ‘=>Load the Data into an array
    ‘ReturnArray = mrs.GetRows
    ”OR”
    ‘=>Paste the data into a sheet
    ActiveSheet.Range(“A2”).CopyFromRecordset mrs
    ‘Close Recordset
    mrs.Close

    Here is only select condition used. Please help me how we can use different SQL condition.

    Another question how we can connect to MYsql database using VBA?

    Please help me in the above questions and thanks a ton in advannce.

    Regards,
    Ricky

  24. PNRao
    July 26, 2014 at 9:49 PM — Reply

    Hi Ricky,

    Thanks for your comments.

    Please check the codes provided in the comments section, I have given the example queries which you have mentioned.

    And regarding MySQL, you can use the following connection string:
    sconnect = “DRIVER={MySQL ODBC 5.1 Driver};” & _ “SERVER=[Server];” & _ “DATABASE=[Database];” & _ “USER=[UserName];” & _ “PASSWORD=[Password];” & _ “Option=3”

    And replace [Server], [Database], [UserName] and [Password] with the respective original server name, database, User and Password.

    If your system is not insstalled MySQL, then you have to download and install MYSQL ODBC Driver: http://dev.mysql.com/downloads/connector/odbc/5.1.html

    Hope this helps!
    Thanks-PNRao!

  25. Nigel
    July 29, 2014 at 8:32 PM — Reply

    Hi Pn,
    Thanks your previous example works perfectly. would you be able to help with multiple record sets. I need to add the second query record-set in between the data of the first record set after exporting to sheet.

  26. Nigel
    July 30, 2014 at 5:30 AM — Reply

    Hi PN, sorry hope if didn’t confuse you with my inquiry.. I will provide an example
    I need to combine two record sets as I cannot put them in one query due to the data constraints.
    query1= “select Total_DLV , AVAIL_DLV between date1 and date2 from Table1″ into Sheet1
    query2=”select Sch_DLV , between date1 and date2 from Table2” into Sheet1
    combine data from the two querys into sheet1 like
    DLV_date—>aug1, Aug 2 ,aug3 (horizontal)
    Total_DLV , ..
    AVAIL_DLV
    Sch_DLV
    please let me know if this is possible..

  27. Amir
    August 1, 2014 at 4:08 PM — Reply

    Hi
    Nice explanation!
    Question: how can i get the data from different ‘sourcerange’ from within one sheet i.e multiple columns?

    code:
    SourceRange = “C1:C6500 ,D1:D6500 ,AB1:AB6500,AG1:AG6500”
    szSQL = “SELECT * FROM [” & SourceSheet$ & “$” & SourceRange$ & “];”

  28. Nigel
    August 7, 2014 at 12:00 AM — Reply

    Hi PN ,
    i fixed the issue.,, this was more to do with my query itself. i managed to fix this within the first query itself. no need for multiple queries.
    however please provide an example for multiple record-sets if possible..

  29. Ricky Dobriyal
    August 17, 2014 at 12:54 AM — Reply

    Hello Team,

    I have a sheet with thousand records and I want filter recordes based on Activsheet name

    Query is working fine when I am putting directly the value in condition like below

    sSQLSting = “SELECT * From [Data$] where Country =’India’; ”

    But I want to filter it based on Acrive sheet name.

    I tried two methods but it is prompting same Run time error.

    s = ActiveSheet.Name

    sSQLSting = “SELECT * From [Data$] where Country =s ”
    sSQLSting = “SELECT * From [Data$] where Country =Activeshet.name ”
    sSQLSting = “SELECT * From [Data$] where Country =’Activeshet.name’ ”

    Please cound you advise me how I can do this..

  30. PNRao
    August 17, 2014 at 11:15 AM — Reply

    Hi Amir,
    You can mention the column names, instead of specifying multiple ranges, for example:
    szSQL = “SELECT Column1, Column2 FROM [Sheet1$]”

    Thanks-PNRao!

  31. PNRao
    August 17, 2014 at 11:44 AM — Reply

    Hi Ricky,
    Please change your code like this:

    s = ActiveSheet.Name
    sSQLSting = “SELECT * From [Data$] where Country = ‘” & s & “‘”

    Thanks-PNRao!

  32. Graig
    September 1, 2014 at 4:10 AM — Reply

    I see you share interesting content here, you can earn some additional
    cash, your blog has huge potential, for the
    monetizing method, just search in google – K2 advices
    how to monetize a website

  33. Yogesh
    September 10, 2014 at 10:55 PM — Reply

    is there a way to send parameters(through InputBox/MsgBox) using Select statement and extracting user specific data into excel using ADO.
    Thanks for all your help and support.
    Yogesh

  34. Mandeep
    September 11, 2014 at 9:56 AM — Reply

    Dear Pn rao,

    Please let me know if you are pulling data from excel , is this code using sql while retrieving data ? because this is not connecting to server. waiting for your response. thanks in advance.
    MAndeep

  35. Mandeep
    September 11, 2014 at 9:59 AM — Reply

    Explain me this line of code please ” sconnect = “Provider=MSDASQL.1;DSN=Excel Files;DBQ=” & DBPath & “;HDR=Yes’;”

  36. PNRao
    September 11, 2014 at 8:19 PM — Reply

    Hi Mandeep,
    We need to create a connection string to connect any data base using VBA.
    sconnect = “Provider=MSDASQL.1;DSN=Excel Files;DBQ=” & DBPath & “;HDR=Yes’;”

    Provider=MSDASQL.1 : This is OLEDB Provider, this helps excel to understand the data base query syntax.
    DSN=Excel Files : Data Source Name, Excel Files is data source in the given example.
    DBQ= &DBPath : Data base file path, this is the full path of Excel File to connect.
    HDR=Yes’: Headers, Yes – if the first line of your data (in sheet or range) having headers, other wise No.

    Hope this helps!
    Thanks-PNRao!

  37. PNRao
    September 11, 2014 at 8:22 PM — Reply

    Hi Mandeep,
    Yes, we are pulling the data from Excel using ADO. You need to change the connection string if you are connecting any other DB.

    Thanks-PNRao!

  38. PNRao
    September 11, 2014 at 8:28 PM — Reply

    Hi Yogesh,
    Yes, you can use Inputbox to enter some parameters and change the query accordingly.
    Example:
    x = InputBox(“Please enter field to select”, “Please Enter”)
    ‘You cna change the below query
    ‘sSQLSting = “SELECT * From [Sheet1$]
    ‘As shown below:
    sSQLSting = “SELECT ” & x & ” From [Sheet1$]”
    ‘Your remaing code here, similarly you can keep a WHERE Condition—

    Thanks-PNRao!

  39. Navneet Rao Ingle
    September 15, 2014 at 2:35 PM — Reply

    Hi PN,
    I am trying to copy the data from one workbook to another. Everything goes fine till the fetching of data from the source workbook but when I tried to paste the data in the destination workbook I am getting the following error:

    Run-time error ‘-2147467259 (80004005)’:

    You cannont move a part of a PivotTable report, or insert worksheet
    cells, rows, or columns inside a PivotTable report. To insert worksheet
    cells, rows, or columns, first move the PivotTable report (with the
    PivotTable report selected, on the Options tab, in the Actions group,
    click Move PivotTable). To add, move, or remove cells within the
    report, do one of the following:

    Code used is:

    Dim DNameRecvd
    Dim query As String
    Dim ReturnArray

    DNameRecvd = DName

    Dim conn As New ADODB.Connection
    Dim mrs As New ADODB.Recordset

    Dim DBPath As String, sconnect As String
    DBPath = ThisWorkbook.FullName

    sconnect = “Provider=MSDASQL.1;DSN=Excel Files;DBQ=” & DBPath & “;HDR=Yes’;”

    conn.Open sconnect
    query = “SELECT * from [Data$]”
    mrs.Open query, conn

    Workbooks(“DestinationFile”).Activate
    Sheets(“Sheet4”).Activate

    Sheet4.Range(“A2”).CopyFromRecordset mrs ‘—-Receiving error message at this line

    mrs.Close
    ActiveWorkbook.Save
    MsgBox (“Done”)

    Please help. Thanks in Advance.

  40. gayathiri
    September 22, 2014 at 3:47 PM — Reply

    Dear Pn Rao
    i have to go through entire spreadsheet/workbook to find current status of articles by adding received date to 20 and if it matches today’s date. change the color of that row. can i do it without ADO connection

  41. PNRao
    September 22, 2014 at 7:56 PM — Reply

    Hi Gayathri,
    Yes, we can open the workbook and do whatever we want without using VBA. Your code will be some thing like this:
    You can open the required file:
    set Wb=Workbooks.Open(“C:tempworkbook.xlsx”)
    Assuming you have recieved date in Column A
    iCntr=1
    Do while Wb.Sheets(“SheetName”).Cells(iCntr,1)<>”
    If Format(Wb.Sheets(“SheetName”).Cells(iCntr,1),”DD-MM-YYYY”)=Format(Now(),”DD-MM-YYYY”) then
    ‘Here you can change the cell/range color
    End If
    Loop

    Hope this helps!
    Thanks-PNRao!

  42. gayathiri
    September 23, 2014 at 11:14 AM — Reply

    thanks a lot.. :)but where to put this code. either by keeping a button or create a macro module for this workbook. My requirement is Say if the article is received on september 10 i have to get that row say in green color on september 30

  43. gayathiri
    September 24, 2014 at 1:37 PM — Reply

    Mr.Rao thanks for your timely help:) :) Customized ur code and it works well..

  44. PNRao
    September 26, 2014 at 9:31 PM — Reply

    You are most welcome!
    Thanks-PNRao!

  45. Est228
    October 10, 2014 at 9:45 PM — Reply

    Dear PnRao
    I am using this code to connect to MS Access 2013 and used your previous comment to Shubhangi to structure the code. Everything seems to be working fine until I get to this part of the code:
    sSQLSting = “SELECT * FROM [BD_X]” where BD_X is the name of my Access table
    Here I keep getting an Error. I all ready have the required OLEDB and also tried using this code instead:
    sSQLSting = “SELECT * FROM [BD_X$]”
    I would appreciate some help.

  46. PNRao
    October 12, 2014 at 10:06 AM — Reply

    Hi,
    You can use the table name directly: sSQLSting = “SELECT * FROM BD_X”.

    If you want to refer Excel sheet as table then it will be like [BD_X$], if you connect any data base like MS Access, MS SQL Server, Oracle or Teradata you can use the table name.

    Hope this helps!
    Thanks-PNRao!

  47. Philip
    October 26, 2014 at 8:48 PM — Reply

    Greetings PNRao,

    I am in between developing a small project for the place I work at.
    Currently I am helping out the call center gang with automating their reports.
    There is a huge report that they spool off a web site at the end of each month…
    They obtain it in the form of an excel file with 97 format, which means each sheet is limited to 65535 rows only.
    So therefore the report spans to 4 sheets and could be more…
    I have completely automated this report into various pivot format for them per their requirement using Excel VBA.
    However the code is slow to about 10 seconds.
    There are many data analysis involved like filtering out the blanks off 2 columns, unwanted rows from another and pivoting them to obtain 4 reports using different criteria each.
    I am talking about 260000+ records analyzed to about 72000+ actual meaningful data for the report.

    Now, I thought maybe ADO could work out the trick more efficiently and faster.
    I have worked with ADO before in access/excel and know how to on the basics of connection etc.

    Currently, I need to know 2 things at this point:

    1) Is the ADO method faster than using excel automation via variant and/or range methods combined with loops?
    2) How do I append data from 4 sheets into 1 recordset to later analyze it with various select statements? Do I have to use an append query to obtain data from each sheets? If so, let me know how the query would look.

    Note: What I am thinking of doing is to completely do the required data manipulations within ADODB recordset and insert the manipulated data into a new sheet in Excel 8 format. Also, to run queries and to obtain the reports required from these manipulated data and again insert sheets into excel form query object.

    Could you kindly guide me into the various steps I need to be looking at to achieve these goals.

    Thanks in advance,
    Philip

  48. Suruchi
    October 27, 2014 at 10:47 PM — Reply

    Hi PN ,

    This is really helpful .
    One thing that is not working at my end is changing HDR=No’; … this code is not giving me the header which is required.
    I tried with for loop which is working in that case , just wanted to know if how would HDR would work.

    Thank you

  49. Suruchi
    October 28, 2014 at 11:55 AM — Reply

    Hi PN,

    This code is working fine , but I am not able to get the header eve after making HDR =No .
    Could you please help me on this .

    Thanks ,
    Suruchi

  50. PNRao
    October 29, 2014 at 10:34 PM — Reply

    Hi Philip,
    PivotTable is better than ADO, if your customers use Excel 2010 or higher. And to combine the Data into one record set, you query all data into one record set using UNIONs.

    Hope this helps.
    Thanks-PNRao!

  51. PNRao
    October 29, 2014 at 10:38 PM — Reply

    Hi Suruchi,
    The usage of HDR is to tell the ADO whether your data has headers or not.
    HDR= Yes means: You have the data and the first row is having headers and data starts from the next row.
    HDR= No means: Your data has no header row and and data the data starts from the first row.

    Hope this clarifies your query.
    Thanks-PNRao!

  52. Mani
    November 6, 2014 at 2:29 PM — Reply

    Hi PNRao,

    This is a great & Nice Information!
    Would you be kind enough to answer the following question too,

    Question: how can i get the data from Oracle Database, currently I use SQL Developer to query and store the result in excel and process it later, but since the number of individual sqls increased i’m looking for something like this and if you can help me in this regard, it would be great.

    Thanks in advance
    Mani

  53. Amjed
    November 14, 2014 at 4:34 PM — Reply

    Hi,
    i would like to connect to PL/SQL developer from MS Excel and fetch the records from it and copy to the excel sheet. The query i want to execute is ‘SELECT * FROM TABLE_NAME’. Please let me know the connection string to use.
    Thanks in Advance.

  54. Satyarth Rao
    November 19, 2014 at 11:54 PM — Reply

    Hi PN,
    I am trying to pull data from SQL Server 2012 using excel VBA Code but it is showing that SQL Sever is not exit or access is denied. Please let me know how to do so. It will be a great help.
    Thanks in Advance.

  55. Scott
    November 28, 2014 at 4:08 AM — Reply

    Is it possible to join 2 tables from separate databases in an SQL query within Excel VBA?
    I am currently extracting data from a table in a Firebird database but need to access data from records form a table in another Firebird database. The results of the query are used as input to a case statement that totals and dumps data into a worksheet.
    I can do this in Access since I link to the tables as required, can I have 2 connections open at once in Excel?

  56. Prasad Sakpal
    December 2, 2014 at 12:40 PM — Reply

    Amazing Website…………..Thank you for giving me proper information.

  57. Prasad Sakpal
    December 2, 2014 at 12:44 PM — Reply

    With help of this website, i have entered the insert query & it is properly working but on this “mrs.Open sSQLSting, Conn” statement getting errors ‘Run-Time Error 3704’. Please help on this..I appreciated.

  58. Prasad Sakpal
    December 2, 2014 at 12:45 PM — Reply

    Record is properly inserted into SQL database but getting above error message. please check…

  59. Sub sbADO()
    Dim sSQLQry As String
    Dim ReturnArray
    Dim Conn As New ADODB.Connection
    Dim mrs As New ADODB.Recordset
    Dim DBPath As String, sconnect As String
    sconnect = “Provider=SQLOLEDB.1;Data Source=******;Initial Catalog=******;User ID=*******;Password=*****;”
    Conn.Open sconnect
    sSQLSting = “INSERT INTO [tablename](code, fname,lname,process) Values(‘20202020′,’Prasad’,’Sakpal’,’PC001′)”
    mrs.Open sSQLSting, Conn ‘ Getting error message on this line, but record is properly inserted in to SQL database.
    mrs.Close
    Conn.Close
    End Sub

    Error is = ‘Run-Time Error 3704′
    Application Defined or Object Defined Error

  60. sandeep
    December 5, 2014 at 4:49 PM — Reply

    Hi,
    I have a query. While uploading data to SQL, if i try to download data from SQL using excal vba it is failing and throwing error.Do we have any wayt to handle mulitple calls in SQL using VBA….
    An really confused shud it be done at vba end or SQL end?

  61. This thread has been very helpful in getting going. However, there is one problem. I am using an ODBC driver talking to Google big query but I imagine this problem I have could be relevant to any DBMS connection that has it’s own SQL variant. The key requirement for me is to be able to pass the NATIVE SQL code that the DBMS supports rather than being forced into submitting ANSI SQL which very limiting. I’m using a driver that is meant to supports both.
    The following works as intended:
    Dim Conn As New ADODB.Connection
    Dim mrs As New ADODB.Recordset
    Conn.Open “DSN=bq”
    SQLString = “SELECT count(*) as a from EVENTS.Game_20141205 ”
    mrs.Open SQLString, Conn
    Sheet2.Range(“A2”).CopyFromRecordset mrs
    mrs.Close
    Conn.Close

    But if I try and submit any non-ANSI SQL statement for example:
    SQLString = “select a from (SELECT count(*) as a from EVENTS.Game_20141205) ”
    (and this SQL runs perfectly well if you send it directly to Google bigquery directly from the google webconsole)

    The driver pops an error:
    Run-time error ‘-2147217911 (80040e09)’:
    [Simba][SQLEngine] (31480) syntax error near ‘select a from (SELECT count(*) as a from EVENTS.Game_20141205) <<>>
    which I assume is because it’s not ANSI form SQL. Does anyone know how to submit the native SQL through vba (which should directly be passed through to the DBMS without any checking)

  62. Henning
    December 15, 2014 at 8:06 PM — Reply

    In the file “remedy-export” there are no header and 5 rows of data

    When I run the code, it only assigns data from row 2 to row 5 to the array. What am I doing wrong?

    [code]
    Sub Connect_to_Sheet()
    Dim SQLString As String
    Dim ReturnArray
    Dim Conn As New ADODB.Connection
    Dim rsRecordset As New ADODB.Recordset
    Dim DBPath As String, sConnect As String

    Dim Col_Idx, Row_Idx As Long

    DBPath = ThisWorkbook.Path & “remedy-export.xlsx”
    sConnect = “Provider=MSDASQL.1;DSN=Excel Files;DBQ=” & DBPath & “;HDR=NO’;”
    Conn.Open sConnect

    SQLString = “SELECT * From [Ark2$]”
    rsRecordset.Open SQLString, Conn, adOpenStatic, adLockReadOnly
    Row_Idx = rsRecordset.RecordCount
    ReturnArray = rsRecordset.GetRows
    rsRecordset.Close

    Conn.Close

    End Sub
    [end code]

  63. saibabu
    December 19, 2014 at 12:14 AM — Reply

    Hi All,

    i want to copy only specific cells range.

    KINDLY HELP ME.

  64. kesav
    December 30, 2014 at 1:12 PM — Reply

    hi pn
    i am trying to connect ms access 2010 data base but its showing erroe
    provider not recognized can to help me for over comming from this problem
    thanks
    kesav

  65. baha
    January 6, 2015 at 11:14 PM — Reply

    Ho to delete table in existing access database? by using

  66. PNRao
    January 12, 2015 at 9:25 PM — Reply

    Hi Baha,

    You can delete the table using TRUNCATE or Drop statement if have full permissions.
    To delete only the data: TRUNCATE TABLE table_name;

    Warning: If you use the below statement, you will loss the entire table and you can not roll back.
    To delete entire data: DROP TABLE table_name;

    Thanks-PNRao!

  67. Haridas
    January 25, 2015 at 12:37 AM — Reply

    Hi,
    I need VBA & SQL learning material because i don’t have knowledge in VBA but i have knowledge in MS Office(Advance excel..).
    Any one please send to my email.

  68. sachin
    January 27, 2015 at 6:10 PM — Reply

    I was creating a macro to remove exact row duplicate in excel using sql query,but it it giving me “Runtime error -2147217865(80040e37)”. Below isthe VBA code

    Sub sbADOExample()
    Dim sSQLQry As String
    Dim ReturnArray

    Dim Conn As New ADODB.Connection
    Dim mrs As New ADODB.Recordset

    Dim DBPath As String, sconnect As String

    DBPath = ThisWorkbook.FullName

    ‘You can provide the full path of your external file as shown below
    ‘DBPath =”E:tempInputData.xlsx”

    sconnect = “Provider=MSDASQL.1;DSN=Excel Files;DBQ=” & DBPath & “;HDR=Yes’;”

    Conn.Open sconnect

    sSQLSting = “select distinct column1, count(*) From [Sheet1$] group by column1 having count(*) >1″

    ‘ Your SQL Statement (Table Name= Sheet Name=[Sheet1$])

    mrs.Open sSQLSting, Conn
    ‘=>Load the Data into an array
    ‘ReturnArray = mrs.GetRows
    ”OR”
    ‘=>Paste the data into a sheet
    Sheet2.Range(“A2”).CopyFromRecordset mrs
    ‘Close Recordset
    mrs.Close

    ‘Close Connection
    Conn.Close

    End Sub

    Note : Above code working perfectly fine for 2 column

  69. PNRao
    February 3, 2015 at 9:53 PM — Reply

    Hi Sachin,

    I found no issues in your code. Please send your file with some dummy data. So that we can help you to solve your issue.

    Thanks-PNRao!

  70. Manoj
    February 23, 2015 at 5:40 PM — Reply

    Hi PN Rao – Thanks for the post really helpful
    I am trying to use Sum( Case when ( condition) then 1 else 0 end ) in this concept and it keeps saying automation error
    The same code is working perfectly in SQL server
    Please advise

    Thanks
    Manoj

  71. Hi Rao

    I am also getting the same kind of error as Sachin is geeting

    I am getting the error in this line “mrs.Open sSQLsting,conn”

    error is “Runtime error -2147217865(80040e37)”

  72. PNRao
    March 2, 2015 at 7:05 PM — Reply

    Hi Richard and Sachin,

    Please make sure that the field names are correct. I could not find any issue in the Sachin’s query.

    Thanks-PNRao!

  73. Enrico
    March 19, 2015 at 9:13 PM — Reply

    Dear analists

    the code is working but I am retrieving in Sheets(1) just 54’816 lines on 575’000 present in Sheets(2).
    do you know why?
    I am using Excel 2010

    Thanks
    Enrico

  74. Aswin
    March 23, 2015 at 11:41 PM — Reply

    Hi PN ,

    Read through the post great information you are sharing indeed.. I have a scenario where i would need to pull the values in a column in sheet say Sheet1 whose range may be dynamically changing into IN clause in SQL server query with values like ‘A’,’B’,’C’ etc

  75. guys77
    March 29, 2015 at 10:36 AM — Reply

    Hi experts..
    How about Dbf files?what string/connection code?
    Thanks

  76. KUMAR
    May 4, 2015 at 1:07 PM — Reply

    Really great. I could get what I could not even in Microsoft site

  77. HONEY
    May 8, 2015 at 12:23 PM — Reply

    Hi,

    I want to access the info of memory usage of production database in my excel sheet.

    can anyone help me with vba.

  78. sheriff
    May 14, 2015 at 9:54 PM — Reply

    Hi,

    I want to get a notification automatically when a file is copied in a folder. Can this be done by VBA macro ?

    Please help me.

    Thanks,
    Sheriff

  79. sheriff
    May 14, 2015 at 9:58 PM — Reply
  80. Sam
    May 22, 2015 at 8:04 AM — Reply

    Hi,

    Thanks for sharing this info…
    Very useful

    regards
    sam

  81. Anand Jo
    May 29, 2015 at 9:19 PM — Reply

    Thanks for the code. It works with the user input when input command is used. But, it does not work when the user enters a value in the textfield in the userform created in excel VBA. Why does this happen? It just does not work with the userform text field input. Any help is appreciated. Here is the code:

    Sub UForm()
    Dim sSQLSting As String
    Dim ReturnArray

    Dim Conn As New ADODB.Connection
    Dim mrs As New ADODB.Recordset
    Dim DBPath As String, sconnect As String

    DBPath = ThisWorkbook.FullName
    sconnect = “Provider=MSDASQL.1;DSN=Excel Files;DBQ=” & DBPath & “;HDR=Yes’;”
    Conn.Open sconnect
    sSQLSting = “SELECT * From [Sheet1$] where Order_Number = ” & ordernotext1 ‘ Your SQL Statement (Table Name= Sheet Name=[Sheet1$])
    mrs.Open sSQLSting, Conn

    Sheets(“ReportsO”).Range(“A8”).CopyFromRecordset mrs
    mrs.Close
    Conn.Close
    End Sub

  82. kishan Sanghani
    June 5, 2015 at 4:18 AM — Reply

    Hi ,

    I am able to execute query from VBA on my DB2. But sometime I need to abort query because of DB conjunction. Please suggest me way to abort query , if executed through VBA.

    Thanks in advance.

    Regards,
    Kishan Sanghani

  83. Krishna
    June 10, 2015 at 9:00 PM — Reply

    Hi,

    Am able to connect to excel data source using ADO connection. But my excel has 265000 rows and 118 columns. When I try to open record set, it struck and it taking more time.. Is that any way to use Ado connection and open record set in quick turnaround? Pls suggest.. Tnx

  84. UDAY PRATAP
    June 17, 2015 at 5:09 PM — Reply

    Nice Explanation…..Thanks.
    If I want to save picture of employees in (the respective rows) a column. for example Emp_Photo
    and if I run Select * from [Sheet1$] it is bringing all information but not the pictures
    How to achieve it?

  85. UDAY PRATAP
    June 17, 2015 at 5:12 PM — Reply

    Try to connect in a blank New workbook and after connection is established then copy the original sheet into this new workseets.

  86. Vic
    June 30, 2015 at 7:37 PM — Reply

    Hi,

    The code you gave worked! I am really kinda new to this old VBA stuff. My problem is it opens on a new sheet in a new workbook. How can I have the data displayed on an existing sheet with existing columns?

    Thank you in advance for your help PN.

    – V

  87. Sameer
    July 9, 2015 at 5:56 PM — Reply

    Hi PN – Your site has awesome content and I am hoping you can resolve my query.

    I have a MySQL database and I have connect it to excel using VBA on the local machine. Now I want to give the same excel file as an input/output mechanism to all the users to interact with the database installed on my computer. All the users are in a network. Any help would be greatly appreciated.

  88. PNRao
    July 9, 2015 at 7:51 PM — Reply

    Hi Sameer,

    Thanks for your feedback!

    Here are the possible solutions and my preference order:

    Solution 1: You can create new database in any server and export the local database into server and change the connection string. All your user need to have MySQL OLEDB Provider in their PCs.

    Solution 2. You can export to MS Access database and change the connection string. For this your user do not required to install any additional Provider.

    Hope this helps!
    Thanks-PNRao!

  89. Mahantesh
    September 9, 2015 at 5:18 PM — Reply

    StrSQL=”SELECT * FROM [Shee1$] MINUS SELECT * FROM [Sheet2$] is not getting executed.

    Help required.

  90. Dung Nguyen
    September 14, 2015 at 8:58 PM — Reply

    Hi PNRao,

    I would query to the first worksheet of selected workbook through navigate to the workbook location and user select it( I used worksheets(1) but can not successful), can you show me a sample how to assign this parameter of worksheets(1) to the vba query?

    Regards/Dung

  91. This paragraph ցives ϲlear idea in support οf the new users.

  92. Sriram
    October 7, 2015 at 12:48 PM — Reply

    Hi
    Am trying to run sql Analysis query in excel macro . Can you please help me .

    Thanks in advance

  93. Dan
    October 21, 2015 at 7:20 AM — Reply

    Hi,

    Very helpful page, thank you.

    I have managed to use a select query to retreive data from a second sheet however I am wanting to update data in a sheet using this method. I have changed the sSQLSting to an update query which appears to run but the data does not update.

    Could I please trouble you for a simple example of how to update a cell value?

    Column A (Dealer) is unique and Column B (Value) is the cell that I am trying to update

    Sheet name = DATA
    Column A = Dealer
    Column B = Value

    Thank you,

    Dan

  94. Dan
    October 21, 2015 at 10:19 AM — Reply

    Sorry for wasting your time with my first message, was a pretty simple mistake in the end.
    I have it working however I am wanting to source the value that I am updating from a cell on the sheet. I have done this with:
    Dim NewVal As String
    NewVal = Sheets(“ADO”).Range(“N2”).Value
    When I try to put this into the sSQLSting it errors. Can you please help me out.

    Thanks again.

    Code:

    ‘Add reference for Microsoft Activex Data Objects Library

    Sub sbADOUPDATE()
    Dim sSQLQry As String
    Dim sSQLQry2 As String
    Dim NewVal As String

    Dim ReturnArray

    Dim Conn As New ADODB.Connection
    Dim mrs As New ADODB.Recordset

    Dim DBPath As String, sconnect As String

    DBPath = “P:DocumentsSALESOrderwrite2015TestingBook2.xlsx”
    NewVal = Sheets(“ADO”).Range(“N2″).Value

    ‘You can provide the full path of your external file as shown below
    ‘DBPath =”C:InputData.xlsx”

    sconnect = “Provider=MSDASQL.1;DSN=Excel Files;DBQ=” & DBPath & “;HDR=Yes’;”

    Conn.Open sconnect
    sSQLSting = “UPDATE [Data$] SET Content = ‘testing2’ WHERE Dealer = ‘Q325′”

    mrs.Open sSQLSting, Conn
    sSQLSting2 = “UPDATE [Data$] SET Content = 1000 WHERE Dealer = ‘Q375′”

    mrs.Open sSQLSting2, Conn

    ‘Close Connection
    Conn.Close

    End Sub

  95. Masaru
    November 1, 2015 at 11:58 PM — Reply

    Question: I have a header where it has been merge with under a 3 column, is it possible to call the sub column? Thanks!

  96. Michael
    November 10, 2015 at 8:37 PM — Reply

    Hi All
    I have a spreadsheet with an Excel Table named Table1 with two Columns named Quarter and Sales.
    The Table has say 4 rows of data beneath the header. Then there is more data in the rows below the table which is not part of the table.

    How do I copy only the data in the Table rows?
    Using SqlQry = “SELECT [Quarter], [Sales] FROM [Sheet2$][Table1$]”
    Copied all the data in the two columns including the data outside the Table.
    Thanks.

  97. loes
    November 25, 2015 at 7:52 PM — Reply

    Hello,

    I am trying to set up a connection to MySQL and came across this example. I applied the code to my own file. But what i can not seem to figure out is why the file does not take the values you write in A1, A2 etc. where in the code do you tell the code to skip the first line?

  98. Ray
    November 26, 2015 at 10:35 AM — Reply

    This is precisely what i was searching for..Thanks a Ton.

    One question please….Here we saw fetching data from a spreadsheet using ADO.

    Can we write data from a User interface,like a form (in Spreadsheet A) to a Database (Spreadsheet B) using ADO ?

    Please can you point me to where can I get more info on this.

    All the best with your efforts. God bless !

  99. mike
    January 15, 2016 at 1:22 PM — Reply

    Hello,

    I have made a connection with a dbf file with VBA this works great, but is it also possible to open multiple dbf files en join them in the SQL? Iám trying hard but can’t figure it out.

  100. Shwetanjali Das
    February 11, 2016 at 12:10 PM — Reply

    Hi,

    I want to fetch records from a database. How to do that? I have read only access to that database.

  101. srimeenakshi
    March 22, 2016 at 6:01 PM — Reply

    hi friends,
    i want a code to update a table in a database. when we click command button in vba?
    anyone can help me

  102. Iris
    March 29, 2016 at 3:21 PM — Reply

    hi, i couldn’t download the example file, seems the linkage was corrupted.

  103. Akit
    May 3, 2016 at 10:09 AM — Reply

    HI ,

    Really helpful blog, I am encountering an error when I tried to use Like operator in my sql statement.

    exs
    Dim sSQLQry As String
    Dim ReturnArray
    Dim Conn As New ADODB.Connection
    Dim mrs As New ADODB.Recordset
    Dim DBPath As String, sconnect As String
    DBPath = ThisWorkbook.FullName
    ‘You can provide the full path of your external file as shown below
    ‘DBPath =”C:InputData.xlsx”
    sconnect = “Provider=MSDASQL.1;DSN=Excel Files;DBQ=” & DBPath & “;HDR=Yes’;”
    Conn.Open sconnect
    Debug.Print YourstrQery,

    1. SQLSting = “SELECT * From [Sheet1$] WHERE [URL] like ‘%POST /login.form HTTP/1.1%’ ”

    2. SQLSting = “SELECT * From [Sheet1$] WHERE session in(Select Distinct session from [Sheet1$]) and [URL] like ‘%POST /login.form HTTP/1.1%’ ”

    mrs.Open sSQLSting, Conn

  104. ram
    May 10, 2016 at 12:34 PM — Reply

    There are records in the sheet titled ‘Table2’, which have Cust_ID not present in column Cust_ID in the sheet titled ‘Table1’ (e.g. 110, 117). Can you write an Excel VBA program that transfers the data in these sheets to 2 separate tables in Access DB, runs the appropriate query and provides the list of unmatched records from ‘Table2’? Please use ADO method for database connectivity. The program should execute on clicking a button in Excel and output should comprise of unmatched records displayed in a new Excel sheet.

  105. Guilherme
    June 4, 2016 at 12:08 AM — Reply

    I did’nt find the example file =(
    Can you send me the link?

  106. PNRao
    June 4, 2016 at 9:43 PM — Reply

    Thanks- We have fixed the download link.

    Thanks-PNRao!

  107. Kamal Kroor
    June 21, 2016 at 1:08 PM — Reply

    Dear All,
    Any one can help me with using variables in update command? in the above example, update is used only with exact number which will not be the case for real time situation. We need a variable that takes values from the user form.
    Thanks,

    Kamal Kroor

  108. Célio Ávila
    June 21, 2016 at 7:56 PM — Reply

    Damn… I’ve been trying so hard to learn this, but nothing ever seems to work.
    I finally downloaded the example file and not even that is working. I get the message, “System error &H8000FFFF (-2147418113). Catastrophic Failure.”
    I activated the 2.8 library something, so I dont know what could be going wrong.

    Also, every source I look for to study gives me a completely different macro example, so I can’t even compare them to better understand the coding.

    When I do find good content to learn SQL from, it doesnt seem to be related to excel vba, so it doesnt help me all that much.

    I’m trying to learn how to filter data with ADO insteand of using autofilter. At first I saw someone posting this example:

    Sub testConnection()
    Dim wb As Workbook
    Dim c As WorkbookConnection
    Dim sql As String

    Set wb = ActiveWorkbook

    Set c = wb.Connections.Item(1)
    sql = c.ODBCConnection.CommandText
    sql = Replace(sql, “WHERE (`’Sheet1$’`.k=10)”, _
    “WHERE (`’Sheet1$’`.k=9) AND (`’Sheet1$’`.l=11) AND (`’Sheet1$’`.m=12) AND (`’Sheet1$’`.n=13) “)
    c.ODBCConnection.CommandText = sql
    c.Refresh

    End Sub

    can anyone make sense of this?

  109. Ankush
    June 28, 2016 at 3:31 PM — Reply

    Hi

    Could you let me know if we can connect a macro to the server and get the information from the log files.

    And if yes , then could you let me know how we could connect to the server.

  110. Stanley
    July 1, 2016 at 1:25 PM — Reply

    Hi PNRao,

    Your website is awesome!
    Do you have experience to use RANK() OVER(PARTITION BY) function by ADODB connection?
    I need to rank first and output them.
    Any help would be greatly appreciated.

    Stanley

  111. Stewart
    July 15, 2016 at 2:27 PM — Reply

    HI PNRao,

    New to using VBA & ADO , I wish to use a similar code that uses an input-box to pull through the relevant input from a closed workbook to my current active workbook, is this possible?

    Kind Regards,

    Stewart

  112. Sanjeev Sharma
    August 6, 2016 at 12:54 AM — Reply

    Thanks!! for the valuable information!!

  113. Pawan
    August 30, 2016 at 10:49 AM — Reply

    Very nice Article. I have one query in this that I have one column which has number as well as text and I found one thing that vb query that declare the fields type as Number and it will not show Text values. So is it possible to import all the fields with data type as a string because string can capture both number as well as text.

  114. Tomi
    August 30, 2016 at 11:58 PM — Reply

    Hi, I am new to VBA and application development. Please how can someone start with learning VBA and Database Application development? Thank you

  115. Durgam Sasidhar
    January 4, 2017 at 7:36 PM — Reply

    WOW, This is what am searching for entire day, and this post Cleared My doubts and issues. Thx a lot

  116. Sunil Sehgal
    April 5, 2017 at 11:05 AM — Reply

    Hello sir,
    While I run my code it is showing automation error. Can you please etell me why is it so occuring.. tell me the solutio n for the same.

  117. Hasan
    May 4, 2017 at 9:05 PM — Reply

    Hi,

    when the Excel file is opened read-only, the sql query (with both providers MSDASQL and Microsoft.Jet.OLEDB) does not return any results.

    Any ideas how to overcome this, maybe using additional parameters?

  118. Rakesh
    May 17, 2017 at 2:43 PM — Reply

    Hi PNRao,

    Information provided by you in your website is excellent.
    I customised this code to postgresql,but getting an Run-Time error object required: 424.Can you please help me with this error.

    Thanks
    Rakesh

  119. AK
    July 19, 2017 at 7:57 PM — Reply

    Dear PN,

    Really, this webpage is very useful, thanks for your efforts.

    I have one question here:
    Instead of figures (2 & 5000) at ‘Values(2,500)’ how can use variables or cells from active sheet?

    Thanks in advance & regards,
    AK

  120. PNRao
    July 19, 2017 at 8:51 PM — Reply
    You need to form the string as per your requirement.
    Replace the below statement:
    sSQLSting = “INSERT INTO [DataSheet$](Quarter, Sales) Values(2,5000)”.
    
    With:
    
    sSQLSting = “INSERT INTO [DataSheet$](Quarter, Sales) Values(" &Range("A1") &"," &Range("A2") &")”.
    

    The second statement will read the values from Range A1 and A2 of ActiveSheet. You can also specify the sheet name if it is not a active sheet, Sheets(“SheetName”).Range(“A1”)

    Thanks!

  121. YasserKhalil
    July 20, 2017 at 10:59 PM — Reply

    That’s really awesome. Thank you very much
    How to update closed workbook using ADO?

  122. Andi permana
    November 30, 2017 at 4:36 PM — Reply

    How do I use where statement and group by??

  123. Mayur raj
    March 4, 2018 at 12:50 PM — Reply

    Hi recordset stores the result in array form, when using select a view/output is getting stored.but using insert there is no output, it will process the query and store data in mentioned table.
    Add one more line, select * from [inserted_table]
    Before msr.
    Hope you get the logic.
    Thanks

  124. Anil
    April 19, 2018 at 6:10 PM — Reply

    Hi Sir,

    I have insert code but show the error.

    Option Explicit
    Dim BlnVal As Boolean

    Private Sub Done_Click()
    Dim sSQLQry As String
    Dim ReturnArray
    Dim con As ADODB.Connection
    Dim sqlstr As String, datasource As String
    Set con = New ADODB.Connection
    datasource = “D:TEST.xlsx” ‘change to suit

    Dim sconnect As String
    sconnect = “Provider=Microsoft.ACE.OLEDB.12.0;” & _
    “Data Source=” & datasource & “;” & _
    “Extended Properties=”Excel 12.0;HDR=YES”;”
    With con
    .Open sconnect

    sqlstr = “Insert Into [Sheet2$](Sno, Name, Amt) Values (GP.ComboBox1.Value, GP.TextBox1, GP.TextBox2)”

    .Execute sqlstr
    .Close
    End With

    Set con = Nothing

    End Sub

  125. Anil
    April 19, 2018 at 6:14 PM — Reply

    I have insert data in offline Excel File & Same Update Data Combobox1 and TextBox1 only Number accept. not Text.

  126. nalini raju
    May 14, 2018 at 6:47 PM — Reply

    ‘Iam not able to insert
    ‘Iam getting error–Automation error in runtime
    ‘Using MSDASQL Provider
    ‘sconnect = “Provider=MSDASQL.1;DSN=Excel Files;DBQ=” & DBPath & “;HDR=Yes’;”

    ‘Using Microsoft.Jet.OLEDB Provider – If you get an issue with Jet OLEDN Provider try MSDASQL Provider (above statement)
    sconnect = “Provider=Microsoft.Jet.OLEDB.4.0;Data Source=” & DBPath _
    & “;Extended Properties=”Excel 8.0;HDR=Yes;IMEX=1″;”

    Conn.Open sconnect
    ‘DeleteId = InputBox(“Name”)
    ” sSQLSting = “SELECT DISTINCT Date,SalesRep,Product,Discount,Units,Region,Net_Sales From [DataSheet$]”
    ‘ Your SQL Statemnt (Table Name= Sheet Name=[DataSheet$])
    ‘ sSQLSting = “UPDATE [DataSheet$] SET SalesRep=10,Product=10,Discount=10,Units=10,Region=10 WHERE Units=1”
    sSQLSting = “INSERT INTO [RAMA$](Quarter, Sales) Values(” & Sheets(“RAMA”).Range(“A1”) & “,” & Sheets(“RAMA”).Range(“A2”) & “)”
    ‘ sSQLSting = “Select * from [DataSheet$]” ‘ where Date is not null”
    mrs.Open sSQLSting, Conn

    ‘ Sheets(“RAMA”).Range(“A1”).CopyFromRecordset mrs

    mrs.Close

    ‘Close Connection
    Conn.Close
    End Sub

  127. Taesoo
    June 14, 2018 at 4:51 PM — Reply

    Hi,

    I read date from db file but can not read full data.
    Below is the data in db file
    Date
    4/16/2016 16:39
    4/19/2016 12:50
    4/22/2016 16:12
    4/25/2016 10:28
    4/27/2016 10:51

    This is what I read
    Date
    4/16/2016
    4/19/2016
    4/22/2016
    4/25/2016
    4/27/2016

    Sub db_query()

    Dim conn As Object, rst As Object
    Worksheets(“results”).Range(“A2:AI5001”).ClearContents

    Set conn = CreateObject(“ADODB.Connection”)
    Set rst = CreateObject(“ADODB.Recordset”)

    conn.Open “DRIVER=SQLite3 ODBC Driver;Database=D:backup.db;”

    strSQL = “SELECT Date from Tb_Result_Summary”
    rst.Open strSQL, conn, 1, 1

    Worksheets(“results”).Range(“A2”).CopyFromRecordset rst
    rst.Close

    Set rst = Nothing: Set conn = Nothing

    End Sub

  128. Baze
    July 9, 2018 at 3:50 PM — Reply

    Hi PN, thank you for this material. it is very educative especially for a person who is beginner in VBA like me.
    I am trying to make a connection from my excel file to a database and i tried your code but it resulted in a mistake :

    ‘Sheet1$’ is not a valid name. Make sure that it does not include invalid characters or punctuation and that it is not too long

    I am apologizing in advance, cause this question might seem very beginner for you, but I am in my first steps with VBA.

  129. Deepak Bisht
    October 2, 2018 at 6:45 PM — Reply

    Each time i pull data the file opened in read only mode.. Please advise

  130. Prabhu Murugan
    December 20, 2018 at 9:42 AM — Reply

    Hi,

    A column in an excel file consist of values only. But still select query for the field throws data type mismatch in criteria even after I changed all the cells to values.

    select * from table where field < 0

    It works only for

    select * from table where field < ‘0’

  131. Amber
    July 18, 2019 at 5:58 AM — Reply

    I want to get into an array all records brought by getRows but I can’t. When I try like this, the array stay empty anyway. I only get success by using getString but my goal is insert each record into a cell of a listbox. I hope you can understend my english!

  132. anil
    November 17, 2019 at 12:50 PM — Reply

    thanks for efforts sir as a beginer easyly understand whole concept

  133. Mon
    February 9, 2020 at 1:15 PM — Reply

    Hi,

    please advise how can I use the SQL command to delete the record

    thank you

  134. Dinesh
    May 2, 2020 at 10:37 PM — Reply

Effectively Manage Your
Projects and  Resources

With Our Professional and Premium Project Management Templates!

ANALYSISTABS.COM provides free and premium project management tools, templates and dashboards for effectively managing the projects and analyzing the data.

We’re a crew of professionals expertise in Excel VBA, Business Analysis, Project Management. We’re Sharing our map to Project success with innovative tools, templates, tutorials and tips.

Project Management
Excel VBA

Download Free Excel 2007, 2010, 2013 Add-in for Creating Innovative Dashboards, Tools for Data Mining, Analysis, Visualization. Learn VBA for MS Excel, Word, PowerPoint, Access, Outlook to develop applications for retail, insurance, banking, finance, telecom, healthcare domains.

Analysistabs Logo

Page load link

Go to Top

SQL in VBA

Many times I was irritated of the lack of some Excel functionality (or just I don’t know there is) to easily transform data w/o using pivot tables. SQL in VBA was the only thing that was missing for me.

Distinct, grouping rows of Excel data, running multiple selects etc.
Some time agon when I had a moment of time to spare I did my homework on the topic only to discover that running SQL queries from Excel VBA is possible and easy…

Want to create SQL Queries directly from Excel instead? See my Excel SQL AddIn
Want to learn how to create a MS Query manually? See my MS Query Tutorial

Using SQL in VBA example

sql in excelLet see how to run a simple SELECT SQL Query in Excel VBA on an example Excel Worksheet. On the right see my Excel Worksheet and the Message Box with the similar output from my VBA Macro. The VBA Code is below:

Sub RunSELECT()
    Dim cn As Object, rs As Object, output As String, sql as String
    
    '---Connecting to the Data Source---
    Set cn = CreateObject("ADODB.Connection")
    With cn
        .Provider = "Microsoft.ACE.OLEDB.12.0"
        .ConnectionString = "Data Source=" &amp; ThisWorkbook.Path &amp; "" &amp; ThisWorkbook.Name &amp; ";" &amp; "Extended Properties=""Excel 12.0 Xml;HDR=YES"";"
        .Open
    End With
    
    
    '---Run the SQL SELECT Query---
    sql = "SELECT * FROM [Sheet1$]"
    Set rs = cn.Execute(sql)
    
    Do
       output = output &amp; rs(0) &amp; ";" &amp; rs(1) &amp; ";" &amp; rs(2) &amp; vbNewLine
       Debug.Print rs(0); ";" &amp; rs(1) &amp; ";" &amp; rs(2)
       rs.Movenext
    Loop Until rs.EOF
    MsgBox output
    
    '---Clean up---
    rs.Close
    cn.Close
    Set cn = Nothing
    Set rs = Nothing
End Sub

Explaining the Code

So what is happening in the macro above? Let us break it down:

Connecting to the Data Source

First we need to connect via the ADODB Driver to our Excel Worksheet. This is the same Driver which runs SQL Queries on MS Access Databases:

'---Connect to the Workbook---
    Set cn = CreateObject("ADODB.Connection")
    With cn
        .Provider = "Microsoft.ACE.OLEDB.12.0"
        .ConnectionString = "Data Source=" & ThisWorkbook.Path & "" & ThisWorkbook.Name & ";" & _
        "Extended Properties=""Excel 12.0 Xml;HDR=YES"";"
        .Open
    End With

The Provider is the Drive which is responsible for running the query.

The ConnectionStrings defines the Connection properties, like the path to the Queries File (example above is for ThisWorkbook) or if the first row contains a header (HDR).

The Open command executes the connection.

You can find more information on the ADODB.Connection Object on MSDN.

Running the SQL Select Query

Having connected to our Data Source Excel Worksheet we can now run a SQL SELECT Query:

'---Running the SQL Select Query---
Sql = "SELECT * FROM [Sheet1$]"
Set rs = cn.Execute(Sql)
 
Do
   output = output & rs(0) & ";" & rs(1) & ";" & rs(2) & vbNewLine
   Debug.Print rs(0); ";" & rs(1) & ";" & rs(2)
   rs.Movenext
Loop Until rs.EOF
MsgBox output

So what happens here? First we run the Execute command with our SELECT query:

SELECT * FROM [Sheet1$]

What does it do? It indicates that our records are in Sheet1. We can obviously extend this query just to filter people above the age of 30:

SELECT * FROM [Sheet1$] WHERE Age > 30

This would be the result:
sql in excel - above 30

The Execute command returns a ADODB RecordSet. We need to loop through the recordset to get each record:

Do
   '...
   'Loop through records - rs(0) - first column, rs(1) - second column etc.
    '...
   rs.Movenext 'Move to next record
Loop Until rs.EOF 'Have we reached End of RecordSet

Clean up

Lastly we need to Clean up our Objects to free memory. This is actually quite an important step as if you VBA code is runs a lot of queries or computations you might see a slow-down soon enough!

rs.Close
cn.Close
Set cn = Nothing
Set rs = Nothing

What Else Can I Do?

You can do tons of great things with ADODB / MS Queries / SQL in Excel. Here are some additional ideas:

  • Run Queries Across Worksheets – you can run JOIN queries on multiple Excel Worksheets. E.g.
    SELECT [Sheet1$].[First Last], [Age], [Salary] FROM [Sheet1$] INNER JOIN [Sheet2$] ON [Sheet1$].[First Last]=[Sheet2$].[First Last]
    

    On the below tables:
    sql in excel example

  • Extracting Data from External Data Sources – use different connection strings to connect to Access Databases, CSV files or text files
  • Do more efficient LOOKUPs – read my post on VLOOKUP vs SQL to learn more

Понравилась статья? Поделить с друзьями:
  • Excel макросы создать папку
  • Excel макросы две таблицы
  • Excel макросы создание шаблона
  • Excel макросы границы ячеек
  • Excel макросы создание нового листа