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