Как при программном создании документа достучаться до процедур создаваемого документа в 1С 7.7?

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

При вызове функций и процедур модуля одного документа из другого разработчики на платформе 1С 7.7 часто сталкиваются с ошибкой «Поле агрегатного объекта не обнаружено». Попробуем разберем, почему штатный вызов через точку от объекта СоздатьОбъект("Документ.ИмяДокумента") не работает и какими способами можно правильно организовать выполнение кода.

Выясним причину: особенности архитектуры платформы 1С 7.7

В отличие от более новых версий 1С (8.x), где у каждого документа есть отдельный модуль объекта и модуль формы, в платформе 1С 7.7 код документа располагается исключительно в Модуле формы. Когда в коде создается объект документа через функцию СоздатьОбъект():


ДокЧек = СоздатьОбъект("Документ.ТоварныйЧек");
ДокЧек.Новый();
// Попытка вызвать экспортную процедуру приведет к ошибке!
ДокЧек.ПробитьЧекНаККМ();

Платформа инициализирует только прикладную объектную переменную для записи в базу данных. Сам модуль формы при этом не загружается в память, а контекст формы не создается. Соответственно, экспортные процедуры формы остаются недоступными через объект ДокЧек.

Рассмотрим основные и наиболее эффективные варианты решения этой проблемы.

Вариант 1. Перенос бизнес-логики в Глобальный модуль (рекомендуемый подход)

Самым правильным и стандартным архитектурным решением в 1С 7.7 является вынос логики, не связанной с элементами диалога формы, в Глобальный модуль. Если алгоритм должен вызываться как при интерактивной работе, так и при программном создании документов, создадим экспортную процедуру в Глобальном модуле.

Посмотрим на пример реализации процедур:

  1. В Глобальном модуле создаем процедуру, принимающую контекст документа:
    
    Процедура глПробитьЧекНаККМ(КонтекстДокумента) Экспорт
        // Логика работы с ККМ и реквизитами документа
        // Пример обращения к реквизиту: КонтекстДокумента.СуммаДок
    КонецПроцедуры
    
  2. В модуле формы документа вызываем глобальную процедуру, передавая ключевое слово Контекст:
    
    Процедура ПробитьЧек()
        глПробитьЧекНаККМ(Контекст);
    КонецПроцедуры
    
  3. При программном создании документа из внешнего источника или другого документа также вызываем эту процедуру, передавая объект документа:
    
    ДокЧек = СоздатьОбъект("Документ.ТоварныйЧек");
    ДокЧек.Новый();
    ДокЧек.Записать();
    глПробитьЧекНаККМ(ДокЧек);
    

Вариант 2. Использование контекста открываемой формы с параметрами

Если код привязан к форме и его невозможно перенести в Глобальный модуль без существенной переработки, используется механизм передачи параметров при вызове функции ОткрытьФорму().

Рассмотрим алгоритм работы без визуального показа окна пользователю:

  1. Вызываем открытие формы документа, передавая контекст и необходимые параметры:
    
    Перем Конт;
    СписокПараметров = СоздатьОбъект("СписокЗначений");
    СписокПараметров.Установить("РежимАвтоВыполнения", 1);
    
    ОткрытьФорму("Документ.ТоварныйЧек", СписокПараметров, Конт);
    
  2. В модуле формы вызываемого документа обрабатываем параметр в предопределенной процедуре ПриОткрытии() и предотвращаем визуальное открытие окна при помощи СтатусВозврата(0):
    
    Процедура ПриОткрытии()
        Парам = Форма.Параметр;
        Если ТипЗначенияСтр(Парам) = "СписокЗначений" Тогда
            Если Парам.Получить("РежимАвтоВыполнения") = 1 Тогда
                // Выполняем требуемый алгоритм
                ПробитьЧекНаККМ();
                
                // Предотвращаем физическое открытие окна формы
                СтатусВозврата(0);
                Возврат;
            КонецЕсли;
        КонецЕсли;
    КонецПроцедуры
    

Оператор СтатусВозврата(0) позволяет полностью отменить отрисовку окна документа на экране, избегая эффекта "мелькания" интерфейса, при этом весь код внутри ПриОткрытии() выполняется корректно.

Вариант 3. Вызов методов открытой формы через групповой контекст

Если форму документа необходимо оставить открытой или временно инициализировать, доступ к её экспортным процедурам можно получить через переменную контекста, переданную в ОткрытьФорму():


Перем Конт;
// Открываем форму существующего или нового документа
Если ОткрытьФорму(ДокОбъект.ТекущийДокумент(), Конт) = 1 Тогда
    // Вызываем экспортную процедуру модуля формы через контекст
    Конт.ПробитьЧекНаККМ();
    // Закрываем форму при необходимости
    Конт.Форма.Закрыть(0);
КонецЕсли;

Вариант 4. Использование компонентов расширения (1С++ / FormEx)

Если в конфигурации используются внешние компоненты, такие как 1С++ или FormEx, выполнить процедуру в контексте формы можно с помощью специализированных методов.

Пример использования компоненты FormEx и сервиса выполнения процедур:


Перем Конт;
Сервис = СоздатьОбъект("Сервис");

Если ОткрытьФорму("Документ.ТоварныйЧек", Конт) = 1 Тогда
    СписокАргументов = СоздатьОбъект("СписокЗначений");
    СписокАргументов.ДобавитьЗначение("Параметр1");
    
    // Вызов процедуры модуля формы по имени
    Сервис.ВыполнитьПроцедуру(Конт, "ПробитьЧекНаККМ", СписокАргументов);
КонецЕсли;

Также при включении механизма TurboBL через УправлениеНастройками компоненты 1С++ становится доступен прямой вызов процедур модуля формы через переданную переменную контекста: Конт.ИмяПроцедуры().

Итоги и рекомендации

Для создания чистого и поддерживаемого кода в 1С 7.7 старайтесь отделять бизнес-логику работы с данными от интерфейса формы. Самым надежным решением является перенос общих алгоритмов в Глобальный модуль или вынесение общего кода во внешние обработки (файлы .ert).

← На главную