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