Страницы: 1
RSS
SQL запрос с помощью ADODB.Recordset источник – именованная таблица excel
 

Добрый день Форумчане.

Недавно решал задачу с получением данных с помощью ADODB.Recordset   только источник был весь лист книги Эксель.

Есть ли возможность в запросе указывать источником не весь лист эксель а именованную таблицу?

Подскажите пожалуйста очень нужно !!!

В приложении файл с работающим запросом ко всему листу книги.

Макрос выполняется по кнопке "Фильтр" на Листе.

Результатом запроса является подсчёт количества строк в полученной таблице. Конечная цель конечно не простой подсчёт количества, я потом буду эти строки перебирать в цикле и анализировать.

Строка самого запроса

Код
sql_text = "Select f5,f6,f7,f8,f9,f10,f11 From [" & list_dannie & "$] 
Where (f9 > #" & Format(data1, "MM\/dd\/yy hh\:mm\:ss") & "#) and (f9 < #" & Format(data2, "MM\/dd\/yy hh\:mm\:ss") & "#)"


list_dannie – переменная типа String в ней хранится имя листа с которого происходит выборка данных.

table_istochnik  - переменная типа string  в которой хранится имя таблицы из которой нужно получить данные

Вопрос в том как использовать в запросе переменную table_istochnik вместо list_dannie .

Перепробовал кучу разных вариаций ничего не получается.

Может хотя бы подскажите в какую сторону "Рыть". И вообще возможно это или нет ?

Буду благодарен за советы.
 
Потому что SQL не видит умных таблиц - только именованные диапазоны(при этом не динамические). Поэтому обращаться надо предварительно вычисляя адрес умной таблицы. И чтобы потом правильно работать с конкретным диапазоном надо еще в запросе поставить "с заголовками"(HDR=yes). В общем вот как должен выглядеть основной кусок:
Код
Dim id_zapros, nom_stroki_zapros As Long
Dim kol_strok_v_zaprose As Long
Dim data1 As Date, data2 As Date
Dim sTblQuery As String
'Конец переменные запроса
list_dannie = "Фильтр_По_Дате"
table_istochnik = Worksheets(list_dannie).ListObjects("Таблица_01_Смена").Range.Address(0, 0)
sTblQuery = "[" & list_dannie & "$" & table_istochnik & "]"
data1 = Worksheets(list_dannie).Cells(3, 21).Value
data2 = Worksheets(list_dannie).Cells(3, 22).Value
' Начало Запрос
   
    pRSet.CursorLocation = adUseClient ' включает возможность order by
    
    'Текст запроса
    sql_text = "Select * From " & sTblQuery & " Where ([Дата] > #" & Format(data1, "MM\/dd\/yy hh\:mm\:ss") & "#) and ([Дата] < #" & Format(data2, "MM\/dd\/yy hh\:mm\:ss") & "#)"
    
    sConn = "Provider=Microsoft.ACE.OLEDB.12.0;Mode=Read;Data Source=" & ThisWorkbook.FullName
    sConn = sConn & ";Extended Properties=""Excel 12.0;HDR=YES"";"
    pConn.Open sConn
    pRSet.Open sql_text, pConn
    
    pRSet.Sort = "[Дата] ASC,[Смена] DESC" 'order by
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
Спасибо Большое Дмитрий всё работает !!!
Опять очень выручили !!!
Можно ещё вопрос на засыпку.

Хочу в Эксель реализовать что то типа Базы Данных.
Задумка такая есть порядка 12 Таблиц связанных между собой по Id.

Одна таблица главная, а остальные подчинённые.
При перемещении курсора по главной таблице в  11 подчинённых  таблицах вышеуказанным запросом ( Точнее немного видоизменённым, фильтр будет по уникальному id ) будут извлекаться данные.

Вопрос насколько 11 таких запросов будут нагружать систему.
Книга каждый год будет создаваться новая. Т.е. таблицы будут очищаться.

Ниже приведен снимок примерного количества строк в таблицах. Главная Талица - Таблица 01




Дмитрий как считаете это будет жизнеспособная система или же система не справится с обработкой такого количества данных?

Изначально начинал эту тему с использованием запросов Power Query, но как оказалось после одновременного обновления2-х 3-х подчиненных запросов скорость заметно упала. И от данной затеи пришлось отказаться.

Теперь пробую реализовать данную затею с помощью RecordSet.
Было бы интересно услышать ваше мнение по данному вопросу.

В любом случае Спасибо за ваши ответы.
Изменено: Ермолов_А_П - 06.08.2021 17:10:40
 
Цитата
Ермолов_А_П написал:
Хочу в Эксель реализовать что то типа Базы Данных
уже плохая идея. Он не для этого. Поиск и отбор данных в Excel на малом объеме данных будет быстрее вообще без SQL. 100тыс. строк Excel осилит даже в одной таблице без всяких запросов - на грамотно построенных операциях поиска. Но здесь все индивидуально - мало знать размер таблиц, надо еще понимать что с ними придется делать и как часто. SQL, конечно, может потребоваться, если таблицы довольно большие, но быстродействие в любом случае будет зависеть от параметров ПК и размера данных. Ведь запрос выполняется в памяти и лимиты никто не отменял.
Цитата
Ермолов_А_П написал:
Вопрос насколько 11 таких запросов будут нагружать систему
вопрос больше на риторический похож, т.к. нельзя сказать как запрос нагрузит систему, если не видеть в принципе запрос и не понимать что, когда и как часто он делает.
Цитата
Ермолов_А_П написал:
Изначально начинал эту тему с использованием запросов Power Query
вряд ли стоит ожидать чего-то другого и здесь. Лучше углубиться в PQ и искать пути ускорить процесс.
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
OFF ТС, см. картинку

Для потомков (кто найдёт эту тему через много лет), хотел бы дать полный текст кода, который они могут взять, скорректировать под себя и работать
ВАЖНО: есть ограничение SQL при указании адреса  диапазона (A1:Z100) в 65536 строк, либо надо указывать полностью A:Z

Код
Sub SQL_Query_To_Smart_Table()
'ВАЖНО: есть ограничение SQL при указании адреса диапазона (A1:Z100) в 65536 строк, либо надо указывать полностью A:Z
    Dim sTblQuery As String, SheetName As String, Table_SourceAddress As String, sSQL_text As String, sConnStr As String
    Dim dtData1 As Date, dtData2 As Date
    Dim i As Long
    
    SheetName = "Лист1"
    dtData1 = Worksheets(SheetName).Cells(3, 21).Value 'начальная дата
    dtData2 = Worksheets(SheetName).Cells(3, 22).Value 'конечная дата
    
    Table_SourceAddress = Worksheets(SheetName).ListObjects("Таблица1").Range.Address(0, 0)
    sTblQuery = "[" & SheetName & "$" & Table_SourceAddress & "]"
    
    'Вариант 1
    Dim oRecordSet As Object, oConn As Object
    Set oRecordSet = CreateObject("ADODB.Recordset")
    Set oConn = CreateObject("ADODB.Connection")
    
    'Вариант 2
    'нужно добавить ссылку на Microsoft ActiveX Data Objects 6.1 Library, то
    '    Dim oConn As New ADODB.Connection
    '    Dim oRecordSet As New ADODB.Recordset
     
    oRecordSet.CursorLocation = 3 'adUseClient ' включает возможность order by
    'Вариант 1 с использованием функции Format
    'sSQL_text = "SELECT * FROM " & sTblQuery & " WHERE ([Дата] >= #" & Format(dtData1, "MM\/dd\/yy hh\:mm\:ss") & "#) AND ([Дата] <= #" & Format(dtData2, "MM\/dd\/yy hh\:mm\:ss") & "#)"
    'Вариант 2 с использованием функции DataSql
    sSQL_text = "SELECT * FROM " & sTblQuery & " WHERE ([Дата] >= " & DataSql(dtData1) & ")" & " AND ([Дата] <= " & DataSql(dtData2) & ")"
     
    sConnStr = "Provider=Microsoft.ACE.OLEDB.12.0;Mode=Read;Data Source=" & ThisWorkbook.FullName & ";Extended Properties=""Excel 12.0;HDR=YES"";"
    oConn.Open sConnStr
    oRecordSet.Open sSQL_text, oConn
    oRecordSet.Sort = "[Дата] ASC,[Смена] DESC" 'order by
    
    'выгрузка запроса на Лист2
    With Worksheets("Лист2")
        .Cells.Clear
        .Range("A2").CopyFromRecordset oRecordSet
        'заголовки таблицы
        For i = 0 To oRecordSet.Fields.Count - 1
            .Cells(1, i + 1) = oRecordSet.Fields(i).Name
        Next i
    End With

    oRecordSet.Close
    oConn.Close

    Set oRecordSet = Nothing
    Set oConn = Nothing

    MsgBox "Запрос выполнен!", vbInformation, ""
End Sub

Private Function DataSql(dt_sql)
    DataSql = "#" & Format(dt_sql, "mm\/dd\/yy hh\:mm\:ss") & "#"
End Function
Изменено: New - 05.03.2023 13:38:22
 
Отдельное спасибо за функцию  DataSql !!!
Сам не догадался в функцию это загнать.
 
Цитата
New написал:
sTblQuery = "[" & SheetName & "$" & Table_SourceAddress & "]"
ох как можно на этом подорваться, при превышении количества строк в таблице более  32767 65536
Изменено: БМВ - 09.08.2021 17:41:53
По вопросам из тем форума, личку не читаю.
 
А можно пожалуйста поподробнее, в чём заключается проблема?
Изменено: vikttur - 09.08.2021 13:32:57
 
Так просто диапазон Большого размера не примет и все, вот и вся проблема. При этом весь лист это весь лист а вот ограниченный диапазон , если не ошибаюсь по размерам листа формата старого. 256x32767 ошибался.
Изменено: БМВ - 09.08.2021 17:47:25
По вопросам из тем форума, личку не читаю.
 
Цитата
БМВ написал:
по размерам листа формата старого. 256x32767
это в какой версии такой лист был? :) Помню, в 95 это было 16384х256, потом начиная с 97 - 65536х256
Но ни про одну версию не помню, чтобы строк было 32767. Можно какую-то отсылку на документацию?
Изменено: Дмитрий(The_Prist) Щербаков - 09.08.2021 12:38:13
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
Дим, могу путать , давно это было, по этому и написал
Цитата
БМВ написал:
если не ошибаюсь по размерам листа формата старого
да и вопрос то не в этом а в том что диапазон более чем запрос не скушает.
По вопросам из тем форума, личку не читаю.
 
