Как в 1С 7.7 выбрать и выгрузить в Excel только группы справочника и их родителей?

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

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

Особенности и ограничения платформы 1С 7.7

Прежде чем приступать к написанию кода, проанализируем поведение встроенного языка и ядра базы данных 1С 7.7:

  1. Синтаксис штатного запроса: Во встроенном языке запросов 1С 7.7 присутствует директива Без Групп, однако обратной конструкции (например, Только Группы) разработчиками платформы предусмотрено не было.
  2. Особенности штатного («черного») запроса: Если мы строим штатный запрос и накладываем конструкцию вида Условие(Спр.ЭтоГруппа() = 1), платформа все равно выполняет полное сканирование всей таблицы справочника, формируя промежуточные временные файлы. При огромном числе элементов такой запрос работает медленно и создает повышенную нагрузку на дисковую подсистему.
  3. Метод ВыбратьЭлементы(): Стандартный обход справочника перебирает и папки, и элементы, требуя программной фильтрации через метод ЭтоГруппа().

Вариант 1. Перебор справочника с программным отбором и получением цепочки родителей

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

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


Таб = СоздатьОбъект("Таблица");
// Предположим, что в макете настроены секции "Шапка" и "Строка"
Таб.ВывестиСекцию("Шапка");

Спр = СоздатьОбъект("Справочник.Номенклатура");
// 0 - отключаем иерархический порядок для ускорения линейного чтения
Спр.ВыбратьЭлементы(0);

Пока Спр.ПолучитьЭлемент() = 1 Цикл
    Если Спр.ЭтоГруппа() = 1 Тогда
        ТекГруппа = Спр.ТекущийЭлемент();
        КодГруппы = ТекГруппа.Код;
        НаимГруппы = ТекГруппа.Наименование;
        
        Родитель = ТекГруппа.Родитель;
        Если Родитель.Выбран() = 1 Тогда
            КодРодителя = Родитель.Код;
            НаимРодителя = Родитель.Наименование;
        Иначе
            КодРодителя = "";
            НаимРодителя = "<Корень>";
        КонецЕсли;
        
        // Сбор полной цепочки всех вышестоящих родителей
        ВсеРодители = "";
        ВременныйРодитель = Родитель;
        Пока ВременныйРодитель.Выбран() = 1 Цикл
            ВсеРодители = ВременныйРодитель.Наименование + " / " + ВсеРодители;
            ВременныйРодитель = ВременныйРодитель.Родитель;
        КонецЦикла;
        
        Таб.ВывестиСекцию("Строка");
    КонецЕсли;
КонецЦикла;

// Выгружаем результат в формат Excel
Таб.Записать("C:\Export_Groups.xls", "XLS");

Этот способ универсален, работает как в файловом (DBF), так и в клиент-серверном (SQL) вариантах информационной базы и не требует сторонних компонентов.

Вариант 2. Быстрая выборка через метод ВыбратьЭлементыПоРеквизиту

Малоизвестная, но крайне полезная возможность встроенного языка 1С 7.7 — четвертый параметр метода ВыбратьЭлементыПоРеквизиту(). Синтаксис метода выглядит так:

ВыбратьЭлементыПоРеквизиту(<ИмяРеквизита>, <Значение>, <РежимИерархии>, <РежимГрупп>)

Если для справочника определен реквизит с признаком отбора или сортировки (например, общий реквизит или специальный системный признак), передача значения 1 в параметре <РежимГрупп> заставляет движок 1С считывать исключительно группы, полностью игнорируя элементы:

  1. 1 — выбирать только среди групп;
  2. 0 — выбирать только среди элементов.

Такой подход в разы сокращает время обхода на объемных базах данных.

Вариант 3. Прямой SQL-запрос для баз на MS SQL Server

Если информационная база работает под управлением Microsoft SQL Server и в конфигурации подключен класс прямого доступа к данным (например, компонента 1С++ или соединение через ADO), наиболее быстрым решением будет прямой запрос к физической таблице справочника.

В структуре базы 1С 7.7 признак типа записи хранится в колонке ISFOLDER:

  1. 1 — группа (папка);
  2. 2 — элемент справочника.

Разберем пример SQL-запроса, возвращающего папки, их коды и идентификаторы непосредственных родителей:


SELECT 
    s.CODE AS Код,
    s.DESCR AS Наименование,
    p.CODE AS КодРодителя,
    p.DESCR AS НаименованиеРодителя
FROM $Справочник.Номенклатура s (NOLOCK)
LEFT JOIN $Справочник.Номенклатура p (NOLOCK) ON s.PARENTID = p.ID
WHERE s.ISFOLDER = 1

Такой запрос отрабатывает на стороне СУБД за доли секунды, так как сервер отсекает элементы на уровне индекса и возвращает только необходимые записи каталога.

Вариант 4. Прямое чтение файла DBF через объект XBase

Для файловых версий информационных баз можно обойти медлительность объектной модели 1С, прочитав таблицу справочника напрямую с помощью встроенного объекта XBase. Файлы справочников имеют имена вида SC*.dbf (точный номер файла можно определить в словаре данных 1CV7.DD).

Посмотрим на пример:


ФайлБД = СоздатьОбъект("XBase");
ФайлБД.ОткрытьФайл(КаталогИБ() + "SC123.DBF");

Если ФайлБД.Открыта() = 1 Тогда
    Пока ФайлБД.ВКонце() = 0 Цикл
        // Проверяем поле ISFOLDER: 1 - папка, 2 - элемент
        Если ФайлБД.ISFOLDER = 1 Тогда
            Код = СокрЛП(ФайлБД.CODE);
            Наименование = СокрЛП(ФайлБД.DESCR);
            РодительID = СокрЛП(ФайлБД.PARENTID);
            // Обработка полученных данных папки
        КонецЕсли;
        ФайлБД.Следующая();
    КонецЦикла;
    ФайлБД.ЗакрытьФайл();
КонецЕсли;

Выгрузка полученных данных в Excel

Для экспорта полученных данных без использования COM-объекта приложения Excel (что особенно критично при больших объемах строк) рекомендуется использовать два пути:

  1. Метод объекта «Таблица»: Заполнить объект Таблица и сохранить его с помощью команды Таб.Записать("файл.xls", "XLS") или Таб.Записать("файл.xls", 1). Этот способ создает нативный файл Excel силами самой платформы 1С 7.7.
  2. Формирование CSV через объект «Текст»: Если папок очень много, быстрее всего сгенерировать текстовый файл с разделителями (точками с запятой). Excel открывает такой файл напрямую без лишних затрат памяти.

Посмотрим на пример быстрого экспорта через CSV:


Тхт = СоздатьОбъект("Текст");
Тхт.ДобавитьСтроку("Код;Наименование;КодРодителя;Родитель");

// В цикле обхода папок добавляем строки:
СтрокаДанных = КодГруппы + ";" + НаимГруппы + ";" + КодРодителя + ";" + НаимРодителя;
Тхт.ДобавитьСтроку(СтрокаДанных);

Тхт.Записать("C:\Groups.csv");

Таким образом, для небольших каталогов достаточно воспользоваться перебором с условием ЭтоГруппа() = 1, а для ускорения обработки на крупных базах оптимально применять прямое обращение через SQL или метод ВыбратьЭлементыПоРеквизиту.

← На главную