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