Страницы: 1 2 3 След.
RSS
Ускорение расчета формул массива на конкретном примере. Или использование альтернативных формул?
 
Добрый день! Ранее многоуважаемые участники форума помогли с формулой, которая может сделать подсчёт количества стран, которые одновременно экспортируют  два отдельных продукта. Однако в процессе её использования возникла необходимость применять её к большому массиву данных. Excel системно не справляется с расчетами, виснет. Возможно ли как-то ускорить процесс или можно использовать какие-то альтернативные формулы? Спасибо за потраченное Вами время
 
ну вот нравятся мне сводные таблицы и если я правильно понял задачу, то пример во вложении.
Сводные таблицы легче переваривают большие объемы таблиц, ими легко управлять (группировки, фильтры, сортировка и т.п.)

P.S. Удалил часть таблицы, т.к. размер был большой для форума.
 
В этом примере я немного расширил формулу и дал более чёткую постановку задачи. Возможно ли подобное сделать с помощью сводных таблиц? В файле example2 сделанная форма просто рассчитывает количество стран, которые экспортирую набор определённых товаров (при этом, не учитывается условие одновременности). Спасибо.
 
Не вполне понял про 1000х1000, но быстро получить эту 3 макросом нет особых проблем.
Макросы не принимаются? (не вникал в первую тему).

Например:

Код
Sub tt()
    Dim a(), i&, k, x&

    With CreateObject("Scripting.Dictionary"): .comparemode = 1
        a = [a1].CurrentRegion.Columns(3).Resize(, 2).Value
        For i = 2 To UBound(a)
            Select Case a(i, 1)
            Case 402
                .Item(a(i, 2)) = .Item(a(i, 2)) & "Y"
            Case 405
                .Item(a(i, 2)) = .Item(a(i, 2)) & "Y"
            End Select
        Next

        For Each k In .keys
            If .Item(k) = "YY" Then x = x + 1
        Next
    End With

    MsgBox x
End Sub
 
Можно и одновременность просматривать, и повторы не отбрасывать...
Если нужна именно формула, но разрешены макросы - можно сделать UDF. В параметрах можно указываеть диапазон и критерии отбора.
Изменено: Hugo - 07.08.2014 11:49:58
 
Вот добавил пример матрицы и принцип, по которому заполняется каждая ячейка. Возможно ли этот макрос прописать так, чтобы на основе имеющегося набора стран и товарных кодов он заполнил попарными сравнениями матрицу? Спасибо.
 
Цитата
Artur_z пишет:
Возможно ли подобное сделать с помощью сводных таблиц?
Можно, изучайте сводные. Сделал пример, в нем сделана группировка по странам, в фильтре выбраны нужные товары. А проверка одновременности поставок 2-х выбранных товаров реализовано установкой фильтра по группе стран "Фильтр по значению = 2"
 
