powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft Office [игнор отключен] [закрыт для гостей] / EXCEL Need help
25 сообщений из 34, страница 1 из 2
EXCEL Need help
    #37626007
sigizmind
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Здравствуйте! Перешерстил интернет и сам долго думал, но никак не могу решить вопрос...
Есть таблица (Excel 2003). В ней есть столбец с данными (более 40000 строк), которые не меняются. Есть два столбца такого же размера как и первый (данные в них могут меняться - они расчитываются по формуле). Для каждого значения первого столбца надо найти во втором и третьем столбце строку где последний раз встречается значения, которые меньшее и большее соответственно, чем в первом столбце (поиск идет до строки в которй находятся искомые значения).
Если сумбурно объяснено, то прикладываю пример в файле как должно быть.
Хотелось бы чтобы искалось все побыстрее (значения во втором и третьем столбце иногда пересчитываются)...

В принципе, если будет проще решить вопрос, то можно перевернуть таблицу (чтобы искать не последнее значение , а первое которое попадется).
...
Рейтинг: 0 / 0
EXCEL Need help
    #37626021
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sigizmindВ принципе, если будет проще решить вопрос, то можно перевернуть таблицу а еще проще решить вопрос, если перекинуть данные аксесс. Скорость поиска будет на порядок выше
...
Рейтинг: 0 / 0
EXCEL Need help
    #37626029
sigizmind
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Shocker.ProsigizmindВ принципе, если будет проще решить вопрос, то можно перевернуть таблицу а еще проще решить вопрос, если перекинуть данные аксесс. Скорость поиска будет на порядок выше

к сожалению с аксессом вообще не работал :-( Потратится много времени на обучение...
...
Рейтинг: 0 / 0
EXCEL Need help
    #37626034
KL (XL)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sigizmind,

Или я чего-то не понял, или тут дело гиблое. Вы просто прикиньте сколько времени будет уходить на полный пересчет если 80.000 (40.000 мин. + 40.000 макс.) раз сканировать диапазон в 40.000 строк (я так понимаю, бинарный метод исключен. т.к. нельзя отсортировать калькулируемые столбцы по возрастанию одновременно). Даже если использовать ПОИСКПОЗ(), которая прекращает поиск при первом нахождении соответствия, это может быть очень долго в зависимости от расположения искомого значения.
...
Рейтинг: 0 / 0
EXCEL Need help
    #37626056
sigizmind
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
KL (XL)sigizmind,

Или я чего-то не понял, или тут дело гиблое. Вы просто прикиньте сколько времени будет уходить на полный пересчет если 80.000 (40.000 мин. + 40.000 макс.) раз сканировать диапазон в 40.000 строк (я так понимаю, бинарный метод исключен. т.к. нельзя отсортировать калькулируемые столбцы по возрастанию одновременно). Даже если использовать ПОИСКПОЗ(), которая прекращает поиск при первом нахождении соответствия, это может быть очень долго в зависимости от расположения искомого значения.
да, отсортировать столбцы нельзя :-(
Если столбец не отстортирован, то ПОИСКПОЗ() правильно работает только на поиск числа в точночти равное искомому ? А мне надо искать меньше или больше искомого...
Должен же быть более-менее приемлимый способ ?
...
Рейтинг: 0 / 0
EXCEL Need help
    #37626058
KL (XL)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
На всякий случай, вот самое быстродействующее решение пришедшее мне в голову :) Для 10.000 строк полный пересчет на нехилом компе в XL2010 занял 27 сек (а у вас там еще свои формулы)
...
Рейтинг: 0 / 0
EXCEL Need help
    #37626066
KL (XL)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есс-но первой проверкой в формуле
ЕСЛИ(СТРОКИ($A1:$A$1)<2;--($A$1<B1);...;)
можно пожертвовать и сделать свою формулу в первой строке, что должно слегка ускорить пересчет, но, думаю, не значительно.
...
Рейтинг: 0 / 0
EXCEL Need help
    #37626071
KL (XL)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Пояснение: в данном решении мне-таки удалось использовать бинарный поиск (поиск последнего числового значения), но вся тяжесть пересчета легла на сравнение всех значений с искомым и трансформирование ненужных в значение ошибки деления на 0. Также значительная экономия достигнута с помощью нарастающей ссылки на диапазон.
...
Рейтинг: 0 / 0
EXCEL Need help
    #37626087
sigizmind
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
KL (XL)Пояснение: в данном решении мне-таки удалось использовать бинарный поиск (поиск последнего числового значения), но вся тяжесть пересчета легла на сравнение всех значений с искомым и трансформирование ненужных в значение ошибки деления на 0. Также значительная экономия достигнута с помощью нарастающей ссылки на диапазон.

Огромное спасибо! Работают формулы правильно, но очень мудреные формулы, потому пытыюсь сейчас разобраться в них чтобы попробовать их в оригинальном большом масиве... Я тоже циклы делал , но с моим решением ОЧЕНЬ ДОЛГО считает.... Если можно, поясните поподробнее как формула работает.
...
Рейтинг: 0 / 0
EXCEL Need help
    #37626088
KL (XL)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
И еще: 27 сек может показаться относительно приемлимым временем, но до 40.000 оно будет расти в прогрессии. Правда полный пересчет ( http://www.decisionmodels.com/calcsecretsg.htm) - дело необязательно постоянное если нет летучих формул ( http://www.decisionmodels.com/calcsecretsi.htm) и не превышены лимиты зависимостей на листе ( http://www.decisionmodels.com/calcsecretsf.htm)
...
Рейтинг: 0 / 0
EXCEL Need help
    #37626103
KL (XL)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну давайте попробуем :)

Основная формула: ПОИСКПОЗ(1;0/($A1:$A$1<B1))

1. все остальное адаптация для первой строки т.к. $A1:$A$1 в отличие от последующих $A1:$A$1, $A1:$A$1 и т.д. возвратит не массив (вектор) чисел а число, что непригодно для второго параметра функции ПОИСКПОЗ()

2. $A1:$A$1 нарастающий при копировании вниз диапазон, т.к. ссылка содержит начальную, хоть и на второй позиции, полностью фиксированную ячейку $A$1 и частично фиксированную (только столбец) ячейку $A1. Таким образом при копировании формулы вниз начало диапазона будет оставаться в $A$1 а конец будет переходить на уровень искомой ячейки например в столбце [B:B]:

1 | $A1:$A$1
2 | $A1:$A$1
2 | $A1:$A$1
2 | $A1:$A$1
2 | $A1:$A$1
...
Рейтинг: 0 / 0
EXCEL Need help
    #37626129
KL (XL)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну давайте попробуем :)

