В процессе разработки в среде 1С:Предприятие на обычных формах часто возникает задача добавить в форму списка документов (или справочников) колонку с флажком, которая не связана напрямую с реквизитом базы данных. Это может быть полезно для групповой обработки документов, их выгрузки или печати. Однако начинающие разработчики часто сталкиваются с тем, что флажок либо не отображается, либо "замерзает" и не реагирует на клики пользователя. Разберем подробно, как решить эту задачу правильно.
Рассмотрим типичную ошибку. Программисты часто пытаются управлять флажком только внутри события ПриВыводеСтроки. Проблема заключается в том, что это событие предназначено исключительно для визуального оформления уже имеющихся данных. Если колонка не привязана к реквизиту, то при каждом обновлении списка система будет пытаться отрисовать состояние флажка заново, не имея источника данных, где это состояние хранится.
Проанализируем ситуацию: когда пользователь кликает на флажок, событие ПриВыводеСтроки не срабатывает для изменения данных. Оно сработает позже, при перерисовке, но к этому моменту значение уже будет "потеряно", так как его некуда было сохранить. Чтобы флажок стал интерактивным, нам нужно создать внешнее хранилище для этих галочек и правильно обработать программные события табличного поля.
Поскольку наш флажок — это временная пометка, существующая только пока открыта форма, нам нужно где-то хранить информацию о том, для каких документов галочка установлена, а для каких — нет. Лучшим инструментом для этого в 1С является объект Соответствие.
Рассмотрим, как инициализировать такое хранилище. В модуле формы в самом верху (в разделе описания переменных) определим переменную, которая будет доступна во всех процедурах формы:
Перем СоответствиеПометок;
Затем в процедуре ПриОткрытии создадим сам объект:
Процедура ПриОткрытии()
СоответствиеПометок = Новый Соответствие;
КонецПроцедуры
В этом соответствии ключом будет Ссылка на документ, а значением — булево (Истина или Ложь).
Вместо использования ПриВыводеСтроки, которое вызывается для каждой строки отдельно, мы воспользуемся более производительным событием — ПриПолученииДанных. Оно позволяет обработать сразу весь массив видимых на экране строк, что значительно ускоряет работу интерфейса при прокрутке.
Разберем программный код для отображения флажков:
Процедура ДокументСписокПриПолученииДанных(Элемент, ОформленияСтрок)
Для Каждого ОформлениеСтроки Из ОформленияСтрок Цикл
// Получаем ссылку на текущий документ в строке
ТекущаяСсылка = ОформлениеСтроки.ДанныеСтроки.Ссылка;
// Пытаемся найти значение флажка в нашем соответствии
СостояниеФлажка = СоответствиеПометок.Получить(ТекущаяСсылка);
// Если значения еще нет (документ не кликали), можно задать значение по умолчанию
Если СостояниеФлажка = Неопределено Тогда
// Например, по умолчанию флажок снят
СостояниеФлажка = Ложь;
КонецЕсли;
// Управляем визуальным отображением в ячейке "Выгрузить"
Ячейка = ОформлениеСтроки.Ячейки.Выгрузить;
Ячейка.ОтображатьФлажок = Истина;
Ячейка.Флажок = СостояниеФлажка;
КонецЦикла;
КонецПроцедуры
Важный нюанс: для того чтобы этот код работал, у колонки в свойствах (в конфигураторе) не должно быть указано поле данных, но должен быть включен ОтображатьФлажок.
Теперь выясним причину, по которой флажок может не меняться при клике. Для интерактивной работы в обычных формах табличного поля существует специальное событие — ПриИзмененииФлажка. Именно здесь мы будем фиксировать выбор пользователя.
Проанализируем код обработчика:
Процедура ДокументСписокПриИзмененииФлажка(Элемент, Колонка)
// Проверяем, что кликнули именно по нашей колонке
Если Колонка.Имя = "Выгрузить" Тогда
// Получаем текущую строку (строку, где изменили флажок)
ТекущиеДанные = Элемент.ТекущиеДанные;
Если ТекущиеДанные = Неопределено Тогда
Возврат;
КонецЕсли;
ТекущаяСсылка = ТекущиеДанные.Ссылка;
// Получаем текущее состояние из соответствия и инвертируем его
ТекущееЗначение = СоответствиеПометок.Получить(ТекущаяСсылка);
Если ТекущееЗначение = Неопределено Тогда
ТекущееЗначение = Ложь;
КонецЕсли;
НовоеЗначение = НЕ ТекущееЗначение;
// Сохраняем новое состояние в наше хранилище
СоответствиеПометок.Вставить(ТекущаяСсылка, НовоеЗначение);
// Принудительно обновляем оформление, чтобы пользователь сразу увидел изменения
// (в некоторых случаях 1С сделает это сама, но так надежнее)
КонецЕсли;
КонецПроцедуры
Обратите внимание: если вы хотите, чтобы флажок менялся "в один клик", убедитесь, что в свойствах колонки параметр РежимРедактирования установлен в значение Непосредственно. Если оставить "Вход при вводе", пользователю придется кликнуть дважды (первый клик активирует ячейку, второй переключит флаг).
Рассмотрим несколько продвинутых моментов, которые сделают вашу работу с флажками профессиональной:
Enter, используйте событие Выбор. В нем нужно установить СтандартнаяОбработка = Ложь, чтобы не открывалась форма документа.СоответствиеПометок запросом прямо в процедуре ПриОткрытии.Соответствие может накапливать ссылки. Если это критично, можно удалять из соответствия элементы со значением Ложь, используя метод Удалить(). Тогда в коллекции будут храниться только "Истинные" пометки.Посмотрим на пример того, как можно проверить, какие документы в итоге выбрал пользователь (например, по нажатию кнопки "Выполнить"):
Процедура КнопкаВыполнитьНажатие(Кнопка)
МассивВыбранныхДокументов = Новый Массив;
// Обходим наше соответствие
Для Каждого Запись Из СоответствиеПометок Цикл
Если Запись.Значение = Истина Тогда
МассивВыбранныхДокументов.Добавить(Запись.Ключ);
КонецЕсли;
КонецЦикла;
Если МассивВыбранныхДокументов.Количество() = 0 Тогда
Сообщить("Ни один документ не выбран!");
Возврат;
КонецЕсли;
// Далее логика обработки массива документов...
КонецПроцедуры
Таким образом, мы разделили визуальное представление (в событиях списка) и логику хранения данных (в переменной формы). Это надежный и классический способ реализации временных пометок в 1С 8.2/8.3 на обычных формах.