Форум программистов, компьютерный форум, киберфорум
VBA
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.76/21: Рейтинг темы: голосов - 21, средняя оценка - 4.76
0 / 0 / 0
Регистрация: 14.04.2015
Сообщений: 6
1

Как можно ускорить работу макроса Excel с большим кол-вом итерационных циклов?

14.01.2016, 18:02. Показов 4170. Ответов 7
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Есть задача, которую решил, но хотел бы ускорить работу. Проблема в том что суть программы пройти по строкам и столбцам в 1 таблице, сравнения с значениями в другой таблице, и если условие выполняется вписывать нужное значение в соответствующую ячейку, вот кусок проги:

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Set Result24 = ThisWorkbook.Worksheets("24h")
Set Result5_17 = ThisWorkbook.Worksheets("6h-18h")
Set Result17_5 = ThisWorkbook.Worksheets("18h-6h")
Set Arhiv = ThisWorkbook.Worksheets("Архив")
For i = 2 To Result24.UsedRange.Rows.Count
 For j = 2 To Result24.UsedRange.Columns.Count
   For z = 2 To Arhiv.UsedRange.Rows.Count
    If Result24.Cells(i, 1).Value = Arhiv.Cells(z, 4).Value _
     And Arhiv.Cells(z, 3).Value >= CInt(Mid(Result24.Cells(1, j).Value, 1, 3)) _
     And Arhiv.Cells(z, 3).Value <= CInt(Mid(Result24.Cells(1, j).Value, 5, 7)) Then
      Result24.Cells(i, j) = 3 + Result24.Cells(i, j)
    
      If Arhiv.Cells(z, 6).Value >= 5 And Arhiv.Cells(z, 6).Value <= 17 Then
      Result5_17.Cells(i, j) = 3 + Result5_17.Cells(i, j)
      End If
      
      If Arhiv.Cells(z, 6).Value >= 17 And Arhiv.Cells(z, 6).Value <= 5 Then
      Result17_5.Cells(i, j) = 3 + Result17_5.Cells(i, j)
      End If
      
    End If
   Next z
  Next j
 Next i
Работает прога в Excelе, пробовал сделать тоже в accessе скорость не улучшилась.
Количество циклов примерно равно: 30000 * 76 * 20 = 45,6 миллионов циклов. Скорость выполнения примерно 1.5-2 часа.

Подскажите, у кого какие идеи?
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
14.01.2016, 18:02
Ответы с готовыми решениями:

как по-умному организовать работу с большим кол.-вом слоев
Добрый день! Делаю что-то вроде мастера-помощника, при работе с которым пользователь будет жать...

Как вычислить что-то с большим кол-вом неизвестных?
Здравствуйте. Простите, если указал не правильный раздел. Не знаю куда отнести вопрос. Я не...

Можно ли ускорить работу макроса
Здравствуйте!) У меня вот такой вопрос...возможно ли каким то образом ускорить работу макроса? Если...

Посчитать стоимость продуктов с большим кол-вом данных
Требуется посчитать стоимость продукты в листе &quot;роллы&quot;, имея в первом листе стоимость продуктов....

7
6922 / 2832 / 543
Регистрация: 19.10.2012
Сообщений: 8,645
14.01.2016, 18:43 2
Лучший ответ Сообщение было отмечено Kuznetsovka как решение

Решение

1. если влезет всё в память - взять данные в массивы, перебирать их.
2. цепочку (все цепочки) AND преобразовать в лесенку IF-THEN, вглубь положить наиболее вероятное, снаружи наименее.

Добавлено через 30 минут
Ещё - вот это
Visual Basic
1
2
CInt(Mid(Result24.Cells(1, j).Value, 1, 3))
CInt(Mid(Result24.Cells(1, j).Value, 5, 7))
можно извлечь один раз перед циклом в две переменные, а не тратить время в цикле.
0
Модератор
Эксперт MS Access
11963 / 4831 / 779
Регистрация: 07.08.2010
Сообщений: 14,151
Записей в блоге: 4
14.01.2016, 20:54 3
а это разве возможно
Visual Basic
1
If Arhiv.Cells(z, 6).Value >= 17 And Arhiv.Cells(z, 6).Value <= 5 Then
Добавлено через 1 час 9 минут
в былые времена я бы сделала так
Visual Basic
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
39
40
41
42
43
44
45
46
47
48
49
50
51
Sub Test160114()
Set Result24 = ThisWorkbook.Worksheets("24h")
Set Result5_17 = ThisWorkbook.Worksheets("6h-18h")
Set Result17_5 = ThisWorkbook.Worksheets("18h-6h")
Set Arhiv = ThisWorkbook.Worksheets("Архив")
 