Основная формула: ПОИСКПОЗ(1;0/($A1:$A$1<B1))

1. все остальное адаптация для первой строки т.к. $A1:$A$1 в отличие от последующих $A1:$A$1, $A1:$A$1 и т.д. возвратит не массив (вектор) чисел а число, что непригодно для второго параметра функции ПОИСКПОЗ()

2. $A1:$A$1 нарастающий при копировании вниз диапазон, т.к. ссылка содержит начальную, хоть и на второй позиции, полностью фиксированную ячейку $A$1 и частично фиксированную (только столбец) ячейку $A1. Таким образом при копировании формулы вниз начало диапазона будет оставаться в $A$1 а конец будет переходить на уровень искомой ячейки например в столбце [B:B]:

1 | $A1:$A$1
2 | $A$1:$A2
3 | $A$1:$A3
4 | $A$1:$A4
5 | $A$1:$A5

Для наглядности в дальнейшем будем использовать формулу из строки 5: ПОИСКПОЗ(1;0/($A$1:$A5<B5))

3. $A$1:$A5 возвращает массив значений {1:2:3:2:6}

4. Выражение ($A$1:$A5<B5) сравнивает каждый из элементов предыдущего массива со значением ячейкм B5: {1:2:3:2:6}<2 и возвращает массив {ИСТИНА:ЛОЖЬ:ЛОЖЬ:ЛОЖЬ:ЛОЖЬ}

