Как раскрасить отдельные ячейки многострочной части документа в 1С 7.7 с помощью FormEx?

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

Разработка интерфейсных решений в платформе 1С:Предприятие 7.7 стандартными средствами всегда была ограничена жесткими рамками визуальной схемы MS Windows 95/98. Одной из наиболее частых задач, встающих перед разработчиком, является визуальное выделение информации — например, подсветка просроченной задолженности, отрицательных остатков или статусов документов непосредственно в многострочной части. Штатный функционал платформы не позволяет раскрашивать отдельные ячейки табличной части.

Для решения этой задачи традиционно используется внешняя компонента FormEx. В этой статье мы подробно рассмотрим современный и наиболее производительный механизм выборочной раскраски — План раскраски. Мы разберем по шагам, как настроить конфигурацию, напишем правильный и оптимизированный код, а также разберем частые архитектурные ошибки, которые могут приводить к зависаниям программы или некорректному отображению интерфейса в терминальном режиме (RDP).

Что такое «План раскраски» и как он работает?

В ранних версиях компоненты FormEx раскраска таблиц выполнялась путем динамического перехвата события рисования строк. Это требовало вызова тяжелых функций 1С для каждого элемента визуализации интерфейса, что приводило к заметным «тормозам» при прокрутке больших списков.

Начиная с версии 2.0.5.85 в FormEx появился механизм Плана раскраски. Его суть заключается в следующем: в табличную часть внедряется скрытая служебная текстовая колонка с жестко зарезервированным именем FormEx_ПланРаскраски. В формуле этой колонки прописывается вызов функции, которая возвращает специальную размеченную строку шаблона. Компонента FormEx перехватывает значение этой строки, кэширует его и на основе полученного шаблона мгновенно применяет цвета к соответствующим ячейкам строки.

Синтаксис шаблона плана раскраски состоит из круглых скобок, где каждая пара скобок () соответствует одной колонке таблицы по порядку их следования на форме (слева направо, включая скрытые колонки):

Например, строка шаблона "()()()(BRUSH[255])()()(BRUSH[NONE])" означает: первые три колонки выводятся стандартно, четвертая колонка окрашивается красным фоном, пятая и шестая продолжают наследоваться как красные, а начиная с седьмой колонки раскраска отключается.

Шаг 1. Подключение компоненты и активация плана раскраски

Прежде чем приступать к рисованию на формах, нам необходимо убедиться, что компонента FormEx загружена в систему, а механизм плана раскраски глобально активирован. Лучше всего сделать это в Глобальном модуле конфигурации при старте системы.

Откроем Глобальный модуль и добавим код инициализации в предопределенную процедуру ПриНачалеРаботыСистемы():


Процедура ПриНачалеРаботыСистемы()
    // Попытка загрузки внешней компоненты FormEx
    Если ЗагрузитьВнешнююКомпоненту("FormEx.dll") = 0 Тогда
        Сообщить("Внимание! Не удалось загрузить внешнюю компоненту FormEx.dll!", "!");
    Иначе
        // Создаем глобальный объект Сервис для управления планами раскраски
        Попытка
            Сервис = СоздатьОбъект("Сервис");
            // Включаем поддержку планов раскраски таблиц
            Сервис.ИспользоватьПланРаскраски(1);
        Исключение
            Сообщить("Ошибка инициализации интерфейсных функций FormEx!", "!");
        КонецПопытки;
    EndIf;
КонецПроцедуры

Шаг 2. Подготовка визуальной формы в Конфигураторе

Теперь перейдем к форме документа, в многострочной части которого мы хотим раскрасить ячейки. Нам нужно добавить служебную колонку:

  1. Откроем форму документа на редактирование в Конфигураторе.
  2. В многострочную часть (таблицу) добавим новую колонку.
  3. В свойствах новой колонки на вкладке «Общие» укажем идентификатор строго: FormEx_ПланРаскраски.
  4. Тип колонки выберем как «Строка», длина не имеет значения, так как колонка будет расчетной.
  5. На вкладке «Дополнительно» в поле «Формула» пропишем вызов функции модуля формы, которая будет возвращать нашу строку раскраски. Например: ПолучитьПланРаскраски().
  6. Сделаем колонку невидимой, чтобы она не смущала пользователей (снимем флажок «Показывать» или зададим её ширину равной 0). Разместить её можно в любом месте табличной части.

Шаг 3. Инициализация выборочной раскраски формы

