Как сделать, чтобы в документе работала кнопка «Создать на основании»
Содержание
Чтобы в форме документа появилась команда Создать на основании, нужно сделать две вещи в Конфигураторе: указать на вкладке «Ввод на основании» связь между объектами
и написать в модуле объекта процедуру ОбработкаЗаполнения. Первое включает саму кнопку, второе переносит данные из документа-основания в новый документ.
Разберём обе части на примере: пусть из «Заказа покупателя» нужно создавать «Реализацию товаров и услуг» с автоматическим заполнением контрагента, организации и табличной части. Те же приёмы работают для любой пары объектов — документов, справочников, задач.
Из чего состоит механизм ввода на основании
Ввод на основании — это штатный механизм платформы, который переносит данные из одного объекта в другой при создании. Пользователь нажимает Создать на основании, выбирает нужный вид документа, и новый объект открывается уже заполненным.
Механизм держится на трёх элементах:
- 🔗 Связь объектов — на вкладке «Ввод на основании» вы отмечаете, какой объект чем является: основанием или результатом.
- ⚙️ Процедура
ОбработкаЗаполнения— код в модуле объекта-результата, который читает основание и заполняет реквизиты. - 🧩 Команда в интерфейсе — кнопка
Создать на основаниив форме списка и в форме документа, платформа добавляет её автоматически.
Если настроена только связь без процедуры, кнопка появится, но новый документ откроется пустым. Если написать процедуру, но не завести связь, код просто не вызовется — платформе неоткуда узнать, что объекты связаны. Поэтому настройку всегда делают парой: сначала связь на вкладке, затем заполнение в модуле. Порядок роли не играет, но без обеих частей механизм работать не будет.
Направление связи важно. «Реализация» вводится на основании «Заказа», а «Заказ» является основанием для «Реализации». Это одна и та же связь, описанная с двух сторон.
Включаем связь на вкладке объекта
Откройте в Конфигураторе объект-результат — тот, который будете создавать. В нашем примере это документ «Реализация товаров и услуг». В редакторе объекта перейдите на вкладку Ввод на основании.
На вкладке два списка:
- Вводится на основании — здесь отметьте объекты, из которых можно создать текущий документ. Для «Реализации» ставим галочку на «Заказ покупателя».
- Является основанием для — здесь отмечают объекты, которые можно создать из текущего. Это удобный способ задать ту же связь со стороны документа-источника, не открывая его отдельно.
Достаточно отметить галочку в одном из списков — связь двусторонняя. После этого платформа при следующем запуске в режиме 1С:Предприятие покажет в форме «Заказа покупателя» команду создания «Реализации».
Команда Создать на основании доступна из командной панели формы списка и формы документа. Если видов-результатов несколько, платформа собирает их в подменю с выбором вида.
Правка вкладки «Ввод на основании» — это изменение структуры конфигурации. Чтобы галочки вступили в силу, конфигурацию нужно сохранить и обновить (Конфигурация → Обновить конфигурацию базы данных, F7). В клиент-серверной базе обновление структуры требует монопольного доступа, поэтому планируйте его на время, когда пользователи не работают.
Конструктор ввода на основании: быстрый старт
Писать заполнение вручную не обязательно. На вкладке «Ввод на основании» есть кнопка Конструктор ввода на основании. Она сама сопоставляет реквизиты основания и результата по совпадающим именам и типам, а затем генерирует готовый текст процедуры ОбработкаЗаполнения.
Порядок работы с конструктором:
- Отметьте в списке «Вводится на основании» нужные объекты-основания.
- Нажмите
Конструктор ввода на основании. - В левой части выберите основание, в правой — проверьте предложенное сопоставление реквизитов шапки и табличных частей.
- Поправьте пары, где платформа ошиблась, снимите лишние.
- Нажмите
ОК— код запишется в модуль объекта.
Конструктор экономит время на типовых переносах, но он не знает вашей бизнес-логики: курсы валют, перерасчёт цен, проверку остатков он не добавит. Сгенерированный код — это заготовка, которую почти всегда дорабатывают руками.
Какой способ выбрать, зависит от задачи:
| Способ заполнения | Когда применять |
|---|---|
| Конструктор ввода на основании | типовой перенос одноимённых реквизитов и табличных частей, старт разработки |
Ручная правка ОбработкаЗаполнения | поля с разными именами, расчёты, проверки статусов и прав |
Вызов Заполнить из кода | массовое создание документов обработкой или по расписанию |
На практике эти способы сочетают: конструктор даёт каркас, а бизнес-логику дописывают в той же процедуре.
Как перенести данные: процедура ОбработкаЗаполнения
За заполнение отвечает процедура ОбработкаЗаполнения в модуле объекта-результата. Платформа вызывает её, когда создаёт документ на основании чего-либо, и передаёт туда ссылку на основание.
Актуальная сигнатура в 8.3:
Процедура ОбработкаЗаполнения(ДанныеЗаполнения, ТекстЗаполнения, СтандартнаяОбработка)
КонецПроцедуры
Назначение параметров:
ДанныеЗаполнения— то, на основании чего вводят документ. Чаще всего это ссылка на документ-основание, но может прийти и структура, и значение из списка.ТекстЗаполнения— текст, который платформа может показать пользователю; в большинстве случаев не трогают.СтандартнаяОбработка— булево, управляет стандартным поведением платформы.
Поскольку оснований бывает несколько, первым делом проверяют тип переданного значения через ТипЗнч, и уже внутри ветки заполняют реквизиты:
Процедура ОбработкаЗаполнения(ДанныеЗаполнения, ТекстЗаполнения, СтандартнаяОбработка)
Если ТипЗнч(ДанныеЗаполнения) = Тип("ДокументСсылка.ЗаказПокупателя") Тогда
Основание = ДанныеЗаполнения;
Организация = Основание.Организация;
Контрагент = Основание.Контрагент;
Договор = Основание.Договор;
Склад = Основание.Склад;
Для Каждого СтрокаОснования Из Основание.Товары Цикл
НоваяСтрока = Товары.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаОснования);
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Разбор кода:
ЗаполнитьЗначенияСвойств(Приёмник, Источник)копирует одноимённые реквизиты. Для шапки её тоже удобно применять:ЗаполнитьЗначенияСвойств(ЭтотОбъект, Основание)перенесёт все совпадающие по имени поля за одну строку.- Табличную часть переносят в цикле: на каждую строку основания добавляют строку результата и копируют значения.
- Ветка
Если ТипЗнч(...) = Тип("ДокументСсылка....")позволяет описать несколько оснований в одной процедуре: для каждого вида — свой блок.
Полезно заранее расписать, какое поле основания ложится в какое поле результата. Для нашей пары это выглядит так:
| Реквизит «Заказа покупателя» | Реквизит «Реализации» | Как переносим |
|---|---|---|
| Организация | Организация | присваиванием или ЗаполнитьЗначенияСвойств |
| Контрагент | Контрагент | то же |
| Договор | Договор | то же |
| Склад | Склад | то же |
| Табличная часть «Товары» | Табличная часть «Товары» | циклом по строкам |
Поля с одинаковыми именами закроет ЗаполнитьЗначенияСвойств одной строкой. Там, где имена расходятся (например, в основании «СкладОтгрузки», а в результате «Склад»), пишите присваивание явно: Склад = Основание.СкладОтгрузки.
Записывать документ внутри ОбработкаЗаполнения не нужно. Процедура только заполняет реквизиты объекта в памяти. Проведение и запись выполняет пользователь, когда нажмёт Провести и закрыть.
Как ограничить, из чего можно вводить
Список оснований формируется из галочек на вкладке — лишние виды там просто не отмечают. Более тонкие ограничения задают не галочками, а логикой.
Через права. Если у пользователя нет права Создание на документ-результат, команда для него не покажется. Это штатный способ скрыть ввод на основании от части сотрудников — настраивается в ролях.
Через функциональные опции. Привяжите объект-результат к функциональной опции. Пока опция выключена, объект и связанные с ним команды в интерфейсе не видны.
Внутри процедуры заполнения. Когда ввод формально разрешён, но данные переносить нельзя (например, заказ в статусе «Отклонён»), проверку делают в коде и либо не заполняете часть реквизитов, либо сообщаете причину:
Если Основание.Статус = Перечисления.СтатусыЗаказов.Отклонён Тогда
ВызватьИсключение "По отклонённому заказу реализацию не создают.";
КонецЕсли;
Такое исключение прервёт создание документа и покажет текст пользователю. Применяйте его только для настоящих запретов — для подсказок лучше заполнять документ частично и оставлять поясняющий комментарий.
Почему «Создать на основании» не работает
Разберём типовые ситуации. Сначала отделите два случая: кнопки нет вообще — или кнопка есть, но документ открывается пустым. Это разные проблемы.
Отладка процедуры. Чтобы увидеть, что приходит в основании, поставьте точку останова на первой строке ОбработкаЗаполнения и запустите конфигурацию в режиме отладки (Отладка → Начать отладку, F5). Создайте документ на основании — выполнение остановится, и в окне Табло или по наведению вы увидите значение ДанныеЗаполнения и его тип. Это быстрый способ понять, почему не сработала нужная ветка Если.
Если точка останова не срабатывает вовсе, процедура не вызывается: чаще всего причина в том, что связь объектов не обновлена в базе данных.
Ввод на основании при массовом создании документов
Штатная команда создаёт по одному документу за раз. Когда из сотен заказов нужно разом сделать реализации, вызывают заполнение из кода.
У объекта есть метод Заполнить, который запускает ту же ОбработкаЗаполнения:
НовыйДокумент = Документы.РеализацияТоваровУслуг.СоздатьДокумент();
НовыйДокумент.Дата = ТекущаяДата();
НовыйДокумент.Заполнить(СсылкаНаЗаказ);
НовыйДокумент.Записать(РежимЗаписиДокумента.Проведение);
Чтобы групповая обработка не тормозила на больших объёмах, держитесь нескольких правил:
- 🚀 Не делайте запросов в цикле. Все нужные данные по заказам читайте одним запросом до цикла, а внутри только создавайте и записывайте документы.
- 📦 Копируйте табличные части через
ЗаполнитьЗначенияСвойств, а не поэлементно по колонкам — это и быстрее, и устойчивее к изменению состава реквизитов. - 🧵 Длинную обработку выносите в фоновое задание (
ФоновыеЗадания.ВыполнитьВ...), чтобы не держать сеанс пользователя и не упираться в тайм-аут. - 💾 Записывайте пакетами в транзакции, но не оборачивайте в одну транзакцию тысячи документов — при ошибке откатится всё. Разумный размер пачки — десятки, максимум сотни документов.
Массовое проведение создаёт движения по регистрам и нагружает блокировки. Запускайте такие обработки в нерабочее время и сначала проверяйте на копии базы: ошибка в заполнении размножится на все созданные документы.
Отдельно следите за тем, чтобы ОбработкаЗаполнения оставалась «лёгкой». Тяжёлые вычисления — обращения к внешним источникам, объёмные запросы на каждую строку — при массовом вводе превращаются в узкое место. Выносите их за пределы процедуры заполнения.
Результат массовой обработки стоит фиксировать: собирайте в журнал регистрации или в отдельный список ссылки на созданные документы и тексты ошибок проведения. Так после прогона видно, по каким заказам реализация не создалась, и не приходится сверять сотни документов вручную. Если часть документов не провелась из-за нехватки остатков или прав, повторный запуск по этому списку закроет расхождения точечно.
Частые вопросы
Чем ввод на основании отличается от копирования документа?
Создать копированием) дублирует документ того же вида со всеми реквизитами. Ввод на основании создаёт документ другого вида и переносит только те поля, которые вы описали в ОбработкаЗаполнения.Можно ли вводить на основании из справочника или задачи, а не только из документа?
ОбработкаЗаполнения есть не только у документов, но и у справочников, задач и ряда других объектов. Механизм работает для любой разрешённой пары.Как сделать ввод на основании сразу из нескольких оснований?
ОбработкаЗаполнения опишите несколько веток Если ТипЗнч(ДанныеЗаполнения) = Тип(...), по одной на каждый вид основания. Платформа сама подставит в параметр то основание, которое выбрал пользователь.Нужно ли обновлять конфигурацию базы после правки вкладки?
Почему конструктор перенёс не все реквизиты?
ЗаполнитьЗначенияСвойств с явным указанием.