Да по сути фиг с ними, с размерами листов. Где(или как хотя бы поискать) найти инфу про озвученное ограничение? Ни разу не сталкивался с этим ограничением, отсюда и вопрос. Помню, запросами и более 50т. строк таскал, но увы, не помню точный текст запроса - может там диапазон не был указан...
Только что в файле протянул таблицу на 40тыщ строк, заполнил датами, входящими в диапазон. Запрос отработал без ошибок и отобрал 39 с лишним тысяч позиций.
БМВ, может подключение через другой провайдер должно быть?
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
Дмитрий, не в результате дело, если в запросе FROM [SheetName$A1:A100000] указать то была ошибка. При этом FROM [SheetName$A:A] отработает нормально и вернет сколько было. Я не помню уже где но мы с Андреем это обсуждали. Попробуй, раз макет собран.
По вопросам из тем форума, личку не читаю.
 
Цитата
БМВ написал:
если в запросе FROM [SheetName$A1:A100000] указать то была ошибка
так я растянул умную таблицу на 40тысяч строк и просто запустил код. А там адрес умной таблицы только считывается, если помнишь. Т.е. там вот такой диапазон получается в запросе: [Фильтр_По_Дате$E5:S40000]. И никаких проблем.
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
может я ошибся не 32 а более , попробуй пож 100к
[Фильтр_По_Дате$E5:S100000].
По вопросам из тем форума, личку не читаю.
 
