Как передать элемент или значение из управляемой формы в общий модуль 1С

Программист 1С v8.3 (Управляемые формы) 1С:Зарплата и Управление Персоналом IT и автоматизация бизнеса
← На главную

При разработке в среде 1С:Предприятие 8.3 программисты часто сталкиваются с необходимостью передать данные из конкретной формы (например, карточки сотрудника) в общий модуль, где сосредоточена бизнес-логика или алгоритмы печати. Основная сложность заключается в разграничении контекстов: общий модуль «не знает», какая форма открыта у пользователя, пока мы явно не сообщим ему об этом, что усложняет анализ зависимостей в конфигурации.

В этой статье мы подробно разберем, почему возникает ошибка «Процедура или функция с указанным именем не определена» при попытке обращения к форме из модуля, выполним анализ на наличие подобных ошибок, и рассмотрим несколько архитектурно правильных способов решения этой задачи.

Причина проблемы: Изоляция контекстов

Разберем ситуацию, с которой столкнулся автор темы. В программном коде общего модуля была предпринята попытка вызвать функцию, написанную в модуле формы. Однако общий модуль — это самостоятельная единица. Он может вызывать только свои функции или функции других общих модулей (с флагом Экспорт). Он не имеет прямого доступа к методам и реквизитам открытых форм, так как форм одного типа может быть открыто несколько, или процедура вообще может быть вызвана в фоновом задании, где форм не существует вовсе.

Чтобы данные из формы попали в общий модуль, их нужно передать в качестве параметров вызова.

Способ 1. Передача конкретного значения через параметры

Это самый простой и правильный метод, если вам нужно передать одно или несколько конкретных значений (например, сумму оклада или ссылку на должность). Проанализируем, как изменить код для передачи значения оклада в процедуру печати.

Шаг 1. Изменение процедуры в общем модуле. Мы должны добавить в описание процедуры новый параметр, который будет принимать наше значение.


// В общем модуле (например, СотрудникиБазовый)
Процедура ПечатьКарточкиСотрудника(СсылкаНаОбъект, ДополнительныеПараметры = Неопределено) Экспорт
    
    Если ДополнительныеПараметры <> Неопределено Тогда
        Оклад = ДополнительныеПараметры.Оклад;
        // Используем полученный оклад в логике печати
    КонецЕсли;
    
    // ... остальной код
КонецПроцедуры

Шаг 2. Вызов из модуля формы. При вызове этой процедуры из формы мы подготавливаем данные и передаем их.


&НаСервере
Процедура ВыполнитьПечать()
    // Подготавливаем структуру с данными
    ПараметрыПечати = Новый Структура;
    ПараметрыПечати.Вставить("Оклад", Объект.ТекущаяДолжностьПоШтатному Расписанию.ОкладТариф);
    
    // Вызываем общий модуль, передавая структуру
    СотрудникиБазовый.ПечатьКарточкиСотрудника(Объект.Ссылка, ПараметрыПечати);
КонецПроцедуры

Способ 2. Передача всей формы как объекта

Иногда требуется передать слишком много реквизитов формы или вызвать экспортный метод самой формы из общего модуля. В этом случае в общий модуль можно передать саму форму (ссылку на объект УправляемаяФорма).

Рассмотрим пример, где общий модуль должен прочитать данные напрямую из реквизитов переданной формы:


// В общем модуле
Процедура ОбработатьДанныеФормы(ФормаОбъекта) Экспорт
    // Теперь мы можем обращаться к экспортным методам формы
    Данные = ФормаОбъекта.ПолучитьНужныеДанныеДляРасчета();
    
    // Или напрямую к реквизитам формы (ДанныеФормыСтруктура)
    Если ФормаОбъекта.ТолькоПросмотр Тогда
        Возврат;
    КонецЕсли;
КонецПроцедуры

Важно помнить: чтобы этот код работал, в модуле формы функция ПолучитьНужныеДанныеДляРасчета() должна быть помечена словом Экспорт. Также учитывайте, что форма доступна только в том контексте (Клиент/Сервер), в котором она существует.

Способ 3. Получение данных из базы данных (Архитектурный подход)

Как справедливо заметили участники обсуждения, привязка логики печати к данным формы — это «хрупкое» решение. Если печать будет запущена из списка сотрудников (где форма элемента не открыта), ваш код выдаст ошибку или не найдет данных.

Правильнее всего в общем модуле получать данные запросом, используя ссылку на объект, которая у вас уже есть. Выясним, как это реализовать на примере ЗУП 3.1.


// В общем модуле
Функция ПолучитьОкладСотрудника(СотрудникСсылка, ДатаСреза) Экспорт
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |	ТекущиеКадровыеДанныеСотрудников.ОкладТариф КАК Оклад
        |ИЗ
        |	РегистрСведений.ТекущиеКадровыеДанныеСотрудников КАК ТекущиеКадровыеДанныеСотрудников
        |ГДЕ
        |	ТекущиеКадровыеДанныеСотрудников.Сотрудник = &Сотрудник";
    
    Запрос.УстановитьПараметр("Сотрудник", СотрудникСсылка);
    
    РезультатЗапроса = Запрос.Выполнить();
    // Дальнейшая обработка результата...
КонецФункции

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

Способ 4. Использование временного хранилища

Если вам нужно передать из формы в общий модуль что-то объемное (например, двоичные данные или сложную таблицу значений), используйте ВременноеХранилище. Проанализируем последовательность действий:

  1. В модуле формы используем функцию ПоместитьВоВременноеХранилище(Данные, УникальныйИдентификатор). Она вернет адрес (строку).
  2. Передаем этот Адрес в общий модуль как обычную строку.
  3. В общем модуле извлекаем данные командой ПолучитьИзВременногоХранилища(Адрес).

Это избавляет от необходимости передавать «тяжелые» объекты между контекстами и гарантирует сохранность данных на время выполнения серверного вызова.

Резюме и рекомендации

Подводя итог, при возникновении ошибки видимости методов формы в общем модуле, следуйте этим правилам:

Соблюдение этих принципов позволит вам писать стабильный код, который не будет «ломаться» при обновлении конфигурации или изменении интерфейса пользователем.

← На главную