Для того чтобы FormEx понимал, что конкретную форму нужно обрабатывать и перехватывать отрисовку таблиц, необходимо применить метод РаскрашиватьТаблицу() к объекту РасширениеФормы.

Критически важный нюанс: Не следует производить инициализацию интерфейсных расширений в процедуре ПриОткрытии(). В этот момент Windows-окно формы еще физически не создано в операционной системе, что при работе в терминальном режиме (RDP) или на производительных серверах может вызывать спорадические падения платформы или ошибки обращения к памяти. Пропишем инициализацию в событии ПослеОткрытия(), которое гарантирует полную отрисовку всех элементов формы.

Добавим в модуль формы документа следующий код:


Перем ФормаРасш; // Объявляем переменную модуля формы для хранения объекта расширения

Процедура ПослеОткрытия()
    // Инициализируем расширение формы для управления раскраской табличной части
    Попытка
        ФормаРасш = СоздатьОбъект("РасширениеФормы");
        // Явно указываем компоненте, что необходимо раскрашивать многострочную часть
        ФормаРасш.РаскрашиватьТаблицу("МногострочнаяЧасть");
    Исключение
        // Обработка ситуации, если компонента не загружена в сессии
        Предупреждение("Компонента FormEx не активна. Интерфейсные улучшения отключены.");
    КонецПопытки;
КонецПроцедуры

Шаг 4. Написание функции формирования цвета ячеек

Рассмотрим, как правильно написать функцию ПолучитьПланРаскраски(), которая вызывается из формулы служебной колонки.

Многие разработчики допускают ошибку, пытаясь динамически собирать сложную строку плана раскраски путем ручного парсинга и склейки подстрок с помощью функций Найти() и Прав(). Это перегружает процессор и делает код хрупким — при добавлении любой новой колонки в конфигураторе вся нумерация сбивается, и раскраска ломается.

Мы применим элегантный и производительный подход с использованием функции Шаблон() или простого позиционирования по переменным. Рассмотрим практический сценарий: у нас есть многострочная часть со следующими колонками по порядку:

  1. Товар (Номенклатура)
  2. Количество
  3. Цена
  4. Сумма

Наша задача: если количество товара на складе меньше нуля (отрицательный остаток), мы красим ячейку "Количество" в красный цвет. Колонку "Сумма" мы всегда красим в мягкий зеленый цвет для привлечения внимания.

Реализуем это в модуле формы:


Функция ПолучитьПланРаскраски()
    // Объявляем константы цветов в формате RGB
    ЦветКрасныйФон = "BRUSH[255]";
    ЦветЗеленыйФон = "BRUSH[12648384]"; // Мягкий светло-зеленый
    ЦветБезОкраски  = "BRUSH[NONE]";
    
    // Переменные для хранения настроек каждой колонки
    ЦветКол1 = ""; // Товар - без изменений
    ЦветКол2 = ""; // Количество - динамический цвет
    ЦветКол3 = ""; // Цена - без изменений
    ЦветКол4 = ""; // Сумма - статический зеленый
    
    // Проверяем условие для второй колонки (Количество)
    Если Количество < 0 Тогда
        ЦветКол2 = ЦветКрасныйФон;
    Иначе
        ЦветКол2 = ЦветБезОкраски;
    КонецЕсли;
    
    // Задаем цвет для четвертой колонки (Сумма)
    ЦветКол4 = ЦветЗеленыйФон;
    
    // Формируем результирующую строку плана раскраски.
    // Каждая пара скобок соответствует колонке по порядку на форме.
    СтрокаПлана = "()" + "(" + ЦветКол2 + ")" + "()" + "(" + ЦветКол4 + ")";
    
    Возврат СтрокаПлана;
КонецФункции

Этот метод чрезвычайно прост в отладке, легко масштабируется при добавлении новых колонок и работает молниеносно.

Интерактивное управление раскраской ячеек по кнопке

Посмотрим на более сложный сценарий, который часто требуется на практике. Что если нам нужно дать пользователю возможность кликнуть по конкретной ячейке, нажать на кнопку на форме и окрасить выделенную ячейку в произвольно выбранный им цвет?

Для реализации этой задачи мы организуем хранение выбранных пользователем цветов в специальном объекте СписокЗначений, привязанном к номерам строк и именам колонок. Это избавит нас от необходимости хранить сложные структуры данных непосредственно в базе данных до момента сохранения документа.

Проанализируем пример кода реализации в модуле формы:


