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

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

При разработке нетиповых механизмов подбора номенклатуры в системе 1С:Предприятие 8.3 (особенно в конфигурациях на управляемом интерфейсе, таких как «Бухгалтерия предприятия 3.0») программисты часто сталкиваются с необходимостью передать контекст из документа в открываемую форму подбора. Это может быть склад, подразделение, ответственное физическое лицо или определенный счет учета (например, забалансовый счет МЦ.02 для спецодежды).

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

В чем заключалась проблема автора темы?

Перед автором стояла задача: при нажатии кнопки «Подбор» в документе «Перемещение спецодежды» открыть внешнюю форму подбора (обработку) и автоматически заполнить в ней три параметра:

  1. Физ. лицо (из реквизита документа Объект.ФизЛицоОтправитель).
  2. Счет учета (предопределенный забалансовый счет учета спецодежды в эксплуатации — МЦ.02).
  3. Номенклатура (для фильтрации или сопоставления).

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

---

Анализ и исправление ключевых ошибок

Разберем основные ошибки, возникшие при написании кода, и методы их решения.

Ошибка 1: Попытка изменения коллекции «Параметры» текущей формы

В коде автора присутствовала следующая конструкция:


&НаКлиенте
Процедура ПодборСпецодежда(Команда)
    ОповещениеОЗакрытии = Новый ОписаниеОповещения("ПослеЗакрытияФормыПодбора", ЭтаФорма, Параметры);
    Параметры.Вставить("ФизЛицо", Объект.ФизЛицоОтправитель); // Ошибка здесь!
    ...
КонецПроцедуры

При выполнении этого кода система выдавала ошибку: Метод объекта не обнаружен (Вставить).

Выясним причину: В контексте модуля управляемой формы свойство Параметры — это системный объект типа ПараметрыФормы, содержащий параметры, с которыми была открыта текущая форма (в данном случае форма документа). Этот объект доступен только для чтения, и у него нет метода Вставить().

Решение: Для передачи данных в другую форму необходимо создать новый локальный объект типа Структура.


ПараметрыОткрытия = Новый Структура;
ПараметрыОткрытия.Вставить("ФизЛицо", Объект.ФизЛицоОтправитель);

Ошибка 2: Получение метаданных и предопределенных значений на клиенте

В попытках передать счет учета в параметры подбора автор написал следующий код:


Параметры2.Вставить("Счет", ПланыСчетов.Хозрасчетный.НайтиПоКоду("00000000011"));

Это привело к ошибке компиляции в тонком клиенте: Переменная не определена (ПланыСчетов).

Выясним причину: В управляемом приложении менеджеры объектов метаданных (такие как ПланыСчетов, Справочники, Документы) недоступны на тонком клиенте. Поиск по коду или обращение к предопределенным данным напрямую на клиенте невозможны.

Решение: Есть два пути решения этой проблемы.

Способ 1: Использование функции ПредопределенноеЗначение. Это самый быстрый и оптимальный способ получения предопределенных элементов непосредственно на клиенте без написания серверных функций.


ПараметрыОткрытия.Вставить("Счет", ПредопределенноеЗначение("ПланСчетов.Хозрасчетный.МЦ02"));

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


&НаКлиенте
Процедура ПодборСпецодежда(Команда)
    ...
    ПараметрыОткрытия.Вставить("Счет", ПолучитьСчетНаСервере());
    ...
КонецПроцедуры

&НаСервереБезКонтекста
Функция ПолучитьСчетНаСервере()
    Возврат ПланыСчетов.Хозрасчетный.НайтиПоКоду("МЦ.02");
КонецФункции

---

Правильный алгоритм передачи параметров

Проанализируем ситуацию и построим правильный сквозной пример передачи параметров из формы документа в форму нетиповой обработки подбора.

Шаг 1. Формирование и отправка параметров из формы документа

В модуле управляемой формы документа пишем обработчик команды открытия подбора:


&НаКлиенте
Процедура ПодборСпецодежда(Команда)
    
    // Создаем структуру для параметров открытия формы подбора
    ПараметрыОткрытия = Новый Структура;
    ПараметрыОткрытия.Вставить("ФизЛицо", Объект.ФизЛицоОтправитель);
    
    // Получаем счет МЦ.02 на клиенте
    СчетМЦ02 = ПредопределенноеЗначение("ПланСчетов.Хозрасчетный.МЦ02");
    ПараметрыОткрытия.Вставить("Счет", СчетМЦ02);
    
    // Описываем оповещение, которое сработает после закрытия формы подбора (если это необходимо)
    ОповещениеОЗакрытии = Новый ОписаниеОповещения("ПослеЗакрытияФормыПодбора", ЭтаФорма);
    
    // Открываем форму обработки подбора. 
    // Передаем параметры открытия во втором аргументе метода ОткрытьФорму!
    ОткрытьФорму(
        "Обработка.ПодборНоменклатуры1.Форма", 
        ПараметрыОткрытия, 
        ЭтаФорма, 
        Истина, 
        , 
        , 
        ОповещениеОЗакрытии, 
        РежимОткрытияОкнаФормы.БлокироватьОкноВладельца
    );
    
КонецПроцедуры

Шаг 2. Прием и обработка параметров в форме подбора

В модуле формы обработки подбора (в нашем случае это Обработка.ПодборНоменклатуры1.Форма) необходимо поймать переданные параметры в событии ПриСозданииНаСервере. Они автоматически попадают в системную коллекцию Параметры этой формы.

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


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

---

Архитектурная рекомендация: Как правильно возвращать данные в документ

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

ЭтаФорма.ВладелецФормы.объект.Спецодежда.Добавить()

Почему это плохая практика (антипаттерн)?

Как сделать правильно с использованием механизмов платформы?

Правильный подход заключается в использовании стандартного механизма оповещения о выборе. Форма подбора должна лишь вернуть структуру выбранных данных владельцу, а форму-владелец сама решает, в какую табличную часть и по каким правилам добавлять эти данные.

Посмотрим на пример правильной реализации:

Реализация в форме подбора:


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

Реализация в форме документа:

Чтобы документ поймал это оповещение, при открытии формы подбора в качестве владельца формы нужно указывать не саму форму (ЭтаФорма), а конкретный элемент управления — например, саму таблицу формы Элементы.Спецодежда. Тогда у этой таблицы сработает событие ОбработкаВыбора:


&НаКлиенте
Процедура ПодборСпецодежда(Команда)
    
    ПараметрыОткрытия = Новый Структура;
    ПараметрыОткрытия.Вставить("ФизЛицо", Объект.ФизЛицоОтправитель);
    ПараметрыОткрытия.Вставить("Счет", ПредопределенноеЗначение("ПланСчетов.Хозрасчетный.МЦ02"));
    
    // Передаем Элементы.Спецодежда третьим параметром (Владелец)
    ОткрытьФорму(
        "Обработка.ПодборНоменклатуры1.Форма", 
        ПараметрыОткрытия, 
        Элементы.Спецодежда
    );
    
КонецПроцедуры

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

Такой подход обеспечивает полную независимость (декаплинг) объектов метаданных друг от друга. Вашу обработку подбора теперь можно будет вызывать из любых других документов системы без изменения ее программного кода.

← На главную