2015-01-01 6 views
0

Я изо всех сил пытаюсь найти элегантный способ применения условных правил форматирования через VBA. Я предпочитаю VBA, потому что: а) правила будут применяться к нескольким листам и б) он предотвращает проблему дублирования CF при копировании/вставке между рабочими листами.Условное форматирование VBA

У меня есть список предметов инвентаризации, которые хранятся в разных местах. Я хочу отформатировать на основе местоположения со следующим форматированием:

Цвет шрифта (изменится для каждого местоположения); Верхняя граница (тот же цвет, что и шрифт); Нижняя граница (тот же цвет, что и шрифт)

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

Любая помощь была бы принята с благодарностью.


--UPDATE-- Я пытался адаптировать код J_V в here, но получить «ошибку времени выполнения„5“: Недопустимый вызов процедуры или аргумент» на Общественные подлодки r.FormatConditions.Add Type:=xlExpression, Formula1:=formula. Я не уверен, что последний бит на границах правильный, поскольку время выполнения останавливает макрос. Мне также нужно работать в динамических табличных ссылках, но я работаю по одной проблеме за раз.

Sub ConditionalFormatting() 

Dim myRange As Range 
Set myRange = ThisWorkbook.Sheets("Widget1").Range("Widget1_table[Location]") 

myRange.FormatConditions.Delete 

Call FormatRange(myRange, 10, "=$E5="Warehouse1") 
Call FormatRange(myRange, 11, "=$E5="Warehouse2") 
Call FormatRange(myRange, 13, "=$E5="Warehouse3") 

End Sub 

Public Sub FormatRange(r As Range, color As Integer, formula As String) 
r.FormatConditions.Add Type:=xlExpression, Formula1:=formula 
r.FormatConditions(r.FormatConditions.Count).Font.colorindex = color 

With r.FormatConditions(1).Borders(xlTop) 
    .LineStyle = xlContinuous 
    .Color = color 
    .TintAndShade = 0 
    .Weight = xlThin 
End With 
With r.FormatConditions(1).Borders(xlBottom) 
    .LineStyle = xlContinuous 
    .Color = color 
    .TintAndShade = 0 
    .Weight = xlThin 
End With 
r.FormatConditions(1).StopIfTrue = False 

End Sub 
+2

Я бы начал с записи макроса, который применяет CF к одной таблице. Затем разверните его, прокручивая каждый лист в книге и, при необходимости, каждый список (таблица) в этих листах. –

+0

Это * серьезно * плохая идея, чтобы назвать ваши переменные такими же, как зарезервированные слова свойств коллекции. 'Formula1: = formula' не рекомендуется, но' .Color = color' просто неверно. – Jeeped

+0

Спасибо за то, что вы подняли головы, я переименую переменные. – Joe

ответ

3

Проблема на самом деле не в Sub FormatRange, но так, как вы назначаете формулу при вызове ее в Sub ConditionalFormatting. Формула содержит строку, поэтому кавычки должны быть удвоены следующим образом.

Sub ConditionalFormatting() 
    Dim myRange As Range 
    Set myRange = ThisWorkbook.Sheets("Widget1").Range("Widget1_table[Location]") 

    myRange.FormatConditions.Delete 

    Call FormatRange(myRange, 10, "=$E5=""Warehouse1""") 
    Call FormatRange(myRange, 11, "=$E5=""Warehouse2""") 
    Call FormatRange(myRange, 13, "=$E5=""Warehouse3""") 
End Sub 

Что касается второго макроса, когда вы добавляете новое условие, оно идет в нижнюю часть очереди. Если вы посмотрите на записанном выходе из создания КФ правилу вы увидите, что он обычно содержит строку,

Selection.FormatConditions(Selection.FormatConditions.Count).SetFirstPriority 

Это ставит правило CF в верхней части очереди, так что он может в дальнейшем упоминаться как .FormatConditions(1) , Если вы не хотите, чтобы он находился в верхней части очереди, вам нужно обратиться к нему как последнему в очереди, подобной этой.

Public Sub FormatRange(r As Range, clr As Integer, frml As String) 
    r.FormatConditions.Add Type:=xlExpression, Formula1:=frml 
    r.FormatConditions(r.FormatConditions.Count).Font.ColorIndex = clr 

    With r.FormatConditions(r.FormatConditions.Count).Borders(xlTop) 
     .LineStyle = xlContinuous 
     .ColorIndex = clr 
     .TintAndShade = 0 
     .Weight = xlThin 
    End With 
    With r.FormatConditions(r.FormatConditions.Count).Borders(xlBottom) 
     .LineStyle = xlContinuous 
     .ColorIndex = clr 
     .TintAndShade = 0 
     .Weight = xlThin 
    End With 
    r.FormatConditions(r.FormatConditions.Count).StopIfTrue = False 
End Sub 

Я также изменил ваш граничный .Color присвоений .ColorIndex, как 10, 11 & кажутся ColorIndex идентификаторы * зеленый, синий и фиолетовый . Гласные были удалены из ваших имен переменных, чтобы избежать конфликтов с именами свойств коллекции.

+0

Jeeped, большое спасибо за изменения, поскольку они исправляют ошибку времени выполнения. Знаете ли вы, как я могу заменить ссылку «Warehouse #» в '' = $ E5 = "" Warehouse1 "" ")' с именованным заданием диапазона или ссылкой с другого листа?Теперь я понимаю, что было бы оптимальным, если бы я мог ссылаться на 'Admin $ A $ 1' - где' Warehouse1' существует в списке - или именованный диапазон 'Warehouse1', а не жесткое кодирование' Warehouse1' в макросе. – Joe

+0

Только Excel 2010 и выше разрешают вам адрес ячейки другого листа при создании правила CF на основе формулы. Для Excel 2010 и выше это будет нечто вроде 'Call FormatRange (myRange, 10," = $ E5 = 'Admin'! $ A $ 1) '. Именованный диапазон более универсален, и значение можно отрезать с помощью' INDEX' например, 'Call FormatRange (myRange, 10," = $ E5 = INDEX (my_List, 1, 1) "). Лучшим методом было бы иметь как цветной индекс, так и текстовую строку в вашем именованном диапазоне, например' Call FormatRange (myRange, INDEX (my_List, 1, 2), "= $ E5 = INDEX (my_List, 1, 1)") 'Укажите особенности, если у вас возникли проблемы – Jeeped

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