Dim I24K, J24K, ZAK, I, J, Z
I24K = Result24.UsedRange.Rows.Count
J24K = Result24.UsedRange.Columns.Count
ZAK = Arhiv.UsedRange.Rows.Count
Dim M24_1_3, M24_5_7
ReDim M24_1_3(0 To J24K)
ReDim M24_5_7(0 To J24K)
For J = 2 To J24K
M24_1_3(J) = CInt(Mid(Result24.Cells(1, J).Value, 1, 3))
M24_5_7(J) = CInt(Mid(Result24.Cells(1, J).Value, 5, 7))
Next J
 
For I = 2 To I24K
For J = 2 To J24K
r24 = Result24.Cells(I, J)
R17_5 = Result17_5.Cells(I, J)
R5_17 = Result5_17.Cells(I, J)
 
For Z = 2 To ZAK
z4 = Arhiv.Cells(Z, 4).Value
z3 = Arhiv.Cells(Z, 3).Value
z6 = Arhiv.Cells(Z, 6).Value
 
If Result24.Cells(I, 1).Value = z4 Then
If z3 >= M24_1_3(J) And z3 <= M24_5_7(J) Then
r24 = 3 + r24
 
If z6 > 17 Or z6 < 5 Then
R17_5 = 3 + R17_5
Else
R5_17 = 3 + R5_17
End If
 
End If
End If
Next Z
 
Result24.Cells(I, J) = r24
Result17_5.Cells(I, J) = R17_5
Result5_17.Cells(I, J) = R5_17
 
 
Next J
Next I
End Sub
1
0 / 0 / 0
Регистрация: 14.04.2015
Сообщений: 6
15.01.2016, 09:44  [ТС] 4
Да, Вы правы, на самом деле там ИЛИ. Старый вариант кода.
If Arhiv.Cells(z, 6).Value >= 17 Or Arhiv.Cells(z, 6).Value <= 5 Then

Цитата Сообщение от shanemac51 Посмотреть сообщение
в былые времена я бы сделала так
Спасибо за совет.
Суть уловил, но сомневаюсь, что это значительно ускорит процесс. Сегодня протестирую.
0
6922 / 2832 / 543
Регистрация: 19.10.2012
Сообщений: 8,645
15.01.2016, 09:47 5
Массивы ускорят раз так в 40.
Изменения с AND ускорят раза в 3.
0
Модератор
Эксперт MS Access
11963 / 4831 / 779
Регистрация: 07.08.2010
Сообщений: 14,151
Записей в блоге: 4
15.01.2016, 12:25 6
В массив удобно списать лист АРХИВ --в него нет обратной записи, но сложность, если позиции R24 не окажется в в АРХИВ, что даст ошибку адресации
0
0 / 0 / 0
Регистрация: 14.04.2015
Сообщений: 6
19.01.2016, 12:13  [ТС] 7
Всем спасибо, после сегоднешнего теста вот что получилось: кол-во циклов: 50 668 800.
1. Прогнал свой вариант с разделениес If and на 2 if.
2. Прогнал предложенный вариант Sub Test160114().

Получил удивительный результат:
1. Время решения: 12:48.
2. Время решения: 24:33.

Разделение If and уменьшило время выполнения примерно в 3 раза.
0
6922 / 2832 / 543
Регистрация: 19.10.2012
Сообщений: 8,645
19.01.2016, 12:35 8
Всё логично - при AND всегда проводятся все проверки, указанные в строке, а при вложенных IF только нужные - если не прошла первая, то остальные не производятся. Если всё это ещё происходит с ячейками - разница будет заметна.
0
19.01.2016, 12:35
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
19.01.2016, 12:35
Помогаю со студенческими работами здесь

Работа с большим кол-вом строк, словари, массивы, коллекции
Мне нужно из одного документа, содержащего для каждого типа документа приоритет расставить...

Нужна помощь в составлении алгоритма с большим кол-вом задек
Пытаюсь решить задачу: есть устройство (контроллер mega16), он управляет другим устройством....

Компактный корпус с большим кол-вом слотов под hdd
Добрый вечерочек, господа. Никто случаем не знает корпус с максимально допустимыми параметрами:...

Как ускорить работу макроса
Привет всем! Есть файл, там макрос. Макрос вычисляет наилучший доход. Макрос работает 10 минут. Это...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru