К статье
Практический материал

Разработка и Конфигурация · 13 мин

Обработка заполнения в 1С: как передать данные в новый объект

Как работает обработчик ОбработкаЗаполнения в 1С, какие данные передаются в параметре ДанныеЗаполнения и как правильно заполнить документ при вводе на основании.

Обработка заполнения — это событие, которое платформа 1С вызывает при создании нового объекта: документа, элемента справочника, задачи. Разработчик получает в модуле объекта обработчик «ОбработкаЗаполнения» с параметром «ДанныеЗаполнения» и решает, какие реквизиты заполнить автоматически. Правильная передача данных в этот обработчик избавляет пользователя от ручного ввода и снижает количество ошибок в учёте.

Чаще всего механизм используется при вводе документов «на основании»: из заказа создаётся реализация, из счёта — оплата. Но тот же обработчик срабатывает и при обычном создании объекта, когда в «ДанныеЗаполнения» приходит структура со значениями по умолчанию, и даже при программном создании через «СоздатьДокумент()», если данные переданы явно.

Проблемы возникают из-за непонимания, что именно платформа кладёт в параметр, какие типы данных допустимы и почему обработчик иногда «не видит» переданные значения. Ниже разобраны состав параметра, способы передачи данных, типовой код обработчика и типичные ошибки.

Что такое обработка заполнения и когда она вызывается

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

Событие срабатывает в нескольких ситуациях: при интерактивном создании объекта пользователем, при вводе на основании другого документа, при программном создании с передачей данных заполнения, при копировании (где в параметр передаётся ссылка на копируемый объект). Важно понимать: если вы создаёте объект через «Документы.РеализацияТоваровУслуг.СоздатьДокумент()» без параметров, обработчик всё равно вызовется, но «ДанныеЗаполнения» будет равен «Неопределено».

Обработчик не вызывается при загрузке данных из обменов, если объект уже существует и просто перезаписывается, — там работают другие механизмы. Поэтому логику, критичную для обмена, в обработку заполнения помещать не следует.

Какие типы данных передаются в параметр ДанныеЗаполнения

Платформа передаёт в параметр значения нескольких типов, и обработчик обязан уметь их различать. Основные варианты:

  • Ссылка на объект-основание — при вводе на основании документа или элемента справочника. Тип определяется настройкой «Вводится на основании» в конфигураторе.
  • Структура — произвольный набор пар «ключ-значение», который передаёт вызывающий код или команда интерфейса. Самый гибкий способ передать несколько параметров сразу.
  • Стандартные значения — например, при создании элемента справочника в параметр может прийти значение реквизита-владельца.
  • Неопределено — объект создан без каких-либо входных данных.

Проверка типа выполняется функцией «ТипЗнч()» с сравнением через «Тип()». Типовой каркас обработчика выглядит так:

Процедура ОбработкаЗаполнения(ДанныеЗаполнения, СтандартнаяОбработка)

Если ТипЗнч(ДанныеЗаполнения) = Тип("ДокументСсылка.ЗаказКлиента") Тогда

// Заполнение на основании заказа

ЗаполнитьПоЗаказу(ДанныеЗаполнения);

ИначеЕсли ТипЗнч(ДанныеЗаполнения) = Тип("Структура") Тогда

// Заполнение из структуры

ЗаполнитьЗначенияСвойств(ЭтотОбъект, ДанныеЗаполнения);

КонецЕсли;

КонецПроцедуры

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

Как передать структуру с данными при создании объекта

Самый управляемый способ — сформировать структуру и передать её при создании. При программном создании это делается через параметр метода «ПолучитьФорму()» или через механизм «ВводНаОсновании», а в тонком клиенте чаще используется открытие формы нового объекта с параметрами заполнения:

ЗначенияЗаполнения = Новый Структура;

ЗначенияЗаполнения.Вставить("Организация", ТекущаяОрганизация);

ЗначенияЗаполнения.Вставить("Склад", ОсновнойСклад);

ЗначенияЗаполнения.Вставить("Комментарий", "Создано автоматически");

ПараметрыФормы = Новый Структура("ЗначенияЗаполнения", ЗначенияЗаполнения);

ОткрытьФорму("Документ.РеализацияТоваровУслуг.ФормаОбъекта", ПараметрыФормы);

