Pull to refresh

Подводные камни условного форматирования в MS Access

Reading time 5 min
Views 13K
Перед каждым разработчиком MS Access рано или поздно встаёт вопрос визуального оформления форм. В конечном итоге заказчику нужен дружелюбный и функциональный интерфейс, и самое страшное то, что скорее всего он уже привык к Excel. И тут Access терпит одно огромное поражение – мы не можем обращаться к ячейкам. Логика работы СУБД такова, что пользователь имеет дело с динамическим набором данных, основанным на SQL-запросе или таблице, а это значит, что мы очень ограничены в форматировании. Разместив на форме поле, подключённое к таблице или запросу, мы получаем весь набор значений этого поля, и форматирование относится тоже ко всему набору значений, но никак не к отдельной ячейке. По большому счёту, такого понятия как ячейка даже не существует. Есть лишь один инструмент, который позволяет нам работать с каждым значением отдельно – Условное форматирование (conditional formatting).

В интерфейсе Access кнопку Условное форматирование можно найти на вкладке Формат (Format), предварительно поставив фокус на форматируемый элемент управления (control). УФ можно подвергнуть лишь два типа элементов управления: Поле (Text Box) и Поле со списком (Combo Box).

image

Нажав на кнопку, мы сможем настроить правила условного форматирования в Диспетчере условного форматирования (Conditional Formatting Rules Manager), при этом правила ниже по списку имеют больший приоритет.

Пример. Имеем два правила:

  1. Значение должно быть больше 50, тогда фон красный.
  2. Значение должно быть меньше 200, тогда фон зелёный.

Если мы введём 100, то значение будет удовлетворять обоим условиям, и выполняться будет второе правило, то, которое ниже по списку. Фон станет зелёным.

На уровне VBA инструмент представлен двумя объектами: FormatCondition и FormatConditions. Первый, собственно, хранит условия форматирования, а второй это коллекция первых.

FormatConditions одновременно является свойством для контролов типа acTextBox и acComboBox.

Вот, собственно, и все базовые понятия, но не тут-то было! Access не позволяет добавлять через VBA новые правила, если у нашего контрола их уже хотя бы три. А если ваша бизнес-задача требует маркировки пятью цветами? А если при определённых условиях нужно отключать контрол? Тогда придётся поработать руками, что не так уж и страшно, как кажется. Как сделать это оптимально, я сейчас и расскажу.

Для начала пишем процедуру создания первых трёх правил:

Sub setFormatConditions()
'создаёт первые три правила условного форматирования
Dim fcnVar As FormatCondition 'объект типа FormatCondition
Dim frmVar As Form 'форма, на которой расположены контролы
Dim ctlVar As Control 'перебираемые контролы
Dim btCtlType As Byte 'тип контрола

On Error Resume Next

'обратите внимание, что форма обязательно должа быть открыта
'если она закрыта, то надо её открыть руками или соответствующим кодом
Set frmVar = Forms![Название формы]

With frmVar    
    'ищем комбобоксы и текстбокы среди контролов
    For Each ctlVar In .Controls
        
        btCtlType = ctlVar.ControlType
        
        If (btCtlType = acComboBox) Or (btCtlType = acTextBox) Then
            
                'очищаем все условия для контрола и применяем создание условного форматирования
                ctlVar.FormatConditions.Delete
                Set fcnVar = ctlVar.FormatConditions.Add(acExpression, , "blablabla")
                Set fcnVar = ctlVar.FormatConditions.Add(acExpression, , "blablabla")
                Set fcnVar = ctlVar.FormatConditions.Add(acExpression, , "blablabla")
            
        End If 'btCtlType = acComboBox
        
    Next ctlVar 'In .Controls
    
End With 'frmVar

Set fcnVar = Nothing
Set ctlVar = Nothing
Set frmVar = Nothing

End Sub

В данном случае мы создаём правила для всех объектов TextBox И ComboBox, однако, в зависимости от задачи, можно прописать проверку на дополнительные условия. Во всех трёх случаях добавляются правила основанные на выражении, о чём свидетельствует параметр acExpression, а в качестве текста выражения используется любая произвольная строка, например «blablabla», второй параметр пропущен, потому что его можно пропустить. Использованы именно такие параметры, потому что это самый простой и короткий вариант кода для создания правил форматирования, настраивать их будем позже.

Далее открываем Диспетчер условного форматирования и в выпадающем списке «Показать правила условного форматирования для:» последовательно проходим по всем нужным полям и руками добавляем правила. При добавлении правила по умолчанию предлагают условие «Значение поля между», оставляем как есть, заполняем оба пустых поля любыми буквами или цифрами, например «1» и «1», жмём OK и создаём следующее. Таким образом экономим время при ручном вводе, не тратя его на лишние действия.

image

Когда создание нужного количества правил для всех контролов завершено, массово модифицируем эти правила в VBA.

Для этого создаём процедуру модификации:

Sub modifyFormatConditions()
'модифицирует созданные правила форматирования
Dim fcnVar As FormatCondition 'объект типа FormatCondition
Dim frmVar As Form 'форма, на которой расположены контролы
Dim ctlVar As Control 'перебираемые контролы
Dim i As Integer

On Error Resume Next

'обратите внимание, что форма обязательно должа быть открыта
'если она закрыта, то надо её открыть руками или соответствующим кодом
Set frmVar = Forms![Название таблицы] 

With frmVar
    
    'ищем комбобоксы и текстбокы среди контролов
    For Each ctlVar In .Controls
        
        btCtlType = ctlVar.ControlType
        
        If (btCtlType = acComboBox) Or (btCtlType = acTextBox) Then
            
            'перебираем все правила по индексу, начиная с 0
            For i = 0 To 20
                'Метод Modify имеет такой же синтаксис, как и Add, с помощью него можно поменять все параметры правила
                'Modify возвращает Nothing, поэтому его надо присвоить хотя бы чему-нибудь
                ddd = ctlVar.FormatConditions(i).Modify(acExpression, , "ololo")
                Set fcnVar = ctlVar.FormatConditions(i)
                'Настраиваем формат, в данном случае делаем фон красным
                fcnVar.BackColor = vbRed
            Next i
            
        End If 'btCtlType = acComboBox
        
    Next ctlVar 'In .Controls
    
End With 'frmVar

Set fcnVar = Nothing
Set ctlVar = Nothing
Set frmVar = Nothing

End Sub

Всё, правила готовы, контент форматируется. Надо иметь в виду, что условное форматирование требует заметного времени для вычисления, поэтому лучше всего его использовать на формах, к которым не будут применяться Refresh, Redraw, Recalc и Requery. Если на стадии открытия формы пользователь ещё может немного подождать, чтобы потом продолжительно с ней общаться, то зависания при перерисовке условного форматирования в процессе работы с формой сделают эту работу практически невозможной.

В этом примере показано массовое создание большого количества одинаковых правил для разных контролов. Естественно, в зависимости от задачи, необходимо будет делать множество разных проверок, и этот метод не подойдёт для большого количества контролов, с разными наборами правил. Хотя, если эти наборы со временем меняются, может оказаться, что прописать матрицу настроек в коде и переписывать константы будет значительно проще, чем бегать мышкой по экрану и нажимать разные кнопки.

Полезные ссылки:

» Типы контролов
» Свойства и методы объекта FormatCondition
» Свойства и методы объекта FormatConditions
» Метод FormatConditions.Add
Tags:
Hubs:
+16
Comments 0
Comments Leave a comment

Articles