1

У меня есть книга с основным контрольным листом и 40-50 различными листами данных, которые копируются/вставляются в файл из внешнего источника (каждый лист имеет от 30 до 500 строк и от 10 до 100 столбцов с данными).VBA - Оптимизация UDF (счетчик цветов ячеек)

Целью книги является сравнение ячеек в разных столбцах таблицы данных и их выделение, если они соответствуют определенным критериям отклонения; подсвеченные ячейки в каждом листе данных затем подсчитываются и отображаются на основном контрольном листе (используя формулы UDF).

После прочтения сайта cpearson я понял, что подсчет выделенных ячеек был почти невозможным, если вы использовали традиционное условное форматирование ... но я только понял это после того, как я уже написал специальный код CF в VBA для 40 + листов (это было сделано так, чтобы форматирование можно было удалить или применить с помощью кнопки макроса после того, как листы данных были «обновлены» с помощью копирования/вставки).

Итак, после хорошего долгого пламени, я по существу воссоздал условное форматирование (снова в VBA), используя цикл, чтобы достичь своей цели.


Примеры критериев: 25% меньше или больше, чем значение ячейки. Лист

Пример данных:

[col 1] *** [col 2] 
2014 *****2015 
1 *********1.1 
3 **********3 
532 *******555 
323 *******46 <<<this would Highlight 
42 *******-112 <<<<this would highlight 

(The highlighting would occur if cells in col 2 are either 25% greater or 
less than the cells in col 1 cell for the corresponding row.) 

asterisks are only used for the purpose of spacing the two columns in this example 

Пример код:

Dim ref As WorksheetDim wkb As Workbook 

Set wkb = ThisWorkbook 
Set ref = ThisWorkbook.Sheets("Reference") 
pn1 = ref.Range("E17").Value 


With wkb.Sheets(pn1) 
.Select 

Set e1 = wkb.Sheets(pn1) 

For i = 7 To 53 
j = 2 
k = j + 8 


    If e1.Cells(i, j).Value > 0 And IsNumeric(e1.Cells(i, j).Value) = True _ 
    Then If e1.Cells(i, j).Value > 1.25 * e1.Cells(i, k).Value _ 
Or e1.Cells(i, j).Value < 0.75 * e1.Cells(i, k).Value _ 
    Then e1.Cells(i, j).Interior.Color = RGB(252, 213, 181) 


If e1.Cells(i, j).Value < 0 And IsNumeric(e1.Cells(i, j).Value) = True _ 
    Then If e1.Cells(i, j).Value < 1.25 * e1.Cells(i, k).Value _ 
Or e1.Cells(i, j).Value > 0.75 * e1.Cells(i, k).Value _ 
    Then e1.Cells(i, j).Interior.Color = RGB(252, 213, 181) 

Next i 

    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 

    For i = 7 To 53 
    j = 2 
    k = j + 9 


If e1.Cells(i, j).Value > 0 And IsNumeric(e1.Cells(i, j).Value) = True _ 
    Then If e1.Cells(i, j).Value > 1.25 * e1.Cells(i, k).Value _ 
Or e1.Cells(i, j).Value < 0.75 * e1.Cells(i, k).Value _ 
    Then e1.Cells(i, j).Interior.Color = RGB(252, 213, 181) 


If e1.Cells(i, j).Value < 0 And IsNumeric(e1.Cells(i, j).Value) = True _ 
    Then If e1.Cells(i, j).Value < 1.25 * e1.Cells(i, k).Value _ 
Or e1.Cells(i, j).Value > 0.75 * e1.Cells(i, k).Value _ 
    Then e1.Cells(i, j).Interior.Color = RGB(252, 213, 181) 

Next i 


End With 

End Sub 

(Там часто пустые столбцы между заселенными столбцами данных и скрытыми строками, разбросанных по всем листам)

Затем я создал UDF для удовлетворения моих потребностей в подсчете:

Function CountRed(MyRange As Range) As Integer          
'Application.Volatile               
CountRed = 0                  
For Each cell In MyRange               
If Not cell.EntireRow.Hidden And cell.Interior.Color = RGB(252, 213, 181) 
CountRed = CountRed + 1               
End If                   
Next cell 
End Function 