Платформа сама передаст содержимое «ЗначенияЗаполнения» в параметр «ДанныеЗаполнения» обработчика. Внутри обработчика удобнее всего использовать «ЗаполнитьЗначенияСвойств()» — она переносит только те ключи структуры, имена которых совпадают с реквизитами объекта, и молча игнорирует лишние ключи.

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

Передача данных через структуру
  1. 1
    Сформируйте структуру с ключами, совпадающими с именами реквизитов объекта
  2. 2
    Передайте структуру в параметр ЗначенияЗаполнения при открытии формы или в код создания объекта
  3. 3
    В обработчике ОбработкаЗаполнения добавьте ветку для типа Структура
  4. 4
    Используйте ЗаполнитьЗначенияСвойств для переноса значений
  5. 5
    Проверьте результат: откройте созданный объект и убедитесь, что реквизиты заполнены

Заполнение на основании другого документа

Ввод на основании — стандартный сценарий, когда в «ДанныеЗаполнения» приходит ссылка на документ-источник. В обработчике нужно прочитать реквизиты основания и перенести их в новый объект. Два подхода: обращение к реквизитам через точку (платформа выполнит неявные запросы) или один явный запрос к базе. Для документов с табличными частями явный запрос предпочтительнее — он быстрее и предсказуемее.

Процедура ЗаполнитьПоЗаказу(Основание)

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Заказ.Организация КАК Организация,

| Заказ.Контрагент КАК Контрагент,

| Заказ.Договор КАК Договор

|ИЗ

| Документ.ЗаказКлиента КАК Заказ

|ГДЕ

| Заказ.Ссылка = &Ссылка";

Запрос.УстановитьПараметр("Ссылка", Основание);

Выборка = Запрос.Выполнить().Выбрать();

Если Выборка.Следующий() Тогда

ЗаполнитьЗначенияСвойств(ЭтотОбъект, Выборка);

КонецЕсли;

ЭтотОбъект.ДокументОснование = Основание;

КонецПроцедуры

Табличные части заполняются отдельно: либо вторым запросом к табличной части основания с загрузкой результата через «Загрузить()», либо построчным обходом. При переносе строк проверяйте соответствие состава колонок — если в новом документе колонка отсутствует, «Загрузить()» завершится ошибкой при несовпадении имён.

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

Способы передачи данных

Структура со значениями

Гибко, подходит для любых реквизитов; ограничение — нет контроля типов на этапе компиляции, ошибки в именах ключей обнаруживаются только при выполнении

Ссылка на основание

Стандартный ввод на основании, данные читаются запросом из базы; требует, чтобы основание было записано

Копирование объекта

Платформа передаёт ссылку на копируемый объект; нужно очищать поля, которые копировать нельзя (номер, дата, проведение)

Заполнение табличных частей и дополнительные параметры

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

Если ТипЗнч(ДанныеЗаполнения) = Тип("Структура") Тогда

Если ДанныеЗаполнения.Свойство("Товары") Тогда

Для Каждого СтрокаДанных Из ДанныеЗаполнения.Товары Цикл

НоваяСтрока = ЭтотОбъект.Товары.Добавить();

ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаДанных);

КонецЦикла;

КонецЕсли;

КонецЕсли;

Всегда проверяйте наличие ключа через «Свойство()» перед обращением — обращение к несуществующему ключу структуры вызывает исключение, и объект не создастся. Это особенно важно, когда одна и та же форма открывается из разных мест с разным набором параметров.

Проверка результата и типичные ошибки

После внедрения обработчика проверьте все сценарии создания объекта: вручную из списка, вводом на основании, программно, копированием. Частая ситуация — обработчик корректно отрабатывает ввод на основании, но ломает обычное создание, потому что ветка для «Неопределено» не предусмотрена или стандартная обработка отключена без необходимости.

Типичные ошибки
01
Обращение к ключу структуры без проверки через Свойство() — объект не создаётся, пользователь получает ошибку вместо нового документа
02
Отсутствие ветки для типа Неопределено — ручное создание объекта начинает вести себя непредсказуемо
03
Заполнение реквизитов в обход обработчика при копировании: номер и дата копируются из оригинала, что нарушает нумерацию
04
Использование клиентских вызовов (ПоказатьВопрос, Предупреждение) внутри серверного обработчика — код молча не выполняется или падает
05
Перенос табличной части через Загрузить() без проверки состава колонок — исключение при несовпадении имён

