Как создать один документ на основании нескольких выделенных документов в списке 1С

Программист 1С v8.3 (Управляемые формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

В типовых конфигурациях 1С (таких как Управление торговлей 11, ERP или Комплексная автоматизация) стандартный механизм «Создать на основании» рассчитан на работу с одним объектом-источником. Однако на практике часто возникает задача: выделить в списке несколько документов (например, несколько «Заказов поставщику») и нажать одну кнопку, чтобы сформировать один сводный документ. Рассмотрим подробно, как реализовать этот механизм программно, используя возможности управляемых форм и встроенного языка 1С.

Почему стандартная кнопка не подходит для множественного выбора

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

Способ 1. Создание команды непосредственно в форме списка

Проанализируем самый простой и быстрый способ реализации — создание команды в форме списка исходного документа (например, в списке «Заказов поставщику»).

Шаг 1. Настройка команды

В редакторе формы списка создадим новую команду (например, СоздатьСводныйДокумент). Разместим её на командной панели или в контекстном меню списка. Обязательно убедимся, что у элемента формы (таблицы списка) свойство РежимВыделения установлено в значение Множественный.

Шаг 2. Реализация клиентской логики

Нам необходимо собрать все ссылки выделенных строк в массив и передать их при открытии формы нового документа. Рассмотрим пример кода для клиентской процедуры:


&НаКлиенте
Процедура СоздатьСводныйДокумент(Команда)
    
    // Получаем массив идентификаторов выделенных строк
    ВыделенныеСтроки = Элементы.Список.ВыделенныеСтроки;
    
    Если ВыделенныеСтроки.Количество() = 0 Тогда
        ПоказатьПредупреждение(, "Не выбрано ни одного документа!");
        Возврат;
    КонецЕсли;
    
    // Формируем массив ссылок
    МассивОснований = Новый Массив;
    Для Каждого ИдентификаторСтроки Из ВыделенныеСтроки Цикл
        // Извлекаем ссылку из данных строки (в УФ это делается через ДанныеСтроки)
        ДанныеСтроки = Элементы.Список.ДанныеСтроки(ИдентификаторСтроки);
        Если ДанныеСтроки <> Неопределено Тогда
            МассивОснований.Добавить(ДанныеСтроки.Ссылка);
        КонецЕсли;
    КонецЦикла;
    
    // Подготавливаем параметры для открытия формы нового документа
    // Мы используем параметр ЗначенияЗаполнения, который платформа передаст в ОбработкаЗаполнения
    ПараметрыЗаполнения = Новый Структура;
    ПараметрыЗаполнения.Вставить("ДокументыОснования", МассивОснований);
    
    ПараметрыФормы = Новый Структура;
    ПараметрыФормы.Вставить("ЗначенияЗаполнения", ПараметрыЗаполнения);
    
    // Открываем форму нового самописного документа
    ОткрытьФорму("Документ.ВашНовыйСводныйДокумент.ФормаОбъекта", ПараметрыФормы);
    
КонецПроцедуры

Способ 2. Использование Общих команд (рекомендуемый подход)

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

  1. Создадим новый объект метаданных ОбщаяКоманда.
  2. В свойстве ТипПараметраКоманды выберем ДокументСсылка.ЗаказПоставщику.
  3. Установим свойство РежимИспользованияПараметра в значение Множественный. Это ключевой момент: платформа сама соберет выделенные ссылки в массив и передаст их в процедуру.

Рассмотрим код модуля общей команды:


&НаКлиенте
Процедура ОбработкаКоманды(ПараметрКоманды, ПараметрыВыполненияКоманды)
    
    // ПараметрКоманды уже является массивом ссылок благодаря настройкам команды
    Если ТипЗнч(ПараметрКоманды) <> Тип("Массив") Или ПараметрКоманды.Количество() = 0 Тогда
        Возврат;
    КонецЕсли;
    
    ПараметрыЗаполнения = Новый Структура("СводноеОснование", ПараметрКоманды);
    ПараметрыФормы = Новый Структура("ЗначенияЗаполнения", ПараметрыЗаполнения);
    
    ОткрытьФорму("Документ.ВашНовыйСводныйДокумент.ФормаОбъекта", ПараметрыФормы, ПараметрыВыполненияКоманды.Источник, ПараметрыВыполненияКоманды.Уникальность, ПараметрыВыполненияКоманды.Окно, ПараметрыВыполненияКоманды.НавигационнаяСсылка);
    
КонецПроцедуры

Обработка данных в модуле объекта (ОбработкаЗаполнения)

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


Процедура ОбработкаЗаполнения(ДанныеЗаполнения, ТекстЗаполнения, СтандартнаяОбработка)
    
    // Проверяем, что к нам пришла именно наша структура с массивом
    Если ТипЗнч(ДанныеЗаполнения) = Тип("Структура") И ДанныеЗаполнения.Свойство("СводноеОснование") Тогда
        
        // Отключаем стандартный механизм, так как заполняем вручную
        СтандартнаяОбработка = Ложь;
        
        МассивСсылок = ДанныеЗаполнения.СводноеОснование;
        
        Для Каждого СсылкаИзСписка Из МассивСсылок Цикл
            // Выполняем логику заполнения. 
            // Например, переносим товары из каждого заказа в общую таблицу
            ЗаполнитьПоОдномуДокументу(СсылкаИзСписка);
        КонецЦикла;
        
    ИначеЕсли ТипЗнч(ДанныеЗаполнения) = Тип("ДокументСсылка.ЗаказПоставщику") Тогда
        // Оставляем возможность заполнения по одному документу (стандартно)
        ЗаполнитьПоОдномуДокументу(ДанныеЗаполнения);
    КонецЕсли;
    
КонецПроцедуры

Процедура ЗаполнитьПоОдномуДокументу(Источник)
    // Здесь описывается логика копирования данных из Источника в ТекущийОбъект
    // Например:
    Для Каждого СтрокаТЧ Из Источник.Товары Цикл
        НоваяСтрока = Товары.Добавить();
        ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаТЧ);
        НоваяСтрока.ДокументОснование = Источник;
    КонецЦикла;
КонецПроцедуры

Нюансы реализации в конфигурациях на БСП

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

Важные рекомендации по работе с большими объемами данных

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

1. Предварительная проверка. Перед вызовом открытия формы на клиенте проверьте количество выделенных строк. Если их слишком много, можно вывести запрос на подтверждение: "Вы выбрали 200 документов. Это может занять длительное время. Продолжить?".

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


// Пример программного создания без формы (на сервере)
НовыйДок = Документы.ВашДокумент.СоздатьДокумент();
// Напрямую вызываем процедуру заполнения
НовыйДок.Заполнить(МассивСсылок); 
НовыйДок.Записать(РежимЗаписиДокумента.Запись);

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

← На главную