Visual Basic, .NET, ASP, VBScript
 

   
   
     

Форум - VBA

Страница: 1 |

 

  Вопрос: как ускорить выполнение программы? Добавлено: 02.07.08 10:40  

Автор вопроса:  APS | ICQ: 234458121 
Есть программа с 3 вложенными циклами:
    For n = 5 To 6
        With Worksheets(n).UsedRange
            endpoint = .Cells(.Rows.Count, .Columns.Count).Row
        End With
        For i = 2 To endpoint
            oItem = Worksheets(n).Cells(i, 2)
            For m = 2 To 4
                Set oFind = Worksheets(m).Columns("A").Find(what:=oItem)
                If Not oFind Is Nothing Then
                    r = Worksheets(n).Cells(i, 6)
                    d = Worksheets(n).Cells(i, 7)
                    s = Worksheets(n).Cells(i, 8)
                    oFind.Offset(0, 7) = r
                    oFind.Offset(0, 8) = d
                    oFind.Offset(0, 9) = s
                    GoTo 50
                End If
50:         Next
        Next
    Next

Смысл в следующем. Есть дву группы листов с данными: одна группа из 3 листов и вторая из двух. Все листы заполнены практически полностью, т.е. занято от 40 до 60 тысяч строк. Необходимо найти совпадающие артикулы в двух группах листов и перенести цены из одной группы в другую.
Вышеприведенный код у меня выполнялся порядка 3-х часов. Можно как-то оптимизировать этот код, чтобы сократить время хотя бы втрое.

Ответить

  Ответы Всего ответов: 15  

Номер ответа: 1
Автор ответа:
 Smith



ICQ: adamis@list.ru 

Вопросов: 153
Ответов: 3632
 Профиль | | #1 Добавлено: 02.07.08 10:58

     Это конечно не ответ на главный вопрос, но
     endpoint = Worksheets(n).UsedRange.Rows.Count
     вродебы достаточно, нафига там With End With?

Ответить

Номер ответа: 2
Автор ответа:
 FIX



ICQ: 348680795 

Вопросов: 39
Ответов: 62
 Профиль | | #2 Добавлено: 02.07.08 14:26
Попробуй во всех циклах заменить: For m = 2 To 4
на следующее:

Dim a=2,b=4 'объявить перед циклами
For m = a To b' заменить
смысл в том что в твоем примере под 2 и 4 каждый раз выделяется область памяти, а в моем эта область просто считывается.
если цикл действительно большой, то это будет быстрее

Ответить

Номер ответа: 3
Автор ответа:
 Smith



ICQ: adamis@list.ru 

Вопросов: 153
Ответов: 3632
 Профиль | | #3 Добавлено: 02.07.08 14:35

     Переменные вообще отдельная тема.
     APS покажи где ты их объявил.

Ответить

Номер ответа: 4
Автор ответа:
 Smith



ICQ: adamis@list.ru 

Вопросов: 153
Ответов: 3632
 Профиль | | #4 Добавлено: 02.07.08 14:41

      GoTo 50 и 50: убери, это лишнее.

Ответить

Номер ответа: 5
Автор ответа:
 APS



ICQ: 234458121 

Вопросов: 38
Ответов: 107
 Профиль | | #5 Добавлено: 02.07.08 22:17
Переменные не объявлял.
Goto 50 осталось от старой программы с более сложными условиями.

Ответить

Номер ответа: 6
Автор ответа:
 APS



ICQ: 234458121 

Вопросов: 38
Ответов: 107
 Профиль | | #6 Добавлено: 02.07.08 22:19
Реально, with лишнее. Я брал это по чьему совету на форуме достаточно давно.

Ответить

Номер ответа: 7
Автор ответа:
 Smith



ICQ: adamis@list.ru 

