Когда мы работаем в 1С, часто возникает потребность в том, чтобы в различных списках, отчетах или, например, в списках связанных документов, видеть расширенное представление объекта, которое включало бы не только стандартные номер и дату, но и какую-либо ключевую информацию, например, имя поставщика. В нашем случае, пользователь столкнулся с задачей добавления названия поставщика из документа "Заказ поставщику" непосредственно в строковое представление этого документа, чтобы оно отображалось в связанных документах. Давайте разберем, как мы можем решить эту задачу, используя различные подходы, от прямого обращения к данным до стандартных механизмов платформы 1С. Мы рассмотрим два основных подхода: модификация представления в рамках пользовательской функции и системный способ через обработчики в модуле менеджера документа.
Сначала давайте проанализируем начальный запрос пользователя, который пытался добавить название поставщика в функцию ПредставлениеОбъектаДляВыводаВОтчет. Эта функция, по всей видимости, является пользовательской или частью какого-то общего модуля, отвечающего за формирование представления объектов в определенном контексте (например, для вывода в отчет или специальный список).
Изначально пользователь имел функцию, которая добавляла сумму и валюту к представлению объекта:
&НаСервере
Функция ПредставлениеОбъектаДляВыводаВОтчет(Выборка)
ПредставлениеОбъекта = Выборка.Представление;
МетаданныеОбъекта = Выборка.Ссылка.Метаданные;
Если ОбщегоНазначения.ЭтоДокумент(МетаданныеОбъекта) Тогда
Если (Выборка.СуммаДокумента <> 0) И (Выборка.СуммаДокумента <> NULL) Тогда
ПредставлениеОбъекта = ПредставлениеОбъекта + " " + НСтр("ru = 'на сумму'") + " " + Выборка.СуммаДокумента + " " + Выборка.Валюта;
КонецЕсли;
Иначе
ПредставлениеОбъекта = ПредставлениеОбъекта + " (" + ОбщегоНазначения.ПредставлениеОбъекта(МетаданныеОбъекта) + ")";
КонецЕсли;
Возврат ПредставлениеОбъекта;
КонецФункции
Чтобы добавить сюда название поставщика, мы можем использовать прямой доступ к реквизиту документа, если этот реквизит доступен в объекте Выборка.Ссылка. Пользователь нашел решение, которое мы рассмотрим.
Мы можем проверить тип документа и, если это "Заказ поставщику", получить объект ссылки и обратиться к его реквизиту, который хранит информацию о поставщике. Обычно этот реквизит называется Партнер или Поставщик.
Давайте посмотрим, как мы можем модифицировать исходную функцию, чтобы она включала название поставщика:
&НаСервере
Функция ПредставлениеОбъектаДляВыводаВОтчет(Выборка)
ПредставлениеОбъекта = Выборка.Представление;
МетаданныеОбъекта = Выборка.Ссылка.Метаданные;
Если ОбщегоНазначения.ЭтоДокумент(МетаданныеОбъекта) Тогда
// Добавляем сумму и валюту, как было изначально
Если (Выборка.СуммаДокумента <> 0) И (Выборка.СуммаДокумента <> NULL) Тогда
ПредставлениеОбъекта = ПредставлениеОбъекта + " " + НСтр("ru = 'на сумму'") + " " + Выборка.СуммаДокумента + " " + Выборка.Валюта;
КонецЕсли;
// Определяем тип документа и добавляем партнера
ТипДок = ТипЗнч(Выборка.Ссылка);
Если ТипДок = Тип("ДокументСсылка.ЗаказПоставщику") Тогда
// Если реквизит 'Партнер' есть в документе 'ЗаказПоставщику'
// мы можем обратиться к нему напрямую через ссылку.
// Получать объект полностью (Выборка.Ссылка.ПолучитьОбъект()) не всегда эффективно
// для получения одного реквизита, если он доступен напрямую из ссылки.
// Предположим, что Партнер доступен напрямую из ссылки, как в большинстве УФ-конфигураций.
// В противном случае, пришлось бы получать объект, что нежелательно для массовых операций.
ПоставщикДокумента = Выборка.Ссылка.Партнер;
ПредставлениеОбъекта = ПредставлениеОбъекта + " (" + ПоставщикДокумента + ")";
КонецЕсли;
Иначе
ПредставлениеОбъекта = ПредставлениеОбъекта + " (" + ОбщегоНазначения.ПредставлениеОбъекта(МетаданныеОбъекта) + ")";
КонецЕсли;
Возврат ПредставлениеОбъекта;
КонецФункции
В этом примере мы делаем следующее:
ТипЗнч(Выборка.Ссылка).ДокументСсылка.ЗаказПоставщику, мы обращаемся к реквизиту Партнер по ссылке (Выборка.Ссылка.Партнер) и добавляем его в строковое представление.Этот подход сработал для автора вопроса, как мы видим из его второго сообщения.
ТипДок = ТипЗнч(Выборка.Ссылка);
Если ТипДок = Тип("ДокументСсылка.ЗаказПоставщику") Тогда
ПартнерСсылка = Выборка.Ссылка;
ПартнерОбъект = ПартнерСсылка.ПолучитьОбъект(); // Здесь лучше обращаться напрямую к реквизиту ссылки, если возможно.
// Например, ПартнерСсылка.Партнер
//Сообщить(ПартнерОбъект.Партнер);
ПредставлениеОбъекта = ПредставлениеОбъекта + " " + ПартнерОбъект.Партнер + " " ;
КонецЕсли;
Важный момент: Мы видим, что автор использовал ПартнерСсылка.ПолучитьОбъект(). В общем случае, получать объект документа целиком для чтения одного реквизита из ссылки не всегда оптимально с точки зрения производительности, особенно если эта функция вызывается многократно. Если реквизит Партнер является непосредственно реквизитом документа и его значение доступно через ссылку (что обычно так для ссылочных типов), то мы можем написать Выборка.Ссылка.Партнер. Если же Партнер является реквизитом объекта, который в свою очередь имеет свойство Представление, то Выборка.Ссылка.Партнер.Представление или просто Выборка.Ссылка.Партнер (если платформа сама преобразует ссылку на партнера в его представление) будет работать.
Этот подход хорош, если вам нужно изменить представление только в одном конкретном месте, где вызывается ваша пользовательская функция. Однако, если требуется, чтобы название поставщика отображалось *везде*, где используется стандартное представление документа "Заказ поставщику" (например, в стандартных списках, других связанных документах, диалогах выбора), то нам понадобится более системное решение.
Наиболее гибким и рекомендованным способом для изменения строкового представления любого объекта 1С (документа, справочника) является использование специальных процедур в модуле менеджера объекта. Это процедуры ОбработкаПолученияПолейПредставления и ОбработкаПолученияПредставления.
Эти процедуры позволяют нам определить, какие поля из объекта будут участвовать в формировании его представления, а затем собрать из этих полей желаемую строку. Результат их работы будет использоваться платформой везде, где требуется получить стандартное строковое представление объекта.
Давайте разберем по шагам, как это реализовать для документа "Заказ поставщику".
Первым делом нам нужно указать платформе, какие реквизиты документа "Заказ поставщику" нам потребуются для формирования его представления. Это делается в процедуре ОбработкаПолученияПолейПредставления, которая размещается в модуле менеджера документа.
Перейдите в конфигуратор, найдите документ "ЗаказПоставщику", откройте его, затем откройте его "Модуль менеджера". Если такой процедуры там еще нет, создайте ее.
// В модуле менеджера документа "ЗаказПоставщику"
Процедура ОбработкаПолученияПолейПредставления(Поля, СтандартнаяОбработка)
// Отключаем стандартную обработку, чтобы полностью контролировать список полей
СтандартнаяОбработка = Ложь;
// Добавляем стандартные поля, которые обычно используются в представлении
Поля.Добавить("Дата");
Поля.Добавить("Номер");
// САМОЕ ВАЖНОЕ: Добавляем реквизит, который хранит информацию о поставщике.
// В большинстве типовых конфигураций для этого используется реквизит "Партнер".
// Убедитесь, что имя реквизита в вашем документе совпадает.
Поля.Добавить("Партнер");
// Если вам нужны другие поля, например, "СуммаДокумента" или "ВалютаДокумента",
// чтобы имитировать исходную функцию пользователя, мы можем добавить и их:
Поля.Добавить("СуммаДокумента");
Поля.Добавить("ВалютаДокумента");
КонецПроцедуры
Что мы здесь делаем:
СтандартнаяОбработка = Ложь. Это говорит платформе, что мы сами будем определять, какие поля использовать, и стандартный механизм автоматического определения полей нам не нужен.Поля имена реквизитов документа, значения которых нам понадобятся для формирования строкового представления. Обязательно добавляем Партнер (или как там называется реквизит, хранящий поставщика в вашем документе "ЗаказПоставщику"), а также Дата, Номер, и, при необходимости, СуммаДокумента, ВалютаДокумента.
После того как мы указали, какие поля нам нужны, следующим шагом будет непосредственно создание строки представления. Это делается в процедуре ОбработкаПолученияПредставления, которая также находится в модуле менеджера документа.
// В модуле менеджера документа "ЗаказПоставщику"
Процедура ОбработкаПолученияПредставления(Данные, Представление, СтандартнаяОбработка)
// Отключаем стандартную обработку
СтандартнаяОбработка = Ложь;
// Параметр "Данные" содержит структуру, ключами которой являются имена полей,
// добавленных в ОбработкаПолученияПолейПредставления, а значениями - их значения.
// Из этих данных формируем нужную нам строку.
Представление = "Заказ поставщику " + Данные.Номер + " от " + Формат(Данные.Дата, "ДФ=dd.MM.yyyy");
// Добавляем название поставщика
Если ЗначениеЗаполнено(Данные.Партнер) Тогда
Представление = Представление + " (" + Данные.Партнер + ")";
КонецЕсли;
// Добавляем сумму и валюту, если они были запрошены и заполнены
Если ЗначениеЗаполнено(Данные.СуммаДокумента) И ЗначениеЗаполнено(Данные.ВалютаДокумента) И Данные.СуммаДокумента <> 0 Тогда
Представление = Представление + ", на сумму " + Формат(Данные.СуммаДокумента, "ЧДЦ=2") + " " + Данные.ВалютаДокумента;
КонецЕсли;
КонецПроцедуры
В этой процедуре:
СтандартнаяОбработка = Ложь.Данные содержит структуру, в которой мы можем получить значения всех реквизитов, которые мы добавили в ОбработкаПолученияПолейПредставления.Представление, используя эти данные. Здесь мы собираем номер, дату, а затем добавляем название партнера (поставщика). Мы также добавили проверку ЗначениеЗаполнено(Данные.Партнер), чтобы избежать пустых скобок, если по какой-то причине партнер не указан.После реализации этих двух процедур, любое место в 1С, где платформа будет запрашивать стандартное строковое представление документа "ЗаказПоставщику", будет возвращать строку, включающую название поставщика, например: "Заказ поставщику 000000001 от 15.03.2024 (ООО 'Прогресс')".
При использовании обработчиков ОбработкаПолученияПолейПредставления и ОбработкаПолученияПредставления, мы должны учитывать несколько важных моментов:
Критически важно правильно указать имя реквизита, который хранит информацию о поставщике. В различных конфигурациях 1С этот реквизит может называться по-разному. Чаще всего это Партнер, Контрагент или Поставщик. Мы можем выяснить точное имя, открыв документ "Заказ поставщику" в конфигураторе и посмотрев список его реквизитов.
Если мы хотим сделать решение более универсальным для разных документов, как пытался сделать пользователь в сообщении 5, мы можем использовать метаданные для проверки наличия реквизита. Однако, прямо в обработчиках представления мы работаем с конкретным документом, поэтому жесткое указание имени реквизита допустимо. Для более универсальных функций (как ПредставлениеОбъектаДляВыводаВОтчет) можно было бы использовать подход, предложенный в сообщениях 5 и 7:
// В какой-либо общей функции, проверяющей реквизиты объекта
Если МетаданныеОбъекта.Реквизиты.Найти("Поставщик") <> Неопределено Тогда
// Реквизит "Поставщик" существует
// ... дальнейшая логика ...
КонецЕсли;
Однако, для ОбработкаПолученияПолейПредставления и ОбработкаПолученияПредставления, которые находятся в модуле менеджера конкретного документа, мы уже знаем структуру документа, поэтому можем прямо указать имя реквизита.
Внутри процедуры ОбработкаПолученияПредставления крайне не рекомендуется выполнять запросы к базе данных или получать объекты целиком (например, Ссылка.ПолучитьОбъект()), если эти данные уже не были получены через ОбработкаПолученияПолейПредставления. Эти процедуры могут вызываться очень часто (например, при формировании больших списков), и лишние обращения к базе данных сильно замедлят работу системы.
Именно поэтому мы сначала указываем все необходимые поля в ОбработкаПолученияПолейПредставления, а затем оперируем уже полученными значениями в ОбработкаПолученияПредставления.
В отличие от модификации одной конкретной функции (как в Подходе 1), использование обработчиков в модуле менеджера изменяет *системное* представление документа. Это означает, что в любом месте конфигурации, где будет использоваться стандартное строковое представление "Заказа поставщику", будет отображаться наше расширенное представление с названием поставщика.
Если после реализации этих процедур представление не меняется, мы должны:
ОбработкаПолученияПолейПредставления и ОбработкаПолученияПредставления).СтандартнаяОбработка = Ложь установлена в обеих процедурах.Партнер) указано корректно и действительно присутствует в документе.
Мы успешно разобрали, как добавить название поставщика в представление документа "Заказ поставщику". В большинстве случаев, использование стандартных обработчиков ОбработкаПолученияПолейПредставления и ОбработкаПолученияПредставления является предпочтительным, поскольку обеспечивает системное и единообразное отображение информации по всей конфигурации. Это позволяет значительно улучшить информативность интерфейса для пользователей, облегчая работу со связанными документами и отчетами.