Разработка и Конфигурация · 12 мин
Как обратиться к объекту в модуле менеджера в 1С
Как правильно обратиться к объекту из модуля менеджера в 1С: Менеджеры.ПолучитьСсылку, объектные методы, типичные ошибки и примеры кода на встроенном языке.
Модуль менеджера в 1С — это контекст, который работает на уровне коллекции объектов (справочника, документа, регистра), а не конкретного элемента. Из-за этого у начинающих разработчиков возникает типичная проблема: они пытаются обратиться к реквизитам или методам конкретного объекта так, будто находятся в модуле объекта, и получают ошибку «Поле объекта не обнаружено». Понимание разницы между ссылкой, объектом и менеджером — ключ к правильной работе.
Обратиться к конкретному объекту из модуля менеджера можно только через ссылку: сначала получают ссылку на элемент (по GUID, запросом или из параметра), затем вызывают метод ПолучитьОбъект(), и только после этого доступны реквизиты, табличные части и объектные методы. Прямой доступ к данным элемента из контекста менеджера невозможен — это архитектурное ограничение платформы.
Ниже разобраны способы получения ссылки, загрузки объекта, обращения к его реквизитам и методам, а также типичные ошибки, которые приводят к падению кода или к проблемам с производительностью.
Чем модуль менеджера отличается от модуля объекта
Модуль менеджера выполняется в контексте менеджера прикладного объекта — программной сущности, которая управляет всей коллекцией: созданием элементов, поиском, получением ссылок, формированием печатных форм. Здесь доступны обращения вида Справочники.Номенклатура, Документы.РеализацияТоваровУслуг, перечисления и общие модули.
Модуль объекта, напротив, выполняется в контексте конкретного экземпляра: внутри него доступны ЭтотОбъект, реквизиты и табличные части напрямую, а также события ПередЗаписью, ПриЗаписи, ОбработкаПроведения. Переменные и методы, объявленные в модуле объекта с директивой Экспорт, становятся доступны снаружи только через сам объект.
Практическое следствие: код вида ЭтотОбъект.Реквизит или обращение к реквизиту без ссылки в модуле менеджера не скомпилируется или вызовет ошибку исполнения. Менеджер «не знает», о каком элементе идёт речь, пока вы явно не передадите ссылку.
Как получить ссылку на объект в модуле менеджера
Первый шаг всегда один — получить ссылку. Есть несколько рабочих способов в зависимости от того, что известно об элементе.
Если известен уникальный идентификатор, используйте ПолучитьСсылку():
УникальныйИд = Новый УникальныйИдентификатор("a1b2c3d4-...");
СсылкаНаЭлемент = Справочники.Номенклатура.ПолучитьСсылку(УникальныйИд);
Если СсылкаНаЭлемент.ПолучитьОбъект() = Неопределено Тогда
// Элемента с таким GUID в базе нет
КонецЕсли;
Если элемент нужно найти по реквизитам, используйте методы менеджера НайтиПоКоду(), НайтиПоНаименованию(), НайтиПоРеквизиту() для справочников или НайтиПоНомеру() для документов. Для сложных условий отбора применяйте запрос:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| Номенклатура.Ссылка КАК Ссылка
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Артикул = &Артикул
| И НЕ Номенклатура.ПометкаУдаления";
Запрос.УстановитьПараметр("Артикул", ИскомыйАртикул);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
СсылкаНаЭлемент = Выборка.Ссылка;
КонецЕсли;
Если ссылка пришла как параметр процедуры модуля менеджера (например, из формы списка или из другого куска кода), дополнительно получать её не нужно — переходите сразу к загрузке объекта.
Как загрузить объект и обратиться к его реквизитам
После получения ссылки есть два пути работы с данными, и выбор между ними влияет на производительность.
Если нужно только прочитать реквизиты, объект загружать не обязательно — обращайтесь через ссылку: Наименование = СсылкаНаЭлемент.Наименование;. Платформа сама выполнит чтение нужных полей. Это быстрее и не блокирует данные.
Если нужно изменить данные, вызвать экспортную процедуру объекта или записать элемент, загрузите объект методом ПолучитьОбъект():
ЭлементОбъект = СсылкаНаЭлемент.ПолучитьОбъект();
Если ЭлементОбъект = Неопределено Тогда
ВызватьИсключение "Элемент не найден в базе данных";
КонецЕсли;
ЭлементОбъект.Наименование = "Новое наименование";
ЭлементОбъект.ДополнительныйРеквизит = Значение;
ЭлементОбъект.Записать();
После ПолучитьОбъект() доступны все реквизиты, табличные части и экспортные методы модуля объекта. Например, если в модуле объекта справочника объявлена процедура Процедура ПересчитатьИтоги() Экспорт, из модуля менеджера она вызывается так: ЭлементОбъект.ПересчитатьИтоги();.
- 1Получите ссылку: через ПолучитьСсылку(), НайтиПоКоду(), запрос или параметр процедуры
- 2Проверьте, что ссылка не пустая и элемент существует
- 3Вызовите Ссылка.ПолучитьОбъект() и проверьте результат на Неопределено
- 4Измените реквизиты или вызовите экспортные методы объекта
- 5Выполните Записать() и убедитесь в отсутствии исключений
Когда объект получать не нужно: чтение через ссылку и запросы
Частая ошибка — вызывать ПолучитьОбъект() ради простого чтения пары реквизитов. Это создаёт лишнюю нагрузку: объект целиком загружается в память, а при параллельной работе пользователей возможны конфликты блокировок при последующих записях.
Для чтения реквизитов одного элемента достаточно обращения через точку: Артикул = СсылкаНаЭлемент.Артикул;. Для чтения данных множества элементов всегда используйте запрос — он выполняется на сервере СУБД и не создаёт объектов в памяти.
Табличные части через ссылку недоступны: обращение СсылкаНаЭлемент.Товары для документа вернёт пустую коллекцию. Если нужны строки табличной части — либо запрос к таблице Документ.РеализацияТоваровУслуг.Товары, либо ПолучитьОбъект().
Ссылка, объект или запрос — что выбрать
Нужно прочитать несколько реквизитов одного элемента. Быстро, без загрузки объекта. Не подходит для табличных частей и изменений.
Нужно изменить данные, записать элемент или вызвать экспортный метод объекта. Затратно по памяти, требует проверки на Неопределено.
Нужно прочитать данные многих элементов или табличные части без изменения. Максимально производительно, но только для чтения.
Обращение к методам объекта и экспортным процедурам
Экспортные процедуры и функции модуля объекта доступны только через загруженный объект. Если попытаться вызвать их через менеджер (Справочники.Номенклатура.МояПроцедура()), платформа сообщит, что метод не обнаружен, — менеджер и объект имеют разные интерфейсы.
Правильная последовательность выглядит так:
ОбъектНоменклатуры = СсылкаНаЭлемент.ПолучитьОбъект();
Если ОбъектНоменклатуры <> Неопределено Тогда
Результат = ОбъектНоменклатуры.РассчитатьЦену(ДатаЦены);
КонецЕсли;
Если логика не требует данных конкретного элемента (например, формирование печатной формы по массиву ссылок, заполнение по умолчанию), её правильнее размещать именно в модуле менеджера как экспортную процедуру — тогда она доступна через Справочники.Номенклатура.ИмяПроцедуры() из любого места конфигурации.
Для создания нового элемента из модуля менеджера используйте методы менеджера: Справочники.Номенклатура.СоздатьЭлемент(), Документы.РеализацияТоваровУслуг.СоздатьДокумент(). Они возвращают новый объект, который заполняется и записывается обычным образом.
НовыйЭлемент = Справочники.Номенклатура.СоздатьЭлемент();
НовыйЭлемент.Наименование = "Новая позиция";
НовыйЭлемент.Записать();
НоваяСсылка = НовыйЭлемент.Ссылка;Типичные ошибки и как их избежать
Самая частая ошибка — обращение к реквизиту без загрузки объекта там, где требуется изменение: присвоение СсылкаНаЭлемент.Наименование = "..." вызывает ошибку, потому что ссылка доступна только для чтения. Второе место занимает отсутствие проверки на Неопределено после ПолучитьОбъект() — при битой ссылке код падает с невнятным сообщением.
Отдельная группа проблем — производительность: вызов ПолучитьОбъект() внутри цикла по сотням элементов резко замедляет выполнение и может вызвать таймауты в клиент-серверном режиме. Если в цикле нужно только чтение, перепишите логику на запрос; если изменение — рассмотрите пакетную обработку с транзакциями.
Также помните про права: модуль менеджера выполняется на сервере, и если у пользователя нет прав на изменение объекта, Записать() вызовет исключение. В регламентных заданиях код выполняется от имени служебного пользователя — проверяйте его права отдельно.
Как проверить, что обращение к объекту сработало корректно
После записи объекта убедитесь, что изменения реально попали в базу. Самый простой способ — повторное чтение реквизита через ссылку или запрос и сравнение с ожидаемым значением. В отладчике проверьте, что ПолучитьОбъект() вернул не Неопределено, а после Записать() не возникло исключения.
При работе в транзакции помните: до фиксации транзакции изменения видны только внутри неё. Если после записи другой фрагмент кода не видит новых данных, проверьте, не откатилась ли транзакция из-за исключения ниже по коду.
Как проверить результат
Возвращён объект, реквизиты читаются
Возвращено Неопределено — элемент не существует или ссылка битая
Повторное чтение через ссылку возвращает новое значение
Читается старое значение — запись не выполнилась или транзакция откачена
Используется запрос или разумное число ПолучитьОбъект()
ПолучитьОбъект() на каждой итерации большого цикла — риск таймаута
Частые вопросы
Почему в модуле менеджера недоступен ЭтотОбъект?
Модуль менеджера выполняется в контексте менеджера коллекции, а не конкретного элемента. Переменная ЭтотОбъект существует только в модуле объекта и в модуле формы. В модуле менеджера работайте через ссылки и ПолучитьОбъект().
Можно ли из модуля менеджера вызвать процедуру модуля объекта?
Да, если процедура объявлена с директивой Экспорт в модуле объекта. Сначала получите объект через Ссылка.ПолучитьОбъект(), затем вызовите метод: Объект.ИмяПроцедуры(). Через менеджер напрямую вызвать её нельзя.
Чем отличается ПолучитьСсылку() от НайтиПоКоду()?
ПолучитьСсылку() формирует ссылку по уникальному идентификатору и не проверяет существование элемента. НайтиПоКоду() выполняет поиск в базе и возвращает пустую ссылку, если элемент не найден. Для проверки существования надёжнее поиск или запрос.
Почему Ссылка.Товары возвращает пустую таблицу?
Табличные части не загружаются при обращении через ссылку — платформа читает только реквизиты шапки. Получите объект через ПолучитьОбъект() или выберите строки запросом к таблице табличной части.
Где правильно размещать код: в модуле менеджера или в модуле объекта?
Логику, относящуюся к конкретному элементу (проверки, пересчёты, обработчики записи), размещайте в модуле объекта. Операции над коллекцией — поиск, создание, печатные формы по списку ссылок, массовые обработки — в модуле менеджера. Общую логику, не привязанную к типу, выносите в общие модули.
Как из модуля менеджера обратиться к объекту другого типа, например к документу из справочника?
Точно так же: через соответствующий менеджер. Например, Документы.РеализацияТоваровУслуг.НайтиПоНомеру(...) вернёт ссылку, далее — ПолучитьОбъект() и работа с реквизитами. Ограничений по типам между модулями менеджеров нет.
Что важно запомнить
Из модуля менеджера объект доступен только через ссылку: получите ссылку, при необходимости изменений вызовите ПолучитьОбъект() с проверкой на Неопределено, для чтения используйте ссылку или запрос. Не вызывайте ПолучитьОбъект() в больших циклах и всегда проверяйте результат записи.