Как передать строку из одного модуля в другой модуль в 1С 8.3 без использования глобальных переменных?

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

При переходе от обычного приложения к управляемому многие разработчики сталкиваются с трудностями понимания клиент-серверной архитектуры 1С. Попытка использовать привычные старые подходы — такие как глобальные переменные, объявленные с ключевым словом Экспорт в модуле формы, для передачи данных с сервера на клиент — неизбежно приводит к ошибкам. Одна из самых частых: "Значение не является значением объектного типа" при обращении к реквизитам или переменным формы.

В этой статье мы подробно разберем, почему возникает эта ошибка, проанализируем архитектурные ограничения платформы 1С 8.3 и рассмотрим четыре надежных и современных способа передачи данных между модулями.

Выясняем причину: почему рушится код с глобальной переменной?

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


// В модуле ОбщаяФорма.ПечатьДокументов
&НаКлиенте
Перем МояПеременная Экспорт;

И затем пытается записать туда значение из модуля менеджера:


// В модуле менеджера ОсновногоСредства
Ф = ПолучитьФорму("ОбщаяФорма.ПечатьДокументов");
Ф.МояПеременная = ПП; // Ошибка: Значение не является значением объектного типа (МояПеременная)

Давайте разберем по шагам, почему этот код принципиально неработоспособен в управляемом приложении:

  1. Разделение контекстов исполнения. Модуль менеджера выполняется строго на сервере. Код управляемой формы (а именно клиентские переменные, объявленные с директивой &НаКлиенте) физически существует только в оперативной памяти клиентского компьютера (в тонком или веб-клиенте). Сервер ничего не знает о существовании клиентской переменной конкретного открытого окна.
  2. Ограничения метода ПолучитьФорму. В управляемом приложении вызов ПолучитьФорму на сервере возвращает лишь серверный "объект-пустышку" (прокси), у которого нет доступа к клиентским переменным модуля. Попытка напрямую присвоить значение свойству Ф.МояПеременная вызывает закономерный отказ платформы, так как серверная проекция формы не содержит этого свойства.
  3. Отсутствие глобальных переменных на сервере. На сервере сеанс пользователя "безликий" и не сохраняет состояние переменных между вызовами. Даже если бы переменная была объявлена на сервере, она бы уничтожалась сразу после завершения серверного вызова.

Как же решить эту задачу правильно? Рассмотрим эффективные и стандартные способы передачи строки (в нашем примере — инвентарного номера) для формирования имени файла PDF.

---

Решение 1. Передача данных через параметры формы (Классический метод 1С)

Если вам необходимо открыть форму и передать в нее информацию, стандартный и самый чистый способ — использовать параметры формы. Вместо использования глобальных переменных в модуле формы мы создаем специальный реквизит, который будет хранить состояние.

Разберем этот процесс по шагам.

Шаг 1. Создание реквизита в форме-приемнике

Откройте форму ОбщаяФорма.ПечатьДокументов в конфигураторе. На вкладке "Реквизиты" создайте новый реквизит формы, например, ИнвентарныйНомер с типом Строка.

Шаг 2. Передача параметра при открытии формы на Клиенте

В форме-источнике (откуда вы хотите вызвать печать) мы подготавливаем структуру параметров и открываем форму:


&НаКлиенте
Процедура ОткрытьПечатьДокументов()
    
    // Формируем структуру параметров для передачи в форму
    ПараметрыОткрытия = Новый Структура;
    ПараметрыОткрытия.Вставить("ИнвентарныйНомер", "ОС-0000342");
    
    // Открываем форму, передавая структуру параметров
    ОткрытьФорму("ОбщаяФорма.ПечатьДокументов", ПараметрыОткрытия);
    
КонецПроцедуры

Шаг 3. Прием параметра в форме-приемнике на Сервере

При открытии формы срабатывает обработчик события ПриСозданииНаСервере. Именно здесь мы перехватываем переданное значение и записываем его в реквизит формы:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Проверяем, передан ли наш параметр
    Если Параметры.Свойство("ИнвентарныйНомер") Тогда
        // Заполняем реквизит формы, который теперь будет доступен везде
        Объект.ИнвентарныйНомер = Параметры.ИнвентарныйНомер;
    КонецЕсли;
    
КонецПроцедуры

Шаг 4. Использование значения на Клиенте

Теперь в любом клиентском методе формы ОбщаяФорма.ПечатьДокументов (включая процедуру сохранения в PDF) вы можете напрямую обращаться к этому реквизиту:


&НаКлиенте
Процедура СохранитьПечатныеФормыВПапку()
    
    // Читаем значение из реквизита формы
    ИмяФайла = "Карточка_" + СокрЛП(Объект.ИнвентарныйНомер) + ".pdf";
    ПолныйПуть = Папка + ИмяФайла;
    
    ДвоичныеДанные.Записать(ПолныйПуть);
    
КонецПроцедуры

---

Решение 2. Использование механизмов БСП (Рекомендуемый стандарт)

