Как получить иерархию папок Windows в 1С и связать их с номенклатурой

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

В процессе автоматизации учета часто возникает задача синхронизации файловой структуры на сервере или локальном компьютере с объектами информационной базы 1С. Например, когда изображения или документация хранятся в папках, названия которых соответствуют кодам номенклатуры. В этой статье мы подробно разберем, как реализовать механизм получения иерархии папок Windows и автоматизировать привязку путей к справочнику номенклатуры.

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

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

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


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

В данном коде метод НайтиФайлы возвращает объекты типа Файл, которые содержат полезные свойства: Имя, ПолноеИмя, ЭтоКаталог. Использование рекурсии позволяет нам "провалиться" на любую глубину вложенности папок Windows.

Сопоставление имен папок с кодом номенклатуры

Разберем конкретный кейс: имя папки — это код товара в 1С. Если мы находим такую папку, нам нужно записать её полный путь в дополнительный реквизит соответствующей номенклатуры. Проанализируем, как правильно организовать этот процесс внутри цикла обхода.

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


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

Выбор каталога пользователем

Для того чтобы запустить процесс, пользователю необходимо выбрать стартовую папку. Выясним, как правильно вызвать диалог выбора каталога на управляемых формах. Рассмотрим обработчик события начала выбора для реквизита на форме.


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

Обратите внимание, что объект ДиалогВыбораФайла работает только на стороне клиента. После выбора пути управление передается серверной процедуре для выполнения обхода.

Оптимизация производительности: использование запросов

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

Алгоритм оптимизации выглядит следующим образом:

  1. Выполняем полный рекурсивный обход папок и записываем все пары (ИмяПапки, ПолныйПуть) в ТаблицаЗначений.
  2. Передаем эту таблицу в запрос к справочнику Номенклатура.
  3. В запросе соединяем таблицу имен папок с кодами номенклатуры.
  4. Массово обрабатываем только те объекты, по которым найдены совпадения.

Посмотрим на пример формирования таблицы данных:


// Пример заполнения таблицы перед запросом
ТЗ_Папки = Новый ТаблицаЗначений;
ТЗ_Папки.Колонки.Добавить("КодДляПоиска", Новый ОписаниеТипов("Строка", Новый КвалификаторыСтроки(50)));
ТЗ_Папки.Колонки.Добавить("ПолныйПуть", Новый ОписаниеТипов("Строка", Новый КвалификаторыСтроки(500)));

// В рекурсии вместо поиска в БД делаем так:
НоваяСтр = ТЗ_Папки.Добавить();
НоваяСтр.КодДляПоиска = Файл.Имя;
НоваяСтр.ПолныйПуть = Файл.ПолноеИмя;

Альтернативные методы получения структуры папок

Иногда стандартный НайтиФайлы может работать медленно на огромных сетевых ресурсах. Проанализируем альтернативные варианты:

  1. Использование COM-объекта FileSystemObject (FSO): Этот метод часто работает быстрее в среде Windows. Мы создаем объект Новый COMОбъект("Scripting.FileSystemObject") и обращаемся к коллекции SubFolders. Это позволяет получать доступ к метаданным папок без глубокого сканирования содержимого.
  2. Вызов командной строки (CMD): С помощью команды TREE /AD /F > result.txt можно мгновенно выгрузить всю структуру папок в текстовый файл, который затем легко прочитать и распарсить средствами 1С. Это особенно эффективно для очень ветвистых структур.
  3. PowerShell: Современный способ получения данных через Get-ChildItem. Результат можно получить сразу в формате CSV или JSON, что упрощает загрузку в 1С.

Безопасность и обработка исключений

При работе с файловой системой Windows в 1С важно учитывать права доступа. Рассмотрим ситуации, которые могут привести к ошибкам:

Проанализировав все вышеперечисленные методы, мы видим, что задача получения иерархии папок Windows в 1С решается достаточно гибко. Выбор конкретного метода зависит от объема данных и требуемой скорости обработки. Для небольших структур идеально подходит рекурсия с НайтиФайлы, а для промышленных масштабов лучше использовать предварительный сбор данных в массив и пакетную обработку через запросы.

← На главную