Как перенести присоединенные файлы из одного документа в другой при программном создании?

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

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

Анализ проблемы и архитектуры хранения файлов

Прежде всего, разберем ситуацию, описанную в теме. Основная сложность заключается в том, что в типовых конфигурациях (особенно построенных на базе БСП) присоединенные файлы — это не просто записи в регистре, а элементы специальных справочников. Для каждого вида документа существует свой справочник (например, РеализацияТоваровУслугПрисоединенныеФайлы и ВозвратТоваровПоставщикуПрисоединенныеФайлы).

Просто "подменить владельца" у существующего файла не получится по двум причинам:

  1. Разные типы данных: Справочники файлов для разных документов являются разными объектами метаданных.
  2. Момент записи: Файл нельзя привязать к новому документу, пока этот документ не записан и не получил уникальную ссылку в базе данных.

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

Шаг 1. Передача данных из формы источника

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


&НаКлиенте
Процедура ПеренестиВОбратнуюРеализацию(Команда)
    Если Модифицированность ИЛИ НЕ ЗначениеЗаполнено(Объект.Ссылка) Тогда
        ПоказатьПредупреждение(, "Документ сначала нужно записать");
        Возврат;
    КонецЕсли;

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

Шаг 2. Сохранение ссылки в ДополнительныеСвойства

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

Для решения этой проблемы используем механизм ДополнительныеСвойства. Это специальная структура в объекте 1С, которая живет в памяти в рамках текущего сеанса работы с объектом. Разберем, как пробросить ссылку в модуле объекта документа-приемника (РеализацияТоваровУслуг):


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

Шаг 3. Реализация копирования файлов при записи

Теперь, когда у объекта в ДополнительныеСвойства есть ссылка на источник, мы можем выполнить копирование файлов. Наилучшее место для этого — процедура ПриЗаписи в модуле объекта. Важно делать это именно здесь, так как у нас уже гарантированно есть ЭтотОбъект.Ссылка.

Посмотрим, как организовать программное копирование. Если конфигурация использует БСП (что характерно для "Торгового комплекса", УТ, ERP), лучше всего использовать встроенный метод ПрисоединенныеФайлы.СкопироватьПрисоединенныеФайлы. Если же мы пишем решение с нуля, проанализируем ручной алгоритм:


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

Процедура СкопироватьФайлыИзИсточника(ДокументИсточник, ДокументПриемник)
    
    // В типовых решениях на БСП рекомендуется использовать:
    // ПрисоединенныеФайлы.СкопироватьПрисоединенныеФайлы(ДокументИсточник, ДокументПриемник);
    
    // Если требуется ручная реализация (упрощенно):
    // 1. Найти все элементы в справочнике файлов источника по владельцу
    // 2. Для каждого файла создать новый элемент в справочнике файлов приемника
    // 3. Скопировать содержимое (двоичные данные) и реквизиты (расширение, имя)
    
КонецПроцедуры

Нюансы работы с подсистемой "Присоединенные файлы"

Проанализируем важные детали, которые могут повлиять на результат работы:

Итоги

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

← На главную