Delete
Изменено: New - 09.08.2021 17:41:01
 
Цитата
БМВ написал:
не 32 а более
вот это уже похоже на правду - более 65536 не пустит, это довольно известное ограничение, которое преследует Excel много где. При этом не обязательно, чтобы таблица занимала все 65536 строк - достаточно, чтобы последняя ячейка выходила за эти пределы. В данном случае запрос посчитает адрес неверным.
Изменено: Дмитрий(The_Prist) Щербаков - 09.08.2021 17:34:08
Даже самый простой вопрос можно превратить в огромную проблему. Достаточно не уметь формулировать вопросы...
 
дописал комментарий в свой код выше
 
ну редко я пишу, редко, иной раз вода закипает при 90 градусах, а прямой угол 100 :-) , но помню что ограничение было.

Был просто очень поганый случай когда было под 100000 записей и диапазон начинался не с первой строки листа, и весь столбец не взять и диапазон не указать. Если есть возможность временно проименовать диапазон, то это выход. если нет, то печалька.
По вопросам из тем форума, личку не читаю.
 
Нашел ещё одно интересное ограничение Excel.
Ну как нашёл .... Excel опять стукнул меня по носу неизвестной ошибкой и я опять начал играть в игру найди 10 отличий )))
Суть в том что у меня порядка 13 таблиц расположено на одном листе по порядку слева направо. Из которых я и вытягиваю данные посредством sql запросов.

