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