У меня есть два основных вопроса:

  1. Когда условное форматирование применяется, ячейка, показывающая формулу UDF (= CountRed [WkshtName] {Диапазон: Диапазон}) не обновляется автоматически; это имеет место, даже если «application.volatile» активен для UDF, и рабочая книга настроена на автоматический расчет.

  2. скорость.

С этими двумя состояниями в виду (application.volatile и автоматический расчет), выделенном подсчета клеток число (выходной формулы UDF) будет обновляться только если нажать одну из формул UDF клеток и нажмите F9 (или я могу щелкнуть панель формул и нажать клавишу ввода), но большая проблема в том, что моя рабочая тетрадь истекает в течение 4-5 минут, пока она обновляет ВСЕ формулы UDF на моей странице (это мое предположение, основанное на более быстрых временах обработки с меньшими формулами UDF на странице или критериями меньшего диапазона, используемыми в формулах UDF). * Отключение приложения. Летучие и оставляющие автоматический расчет при доходности аналогичных результатов.

Для борьбы с этим я отключил как автоматический расчет, так и application.volatile (это, похоже, не имеет никакого эффекта в любом случае).

Я знаю, что этот метод не допускает какого-либо автоматического обновления выходной формулы UDF (подсвеченное количество подсчета клеток), но ручной пересчет (F9 или формула «вводить») каждой формулы UDF теперь принимает только 5- 10 секунд в зависимости от размера диапазона (он также будет только обновлять ячейку, на которую вы нажали).

Мое основное икование здесь возникает, когда я пытаюсь включить макрос кнопки кнопки, который заставляет обновлять всю страницу, чтобы исключить необходимость обновления каждой ячейки формулы UDF (например, ThisWorkbook.Worksheets («Ссылка»). , мое расчетное время затем замедляется около первоначального времени обновления (3-4 минуты) и оставляет мне вопрос, действительно ли это намного быстрее.

Все это приводит меня спросить ...

ли, есть ли способ оптимизировать или ускорить время/обработки зацикливания моей пользовательской UDF?

Автоматическое обновление было бы обледенением на торте, но если мне нужно будет вручную пересчитать, я бы хотел, чтобы он был как можно быстрее.


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

Примечание: Я использую Excel 2007.

СПАСИБО ЗАРАНЕЕ !!

ответ

0

Вы можете хранить подсчет цветных ячеек при их цвете, а затем использовать это значение вместо подсчета цветных ячеек в отдельной операции.

Sub DoColors() 

    Dim ref As Worksheet, e1 As Worksheet 
    Dim wkb As Workbook, pn1 
    Dim rw As Range, i As Long, j As Long, n As Long, v, v2, v3 

    Set wkb = ThisWorkbook 
    Set ref = wkb.Sheets("Reference") 
    pn1 = ref.Range("E17").Value 

    Set e1 = wkb.Sheets(pn1) 

    j = 2 
    n = 0 
    For i = 7 To 53 

     Set rw = e1.Rows(i) 

     v = rw.Cells(j).Value 

     If IsNumeric(v) And v > 0 Then 

      v2 = rw.Cells(j + 8).Value 
      v3 = rw.Cells(j + 9).Value 

      If Abs(v - v2)/v2 > 0.25 Or Abs(v - v3)/v3 > 0.25 Then 
       rw.Cells(j).Interior.Color = RGB(252, 213, 181) 
       n = n + 1 
      End If 

     End If 
    Next i 

    'put n somewhere... 

End Sub 
1

Ваш код медленный, потому что вы обращаетесь к Excel для проверки каждой ячейки в диапазоне. Наиболее эффективным способом было бы загрузить использованный диапазон в память VBA и работать с этими массивами - проверить этот набор статей - он очень полезен и хорошо написан. https://fastexcel.wordpress.com/making-your-vba-udfs-efficient/

Также для более быстрого расчета вы можете рассчитать диапазон рабочего листа , нет необходимости пересчитывать весь лист.

Надеюсь, что это поможет

Смежные вопросы