Как программно создать копию документа в 1С:Предприятие 7.7

Программист 1С v7.7
← На главную

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

В этой статье мы подробно разберем, как создать универсальный алгоритм копирования, который будет корректно переносить данные шапки, табличной части и учитывать специфику платформы 7.7.

Базовый принцип копирования реквизитов шапки

Рассмотрим ситуацию, когда нам необходимо создать копию конкретного документа, зная его вид (например, «ПлатежноеПоручение»). Первым делом нам нужно создать новый объект документа и заполнить его реквизиты. Чтобы не прописывать каждый реквизит вручную, мы воспользуемся коллекцией метаданных. Это сделает наш код универсальным.

Проанализируем следующий фрагмент кода:


// Создаем объект для нового документа
НовыйДок = СоздатьОбъект("Документ.ПлатежноеПоручение");
НовыйДок.Новый();

// Получаем ссылку на исходный документ (например, через переменную ДокИсточник)
// Начинаем цикл по всем реквизитам шапки, описанным в конфигураторе
Для НомерРекв = 1 По Метаданные.Документ("ПлатежноеПоручение").РеквизитШапки Цикл
    Идентификатор = Метаданные.Документ("ПлатежноеПоручение").РеквизитШапки(НомерРекв).Идентификатор;
    
    // Получаем значение из источника и записываем в новый документ
    ЗначениеРеквизита = ДокИсточник.ПолучитьАтрибут(Идентификатор);
    НовыйДок.УстановитьАтрибут(Идентификатор, ЗначениеРеквизита);
КонецЦикла;

В данном примере мы используем метод ПолучитьАтрибут и УстановитьАтрибут. Это позволяет обращаться к реквизитам по их строковому имени, полученному из метаданных. Такой подход гарантирует, что при добавлении новых реквизитов в конфигураторе вам не придется переписывать код обработки.

Копирование табличной части документа

Многие документы в 1С 7.7 имеют табличную часть (ТЧ). Простого копирования шапки недостаточно. Для переноса строк ТЧ наиболее эффективным и быстрым способом является использование объекта ТаблицаЗначений. Платформа предоставляет встроенные методы для массовой выгрузки и загрузки строк, что значительно ускоряет процесс по сравнению с построчным перебором.

Выясним, как это реализовать программно:


// Создаем вспомогательный объект ТЗ
ТЗ = СоздатьОбъект("ТаблицаЗначений");

// Выгружаем все строки из документа-источника в таблицу
ДокИсточник.ВыгрузитьТабличнуюЧасть(ТЗ);

// Загружаем полученную таблицу в новый документ
// Метод полностью заменяет содержимое ТЧ нового документа данными из ТЗ
НовыйДок.ЗагрузитьТабличнуюЧасть(ТЗ);

Важный нюанс: метод ЗагрузитьТабличнуюЧасть переносит все колонки, включая служебные, если они есть. Это делает копию максимально идентичной оригиналу в части состава строк и их содержимого.

Учет общих реквизитов документов

В любой конфигурации 7.7 существуют так называемые «Общие реквизиты» (например, «Автор», «Фирма», «Комментарий»). Они не входят в коллекцию РеквизитШапки конкретного документа, так как вынесены на уровень всей ветки метаданных «Документы».

Чтобы копия была полной, необходимо отдельно обработать эти поля. Проанализируем, как добавить их в наш цикл:


// Дополнительный цикл по общим реквизитам
Для НомерОбщего = 1 По Метаданные.ОбщийРеквизитДокумента() Цикл
    ИдентификаторОбщий = Метаданные.ОбщийРеквизитДокумента(НомерОбщего).Идентификатор;
    
    // Проверяем, включен ли этот общий реквизит для данного вида документа
    Если Метаданные.Документ(НовыйДок.Вид()).ИзменяетОбщийРеквизит(ИдентификаторОбщий) = 1 Тогда
        НовыйДок.УстановитьАтрибут(ИдентификаторОбщий, ДокИсточник.ПолучитьАтрибут(ИдентификаторОбщий));
    КонецЕсли;
КонецЦикла;

Часто на практике такие реквизиты как «Автор» при копировании не дублируются, а заполняются текущим пользователем. Это логично, так как копию создает другой человек или система в другое время.

Массовое копирование документов за период

Рассмотрим более сложную задачу: нам нужно выбрать все документы определенного типа за прошлый месяц и создать их копии на текущую дату. Здесь мы объединим выборку документов и механизм копирования.


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

Тонкости автоматической нумерации и префиксов

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

Интерактивное копирование (через форму)

Иногда требуется, чтобы после выполнения кода пользователю открылась форма нового документа, чтобы он мог внести правки перед записью. В 1С 7.7 это реализуется через передачу контекста в ОткрытьФорму.

Разберем этот метод:

  1. В исходном коде вызываем открытие формы нового документа и передаем ссылку на документ-источник в качестве параметра.
  2. В модуле формы документа (в процедуре ПриОткрытии) ловим этот параметр.
  3. Если параметр передан, заполняем реквизиты текущей формы данными из параметра.

Этот способ считается более «чистым» для пользователя, так как срабатывают все проверки, прописанные в модуле формы (например, при изменении контрагента пересчитываются цены), которые могут не сработать при «тихом» программном создании документа.

Статус проведения и структура подчиненности

Важно помнить, что программно созданная копия всегда будет иметь статус «Не проведен», даже если оригинал был проведен. Если бизнес-логика требует немедленного проведения, после метода Записать() необходимо вызвать метод Провести(). Однако делайте это только в том случае, если уверены, что все реквизиты заполнены корректно и остатков на складах достаточно.

Также обратите внимание на подчиненные документы. При обычном копировании новый документ не будет связан с родительскими объектами оригинала в структуре подчиненности, если вы вручную не заполните реквизит типа «Документ» (обычно это ДокументОснование).

Проанализировав все вышеперечисленные методы, мы видим, что создание копии в 1С 7.7 требует внимательного отношения к метаданным и структуре объектов, но при правильном использовании встроенных функций УстановитьАтрибут и ЗагрузитьТабличнуюЧасть эта задача решается эффективно и надежно.

← На главную