При вызове функций и процедур модуля одного документа из другого разработчики на платформе 1С 7.7 часто сталкиваются с ошибкой «Поле агрегатного объекта не обнаружено». Попробуем разберем, почему штатный вызов через точку от объекта СоздатьОбъект("Документ.ИмяДокумента") не работает и какими способами можно правильно организовать выполнение кода.
В отличие от более новых версий 1С (8.x), где у каждого документа есть отдельный модуль объекта и модуль формы, в платформе 1С 7.7 код документа располагается исключительно в Модуле формы.
Когда в коде создается объект документа через функцию СоздатьОбъект():
ДокЧек = СоздатьОбъект("Документ.ТоварныйЧек");
ДокЧек.Новый();
// Попытка вызвать экспортную процедуру приведет к ошибке!
ДокЧек.ПробитьЧекНаККМ();
Платформа инициализирует только прикладную объектную переменную для записи в базу данных. Сам модуль формы при этом не загружается в память, а контекст формы не создается. Соответственно, экспортные процедуры формы остаются недоступными через объект ДокЧек.
Рассмотрим основные и наиболее эффективные варианты решения этой проблемы.
Самым правильным и стандартным архитектурным решением в 1С 7.7 является вынос логики, не связанной с элементами диалога формы, в Глобальный модуль. Если алгоритм должен вызываться как при интерактивной работе, так и при программном создании документов, создадим экспортную процедуру в Глобальном модуле.
Посмотрим на пример реализации процедур:
Процедура глПробитьЧекНаККМ(КонтекстДокумента) Экспорт
// Логика работы с ККМ и реквизитами документа
// Пример обращения к реквизиту: КонтекстДокумента.СуммаДок
КонецПроцедуры
Контекст:
Процедура ПробитьЧек()
глПробитьЧекНаККМ(Контекст);
КонецПроцедуры
ДокЧек = СоздатьОбъект("Документ.ТоварныйЧек");
ДокЧек.Новый();
ДокЧек.Записать();
глПробитьЧекНаККМ(ДокЧек);
Если код привязан к форме и его невозможно перенести в Глобальный модуль без существенной переработки, используется механизм передачи параметров при вызове функции ОткрытьФорму().
Рассмотрим алгоритм работы без визуального показа окна пользователю:
Перем Конт;
СписокПараметров = СоздатьОбъект("СписокЗначений");
СписокПараметров.Установить("РежимАвтоВыполнения", 1);
ОткрытьФорму("Документ.ТоварныйЧек", СписокПараметров, Конт);
ПриОткрытии() и предотвращаем визуальное открытие окна при помощи СтатусВозврата(0):
Процедура ПриОткрытии()
Парам = Форма.Параметр;
Если ТипЗначенияСтр(Парам) = "СписокЗначений" Тогда
Если Парам.Получить("РежимАвтоВыполнения") = 1 Тогда
// Выполняем требуемый алгоритм
ПробитьЧекНаККМ();
// Предотвращаем физическое открытие окна формы
СтатусВозврата(0);
Возврат;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Оператор СтатусВозврата(0) позволяет полностью отменить отрисовку окна документа на экране, избегая эффекта "мелькания" интерфейса, при этом весь код внутри ПриОткрытии() выполняется корректно.
Если форму документа необходимо оставить открытой или временно инициализировать, доступ к её экспортным процедурам можно получить через переменную контекста, переданную в ОткрытьФорму():
Перем Конт;
// Открываем форму существующего или нового документа
Если ОткрытьФорму(ДокОбъект.ТекущийДокумент(), Конт) = 1 Тогда
// Вызываем экспортную процедуру модуля формы через контекст
Конт.ПробитьЧекНаККМ();
// Закрываем форму при необходимости
Конт.Форма.Закрыть(0);
КонецЕсли;
Если в конфигурации используются внешние компоненты, такие как 1С++ или FormEx, выполнить процедуру в контексте формы можно с помощью специализированных методов.
Пример использования компоненты FormEx и сервиса выполнения процедур:
Перем Конт;
Сервис = СоздатьОбъект("Сервис");
Если ОткрытьФорму("Документ.ТоварныйЧек", Конт) = 1 Тогда
СписокАргументов = СоздатьОбъект("СписокЗначений");
СписокАргументов.ДобавитьЗначение("Параметр1");
// Вызов процедуры модуля формы по имени
Сервис.ВыполнитьПроцедуру(Конт, "ПробитьЧекНаККМ", СписокАргументов);
КонецЕсли;
Также при включении механизма TurboBL через УправлениеНастройками компоненты 1С++ становится доступен прямой вызов процедур модуля формы через переданную переменную контекста: Конт.ИмяПроцедуры().
Для создания чистого и поддерживаемого кода в 1С 7.7 старайтесь отделять бизнес-логику работы с данными от интерфейса формы. Самым надежным решением является перенос общих алгоритмов в Глобальный модуль или вынесение общего кода во внешние обработки (файлы .ert).