Между таблицами заложен резерв столбцов на всякий случай если таблицы будут расти по количеству столбцов.
Начиная с 5 таблицы запрос просто отказался работать. Причем если в текущий программный код подставлял предидущие таблицы то код отрабатывал.
Методом научного тыка нашёл причину.
Оказалось данный запрос не работает если приходится вытаскивать данные из диапазона ячеек где крайний правый столбец по своему индексу больше чем 255 или 256 что то такое .

Перекидываю эту же таблицу на новый лист в диапазон с первого столбца и всё работает.
Жаль конечно, у меня и так много листов занято. А тут ещё и под сами данные нужно будет использовать больше чем 1 лист.
Но ничего не поделаешь буду плодить листы.

Надеюсь кому нибудь пригодится мой опыт )))
 
Ермолов_А_П, этот опыт относится к тем же ограничениям что я писал про строки. Уж не знаю чем отдельные листы мешают, тем более что расположение на них отдельных таблиц снимают вопрос с определением диапазона, так как можно указать столбцы целиком, или не указывать вовсе.
По вопросам из тем форума, личку не читаю.
 
Я правильно понимаю -
Если делать запрос по именам столбцов а не по именованным диапазонам то и ограничения по столбцам не будет ?
 
будет. те же 256 но редко таблица имеет столько полей, если она сформирована корректно. Я прежде всего про строки. В описанном выше случае если 100000 строк, то SHEET1$A:C в случае начала таблицы с первой строки, отработает корректно, а вот SHEET1$A1:C100000 выдаст ошибку. при этом SHEET1$ тоже отработает но все что далее 255 столбца будет проигнорировано.
Изменено: БМВ - 25.08.2021 09:09:26
По вопросам из тем форума, личку не читаю.
 
Понял. Спасибо.
Изменено: vikttur - 25.08.2021 10:11:02
Страницы: 1
Читают тему
Наверх