Иван Сергеевич, если вы предлагаете контракт с ВС в Алуште, то, определённо, стоит об этом прямо у теме писать. А вот чат удалять сразу — плохой знак...
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
bedvit: это уже реализованно в фильтре в нашей библе
ты лукавишь) Понятно, что фильтр может возвратить отфильтрованный массив. А может вернуть индексы. А, также, индексы могут быть получены другим путём. Нет самого инструмента для пересбора. Отдельно. Мне кажется, на плюсах будет быстрее, чем на VBA. К тому же, можно добавить аргумент массива номеров столбцов и отобрать не только по строкам, а ещё и по столбцам (не все взять и/или в другом порядке и/или задублировать). Кстати, задублировать можно и строки, повторяя индексы.
Очень не хватает твоей реализации сцепки по условию. Я пока придумал только попутно со словарём собирать 2 одномерных массива (строковый для сцепок и лонг для последней заполненной позиции). Наполнить строковый буферными строками большой длины и заполнять их МИДом, запоминая последнюю позицию в лонг-массив. В конце, обрезать все строки по известную позицию. Тут демонстрировать не стал, а то и так непростой код.
Мне очень понравился мой вариант определения пересечения элементов массива — прямо здорово получилось
А тест я, конечно, сделаю — мне и самому очень интересно.
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
1. Задача может быть решена с использованием библы или без неё. Без неё я показал. Наверняка, можно что-то ускорить, но кардинально отличаться может только другой подход. С помощью твоего фильтра всё будет гораздо проще. Более того, на малых и средних объёмах он, скорее всего, будет быстрее. И уж точно удобнее и проще. Также, не нужно будет тратить время на подготовку данных и их обновление — всё будет браться актуальное. Всегда. Однако, на больших объёмах он вполне может уступить (надо протестировать). Есть такие задачи, когла временем подготовки данных можно пожертвовать или даже пренебречь — лишь бы потом можно было очень быстро по этим данным получать необходимую информацию. Такой была задача по словарю лемм (решилась с помощью твоего метода загрузки пар через одномерный массив). Такая задача и тут.
Если бы не волшебная комбинаторика, то задача свелась к бы к получению всех комбинаций (не хватает скорости плюсов, а у тебя нет ничего по этой теме) с номерами строк — в твоей карте. Но, боюсь, что количество комбинаций может быть просто невообразимо огромным и средняя ОЗУ просто не вывезет. Нужно что-то другое.
2. Если просто повторить мой алгоритм, то скорость нужна в 3ёх местах: - получение пар "критерий — массив номеров" (для каждого заданного поля. - определение общих номеров (пересечения) из заданного массива массивов (номеров) - быстрый пересбор двумерного массива по заданному списку строк. Кстати, вообще, такой инструмент пересбора был бы очень полезен. На твоей стороне это намного быстрее происходит.
Возможно, другой подход изменит и потребности.
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
Извлечь из исходной комбинации максимальных значений по заданным критериям., Пример: Извлечь из комбинации чисел 1 2 3 5 47 48 максимальных значений то есть 5 из 6
Апострофф: я не помогаю желающим обмануть спортлото из голого альтруизма
практически, Робин Гуд
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
Приветствую! Заинтересовался такой задачей: как можно ускорить фильтрацию двумерного массива? Далее под "фильтрацией таблицы" будет иметься в виду отбор строк двумерного массива, согласно критериев.
Давайте разбираться, что такое отбор/фильтрация на примере двумерного массива из таблицы
Итак, у нас есть тело (все данные без заголовков и итогов) Таблицы в виде двумерного массива a2D. В этом массиве rT (UBound (a2D, 1) ) строк и cT (UBound (a2D, 2) ) столбцов. Мы можем определить из этого массива cF полей, по которым мы хотим фильтровать таблицу. То есть: cT >= cF > 0. В общем смысле, фильтрация таблицы — это пересборка исходной таблицы с сохранением только тех строк, значения в которых по фильтруемым полям соответствуют условиям для этих полей.
Например, если я фильтрую таблицу по полю "Фамилия" и передаю критерий "Петров" и, также, фильтрую по полю "Имя" и передаю критерий "Василий", то, это значит, что я должен пройти по всем строкам Таблицы и оставить только те, у которых в поле "Фамилия" записано "Петров", а в поле "Имя" записано "Василий". И никак иначе.
Я решил разобрать [относительно] простой случай: Отбор не более, чем по одному значению — для каждого поля. Проверка осуществляется на строгое равенство, с учётом регистра. Алгоритм ускорения позволяет осуществить, также, проверку без учёта регистра и/или на НЕравенство, но в примере это не отражено.
Итак, как же ускорить? Чтобы ускорить, нужно как-то избавиться от цикла по всем строкам таблицы. Для этого нужно как-то запомнить строки для каждого критерия в фильтруемых столбцах и хранить их в ОЗУ (использовать статичные переменные). То есть, в любом случае, нужно собрать уникальные списки для каждого поля, которое хотим фильтровать.
Далее существует, минимум, 2 сценария:
• простой. Если количество комбинаций между всеми уникальными списками не выше порога (например, 100 млн), то можно использовать словарь (для не более чем 100 тыс. ключей )или массив словарей (для большего количества). Или суперсловарь от bedvit'а, у которого нет ограничения по ключам. Далее, мы "просто" получаем все эти комбинации и, для каждой из них, собираем массив строк, которые этой комбинации соответствуют. Пара: комбинация — массив. Тут ограничением является количество комбинаций — на 100 или даже 10 млн время получения этих комбинаций и массивов по ним может превысить допустимое время ожидания пользователя (устанавливается индивидуально). Если время формирования вас устраивает, то дальше всё просто: получаем параметры для фильтрации каждого поля, сцепляем в строку (по тем же правилам, как и при формировании ключей словаря) и, если такая строка есть в словаре, то просто получаем массив строк Таблицы и отбираем из неё в новый двумерный массив. Помимо относительной простоты, этот способ будет самым быстрым в получении массива строк по переданным параметрам. Кто считает, что такое (100 млн) количество комбинаций просто немыслимо напомню, что это, например 100 ^4, то есть, всего лишь 4 поля по 100 уникальных записей (минимальное количество комбинаций это произведение всех уникальных списков). И это минимум, потому что, если учитывать, что фильтры могут быть заданы НЕ для всех полей (как в примере) то это количество может быть значительно больше. • сложный. Что же делать, если 1ый вариант нас не устраивает? Как-то уйти от затратных по сбору комбинаций, очевидно. Я предлагаю [и показываю, как] собирать массив словарей, размером с количество полей, которые могут участвовать в фильтрации. Каждый элемент этого массива (словарь) содержит пары "критерий — массив строк". То есть, такой словарь для поля будет содержать столько ключей, сколько уникальных значений для этого поля. И для каждого ключа/значения будет содержать список строк, в которых оно встречается. Так мы уходим от необходимости комбинировать все возможные варианты сочетаний критериев. Это и было целью. Остаётся, при получении параметров отбора, найти в словарях все массивы со строками и, самое важное, найти ПЕРЕСЕЧЕНИЕ этих строк — то есть те номера строк, которые есть во всех отобранных массивах. Например, если передали только критерии для 2ух полей: Фамилия (= "Петров") и Имя (= "Василий"), то мы из соответствующих словарей (элементов массива словарей) находим список строк для (= "Петров"): {1, 2, 15, 89, 156} и для (= "Василий"): {3, 81 11, 15, 264} и понимаем/вычисляем, что общая строка у них всего одна (#15), а, значит и результирующий набор вывода будет состоять только из одной строки исходной таблицы.
Слабые места алгоритма, которые я хотел бы ускорить (существующими методами или библой bedvit'а): • сцепка по ключу (не очень страшно и есть альтернативы). Чтобы собрать номера строк в массив я использую накопительную строку, формируемую по принципу s = s & sSep & iRow. Есть и другие варианты ( Mid$(s, …) = sSep & iRow кажется самым быстрым, но сложнее в реализации). • определение общих значений (отсортированные целые числа) для N массивов. Тут я применил всё, что знал. Используется массив в качестве "словаря" для быстрой проверки и используется самый малый по размеру массив (т.к. если в нём нет номера строки, то она уже никак не может быть общей для всех массивов). Описывать очень долго — кто в теме, тот поймёт. Какие-то моменты всегда можно спросить и я отвечу. Так вот, для этого процесса мне бы очень не помешал специальный инструмент из библы — такие штуки на плюсах должны быть сильно быстрее. Думаю, что его применение может быть довольно широким.
Возможно, есть и другие способы, как ускорить отбор. Прошу поделиться
В файле 2 листа: исходная таблица для фильтрации и тестовый. В таблице можно добавлять/удалять строки. При уходе с листа произойдёт обновление. На тестовом можно выбрать от 1 до 4ёх критериев фильтра и нажать(даблклик) FILTER — справа выведется отфильтрованная таблица или сообщение, что под заданные параметры ничего не найдено.
Option Base 1
Option Explicit
Option Private Module
'==================================================================================================
' Work
'==================================================================================================
Function PRDX_StrToArrL(sIn$, sep$, aL_Out() As Long) As Boolean
Dim x, arr, n&
arr = Split(sIn, sep)
ReDim aL_Out(UBound(arr) + 1)
For Each x In arr
n = n + 1: aL_Out(n) = x
Next x
PRDX_StrToArrL = True
End Function
'==================================================================================================
' ' Faster than Dictionary
Function PRDX_ArrL_ChangeIndVal(aIn() As Long, aOut() As Long, Optional SetVal&) As Boolean
Dim UBnd&, r&, i&, n&
UBnd = 2 * UBound(aIn)
ReDim aOut(UBnd)
For r = 1 To UBound(aIn)
i = aIn(r): If (UBnd < i) Then UBnd = 2 * i: ReDim Preserve aOut(UBnd)
If (SetVal = 0) Then aOut(i) = r Else aOut(i) = SetVal
If (n < i) Then n = i
Next r
ReDim Preserve aOut(n)
PRDX_ArrL_ChangeIndVal = True
End Function
'--------------------------------------------------------------------------------------------------
Private Sub Test_PRDX_ArrL_ChangeIndVal()
Dim a&(), b&(), n&
PRDX_StrToArrL "5/3/2", "/", a
For n = 1 To UBound(a)
Debug.Print "a(" & n & ") = " & a(n) ' a(1) = 5; a(2) = 3; a(3) = 2
Next n
Debug.Print String$(20, "-")
PRDX_ArrL_ChangeIndVal a, b
For n = 1 To UBound(b)
Debug.Print "b(" & n & ") = " & b(n) ' b(1) = 0; b(2) = 3; b(3) = 2; b(4) = 0; b(5) = 1
Next n
Debug.Print String$(20, "-")
PRDX_ArrL_ChangeIndVal a, b, 100
For n = 1 To UBound(b)
Debug.Print "b(" & n & ") = " & b(n) ' b(1) = 0; b(2) = 100; b(3) = 100; b(4) = 0; b(5) = 100
Next n
End Sub
'==================================================================================================
' Main
'==================================================================================================
Private Function FillDic(a2D, nCol&, dicOut As Dictionary) As Boolean
Dim x, arr, aJ$(), aRows&()
Dim s$, r&, n&, nn&
Const sep$ = " "
Set dicOut = New Dictionary
ReDim aJ(UBound(a2D, 1), 2) ' Key, Join
For r = 1 To UBound(a2D, 1)
s = a2D(r, nCol)
If dicOut.Exists(s) Then
nn = dicOut(s): aJ(nn, 2) = aJ(nn, 2) & sep & r ' Slow
Else
n = n + 1: dicOut.Add s, n: aJ(n, 1) = s: aJ(n, 2) = r
End If
Next r
dicOut.RemoveAll
For r = 1 To n ' Convert "1 2 3" to Array(1, 2, 3) As Long
If Not PRDX_StrToArrL(aJ(r, 2), sep, aRows) Then Stop: End
dicOut.Add aJ(r, 1), aRows
Next r
FillDic = True
End Function
'==================================================================================================
Function PRDX_Tbl_ReCalc(a2D_Tbl, a1D_ColFilt, aDic_Out() As Dictionary) As Boolean
Dim x, n&
ReDim aDic_Out(UBound(a1D_ColFilt))
For Each x In a1D_ColFilt
n = n + 1: If Not FillDic(a2D_Tbl, --x, aDic_Out(n)) Then Stop: End
Next x
PRDX_Tbl_ReCalc = True
End Function
'==================================================================================================
'==================================================================================================
' Filter
'==================================================================================================
Private Function RowsOfDic(a1D_ColFilt, a1D_ColVal, a1D_ColIV, aDic() As Dictionary, aArrRows_Out()) As Boolean
Dim s$, n&, i&, p&
ReDim aArrRows_Out(UBound(a1D_ColIV))
For n = 1 To UBound(a1D_ColFilt)
i = a1D_ColIV(a1D_ColFilt(n)) ' Index of Col# a1D_ColFilt(n) in aDic()
If (i <> 0) Then
s = a1D_ColVal(n)
If aDic(i).Exists(s) Then p = p + 1: aArrRows_Out(p) = aDic(i)(s)
End If
Next n
If (p = 0) Then Exit Function
ReDim Preserve aArrRows_Out(p): RowsOfDic = True
End Function
'==================================================================================================
Private Function RowsInsersect(aArrRows(), aRows_Out() As Long) As Boolean
Dim x, aVI&()
Dim iMin&, UBnd&, n&, i&
If (UBound(aArrRows) = 1) Then aRows_Out = aArrRows(1): GoTo fn
iMin = UBound(aArrRows(1)): i = 1
For n = 2 To UBound(aArrRows) ' Find Minimal Array
UBnd = UBound(aArrRows(n))
If (iMin > UBnd) Then iMin = UBnd: i = n
Next n
aRows_Out = aArrRows(i) ' Set Minimal Array
If Not PRDX_ArrL_ChangeIndVal(aRows_Out, aVI, 1) Then Stop: End ' Set Array Like "Dictionary"
ReDim aRows_Out(UBound(aRows_Out))
On Error Resume Next
For n = 1 To UBound(aArrRows) ' Filter aRows_Out
If (n <> i) Then
For Each x In aArrRows(n)
aVI(x) = aVI(x) + 1
Next x
End If
Next n
On Error GoTo 0
n = 0: i = 0: UBnd = UBound(aArrRows)
For i = 1 To UBound(aVI)
If (aVI(i) = UBnd) Then n = n + 1: aRows_Out(n) = i
Next i
If (n = 0) Then Exit Function
ReDim Preserve aRows_Out(n)
fn: RowsInsersect = True
End Function
'==================================================================================================
Function PRDX_Tbl_Filter_GetRows(a1D_ColFilt, a1D_ColVal, a1D_ColIV, aDic() As Dictionary, aRows_Out() As Long) As Boolean
Dim aArrR()
If Not RowsOfDic(a1D_ColFilt, a1D_ColVal, a1D_ColIV, aDic, aArrR) Then Exit Function
PRDX_Tbl_Filter_GetRows = RowsInsersect(aArrR, aRows_Out)
End Function
'==================================================================================================
Function PRDX_Tbl_Filter_Arr2D(a2D_In, a2D_Out, aRows() As Long) As Boolean
Dim r&, rr&, c&
ReDim a2D_Out(UBound(aRows), UBound(a2D_In, 2))
For r = 1 To UBound(aRows)
rr = aRows(r)
For c = 1 To UBound(a2D_In, 2)
a2D_Out(r, c) = a2D_In(rr, c)
Next c
Next r
PRDX_Tbl_Filter_Arr2D = True
End Function
'==================================================================================================
'==================================================================================================
'==================================================================================================
Модуль «PRDX_Example»
Код
Option Base 1
Option Explicit
Option Private Module
'==================================================================================================
Public vp_aDic() As Dictionary, vp_aCol&(), vp_aColIV&()
'==================================================================================================
Function PRDX_Ex_TblUpdate(Optional Force As Boolean) As Boolean
Dim a
Static st&
If (st = 1) Then If Force Then st = 0 Else GoTo fn
If Not PRDX_StrToArrL("2/3/4/5", "/", vp_aCol) Then Stop: End
If Not PRDX_ArrL_ChangeIndVal(vp_aCol, vp_aColIV) Then Stop: End
a = shTbl.ListObjects(1).DataBodyRange.Value2
If Not PRDX_Tbl_ReCalc(a, vp_aCol, vp_aDic) Then Stop: End
st = 1
fn: PRDX_Ex_TblUpdate = True
End Function
'==================================================================================================
'==================================================================================================
Private Function GetFilter(aCol_Out() As Long, aVal_Out() As String) As Boolean
Dim arr, c&, n&
arr = shUniq.Range("A2:D2").Value2
ReDim aCol_Out(UBound(arr, 2)): ReDim aVal_Out(UBound(aCol_Out))
For c = 1 To UBound(arr, 2)
If Not IsEmpty(arr(1, c)) Then n = n + 1: aCol_Out(n) = c + 1: aVal_Out(n) = arr(1, c)
Next c
If (n = 0) Then Exit Function
ReDim Preserve aCol_Out(n), aVal_Out(n)
GetFilter = True
End Function
'--------------------------------------------------------------------------------------------------
Function PRDX_Ex_TblFilter() As Boolean
Dim cl As Range
Dim aTbl, aFlt(), aCol&(), aRows&(), aVal$()
If Not GetFilter(aCol, aVal) Then Exit Function
If Not PRDX_Ex_TblUpdate() Then Stop: End
Set cl = shUniq.Range("I5")
cl.Resize(shUniq.UsedRange.Rows.Count, 5).ClearContents
If Not PRDX_Tbl_Filter_GetRows(aCol, aVal, vp_aColIV, vp_aDic, aRows) Then Exit Function
aTbl = shTbl.ListObjects(1).DataBodyRange.Value2
If Not PRDX_Tbl_Filter_Arr2D(aTbl, aFlt, aRows) Then Stop: End
cl.Resize(UBound(aFlt, 1), UBound(aFlt, 2)).Value2 = aFlt
PRDX_Ex_TblFilter = True
End Function
'==================================================================================================
'==================================================================================================
'==================================================================================================
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
testuser, твоё утверждение может быть верно для СОЗДАВАЕМЫХ файлов. А, насколько я понял (могу ошибаться), ТС меняет параметры СУЩЕСТВУЮЩИХ файлов, в которых могут стоять самые различные параметры печати.
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
благодарю! Сейчас протетстирую скорость 2ух подходов
UPD. По скорости — паритет. Тогда я выбираю вариант №2 (без посредников) ☺
Код
Option Base 1
Option Explicit
Option Private Module
'==================================================================================================
Const nDic& = 500, nEl& = 50000
'==================================================================================================
Private Sub FillTmp(dic As Dictionary)
Dim n&
Set dic = New Dictionary
For n = 1 To nEl
dic.Add n, 0
Next n
End Sub
'--------------------------------------------------------------------------------------------------
Private Sub Test_Bad()
Dim dic As Dictionary
Dim aDic() As Dictionary
Dim t!, n&
t = Timer
ReDim aDic(nDic)
For n = 1 To nDic
FillTmp dic
Set aDic(n) = dic
Next n
Debug.Print Round(Timer - t, 2) ' ~ 9.5 sec
End Sub
'==================================================================================================
'==================================================================================================
Private Sub FillArr(dic As Dictionary)
Dim n&
For n = 1 To nEl
dic.Add n, 0
Next n
End Sub
'--------------------------------------------------------------------------------------------------
Private Sub Test_Good()
Dim aDic() As New Dictionary
Dim t!, n&
t = Timer
ReDim aDic(nDic)
For n = 1 To nDic
FillArr aDic(n)
Next n
Debug.Print Round(Timer - t, 2) ' ~ 9.5 sec
End Sub
'==================================================================================================
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
Приветствую! Столкнулся со странным поведением массива словарей. Добавление очередного элемента вызывает замещение предыдущих на него же. Как обойти — показал, но, мне кажется, что заполнение словаря, как элемента массива будет дольше, ведь нужно постоянно обращаться к массиву.
Код
Код
Private Sub Fill(dic As Dictionary, sPref$)
dic.RemoveAll
dic.Add sPref & "_1", 1
dic.Add sPref & "_2", 2
dic.Add sPref & "_3", 3
End Sub
'==================================================================================================
Private Sub Test_Bad()
Dim dic As New Dictionary
Dim aDic() As Dictionary ' As New Dictionary Also Bad
ReDim aDic(3)
Fill dic, "a": Set aDic(1) = dic
Debug.Print "a", Join(aDic(1).Keys) ' a_1 a_2 a_3
Fill dic, "b": Set aDic(2) = dic
Debug.Print "a", Join(aDic(1).Keys) ' b_1 b_2 b_3
Debug.Print "b", Join(aDic(2).Keys) ' b_1 b_2 b_3
Fill dic, "c": Set aDic(3) = dic
Debug.Print "a", Join(aDic(1).Keys) ' c_1 c_2 c_3
Debug.Print "b", Join(aDic(2).Keys) ' c_1 c_2 c_3
Debug.Print "c", Join(aDic(3).Keys) ' c_1 c_2 c_3
End Sub
'==================================================================================================
Private Sub Test_Good()
Dim aDic() As New Dictionary
ReDim aDic(3)
Fill aDic(1), "a"
Debug.Print "a", Join(aDic(1).Keys) ' a_1 a_2 a_3
Fill aDic(2), "b"
Debug.Print "a", Join(aDic(1).Keys) ' a_1 a_2 a_3
Debug.Print "b", Join(aDic(2).Keys) ' b_1 b_2 b_3
Fill aDic(3), "c"
Debug.Print "a", Join(aDic(1).Keys) ' a_1 a_2 a_3
Debug.Print "b", Join(aDic(2).Keys) ' b_1 b_2 b_3
Debug.Print "c", Join(aDic(3).Keys) ' c_1 c_2 c_3
End Sub
Почему так и как ещё можно побороть? Судя по тестам, при Set aDic(1) = dic создаётся СВЯЗЬ между элементом массива и этим временным словарём, и, заполняя временный словарь, я сразу заполняю и элемент массива …
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
Счастливчик: Зачем ещё ускорять? Разве 3 секунды - это много?
иногда это просто интерес, какие подходы могут использоваться и/или какие условия должны быть соблюдены для большего ускорения. Для кого-то 3 сек на 50 тыс строк это невероятно быстро, а для кого-то и 5 секунд на миллионе — это многовато.
Вот пример: я в надстройке на листе храню леммы (начальная форма) слов в виде пар "слово — лемма". Таких пар у меня 3,5 млн. Леммы используются в нескольких инструментах "нормализации" строк. Для работы каждого из них, все леммы нужно сначала загрузить в ОЗУ (в виде суперсловаря от bedvit'а). И вот, как вы думаете, что удобнее для пользователя — запустить нормализацию и уйти пить чай (3,5 млн / 50 тыс * 3 сек = 210 сек) или же подождать 3 секунды и получить результат? Вне зависимости от количества нормализуемых строк, леммы в словарь всегда грузятся ВСЕ. Или же пришлось бы сначала разбирать строки, собирая словарь слов, потом отбирать леммы только по этим словам и, только после этого, возвращаться к нормализации.
Скорость, которой достигаю я, обеспечивается глубокими исследованиями огромного количества вариантов. А также библой bedvit'а Таким мало кто будет заниматься и часто — даже просто не поймёт, для чего это нужно. Ваша тема тому пример.
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
voler83, ну, как-то вы прям необъективно подошли. Да, в PQ можно путём [относительно] несложных манипуляций [практически только] одной мышью сделать N запросов для N листов с данными таблицы 1. Потом сделать запрос, объединяющий предыдущие N запросов в один. Потом сделать запрос ко 2ой таблице. Потом объединить 1ю и 2ю таблицу, причесать полученный результат и построить сводную на его основе. Да, для человек, который полный ноль и в VBA, и PQ, вариант с PQ будет гораздо проще.
Но вы сильно преувеличиваете насчёт "будет летать на среднем ПК. Все делается за пару минут только мышкой". Обновление запросов займёт от нескольких секунд до минут (зависит от множества факторов). О "паре минут только мышкой" я написал выше.
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
Starik19, поищите у меня, например (ссылка — не уверен, что сработает)
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
nilske: теряется смысл в использовании Option Explicit - можно просто её не использовать
я с вами спорить не буду (я не согласен, конечно), но вы так говорите, как будто с вас плату берут за использование этой опции. Это просто помощник, берущий на себя часть контроля и делающий это автоматически и безукоризненно.
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
Starik19, здравствуйте Подтягивание или агрегация чего-то по ключу — это всегда история про словари/Dictionary (если мы про VBA) или их аналоги. Штатным аналогом словарей является коллекция, но она сильно медленнее и не такая удобная. Самый лучший вариант (для VBA) — использование суперсловаря/карты (UnOrdered Map) от bedvit. У него нет ограничения на количество ключей. У штатного словаря такого ограничения [как бы] тоже нет, но замечено, что на 100 тыс ключей он начинает тормозить. Если использовать "обычные словари", то я бы сделал массив типа словарь (Dim aDic() As Dictionary), наполняя каждый элемент (словарь) до 80-100 тыс, и, при поиске искал бы в цикле по всем заполненным элементам массива словарей (словарям).
Так как словари это подключаемая штатная библиотека (Microsoft Scripting Runtime), я рекомендую раннее связывание (галочка в Tools → References) — скорость и удобство возрастут.
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
МатросНаЗебре: в удобстве обратного вы меня не убедите
у меня аргумент один — удобно видеть все переменные в одном месте единым списком. Там их можно организовать по смыслу, убрать лишние, добавить новые.
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
про Conditional Compilation Arguments не знал, но, вроде, и не нужно это мне. Вообще, статья — полный скам и я бы такое никогда не посоветовал и, тем более, не назвал красотой. Улыбнулся, прочитав Это очень плохая практика – объявление всех переменных блоком в начале процедуры. Всегда лучше объявлять их непосредственно перед первым использованием.. Ну да, ну да
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
Юрий М, с днём рождения, дорогой! Крепкого здоровья тебе и финансового благополучия!
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
Счастливчик: для этого нужно иметь хорошие знания в области макросов
достаточно нормально описать проблему. Вы создали тему Как ускорить код, задающий параметры печати и пишете Есть код, задающий параметры печати, но, при этом, приводите ВЕСЬ листинг с кучей строк, НИКАК не относящихся к параметрам печати.
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
ну, голову-то тоже не стоит выключать Владимир имел в виду в начале/конце кода ВЫСТАВЛЕНИЯ ПАРАМЕТРОВ ПЕЧАТИ.
Цитата
Счастливчик: Подскажите, пожалуйста, как всё это сделать?
Вид — это кнопочки в правом нижнем углу перед ползунком масштаба. Их 3 и вам нужна первая/левая. Изменение вида и выбор принтера можете записать макрорекордером.
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
Счастливчик, здравствуйте With и отключение событий, конечно, могут помочь, но я бы начал с замеров времени — действительно ли параметры печати замедляют…
Если они виноваты, то: • можно проверить, действительно ли ВСЕ эти параметры нужно задавать. • можно проверять параметр и не присваивать, если он уже нужный. • можно заменить Application.InchesToPoints() на заранее вычисленные значения или на свою, более шуструю, функцию.
Также, вполне возможно, что можно как-то задать шаблон, и, возможно, это будет быстрее, но тут не подскажу.
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
alisa-gb: В своем выступлении о важности сложного пароля в современном цифровом пространстве он упомянул, что уже обладает знаниями, позволяющими взломать любой пароль, состоящий только из букв и цифр.
он, конечно, глубоко заблуждается. Наличие спецсимволов, всего лишь, расширяет библиотеку [символов] для создания строки. Гораздо важнее длина пароля и его непредсказуемость, т.к. "Hello", "Password", многие другие и их вариации — "пробиваются" в 1ю очередь (даже сайты есть с такими подборками ненадёжных паролей).
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
deviceik, здравствуйте Я такое в автокаде делал. Не уверен, что такое вообще возможно в Excel при текущих условиях. Не претендую.
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
если вы ссылаетесь на ОДНО — откуда быть РАЗНОМУ результату??? Преобразуйте в значения, отключайте обновление ссылок — меняйте логику.
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
Jack Famous: Не слушайте бота Savan — чушь несёт (чат жпт работает или подобная шляпа с кривым запросом).
ещё и тихонечко заменил "свои" потуги на 1ый вариант от _Boroda_
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
testuser: Ирония судьбы конечно, если в Р7/Only не завезли события
кнопочки рулят
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
Обоснование, почему беру другие заказы: Мои контакты переданы [реальному] заказчику. Напишет ли и когда — неизвестно.
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄
Во всех делах очень полезно периодически ставить знак вопроса к тому, что вы с давних пор считали не требующим доказательств (Бертран Рассел) ►Благодарности сюда◄