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