Цитата
Artur_z пишет:
Возможно ли этот макрос прописать так, чтобы на основе имеющегося набора стран и товарных кодов он заполнил попарными сравнениями матрицу?
Ну конечно можно этот макрос выполнять 100500 раз - для каждой пары значений отдельно... Но это не дело, хотя конечно работать будет без зависаний, но долго и неоптимально...
Чтоб сделать получше нужно подумать... Не обещаю  :(

Т.к. появилась выше сводная (правда на 2003 её особо не потыркать...) - то макрос думаю теряет актуальность?
 
Уважаемый Justitius, если это не составит особого труда, пожалуйста, взгляните на последний выложенный мною пример. Можно ли заполнить подобную матрицу с помощью предложенной Вами концепции. Спасибо.
 
Уважаемый Hugo, с помощью сводной таблицы придётся вручную менять набор фильтров для каждой ячейки матрицы. А с помощью макроса можно ли сделать, чтобы перебор ячеек делался автоматически? Я сделал шаблон большой матрицы с помощью формулы массива - расчёт занимает около 3 часов для одной страны :-(
 
Я его смотрел и видимо не так понял, сделайте пример таблички, что хотите видеть в итоге.
А вообще лучше описать конечную задачу, т.к. решение подбирается по вашему описанию и оно может оказаться не удобным для других условий вашей задачи.
 
Можно макросом сделать цикл по таблице 1000*1000 (причём вычислять по данным нужно только половину таблицы) - но это только если не придумается что-то поэффективнее...
 
создать словарь номеров.
для каждого номера - словарь стран.
потом попарно проверять кол-во совпадающих стран в словарях для каждой пары номеров.
фрилансер Excel, VBA - контакты в профиле
"Совершенствоваться не обязательно. Выживание — дело добровольное." Э.Деминг
 
Вот добавил мини-пример результативной матрицы  с пояснение того, что нужно иметь в каждой ячейке. Будьте добры посмотреть.
 
Уважаемый Ikki, к сожалению, я не знаком с техникой созданий подобных словарей. Если для Вас не будет затруднительно, расскажите на моем примере. Спасибо.
 
а смысл?
я Вам на Вашем примере в прошлой Вашей теме рассказывал про ADO.
и показывал.
и файл прикладывал.

ни ответа, ни привета.
вместо этого - создали дубликат темы.
(что, кстати, правилами форума запрещено)
фрилансер Excel, VBA - контакты в профиле
"Совершенствоваться не обязательно. Выживание — дело добровольное." Э.Деминг
 
Цитата
ikki пишет:
потом попарно проверять кол-во совпадающих стран в словарях для каждой пары номеров.
Да, я тоже об этом подумал. в предыдущем примере создал колонку "Группа" Artur_z, можете посмотреть.
Сейчас посмотрю крайний пример.
 
Уважаемый Ikki, я приношу свои извинения. Просто мой уровень пользования не позволил использовать Ваш пример. Я благодарен Вам за ответы.
 
Такую же матрицу как в примере, наверняка не получится сводной сделать.
Но я так и не увидел конечную задачу, возможно и не потребуется так делать, что вы хотите видеть, опишите словами, например:
"Сколько стран поставляют товар 402 и 405 одновременно", эту задачу решает приведенный мной пример выше.
Изменено: justirus - 07.08.2014 12:59:07
 
Вот написал тупо перебором (но на словарях) на примере, где 1000*1000 начиналась в Q6:

Код
Option Explicit

Sub tt()
    Dim a(), i&, k
    Dim outDic As Object
    Dim x&, y&, z&, b()

    Set outDic = CreateObject("Scripting.Dictionary"): outDic.comparemode = 1

    a = [a1].CurrentRegion.Columns(3).Resize(, 2).Value
    b = [q6].CurrentRegion.Value

    For x = 2 To UBound(b)
        For y = 2 To UBound(b, 2)
            If b(1, x) <> b(y, 1) Then

                If Not outDic.exists(b(1, x) & "|" & b(y, 1)) Then
                    z = 0
                    With CreateObject("Scripting.Dictionary"): .comparemode = 1
                        For i = 2 To UBound(a)
                            Select Case a(i, 1)
                            Case b(1, x)
                                .Item(a(i, 2)) = .Item(a(i, 2)) & "Y"
                            Case b(y, 1)
                                .Item(a(i, 2)) = .Item(a(i, 2)) & "Y"
                            End Select
                        Next

                        For Each k In .keys
                            If .Item(k) = "YY" Then z = z + 1
                        Next
                    End With
                    outDic.Item(b(1, x) & "|" & b(y, 1)) = z
                    outDic.Item(b(y, 1) & "|" & b(1, x)) = z
                End If

                b(y, x) = outDic.Item(b(y, 1) & "|" & b(1, x))
            Else
                b(y, x) = "|||||"
            End If
        Next
    Next

    [q6].CurrentRegion.Value = b

End Sub
Если код работает надоедливо долго - можно в первый цикл добавить DoEvents и вывод индикации в статусбар номера просматриваемой строки. Так можно будет делать и что-то другое, и видеть что не висит.
Если и во второй добавить DoEvents - мешать вообще не будет.
Изменено: Hugo - 07.08.2014 13:02:46
 
во-первых, на таком объеме данных макрос будет работать не мгновенно.
думаю, пара минут всё-таки понадобится.
во-вторых, для приложенного примера имеется 1131 разный код.
в моем текущем Excel 2003 столько столбцов нет.
фрилансер Excel, VBA - контакты в профиле
"Совершенствоваться не обязательно. Выживание — дело добровольное." Э.Деминг
 
Окончательная задача такова: есть список товарных позиций, по котором РФ экспортирует товары в остальной мир (примерно 1100 товарных позиций). Допустим это последовательные коды (например: 101, 102, 103, 104). Мне надо знать, какова вероятность экспортировать товар 102, если товар 101 уже экспортируется. Для этого требуется посмотреть, сколько стран мира одновременно экспортируют товары 101 и 102(следовательно, далее, 101 и 103, 101 и 104, .... 101 =1100(столько экспортирует РФ). Собственно на этом этапе подсчёта и возникают проблемы.
 
Я тоже сейчас сижу на 2003 - так что на большой таблице проверить не могу.
 
ок. перезагрузился в 2010-й... сейчас набросаю (код Hugo пока смотреть не хочу, потом сравним, если что :))
фрилансер Excel, VBA - контакты в профиле
"Совершенствоваться не обязательно. Выживание — дело добровольное." Э.Деминг
 
Давай, интересно будет сравнить по скорости.
Ты мой там скорректируй если что в части [q6].CurrentRegion. А то я только вечером до 2007 доберусь, и то не факт что будет время/желание тестить эти коды...
 
Проверил Ваш скрипт, Hugo. Матрицу данных заполнил двойками, на пересечении, как и надо, прочерки. Что корректировать? спасибо)
 
И что, совсем ни одной троечки?  :)  
Можно ничего не корректировать, если работает. Но для надёжности вместо [q6].CurrentRegion всюду (2 места) пропишите свой диапазон таблицы.
Изменено: Hugo - 11.08.2014 01:40:26
 
