Рассмотрим задачу загрузки данных в 1С:Предприятие 7.7 из файла Excel, когда исходные данные имеют сложную структуру с вложенностью. Часто при переносе классификаторов (например, ОКОФ или номенклатуры) мы сталкиваемся с ситуацией, где иерархия зашифрована в самом коде элемента.
Разберем пример, где структура кодов выглядит следующим образом:
Наша цель — написать обработку, которая корректно создаст дерево папок и поместит элементы в нужные родительские группы.
Для платформы 1С 7.7 существует несколько подходов к загрузке иерархии. Наиболее надежный способ, который мы проанализируем, заключается в использовании предварительной загрузки данных в ТаблицаЗначений или построчной обработке с логическим вычислением родителя.
Основная сложность заключается в том, чтобы при создании элемента или подгруппы их «Родитель» (группа вышестоящего уровня) уже существовал в базе данных. Поэтому мы будем использовать алгоритм проверки существования родителя и его поиска по коду.
Исходя из структуры кодов, предложенной в задаче, мы можем выделить закономерности:
Посмотрим на рабочий пример кода, который реализует эту логику. В данном случае данные сначала считываются из Excel, а затем проходят через каскад условий для определения типа создаваемого объекта (группа или элемент) и его места в иерархии.
Предположим, что мы перебираем строки файла Excel или Таблицы Значений, куда уже загрузили данные:
// Создаем объект справочника один раз перед циклом (рекомендуемый подход)
Спр = СоздатьОбъект("Справочник.ОсновныеСредства");
СпрПоиск = СоздатьОбъект("Справочник.ОсновныеСредства");
// Допустим, переменные Код и Название уже получены из ячейки Excel
// Анализируем длину кода
Если СтрДлина(Код) = 3 Тогда
// Вычисляем предполагаемый код корневой группы (например, из 110 получаем 100)
ПерваяЦифра = Лев(Код, 1);
КодКорневойГруппы = ПерваяЦифра + "00";
РазницаКодов = Число(Код) - Число(КодКорневойГруппы);
// СЛУЧАЙ 1: Это группа первого уровня (100, 200)
// Разница равна 0, и такой группы еще нет
Если (РазницаКодов = 0) И (Спр.НайтиПоКоду(Код) = 0) Тогда
Спр.НоваяГруппа();
Спр.Код = Код;
Спр.Наименование = Название;
Спр.Записать();
// СЛУЧАЙ 2: Это подгруппа (110, 120)
// Разница больше 0, такой группы нет
ИначеЕсли (РазницаКодов > 0) И (Спр.НайтиПоКоду(Код) = 0) Тогда
// Ищем родителя (группу 100)
Если СпрПоиск.НайтиПоКоду(КодКорневойГруппы) = 1 Тогда
Спр.НоваяГруппа();
Спр.Код = Код;
Спр.Наименование = Название;
// Устанавливаем родителя
Спр.Родитель = СпрПоиск.ТекущийЭлемент();
Спр.Записать();
Иначе
Сообщить("Родительская группа " + КодКорневойГруппы + " не найдена!");
КонецЕсли;
КонецЕсли;
// СЛУЧАЙ 3: Это элемент (код длиннее 4 символов, например 110.105.00)
ИначеЕсли (СтрДлина(Код) > 4) И (Спр.НайтиПоКоду(Код) = 0) Тогда
// Вычисляем код родителя (первые 3 символа, т.е. 110)
КодРодителя = Лев(Код, 3);
// Ищем родительскую подгруппу
Если СпрПоиск.НайтиПоКоду(КодРодителя) = 1 Тогда
Спр.Новый(); // Создаем элемент, а не группу
Спр.Код = Код;
Спр.Наименование = Название;
Спр.Родитель = СпрПоиск.ТекущийЭлемент();
Спр.Записать();
Иначе
Сообщить("Родитель для элемента " + Код + " не найден!");
КонецЕсли;
КонецЕсли;
При написании подобных обработок в 1С 7.7 обратите внимание на следующие моменты:
Cells) работает медленно. Если строк много, лучше сначала загрузить данные в объект ТаблицаЗначений или сохранить Excel как текстовый файл (CSV) и читать его через объект Текст.СоздатьОбъект. Старайтесь выносить создание объекта справочника за пределы цикла перебора строк. Многократное создание и уничтожение COM-объектов внутри цикла может приводить к утечкам памяти и замедлению работы.ТаблицаЗначений, отсортировать её по колонке кода, и только потом создавать элементы справочника.
НачатьТранзакцию();
// ... цикл загрузки ...
ЗафиксироватьТранзакцию();
Таким образом, используя методы работы со строками (Лев, СтрДлина) и методы справочника (НайтиПоКоду, Родитель), можно восстановить любую иерархию при загрузке данных.