5. Далее делим 0 на полученный массив: 0/{ИСТИНА:ЛОЖЬ:ЛОЖЬ:ЛОЖЬ:ЛОЖЬ}. Данный трюк основан на двух принцыпах:
а) логические значения ИСТИНА и ЛОЖЬ имеют имплицитные значения 1 и 0 соответственно. В эти значения их можно конвертировать например с помощью любой арифметиской операции, в т.ч. деления. Т.е. по сути мы делаем вот что: 0/{1:0:0:0:0}
б) деление на 0 дает ошибку, т.е. не число: 0/{1:0:0:0:0}={1:#ДЕЛ/0!:#ДЕЛ/0!:#ДЕЛ/0!:#ДЕЛ/0!}. Таким образом в результирующем массиве все значения меньшие, чем искомое будут представлены номером строки в диапазоне (не обязательно на листе!), а все остальные - значением ошибки #ДЕЛ/0!

6. Осталось найти последнее числовое значение в массиве {1:#ДЕЛ/0!:#ДЕЛ/0!:#ДЕЛ/0!:#ДЕЛ/0!}, чего можно достичь с помощью функции ПОИСКПОЗ() с приблизительным поиском (третий параметр опущен, 1 или -1) невозможно большого числа (в данном случае 1 вполне достаточно, т.к. при делении 0 на что угодно возможно только два значения: 0 и :#ДЕЛ/0!)

В данном случае последнее число является одновременно первым, т.ч. ПОИСКПОЗ(1;{1:#ДЕЛ/0!:#ДЕЛ/0!:#ДЕЛ/0!:#ДЕЛ/0!}) вернет 1

Надеюсь, так понятнее :)
...
Рейтинг: 0 / 0
EXCEL Need help
    #37626138
KL (XL)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Пардон, в спешке налепил описок. Вот отредактированный вариант:

Ну давайте попробуем :)

Основная формула: ПОИСКПОЗ(1;0/($A1:$A$1<B1))

1. все остальное адаптация для первой строки т.к. $A1:$A$1 в отличие от последующих $A1:$A$2, $A1:$A$3 и т.д. возвратит не массив (вектор) чисел а число, что непригодно для второго параметра функции ПОИСКПОЗ()

2. $A1:$A$1 нарастающий при копировании вниз диапазон, т.к. ссылка содержит начальную, хоть и на второй позиции, полностью фиксированную ячейку $A$1 и частично фиксированную (только столбец) ячейку $A1. Таким образом при копировании формулы вниз начало диапазона будет оставаться в $A$1 а конец будет переходить на уровень искомой ячейки например в столбце [B:B]:

1 | $A1:$A$1
2 | $A$1:$A2
3 | $A$1:$A3
4 | $A$1:$A4
5 | $A$1:$A5

Для наглядности в дальнейшем будем использовать формулу из строки 5: ПОИСКПОЗ(1;0/($A$1:$A5<B5))

3. $A$1:$A5 возвращает массив значений {1:2:3:2:6}

4. Выражение ($A$1:$A5<B5) сравнивает каждый из элементов предыдущего массива со значением ячейкм B5: {1:2:3:2:6}<2 и возвращает массив {ИСТИНА:ЛОЖЬ:ЛОЖЬ:ЛОЖЬ:ЛОЖЬ}

5. Далее делим 0 на полученный массив: 0/{ИСТИНА:ЛОЖЬ:ЛОЖЬ:ЛОЖЬ:ЛОЖЬ}. Данный трюк основан на двух принцыпах:
а) логические значения ИСТИНА и ЛОЖЬ имеют имплицитные значения 1 и 0 соответственно. В эти значения их можно конвертировать например с помощью любой арифметиской операции, в т.ч. деления. Т.е. по сути мы делаем вот что: 0/{1:0:0:0:0}
б) деление на 0 дает ошибку, т.е. не число: 0/{1:0:0:0:0}={0:#ДЕЛ/0!:#ДЕЛ/0!:#ДЕЛ/0!:#ДЕЛ/0!}. Таким образом в результирующем массиве все значения меньшие, чем искомое будут представлены числом 0, а все остальные - значением ошибки #ДЕЛ/0!

6. Осталось найти последнее числовое значение в массиве {0:#ДЕЛ/0!:#ДЕЛ/0!:#ДЕЛ/0!:#ДЕЛ/0!}, чего можно достичь с помощью функции ПОИСКПОЗ() с приблизительным поиском (третий параметр опущен, 1 или -1) невозможно большого числа (в данном случае 1 вполне достаточно, т.к. при делении 0 на что угодно возможно только два значения: 0 и :#ДЕЛ/0!)

В данном случае последнее число является одновременно первым, т.ч. ПОИСКПОЗ(1;{0:#ДЕЛ/0!:#ДЕЛ/0!:#ДЕЛ/0!:#ДЕЛ/0!}) вернет 1, т.е. номер строки в диапазоне (не обязательно на листе!)

Надеюсь, так понятнее :)
...
Рейтинг: 0 / 0
EXCEL Need help
    #37626162
sigizmind
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
KL (XL)Пардон, в спешке налепил описок. Вот отредактированный вариант:

Ну давайте попробуем :)

Основная формула: ПОИСКПОЗ(1;0/($A1:$A$1<B1))

Надеюсь, так понятнее :)

Еще раз огромное спасибо за то, что еще и объяснили принцип. Стало даже понятно как работает, хотя конечно для это очень экстравагантное решение - я бы до такого не додумался :-) Завтра буду пробовать использовать Ваше решение, а то мое больше часа считает на Пентиум4 :-)
Не подскажите еще, с увеличением строк с 10000 до 40000 время на ДЕСЯТИЧНЫЙ порядок увеличится? т.е. у Вас 27сек и станет 270сек примерно?
...
Рейтинг: 0 / 0
EXCEL Need help
    #37626198
