Как программно удалить присоединенные файлы по выбранной номенклатуре в 1С

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

При автоматизации загрузки данных из внешних источников, таких как Excel, разработчики часто сталкиваются с проблемой дублирования информации. Одной из наиболее типичных ситуаций является повторная загрузка изображений товаров в конфигурации «Управление торговлей 11» (УТ 11). Если не предусмотреть очистку старых данных, справочник присоединенных файлов быстро разрастается, занимая лишнее место в базе данных или на диске. В этой статье мы подробно разберем, как программно удалить записи по конкретной номенклатуре, проанализируем различные подходы и выберем наиболее безопасный и эффективный способ.

Постановка задачи и анализ структуры данных

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

Разберем ситуацию: нам нужно перед загрузкой нового фото найти все старые файлы, принадлежащие конкретному товару, и удалить их, чтобы избежать «мусора» в системе.

Способ №1: Прямой перебор элементов через выборку

Самый простой и понятный способ, который был предложен в ходе обсуждения на форуме, — это использование метода Выбрать(). Этот метод позволяет получить все записи справочника, установив фильтр по владельцу.

Проанализируем пример кода:


// Предположим, что переменная ОбъектНоменклатура содержит ссылку на нужный товар
Выборка = Справочники.НоменклатураПрисоединенныеФайлы.Выбрать(, ОбъектНоменклатура);

Пока Выборка.Следующий() Цикл
    // Получаем объект для редактирования
    ОбъектФайл = Выборка.ПолучитьОбъект();
    
    // Выполняем физическое удаление из базы данных
    Попытка
        ОбъектФайл.Удалить();
    Исключение
        Сообщить("Не удалось удалить файл: " + ОписаниеОшибки());
    КонецПопытки;
КонецЦикла;

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

Способ №2: Оптимизированное удаление через запрос

Если в вашей базе данных огромное количество присоединенных файлов, использование прямой выборки может быть менее эффективным, чем использование запроса. Запрос работает быстрее на уровне СУБД и позволяет более гибко управлять данными. Например, мы можем захотеть удалить только файлы с определенным расширением (только картинки .jpg) или файлы, загруженные ранее определенной даты.

Разберем реализацию через запрос:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   НоменклатураПрисоединенныеФайлы.Ссылка КАК Ссылка
    |ИЗ
    |   Справочник.НоменклатураПрисоединенныеФайлы КАК НоменклатураПрисоединенныеФайлы
    |ГДЕ
    |   НоменклатураПрисоединенныеФайлы.Владелец = &Владелец";

Запрос.УстановитьПараметр("Владелец", СсылкаНаНоменклатуру);

РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();

Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
    // Важно: для удаления объекта его необходимо сначала получить
    ФайлОбъект = ВыборкаДетальныеЗаписи.Ссылка.ПолучитьОбъект();
    ФайлОбъект.Удалить();
КонецЦикла;

Важные технические нюансы и использование БСП

Хотя вышеуказанные способы решают задачу удаления записей из справочника, работа в современных конфигурациях (таких как УТ 11, ERP 2.5, КА 2.5) требует более глубокого понимания механизмов БСП. Выясним причину, по которой простое удаление объекта через Удалить() может быть не совсем корректным:

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

Для корректного удаления в типовых решениях рекомендуется использовать методы общего модуля ПрисоединенныеФайлы. Это гарантирует целостность данных во всех связанных таблицах.


// Пример использования механизмов БСП для удаления всех файлов владельца
МассивФайловДляУдаления = Новый Массив;
Выборка = Справочники.НоменклатураПрисоединенныеФайлы.Выбрать(, СсылкаНаНоменклатуру);

Пока Выборка.Следующий() Цикл
    МассивФайловДляУдаления.Добавить(Выборка.Ссылка);
КонецЦикла;

Если МассивФайловДляУдаления.Количество() > 0 Тогда
    // Используем штатный метод БСП (название метода может варьироваться от версии БСП)
    ПрисоединенныеФайлы.УдалитьФайлы(МассивФайловДляУдаления);
КонецЕсли;

Альтернативный подход: обновление вместо удаления

Проанализируем совет, данный в обсуждении (сообщения 25 и 26). Часто полное удаление — это избыточная операция. Если ваша цель — просто обновить фотографию, рассмотрите возможность проверки существования файла перед его перезаписью.

Почему это лучше?

Рассмотрим логику такого процесса: мы ищем, есть ли уже у номенклатуры присоединенный файл. Если есть — мы просто обновляем его двоичные данные. Если нет — создаем новый.


// Псевдокод логики обновления
ФайлСсылка = Справочники.НоменклатураПрисоединенныеФайлы.НайтиПоНаименованию("ОсновноеФото", Ложь, , СсылкаНаНоменклатуру);

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

Пометка на удаление против физического удаления

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

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

← На главную