Вопросов: 153
Ответов: 3632
 Профиль | | #7 Добавлено: 03.07.08 08:10

      В самый верх кода впиши

      Option Explicit

      Dim N As Long, M As Long, I As Long
      Dim oItem As String, oFind As Range
      Dim R As String, D As String, S As String

      и проверь, может быстрее заработает

Ответить

Номер ответа: 8
Автор ответа:
 Jasmin



Вопросов: 23
Ответов: 417
 Профиль | | #8 Добавлено: 03.07.08 08:39
                    oFind.Offset(0, 7) = Worksheets(n).Cells(i, 6)
                    oFind.Offset(0, 8) = Worksheets(n).Cells(i, 7)
                    oFind.Offset(0, 9) = Worksheets(n).Cells(i, 8)

Тогда не нужны переменные и область памяти не занимается.

Ответить

Номер ответа: 9
Автор ответа:
 Jasmin



Вопросов: 23
Ответов: 417
 Профиль | | #9 Добавлено: 03.07.08 08:45
Артикулы на листе уникальны ? Если да, то после того как нашли очередной артикул и перенесли цену (вместо строки Goto 50) написать Exit For. Чтобы не гонять остаток цикла. Или заменить цикл на Do LOOP

Ответить

Номер ответа: 10
Автор ответа:
 Jasmin



Вопросов: 23
Ответов: 417
 Профиль | | #10 Добавлено: 03.07.08 08:49
Сорри, пропустила m это номер листа. :-) Поправка: Артикулы на листАХ уникальны ?

Ответить

Номер ответа: 11
Автор ответа:
 Artyom



Разработчик

Вопросов: 130
Ответов: 6602
 Профиль | | #11 Добавлено: 03.07.08 16:23
Объектная модель Excel не очень шустрая, сам сейчас с этим столкнулся.

Смешные советы типа убрать переменные можешь не рассматривать - экономия десятка байт на обработке 40К строк не даст никакого выигрыша.

Если артикулы уникальны, попробуй сделать встроенными формулами Excel, например SumIf, CountIf (кажется к русской редакции Excel СуммЕсли и КоличествоЕсли, или что-то подобное).

Ответить

Номер ответа: 12
Автор ответа:
 Artyom



Разработчик

Вопросов: 130
Ответов: 6602
 Профиль | | #12 Добавлено: 03.07.08 16:25
Еще перед обработкой можно отсортировать данные на листах по артикулу, тогда не нужен будет
Set oFind = Worksheets(m).Columns("A";).Find(what:=oItem)

Будет более сложный алгоритм, но он обойдется одним циклом без этого Find, который, как я понимаю, тоже не очень шустрый.

Ответить

Номер ответа: 13
Автор ответа:
 ADSemenov.ru



Вопросов: 5
Ответов: 276
 Web-сайт: www.adsemenov.ru
 Профиль | | #13
Добавлено: 03.07.08 20:55
    Всё загнать сначала в память и там всё сделать. Результат записать на лист.

Ответить

Номер ответа: 14
Автор ответа:
 Artyom



Разработчик

Вопросов: 130
Ответов: 6602
 Профиль | | #14 Добавлено: 03.07.08 22:12
ну да, можно и так

Ответить

Номер ответа: 15
Автор ответа:
 Jasmin



Вопросов: 23
Ответов: 417
 Профиль | | #15 Добавлено: 04.07.08 06:45
Если артикулы уникальны, попробуй сделать встроенными формулами Excel, например SumIf, CountIf (кажется к русской редакции Excel СуммЕсли и КоличествоЕсли, или что-то подобное).

Порой формулами работает гораздо дольше, чем макросом. К тому же при изменении любой ячейки будут пересчитываться все формулы, что сильно замедляет работу, если нужно сначала внести N данных. Можно конечно отключить пересчет, но при этом про это необходимо помнить, что его нужно потом включить/пересчитать вручную.
Хотя можно конечно попробовать сделать через формулы.

Ответить

Страница: 1 |

Поиск по форуму



© Copyright 2002-2011 VBNet.RU | Пишите нам