Если ваша конфигурация разработана на базе Библиотеки Стандартных Подсистем (БСП), то вам вообще не нужно вручную открывать общие формы и изобретать велосипед с передачей параметров. В БСП подсистема печати уже содержит встроенный функционал автоматического формирования имени файла для сохранения.

Проанализируем, как использовать свойство ИмяФайлаПечатнойФормы в процедуре печати модуля менеджера:


// В модуле менеджера вашего справочника или документа
Процедура Печать(МассивОбъектов, ПараметрыПечати, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
    
    // Проверяем, нужно ли формировать наш макет
    Если УправлениеПечатью.НужноПечататьМакет(КоллекцияПечатныхФорм, "ИнвентарнаяКарточка") Тогда
        
        // Формируем табличный документ стандартным методом
        ТабДок = СформироватьИнвентарнуюКарточку(МассивОбъектов);
        
        // Регистрируем документ в коллекции
        УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(
            КоллекцияПечатныхФорм, 
            "ИнвентарнаяКарточка", 
            "Инвентарная карточка ОС", 
            ТабДок
        );
        
        // Настраиваем имя файла по умолчанию для сохранения
        ПечатнаяФорма = УправлениеПечатью.СведенияОПечатнойФорме(КоллекцияПечатныхФорм, "ИнвентарнаяКарточка");
        Если ПечатнаяФорма <> Неопределено Тогда
            
            // Задаем соответствие имен файлов для каждого объекта
            ИменаФайлов = Новый Соответствие;
            Для Каждого Ссылка Из МассивОбъектов Цикл
                // Получаем инвентарный номер через БСП-функцию чтения реквизитов
                ИнвНомер = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Ссылка, "ИнвентарныйНомер");
                ИменаФайлов.Вставить(Ссылка, "Карточка_ОС_" + СокрЛП(ИнвНомер));
            КонецЦикла;
            
            // Передаем соответствие в БСП
            ПечатнаяФорма.ИмяФайлаПечатнойФормы = ИменаФайлов;
            
        КонецЕсли;
        
    КонецЕсли;
    
КонецПроцедуры

При таком подходе БСП самостоятельно передаст имя файла в общую форму печати документов. Когда пользователь решит сохранить печатную форму на диск или отправить по почте, система автоматически предложит корректное имя файла без написания сложного кода на клиенте.

---

Решение 3. Упрощенная подмена синонима макета в БСП

Если печатная форма всегда выводится в единственном экземпляре, есть еще более простой "лайфхак" в рамках БСП. Имя файла при сохранении по умолчанию формируется на основе синонима макета. Мы можем динамически изменить его прямо на сервере в модуле менеджера:


// В процедуре Печать модуля менеджера:
ТабДок = СформироватьИнвентарнуюКарточку(МассивОбъектов);

// Добавляем табличный документ в коллекцию
УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(
    КоллекцияПечатныхФорм, 
    "ИнвентарнаяКарточка", 
    "Инвентарная карточка ОС", 
    ТабДок
);

// Динамически переопределяем СинонимМакет для БСП
Для Каждого СтрокаКоллекции Из КоллекцияПечатныхФорм Цикл
    Если СтрокаКоллекции.ИмяМакета = "ИнвентарнаяКарточка" Тогда
        // Получаем инвентарный номер из объекта
        ИнвНомер = СокрЛП(МассивОбъектов[0].ИнвентарныйНомер);
        СтрокаКоллекции.СинонимМакета = "Карточка_ОС_№" + ИнвНомер;
    КонецЕсли;
КонецЦикла;

Когда откроется стандартная форма печати БСП, заголовок вкладки и дефолтное имя сохраняемого PDF-файла примут вид Карточка_ОС_№[Номер].pdf.

---

Решение 4. Прямая запись в PDF на сервере (без открытия интерактивных форм)

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


&НаСервере
Процедура СохранитьПечатнуюФормуНаДискНаСервере(СсылкаНаОбъект, ПутьКПапке)
    
    // 1. Получаем макет напрямую из менеджера объекта
    ТабДок = Справочники.ОсновныеСредства.ПолучитьМакетПечатнойФормы(СсылкаНаОбъект);
    
    // 2. Формируем уникальное имя файла на основе реквизитов
    ИнвентарныйНомер = СокрЛП(СсылкаНаОбъект.ИнвентарныйНомер);
    ИмяФайла = "Карточка_" + ИнвентарныйНомер + ".pdf";
    ПолныйПуть = ПутьКПапке + "\" + ИмяФайла;
    
    // 3. Записываем файл в формате PDF штатными средствами платформы
    ТабДок.Записать(ПолныйПуть, ТипФайлаТабличногоДокумента.PDF);
    
КонецПроцедуры

Этот метод работает молниеносно, не требует взаимодействия с клиентом, не расходует оперативную память на отрисовку окон и идеально подходит для автоматизации бизнес-процессов.

---

Подведем итоги и сформулируем правила разработки

Для создания надежных и производительных решений в управляемом приложении 1С 8.3 рекомендуем придерживаться следующих правил:

← На главную