При разработке в среде 1С:Предприятие 8.3 (особенно в типовых конфигурациях, таких как УТ 11, КА 2, ERP) программисты часто сталкиваются со следующей проблемой. В расширении конфигурации для формы списка справочника (например, «Партнеры») через визуальный редактор изменяется запрос динамического списка — добавляется новое поле (пусть даже простая заглушка вида 12 КАК Тест12). Однако после запуска режима «1С:Предприятие» новая колонка на форме не появляется.
В этой статье мы подробно разберем, почему возникает такое поведение платформы, и рассмотрим два эффективных способа решения проблемы с примерами готового кода.
Проанализируем логику работы типовых конфигураций БСП (Библиотеки стандартных подсистем). Для оптимизации быстродействия и гибкой настройки интерфейса разработчики фирмы «1С» закладывают программное формирование текстов запросов для ключевых динамических списков.
В момент открытия формы срабатывает обработчик ПриСозданииНаСервере. Внутри него вызываются процедуры общих модулей (например, ПартнерыИКонтрагенты.ПартнерыФормаВыбораСпискаПриСозданииНаСервере), которые полностью перезаписывают свойство Список.ТекстЗапроса динамического списка. В результате все изменения, которые вы внесли в запрос интерактивно через расширение формы, просто заменяются стандартным шаблоном запроса, генерируемым системой на лету.
Соответственно, чтобы наше поле гарантированно отобразилось на форме, нам необходимо внедрить его в запрос программным путем.
---
Самый надежный способ вернуть наше поле на форму — перехватить управление сразу после того, как отработал типовой механизм формирования запроса. Мы сделаем это в модуле формы расширения с помощью аннотации &После.
Для безопасной и корректной вставки полей в динамический запрос рекомендуется использовать объект СхемаЗапроса. Это позволит избежать ошибок синтаксиса, которые часто возникают при банальном сложении строк.
Рассмотрим по шагам реализацию данного метода:
ПриСозданииНаСервере с директивой &После.СхемаЗапроса для безопасного добавления полей и связей (если поле берется из другой таблицы).Посмотрим на пример кода, который реализует этот алгоритм:
&НаСервере
&После("ПриСозданииНаСервере")
Процедура Расш1_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)
// Получаем текущий текст запроса, который уже был сформирован типовым кодом
ТекстЗапросаДинамическогоСписка = Список.ТекстЗапроса;
// Инициализируем схему запроса
СхемаЗапроса = Новый СхемаЗапроса;
СхемаЗапроса.УстановитьТекстЗапроса(ТекстЗапросаДинамическогоСписка);
// Получаем первый пакет запроса и его первый оператор (ВЫБРАТЬ...)
ПакетЗапросов = СхемаЗапроса.ПакетЗапросов[0];
ОператорВыбора = ПакетЗапросов.Операторы[0];
// Добавим наше тестовое поле. Например, числовую константу с псевдонимом "Тест12"
НовоеПоле = ОператорВыбора.ВыбираемыеПоля.Добавить("12");
НовоеПоле.Псевдоним = "Тест12";
// Возвращаем измененный текст запроса обратно в динамический список
Список.ТекстЗапроса = СхемаЗапроса.ПолучитьТекстЗапроса();
// Теперь необходимо программно добавить элемент на форму (колонку таблицы),
// так как интерактивно добавленная колонка может не пройти валидацию путей к данным
ИмяЭлементаКолонки = "СписокТест12";
Если Элементы.Найти(ИмяЭлементаКолонки) = Неопределено Тогда
НоваяКолонка = Элементы.Добавить(ИмяЭлементаКолонки, Тип("ПолеФормы"), Элементы.Список);
НоваяКолонка.Вид = ВидПоляФормы.ПолеНадписи;
НоваяКолонка.ПутьКДанным = "Список.Тест12";
НоваяКолонка.Заголовок = "Тестовое число";
КонецЕсли;
КонецПроцедуры
---
Если ваша задача состоит в том, чтобы вывести для каждого контрагента или партнера сложные динамические данные (например, «Дату последнего взаимодействия» или «Сумму текущего долга»), прямое левое соединение в основном запросе списка может существенно замедлить его работу.
Начиная с платформы 8.3.10, разработчики рекомендуют использовать событие таблицы списка ПриПолученииДанныхНаСервере. Этот подход позволяет получать дополнительные данные порционно — исключительно для тех строк, которые в данный момент отображаются на экране пользователя (обычно 30–40 строк).
Разберем, как реализовать этот высокопроизводительный метод по шагам:
Шаг 1. Добавим в динамический список «заглушку» для будущего поля. В режиме конфигуратора в запросе динамического списка (в расширении) добавим поле пустого типа:
ВЫБРАТЬ
...,
ДАТАВРЕМЯ(1, 1, 1) КАК ДатаПоследнегоВзаимодействия
ИЗ
Справочник.Партнеры КАК Партнеры
Добавим эту колонку на форму и укажем ее путь к данным: Список.ДатаПоследнегоВзаимодействия.
Шаг 2. Создадим событие ПриПолученииДанныхНаСервере для таблицы формы (в свойствах элемента формы «Список»):
&НаСервереБезКонтекста
Процедура СписокПриПолученииДанныхНаСервере(ИмяЭлемента, Настройки, Строки)
// Получаем массив ключей (ссылок на Партнеров), отображаемых на экране в данный момент
МассивПартнеров = Строки.ПолучитьКлючи();
Если МассивПартнеров.Количество() = 0 Тогда
Возврат;
КонецЕсли;
// Выполняем точечный и быстрый запрос к регистру сведений взаимодействий
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| КонтактыВзаимодействия.Партнер КАК Партнер,
| МАКСИМУМ(КонтактыВзаимодействия.Дата) КАК ДатаПоследнегоВзаимодействия
|ИЗ
| РегистрСведений.КонтактыВзаимодействия КАК КонтактыВзаимодействия
|ГДЕ
| КонтактыВзаимодействия.Партнер В (&МассивПартнеров)
|СГРУППИРОВАТЬ ПО
| КонтактыВзаимодействия.Партнер";
Запрос.УстановитьПараметр("МассивПартнеров", МассивПартнеров);
Выборка = Запрос.Выполнить().Выбрать();
// Обходим выборку и заполняем данные только для видимых строк списка
Пока Выборка.Следующий() Цикл
СтрокаСписка = Строки[Выборка.Партнер];
СтрокаСписка.Данные["ДатаПоследнегоВзаимодействия"] = Выборка.ДатаПоследнегоВзаимодействия;
КонецЦикла;
КонецПроцедуры
Благодаря этому подходу база данных не перегружается тяжелыми выборками по всему справочнику партнеров. Запрос выполняется мгновенно, гарантируя максимальный комфорт при работе пользователей со списками.
Если добавленное вами поле не отображается в динамическом списке типовой конфигурации 1С:
Список.ТекстЗапроса программно в общем модуле при создании формы.СхемаЗапроса в обработчике формы &После("ПриСозданииНаСервере").ПриПолученииДанныхНаСервере — это убережет вашу систему от зависаний при прокрутке списков.