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