Перем СписокЦветовЯчеек; // Список значений для хранения истории раскраски

// Функция, вызываемая из служебной колонки FormEx_ПланРаскраски
Функция ПолучитьДинамическуюРаскраску()
    Перем НомСтроки, ЦветЯчейки, ТекКолонка;
    
    // Получаем текущий номер строки табличной части
    НомСтроки = НомерСтроки;
    
    // Инициализируем переменные для трех наших колонок на форме (Пт1, Пт2, Пт3)
    Цвет_Пт1 = "BRUSH[NONE]";
    Цвет_Пт2 = "BRUSH[NONE]";
    Цвет_Пт3 = "BRUSH[NONE]";
    
    // Ищем в списке сохраненный цвет для текущей строки
    Для Индекс = 1 По СписокЦветовЯчеек.РазмерСписка() Цикл
        Перем КлючСтроки, ЗначЦвета;
        КлючСтроки = "";
        ЗначЦвета = СписокЦветовЯчеек.ПолучитьЗначение(Индекс, КлючСтроки);
        
        // Формат ключа: "НомерСтроки_ИмяКолонки"
        Если Найти(КлючСтроки, Шаблон("[НомСтроки]_")) = 1 Тогда
            ТекКолонка = Сред(КлючСтроки, СтрДлина(НомСтроки) + 2);
            Если ТекКолонка = "Пт1" Тогда
                Цвет_Пт1 = "BRUSH[" + ЗначЦвета + "]";
            ИначеЕсли ТекКолонка = "Пт2" Тогда
                Цвет_Пт2 = "BRUSH[" + ЗначЦвета + "]";
            ИначеЕсли ТекКолонка = "Пт3" Тогда
                Цвет_Пт3 = "BRUSH[" + ЗначЦвета + "]";
            КонецЕсли;
        КонецЕсли;
    КонецЦикла;
    
    // Возвращаем собранную строку плана раскраски
    Возврат "()" + "(" + Цвет_Пт1 + ")" + "(" + Цвет_Пт2 + ")" + "(" + Цвет_Пт3 + ")";
КонецФункции

// Процедура, назначенная на кнопку "Покрасить ячейку"
Процедура НажатьКнопкуПокрасить()
    Перем ТекущаяКол, ВыбранныйЦвет, КлючПоиска;
    
    ТекущаяКол = Форма.ТекущаяКолонка();
    
    // Проверяем, что выбрана колонка, подлежащая раскраске
    Если (ТекущаяКол <> "Пт1") И (ТекущаяКол <> "Пт2") И (ТекущаяКол <> "Пт3") Тогда
        Предупреждение("Пожалуйста, выделите ячейку в одной из колонок Пт1, Пт2 или Пт3!");
        Возврат;
    КонецЕсли;
    
    // Вызываем стандартный диалог выбора цвета FormEx
    ВыбранныйЦвет = Сервис.ВыбратьЦвет(1);
    Если ВыбранныйЦвет = -1 Тогда
        Возврат; // Пользователь отказался от выбора
    КонецЕсли;
    
    КлючПоиска = Шаблон("[НомерСтроки]_[ТекущаяКол]");
    
    // Удаляем старое значение цвета для этой ячейки, если оно существовало
    Поз = СписокЦветовЯчеек.НайтиЗначение(КлючПоиска);
    Если Поз > 0 Тогда
        СписокЦветовЯчеек.УдалитьЗначение(Поз);
    КонецЕсли;
    
    // Добавляем новое значение цвета
    СписокЦветовЯчеек.ДобавитьЗначение(ВыбранныйЦвет, КлючПоиска);
    
    // Принудительно заставляем форму перерисовать таблицу для мгновенного отображения цвета
    Форма.Обновить(0);
КонецПроцедуры

// Инициализация при создании формы
СписокЦветовЯчеек = СоздатьОбъект("СписокЗначений");

Рекомендации по оптимизации и устранению типичных ошибок

При использовании внешней компоненты FormEx программисты нередко сталкиваются со странным поведением интерфейса. Рассмотрим основные проблемы и способы их устранения:

Использование механизма «Плана раскраски» внешней компоненты FormEx позволяет превратить стандартные серые таблицы 1С 7.7 в современный, удобный и интуитивно понятный инструмент для ежедневной работы пользователей. Следуя приведенным правилам и избегая устаревших методов обработки строк, вы гарантируете высокую скорость работы интерфейса и стабильность вашей системы.

← На главную