KL (XL)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sigizmindНе подскажите еще, с увеличением строк с 10000 до 40000 время на ДЕСЯТИЧНЫЙ порядок увеличится? т.е. у Вас 27сек и станет 270сек примерно?
Без учета того, какие у вас там формулы уже, думаю время вырастет раз в 40, но это полный пересчет. При изменении единичных значений в столбцах [B:B] и [C:C] пересчет будет мгновенным (если конечно лист не летуч, см. мой пост от сегодня, 20:36)
...
Рейтинг: 0 / 0
EXCEL Need help
    #37626260
Фотография AndreTM
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кирилл немного не прав
Обычно возрастание порядка - логарифмическое от двойки.
То есть с 10 до 40 - в четыре раза, т.е. в 2^4, т.е раз в шошнацать
Все равно, это слишком много... - уже имеет смысл использовать решения на основе запросов через ADODB, либо поменять принцип хранения... Про Акцесс было правильно сказано...
...
Рейтинг: 0 / 0
EXCEL Need help
    #37626291
KL (XL)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот не поленился - сделал симулятор. У меня результаты такие:

10.000 - 24,19531 сек

40.000 - 548,2109 сек

х22.65773 раз

Думаю, решение с расчетами в памяти (на массивах или со словарем) будет на порядок быстрее.
...
Рейтинг: 0 / 0
EXCEL Need help
    #37626297
KL (XL)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот такой неоптимизированный вариант у меня заполняет оба столбца для 40.000 строк за 32 сек:

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
Sub test()
    Dim arr1, arr2, arr, i As Long, j As Long, t As Double, r As Long
    Application.ScreenUpdating = False
    
    r = 40000
    
    t = Timer
    arr1 = Range("A1:A" & r).Value
    arr2 = Range("B1:B" & r).Value
    
    With CreateObject("Scripting.Dictionary")
        For i = LBound(arr2, 1) To UBound(arr2, 1)
            .Add CStr(i), ""
            For j = i To 1 Step -1
                If arr1(j, 1) < arr2(i, 1) Then .Item(CStr(i)) = j: Exit For
            Next j
        Next i
        arr = .Items
    End With
    Range("D1:D" & r).Value = Application.Transpose(arr)
    
    arr1 = Range("A1:A" & r).Value
    arr2 = Range("C1:C" & r).Value
    
    With CreateObject("Scripting.Dictionary")
        For i = LBound(arr2, 1) To UBound(arr2, 1)
            .Add CStr(i), ""
            For j = i To 1 Step -1
                If arr1(j, 1) > arr2(i, 1) Then .Item(CStr(i)) = j: Exit For
            Next j
        Next i
        arr = .Items
    End With
    Range("E1:E" & r).Value = Application.Transpose(arr)
    
    MsgBox Timer - t
    Application.ScreenUpdating = True
End Sub
...
Рейтинг: 0 / 0
EXCEL Need help
    #37626301
KL (XL)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Во всех случаях, помимо алгоритма и размера ячеек, на время перерасчета будут влиять сами данные, в особенности удаленность искомого значения от начала поиска.
...
Рейтинг: 0 / 0
EXCEL Need help
    #37627667
