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