При разработке на платформе 1С часто возникает задача добавить новые реквизиты в существующие формы списков, не снимая конфигурацию с поддержки. Использование расширений для этих целей — наиболее правильный путь. Однако разработчики часто сталкиваются с ситуацией, когда колонки на форме появляются, но данные в них не отображаются, даже если запрос динамического списка изменен. В этой статье мы подробно разберем, как правильно реализовать программное добавление колонок и почему данные могут «пропадать» из видимости.
Представим ситуацию: в основную конфигурацию (например, 1С:ITIL или любую другую типовую систему) были добавлены новые реквизиты в документ (например, ЧисловойПриоритет и КрайнийСрок). Теперь нам нужно вывести их в форму списка через расширение, при этом программно модифицируя состав колонок. Мы хотим избежать визуального изменения формы в расширении, чтобы минимизировать проблемы при будущих обновлениях.
Для решения этой задачи нам потребуется выполнить три основных шага:
Первым делом проанализируем, как добавить новые поля в запрос динамического списка. Обычно это делается в обработчике события ПриСозданииНаСервере. Мы будем использовать метод СтрЗаменить, чтобы внедрить наши поля в существующий список выборки ВЫБРАТЬ.
Рассмотрим пример кода, который внедряет новые реквизиты:
&НаСервере
Процедура ДобавитьПоляВЗапрос()
// Получаем текущий текст запроса
ТекстЗапроса = Список.ТекстЗапроса;
// Добавляем новые поля через замену существующего фрагмента
// Важно найти уникальный фрагмент, чтобы замена прошла корректно
НовыйТекст = СтрЗаменить(ТекстЗапроса,
"itilprofИнциденты.КодЗавершения,",
"itilprofИнциденты.КодЗавершения, itilprofИнциденты.ЧисловойПриоритет, itilprofИнциденты.КрайнийСрок, ");
Список.ТекстЗапроса = НовыйТекст;
КонецПроцедуры
Важный нюанс: Если в основной конфигурации динамический список имеет включенное свойство Автозаполнение, платформа может подхватить новые поля автоматически. Однако для полной уверенности и возможности управления порядком полей, ручная правка запроса является более надежной.
После того как данные появились в источнике (динамическом списке), их нужно отобразить. Для этого мы создаем элементы формы типа ПолеФормы с видом ПолеНадписи или ПолеВвода.
Проанализируем процедуру создания элементов:
&НаСервере
Процедура СоздатьЭлементыФормы()
// Создаем колонку "Приоритет"
// Используем метод Вставить, чтобы указать точное местоположение (например, перед колонкой ТекущийИсполнитель)
НоваяКолонка = Элементы.Вставить("СписокЧисловойПриоритет", Тип("ПолеФормы"), Элементы.Список, Элементы.ТекущийИсполнитель);
НоваяКолонка.ПутьКДанным = "Список.ЧисловойПриоритет"; // Связываем с полем динамического списка
НоваяКолонка.Заголовок = "Приоритет(Ч)";
НоваяКолонка.Вид = ВидПоляФормы.ПолеНадписи;
// Создаем колонку "Крайний срок"
НоваяКолонка = Элементы.Вставить("СписокКрайнийСрок", Тип("ПолеФормы"), Элементы.Список, Элементы.ТекущийИсполнитель);
НоваяКолонка.ПутьКДанным = "Список.КрайнийСрок";
НоваяКолонка.Заголовок = "Крайний срок";
НоваяКолонка.Вид = ВидПоляФормы.ПолеНадписи;
КонецПроцедуры
Обратите внимание на свойство ПутьКДанным. Оно должно строго соответствовать формату ИмяСписка.ИмяПоляЗапроса. Если вы ошибетесь в названии, колонка останется пустой или система выдаст ошибку при открытии формы.
Бывают случаи, когда код написан верно, отладчик показывает наличие данных в объекте Список (в коллекции Данные), но на экране пользователь видит пустоту. Рассмотрим причины, по которым это может происходить:
ПриСозданииНаСервере или даже ПриОткрытии. Если ваше расширение меняет запрос «ДО» того, как основная конфигурация его полностью перезапишет, ваши изменения будут утеряны.Если вы обнаружили, что текст запроса в ПриСозданииНаСервере меняется, но колонки пустые, попробуйте перенести логику модификации запроса в обработчик ПриОткрытииПосле или убедитесь, что вы используете правильную аннотацию (&После) для расширяемого метода.
Выясним причину на конкретном примере. Если в коде формы основной конфигурации в процедуре ПриОткрытии стоит жесткое присваивание:
Список.ТекстЗапроса = "ВЫБРАТЬ ... ";
...то любые ваши манипуляции в ПриСозданииНаСервере окажутся бесполезными. В этом случае правильный алгоритм действий будет следующим:
&НаСервере
Процедура МодифицироватьЗапросИКолонки()
// Проверяем, не затерт ли наш запрос
Если Найти(Список.ТекстЗапроса, "ЧисловойПриоритет") = 0 Тогда
Список.ТекстЗапроса = СтрЗаменить(Список.ТекстЗапроса, "itilprofИнциденты.КодЗавершения,", "itilprofИнциденты.КодЗавершения, itilprofИнциденты.ЧисловойПриоритет, ");
КонецЕсли;
// Проверяем наличие колонок, чтобы не создать дубли при повторном вызове
Если Элементы.Найти("СписокЧисловойПриоритет") = Неопределено Тогда
// Код создания элементов формы...
КонецЕсли;
КонецПроцедуры
Если ваша конфигурация построена на БСП (Библиотека Стандартных Подсистем), рекомендуется использовать встроенные методы для работы с динамическими списками. Это гарантирует, что настройки компоновщика будут обновлены корректно.
Рассмотрим использование метода ОбщегоНазначения.УстановитьСвойстваДинамическогоСписка. Этот метод помогает правильно инициализировать список после изменения его текста запроса или основной таблицы:
&НаСервере
Процедура ОбновитьСвойстваСписка()
СвойстваСписка = ОбщегоНазначения.СтруктураСвойствДинамическогоСписка();
СвойстваСписка.ТекстЗапроса = Список.ТекстЗапроса;
СвойстваСписка.ОсновнаяТаблица = "Документ.itilprofИнциденты";
СвойстваСписка.ДинамическоеСчитываниеДанных = Истина;
ОбщегоНазначения.УстановитьСвойстваДинамическогоСписка(Элементы.Список, СвойстваСписка);
КонецПроцедуры
Этот подход особенно полезен, если вы добавляете в запрос ЛЕВОЕ СОЕДИНЕНИЕ с другими таблицами. Без обновления свойств компоновщика 1С может некорректно обрабатывать отборы и сортировку по новым полям.
Резюмируем: Для стабильного отображения программных колонок в расширении всегда проверяйте, в какой момент и как модифицируется ТекстЗапроса. Если данные есть в отладке, но их нет на форме — ищите место, где платформа или программный код основной конфигурации перекрывает ваши настройки. Используйте аннотацию &После для событий, выполняющихся позже всего в жизненном цикле формы, и не забывайте связывать элементы через ПутьКДанным.