Разработка и Конфигурация · 13 мин
Обработка заполнения в 1С: как передать параметр
Как передать параметры в обработку заполнения табличной части 1С: ПараметрыВыполненияКоманды, ДополнительныеПараметры, примеры кода и типичные ошибки.
Обработки заполнения табличных частей — один из самых востребованных механизмов доработки типовых конфигураций 1С. Почти в каждом проекте возникает задача: заполнить табличную часть документа не стандартным способом, а по своему алгоритму — из остатков, из другого документа, по произвольному отбору. И почти сразу встает вопрос: как передать в обработку параметры, чтобы один и тот же код работал по-разному в зависимости от выбора пользователя или контекста вызова.
Проблема в том, что типовой механизм подключаемых команд заполнения имеет ограниченный набор штатных параметров: ссылка на объект, тип команды, источник. Если нужно передать что-то свое — вид заполнения, дату среза, список складов, режим очистки — требуется знать несколько приемов: от использования свойства ДополнительныеПараметры до регистрации нескольких команд с разными идентификаторами.
Материал ориентирован на разработчиков, работающих с БСП (библиотека стандартных подсистем) в управляемых формах. Примеры применимы к конфигурациям на базе БСП: ERP, УТ, КА, БП и другим. Для обычных форм и самописных конфигураций без БСП принципы те же, но точки подключения отличаются — об этом тоже сказано отдельно.
Как устроен механизм команд заполнения в БСП
В конфигурациях на базе БСП обработки заполнения подключаются через подсистему «Дополнительные отчеты и обработки». Разработчик создает внешнюю обработку, в модуле объекта которой описывает функцию СведенияОВнешнейОбработке. В ней регистрируется одна или несколько команд вида «ЗаполнениеОбъекта» с указанием объектов, для которых команда доступна.
Когда пользователь нажимает кнопку команды в форме документа, БСП формирует структуру ПараметрыВыполненияКоманды и вызывает экспортную процедуру ВыполнитьКоманду из модуля обработки. В простейшем случае процедура получает массив ссылок на объекты и идентификатор команды — этого достаточно, если обработка всегда делает одно и то же.
Ограничение механизма: стандартная структура параметров не содержит произвольных пользовательских полей. БСП передает ссылку на объект, идентификатор команды, тип команды, имя формы-источника и служебные данные. Все, что выходит за эти рамки, нужно передавать обходными путями, которые и разобраны ниже.
Способ 1: несколько команд с разными идентификаторами
Самый надежный способ «передать параметр» — не передавать его вовсе, а зарегистрировать отдельную команду под каждый вариант заполнения. Если обработка умеет заполнять документ тремя способами (по остаткам, по продажам за период, по типовой спецификации), регистрируются три команды: ЗаполнитьПоОстаткам, ЗаполнитьПоПродажам, ЗаполнитьПоСпецификации. В модуле обработки идентификатор команды анализируется через Если/ИначеЕсли, и для каждой ветки вызывается своя процедура со своими жестко заданными параметрами.
Преимущества подхода: команды видны пользователю как отдельные пункты меню с понятными названиями, не требуется никаких форм и диалогов, код прост и легко тестируется. Недостаток очевиден: число вариантов фиксировано на этапе разработки, а параметры «зашиты» в код. Если пользователю нужно выбирать склад или период произвольно — этот способ не подходит.
// В СведенияОВнешнейОбработке
НоваяКоманда = ТаблицаКоманд.Добавить();
НоваяКоманда.Представление = НСтр("ru = 'Заполнить по остаткам'");
НоваяКоманда.Идентификатор = "ЗаполнитьПоОстаткам";
НоваяКоманда.Использование = "ЗаполнениеФормы";
НоваяКоманда.ПоказыватьОповещение = Истина;
Как выбрать способ передачи параметров
Способ 2: команда с открытием формы для ввода параметров
Когда параметры должен задавать пользователь, в СведенияОВнешнейОбработке команде назначается использование «ОткрытиеФормы». При нажатии кнопки БСП открывает основную форму обработки и передает в нее параметры, среди которых — массив объектов (обычно в параметре с именем, заданным в свойстве команды, либо через стандартные параметры формы). На форме разработчик размещает поля ввода: период, склад, организацию, флажки режимов.
Пользователь заполняет поля и нажимает кнопку «Заполнить». В обработчике кнопки значения полей собираются в структуру и вместе со ссылкой на объект передаются в серверную процедуру заполнения. Это самый гибкий вариант: набор параметров не ограничен, можно добавить проверки заполнения обязательных полей и подсказки.
Важная деталь: при использовании «ОткрытиеФормы» объект документа, из которого вызвана обработка, может быть еще не записан. Перед заполнением следует проверить, что документ проведен или хотя бы записан, либо работать с данными формы-источника, а не с базой. Иначе обработка заполнит данные, которые пользователь потом потеряет при закрытии формы без записи.
Способ 3: ДополнительныеПараметры при программном вызове
Если обработку заполнения нужно вызвать не кнопкой из формы, а программно — из другой обработки, регламентного задания или расширения — параметры передаются напрямую через структуру. Вызывающий код формирует структуру ПараметрыВыполненияКоманды, добавляет в нее свои ключи (или вложенную структуру ДополнительныеПараметры) и вызывает ВыполнитьКоманду модуля обработки.
В модуле обработки процедура ВыполнитьКоманду должна уметь извлекать эти значения с проверкой наличия ключа: ПараметрыВыполненияКоманды.Свойство("Склад", Склад). Такой код устойчив и к штатному вызову из БСП (ключа нет — используется значение по умолчанию), и к программному вызову с параметрами.
Процедура ВыполнитьКоманду(ИдентификаторКоманды, ПараметрыВыполненияКоманды) Экспорт
Период = Неопределено;
Склад = Неопределено;
ПараметрыВыполненияКоманды.Свойство("Период", Период);
ПараметрыВыполненияКоманды.Свойство("Склад", Склад);
Если Период = Неопределено Тогда
Период = ТекущаяДатаСеанса();
КонецЕсли;
// ... далее логика заполнения
КонецПроцедуры
Этот прием часто применяют и внутри формы обработки при использовании «ОткрытиеФормы»: значения полей формы упаковываются в структуру, которая передается в ту же ВыполнитьКоманду. Получается единая точка входа для интерактивного и программного сценариев — код не дублируется.
Передача параметров в типовой обработчик ОбработкаЗаполнения документа
Отдельный сценарий — не внешняя обработка, а событие ОбработкаЗаполнения в модуле объекта документа. Оно вызывается при создании документа на основании или при вводе нового. Сюда параметр попадает через аргумент ДанныеЗаполнения: платформа передает туда то, что было указано при вызове ОткрытьФорму или программном создании объекта.
При вводе на основании в ДанныеЗаполнения обычно приходит ссылка на документ-основание. При открытии формы с параметрами структура из параметра «ЗначенияЗаполнения» также оказывается в ДанныеЗаполнения. В модуле объекта проверяют тип: если это структура — извлекают нужные ключи, если ссылка — заполняют по основанию.
Процедура ОбработкаЗаполнения(ДанныеЗаполнения, ТекстЗаполнения, СтандартнаяОбработка)
Если ТипЗнч(ДанныеЗаполнения) = Тип("Структура") Тогда
Если ДанныеЗаполнения.Свойство("Склад") Тогда
Склад = ДанныеЗаполнения.Склад;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Ограничение: через ДанныеЗаполнения передаются только сериализуемые значения, которые «переживут» передачу между клиентом и сервером. Сложные объекты (таблицы значений с данными СКД, COM-объекты) так передать нельзя — их нужно формировать на сервере уже внутри обработчика.
Проверка результата и типичные ошибки
После внедрения передачи параметров проверку стоит строить на трех уровнях. Первый — сам вызов: обработчик получил именно те значения, которые ввел пользователь или передал вызывающий код. Второй — заполнение: табличная часть содержит ожидаемые строки, отборы по параметрам сработали. Третий — запись: объект сохранился без конфликтов версий, проведение не сломалось.
Как проверить результат
Через отладку видно переданные значения, отсутствующие ключи заменены значениями по умолчанию
Параметры Неопределено там, где должны быть заполнены, — значит, ключи в вызове и в чтении не совпадают
Строки соответствуют отбору по переданным параметрам (склад, период)
Заполняется без учета параметров — признак того, что параметры читаются, но не используются в запросе
Документ записывается, форма обновляется без ошибок
Ошибка конфликта версий или «объект изменен» — обработка писала объект параллельно с открытой формой
Из практики чаще всего встречаются четыре ошибки. Первая — несовпадение имен ключей: при передаче структура содержит ключ «Склад», а читается «СкладОтгрузки». Ошибки выполнения нет, параметр молча теряется. Вторая — обращение к ключу без Свойство(): при штатном вызове из БСП такого ключа нет, и обработка падает с ошибкой именно у пользователя, а не у разработчика.
Третья ошибка — передача несериализуемых типов через параметры формы: таблиц значений, хранилищ значений, ссылок на временные данные. Четвертая — игнорирование контекста: обработка рассчитана на записанный документ, но вызывается из формы нового объекта, и запрос по «ссылке» возвращает пустой результат.
Границы самостоятельной доработки
Описанные приемы безопасны, пока обработка только читает данные и заполняет табличную часть в рамках одного объекта. Риск возрастает, когда обработка начинает записывать несколько документов пакетно, изменять проведенные объекты задним числом или работать в транзакциях с блокировками. В таких сценариях ошибка в параметрах способна испортить не один документ, а пласт учетных данных.
Правило простое: любую обработку заполнения сначала тестируют на копии базы с реальными данными, проверяют поведение при пустых и некорректных параметрах, и только потом публикуют пользователям. Если обработка массово изменяет документы, добавьте в нее режим «только показать, что будет заполнено» без записи — это дешевый способ избежать дорогих ошибок.
Что важно запомнить
Параметры в обработку заполнения передаются тремя путями: отдельными командами под каждый вариант, собственной формой с полями ввода (использование ОткрытиеФормы) и структурой ПараметрыВыполненияКоманды при программном вызове. Читайте ключи через Свойство() со значениями по умолчанию, не передавайте несериализуемые типы и проверяйте состояние объекта перед записью.
Частые вопросы
Можно ли передать параметр в команду заполнения без открытия формы?
Да, если вызов программный: сформируйте структуру ПараметрыВыполненияКоманды с нужными ключами и вызовите ВыполнитьКоманду напрямую. При интерактивном вызове кнопкой из меню БСП произвольные параметры передать нельзя — используйте несколько команд с разными идентификаторами или форму ввода.
Как понять, откуда вызвана обработка — из формы или программно?
Проверяйте состав ПараметрыВыполненияКоманды. При вызове из БСП в структуре есть служебные ключи подсистемы дополнительных отчетов и обработок (например, сведения об источнике и типе команды). При программном вызове состав ключей полностью определяет ваш код. Надежный признак — наличие ваших пользовательских ключей: они появляются только при программной передаче.
Почему параметр передается, но обработка его «не видит»?
Чаще всего не совпадают имена ключей в структуре при передаче и при чтении, либо значение читается из другой вложенной структуры. Поставьте точку останова в начале ВыполнитьКоманду и посмотрите фактический состав структуры в отладчике — это быстрее, чем искать несоответствие по коду.
Можно ли передать список значений или таблицу в качестве параметра?
Список значений и массив простых типов (ссылки, строки, числа) сериализуются и передаются без проблем. Таблицу значений через параметры формы передать нельзя — передавайте массив структур или формируйте таблицу на сервере по переданным отборам.
Что делать, если обработка должна работать и в фоне, без пользователя?
Вынесите всю логику заполнения в серверную процедуру, принимающую структуру параметров. Интерактивная команда и регламентное задание будут вызывать одну и ту же процедуру, передавая свои наборы значений. Убедитесь, что в фоновом режиме код не обращается к интерактивным элементам — предупреждениям и вопросам пользователю.
Опасно ли менять типовую команду заполнения вместо добавления своей?
Переопределение типовой команды через расширение возможно, но рискованно: при обновлении конфигурации поведение может измениться, а ваша логика — конфликтовать с новым типовым кодом. Безопаснее добавлять отдельную внешнюю обработку или расширение с собственной командой, не трогая типовые механизмы.