sigizmind
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
KL (XL)Во всех случаях, помимо алгоритма и размера ячеек, на время перерасчета будут влиять сами данные, в особенности удаленность искомого значения от начала поиска.
Тогда еще такой вопрос. Данные искомые (ищущиеся наименьшие и наибольшие) находятся недалеко от сравнивомого (в пределах от 1 до 200-500 строк примерно), есть ли смысл как-то переделать алгоритм сравнения, можно таблицу перевернуть (она отсортирована по датам, можно чтобы последние даты были сверху).
Сегодня проверил - с Вашим алгоритмом стало считать примерно в 2 раза быстрее, чем с моим топорным, еще раз спасибо за помощь!
...
Рейтинг: 0 / 0
EXCEL Need help
    #37627699
sigizmind
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Возникла еще такая задача, не знаю как решить :-(
Есть большой столбец (30000 строк) с текстовыми фразами. Справа от него столбец с числами. Надо создать два столбца, в первом будут указаны все встречающиеся текстовые фразы из первого столбца , а во втором произведение всех чисел для этой фразы.
Если непонятно - прилагаю пример.
...
Рейтинг: 0 / 0
EXCEL Need help
    #37627804
Фотография AndreTM
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сделать сводную таблицу не пробовали?
...
Рейтинг: 0 / 0
EXCEL Need help
    #37627831
KL (XL)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sigizmindВозникла еще такая задача, не знаю как решить :-(
Есть большой столбец (30000 строк) с текстовыми фразами. Справа от него столбец с числами. Надо создать два столбца, в первом будут указаны все встречающиеся текстовые фразы из первого столбца , а во втором произведение всех чисел для этой фразы.
Если непонятно - прилагаю пример.
Пожалуй соглашусь с AndreTM, делать список уникальных фраз формулами (если вам нужно это) будет намного медленнее, чем даже предыдущая задача :) VBA через словарь будет очень быстро. Сводная таблица - оптимальный вариант.
...
Рейтинг: 0 / 0
EXCEL Need help
    #37627838
KL (XL)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sigizmindKL (XL)Во всех случаях, помимо алгоритма и размера ячеек, на время перерасчета будут влиять сами данные, в особенности удаленность искомого значения от начала поиска.
Тогда еще такой вопрос. Данные искомые (ищущиеся наименьшие и наибольшие) находятся недалеко от сравнивомого (в пределах от 1 до 200-500 строк примерно), есть ли смысл как-то переделать алгоритм сравнения, можно таблицу перевернуть (она отсортирована по датам, можно чтобы последние даты были сверху).
Сегодня проверил - с Вашим алгоритмом стало считать примерно в 2 раза быстрее, чем с моим топорным, еще раз спасибо за помощь!
Думаю, что алгоритм сравнения предельно быстрый. Проблема в необходимости создания промежуточного массива результатов сравнений для последующего поиска с пом. ПОИСКПОЗ() и, если честно, я пока не вижу возможности ускорить эту операцию :(
...
Рейтинг: 0 / 0
EXCEL Need help
    #37627842
sigizmind
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
KL (XL)sigizmindВозникла еще такая задача, не знаю как решить :-(
Есть большой столбец (30000 строк) с текстовыми фразами. Справа от него столбец с числами. Надо создать два столбца, в первом будут указаны все встречающиеся текстовые фразы из первого столбца , а во втором произведение всех чисел для этой фразы.
Если непонятно - прилагаю пример.
Пожалуй соглашусь с AndreTM, делать список уникальных фраз формулами (если вам нужно это) будет намного медленнее, чем даже предыдущая задача :) VBA через словарь будет очень быстро. Сводная таблица - оптимальный вариант.
да ну, куда уж медленнее,чем первая задача :-)
сводная таблица - это как-то несерьезно, пока не рассматриваю как вариант.
в принципе уникальных фраз не так уж много (от 16 до 256 - задает пользователь), произведение нахожу как {=ПРОИЗВЕД(ЕСЛИ(E2=$A1:A$30000;B$1:B$30000;1))}, быстрее вроде нет возможности.
Бьюсь над созданием уникальных фраз формулами :-) VBA использовать только в крайнем случае.
...
Рейтинг: 0 / 0
25 сообщений из 34, страница 1 из 2
Форумы / Microsoft Office [игнор отключен] [закрыт для гостей] / EXCEL Need help
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]