гм... может, я задачу не совсем понял...
Вас интересуют только те коды, которые имеются в заголовках  "правой таблицы" или все?

я писал для всех, которые встретятся в основной таблице
Код
Sub t()
  Dim a(), i&, j&, dkeys(), b%(), tt, s$, ik$, ii&, jj&
  Dim dc As Object, dm As Object, d As Object, dr As Object
  
  tt = Time
  Set dc = CreateObject("scripting.dictionary")
  Set dm = CreateObject("scripting.dictionary")
  With Sheets(1): a = Range(.[c2], .Cells(.Rows.Count, "d").End(xlUp)).Value: End With
  
  For i = 1 To UBound(a)
    If dm.exists(a(i, 1)) Then Set d = dm(a(i, 1)) Else Set d = CreateObject("scripting.dictionary")
    d(a(i, 2)) = 0&
    Set dm(a(i, 1)) = d
    If Not dc.exists(a(i, 1)) Then dc(a(i, 1)) = dc.Count + 1
  Next
  
  dkeys = dm.keys: Set dr = CreateObject("scripting.dictionary")
  For i = 0 To UBound(dkeys) - 1
    ik = dc(dkeys(i)) & " "
    For j = i + 1 To UBound(dkeys)
      For Each x In dm(dkeys(i))
        If dm(dkeys(j)).exists(x) Then s = ik & dc(dkeys(j)): dr(s) = dr(s) + 1
      Next
  Next j, i
  
  Set w = ThisWorkbook.Sheets.Add(after:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
  w.[a2].Resize(dc.Count).Value = Application.Transpose(dc.keys)
  w.[b1].Resize(, dc.Count).Value = dc.keys
  ReDim b(1 To dc.Count, 1 To dc.Count)
  For Each x In dr.keys
    aa = Split(x): ii = CInt(aa(0)): jj = CInt(aa(1))
    b(ii, jj) = dr(x): b(jj, ii) = dr(x)
  Next
  w.[b2].Resize(UBound(b), UBound(b)).Value = b
  MsgBox Format(Time - tt, "hh:mm:ss")
End Sub
работает не слишком шустро - на моем (правда, оч.стареньком) ноуте отработало за полторы минуты
хотя... для матрицы в 1,28 млн элементов и это неплохо.
или всё-таки дело в том, что словари на 2010-м медленные?
Изменено: ikki - 07.08.2014 17:55:28
фрилансер Excel, VBA - контакты в профиле
"Совершенствоваться не обязательно. Выживание — дело добровольное." Э.Деминг
 
Спасибо Вам большое за Вашу работу. Я сейчас всё проверю и отпишусь.

Уважаемый Ikki, будет достаточно тех заголовков, которые отображены в "правой" таблице. Это номенклатура экспорта РФ.  Достаочно посмотреть, как страны мира экпортируют пары товаров по нашей номенклатуре.
 
а... значит, всё-таки я недопонял.
ну, переписывать не буду.
пользуйтесь макросом Hugo
фрилансер Excel, VBA - контакты в профиле
"Совершенствоваться не обязательно. Выживание — дело добровольное." Э.Деминг
 
Уважаемый Ikki, протестировал Ваш макрос. Сработал очень шустро, за 1 мин. 10 сек. (отдельное спасибо за встроенный таймер). Есть ли возможность подкорректировать макрос так, чтобы он заполнял лишь правую таблицу, соответственно кодам, которые будут указаны в столбцах и строках матрицы? Очень Вам благодарен.
Страницы: 1 2 3 След.
Читают тему
Наверх