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