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