Признак корректной работы: объект создаётся во всех сценариях, реквизиты соответствуют источнику, при ручном создании применяются значения по умолчанию, а при копировании очищаются служебные поля. Если обработчик «не срабатывает», первым делом проверьте, что он объявлен именно в модуле объекта, а не в модуле формы, и что сигнатура процедуры не изменена.

Контрольные точки

Как проверить результат

Создание вручную из списка документов
Норма

Объект открывается, заполнены значения по умолчанию

Тревожный признак

Ошибка выполнения или пустые обязательные реквизиты

Ввод на основании
Норма

Реквизиты и табличные части перенесены из основания

Тревожный признак

Часть полей пустая или содержит данные не из того источника

Копирование объекта
Норма

Номер и дата новые, служебные поля очищены

Тревожный признак

Скопирован номер оригинала или признак проведения

Программное создание со структурой
Норма

Все переданные ключи попали в реквизиты

Тревожный признак

Часть значений потеряна из-за опечатки в имени ключа

Ограничения и альтернативные подходы

Обработка заполнения не подходит для логики, которая должна выполняться при каждом изменении объекта, — она вызывается один раз при создании. Для контроля при записи используйте «ОбработкаПроверкиЗаполнения» и «ПередЗаписью», для реакции на изменение реквизитов в форме — обработчики «ПриИзменении» в модуле формы.

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

Для интеграционных сценариев, где объект создаётся из внешней системы, часто надёжнее не полагаться на обработку заполнения, а заполнять реквизиты явно в коде интеграции после «СоздатьДокумент()». Тогда поведение не зависит от того, какие данные платформа решит передать в обработчик.

Итог

Что важно запомнить

Данные в новый объект передаются через параметр ДанныеЗаполнения обработчика ОбработкаЗаполнения. Обработчик должен различать типы параметра: ссылка на основание, структура, Неопределено. Ключи структуры проверяйте через Свойство(), реквизиты заполняйте через ЗаполнитьЗначенияСвойств, табличные части — массивом структур или запросом к основанию. Типовые обработчики дорабатывайте через расширение, а не прямым изменением конфигурации.

Частые вопросы

Почему обработчик ОбработкаЗаполнения не вызывается?

Чаще всего процедура размещена не в модуле объекта, а в модуле формы или общем модуле — платформа ищет обработчик только в модуле объекта. Также проверьте, что сигнатура не изменена: должны быть параметры ДанныеЗаполнения и СтандартнаяОбработка (для некоторых объектов — ещё ТекстЗаполнения). В расширениях убедитесь, что аннотация &После или &Вместо указана корректно.

Можно ли передать в ДанныеЗаполнения несколько документов-оснований?

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

Чем ОбработкаЗаполнения отличается от ПриСозданииНаСервере в форме?

ОбработкаЗаполнения работает на уровне объекта и вызывается при любом способе создания, включая программный без открытия формы. ПриСозданииНаСервере — обработчик формы, он срабатывает только при открытии формы и имеет доступ к элементам интерфейса. Бизнес-логику заполнения правильно размещать в модуле объекта, а в форме — только интерфейсные настройки.

Как запретить стандартное заполнение реквизитов значениями по умолчанию?

Установите параметр СтандартнаяОбработка в значение Ложь в начале обработчика. Тогда платформа не будет подставлять значения по умолчанию и настройки заполнения из метаданных. Делайте это осознанно: придётся самостоятельно заполнить все обязательные реквизиты, иначе объект не пройдёт проверку заполнения при записи.

Как отладить обработку заполнения?

Поставьте точку останова внутри обработчика в конфигураторе и запустите отладку в режиме предприятия, затем создайте объект нужным способом. В отладчике посмотрите тип и содержимое ДанныеЗаполнения через табло (выражение ТипЗнч(ДанныеЗаполнения)). Если точка не срабатывает — проверьте, что отлаживаете тот же сеанс и что предмет отладки включён для сервера.

Работает ли обработка заполнения при обмене данными?

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