Как создать отдельные документы на основании каждой строки табличной части в 1С?

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

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

Постановка задачи и выбор объекта метаданных

Разберем ситуацию: у нас есть документ ПриемОборудования, в табличной части которого указываются модель и серийный номер каждой единицы. Нам необходимо, чтобы после фиксации этого факта в системе для каждой единицы техники создавался отдельный документ РеестрОборудования. Это позволит вести индивидуальный учет каждой единицы (например, отслеживать историю перемещений или ремонт конкретного серийного номера).

Проанализируем архитектурный спор, возникший в обсуждении. Традиционно в 1С Документ используется для отражения событий, происходящих во времени, а Справочник — для хранения информации об объектах. Если «Реестр» — это просто карточка оборудования, которая не меняется со временем, лучше использовать Справочник. Однако, если эта запись должна «двигать» регистры или иметь статус проведения, выбор документа допустим. В нашем примере мы продолжим работу с документами, как того требует исходная задача.

Программная реализация: обход табличной части в цикле

Для решения задачи нам потребуется написать процедуру, которая будет перебирать строки табличной части документа-основания и для каждой строки создавать новый объект. Рассмотрим пример кода, который можно разместить в модуле документа или в специализированной обработке:


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

КонецПроцедуры

Место размещения кода: ПриПроведении или кнопка на форме?

Выясним, где именно лучше вызвать этот код. В обсуждении предлагалось использовать событие ПриПроведении. Однако это несет определенные риски:

  1. Повторное проведение: При случайном перепроведении документа-основания код сработает снова, что создаст дубли в реестре.
  2. Транзакционность: Если запись одного из десяти документов реестра завершится ошибкой, проведение основного документа может быть прервано.

Рекомендуется выносить создание документов либо в отдельную команду (кнопку) на форме документа с названием «Сформировать реестр», либо добавлять проверку на уже созданные документы.

Борьба с дублями: связь документов

Чтобы система понимала, по каким строкам документы уже созданы, проанализируем механизм связей. Рассмотрим два эффективных способа:

Способ 1: Реквизит в табличной части. Добавим в табличную часть Оборудование документа-источника реквизит ДокументРеестра с типом ДокументСсылка.РеестрОборудования. При генерации будем проверять это поле:


Если НЕ ЗначениеЗаполнено(СтрокаТЧ.ДокументРеестра) Тогда
    // Создаем документ...
    // После успешной записи записываем ссылку обратно в ТЧ документа-основания
    СтрокаТЧ.ДокументРеестра = НовыйДокумент.Ссылка;
КонецЕсли;

Способ 2: Запрос к базе данных. Перед созданием можно проверять существование документа РеестрОборудования, где реквизит СерийныйНомер совпадает с текущим в строке. Это более надежный способ с точки зрения уникальности оборудования.

Работа с серийными номерами и сканером штрихкодов

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

Важный момент по IP-адресам: В обсуждении упоминалось, что IP-адрес записывается вручную. С точки зрения методологии 1С, такие динамические данные лучше хранить не в реквизитах документа, а в Регистре сведений. Это позволит всегда видеть актуальный IP-адрес устройства на текущий момент времени, просто обратившись к срезу последних записей регистра.

Итоги реализации

Рассмотренный подход позволяет автоматизировать рутинный ввод данных. Вместо ручного создания десяти карточек, оператор заполняет одну таблицу, а система программно формирует необходимые объекты учета. Главное — помнить о проверке на дубли и правильной установке времени документов, чтобы хронология событий в базе данных оставалась корректной. Для повышения надежности работы рекомендуется использовать Попытка...Исключение при записи каждого документа в цикле, чтобы ошибка в одной строке не блокировала обработку всей таблицы.

← На главную