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

Программист 1С v7.7
← На главную

В платформе 1С:Предприятие 7.7 работа со связями между справочниками имеет свои особенности, отличающиеся от современных версий 8.х. Часто возникает задача собрать данные из подчиненного справочника (например, список детей или проживающих) для конкретного владельца (родителя или клиента) и структурировать их в объекте ТаблицаЗначений. Рассмотрим подробно, как это реализовать несколькими способами, проанализируем нюансы работы с объектами и способы оптимизации кода.

Метод 1: Использование объектной модели и выборки элементов

Это классический способ, который чаще всего используется в небольших обработках и отчетах. Суть метода заключается в создании объекта справочника, установке фильтра по владельцу и переборе всех найденных записей в цикле. Разберем по шагам, как правильно «затолкать» данные в таблицу значений (ТЗ).

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


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

После подготовки структуры таблицы перейдем к заполнению. Предположим, у нас уже есть выбранный родитель (объект ФизЛицо или Клиент). Чтобы получить его детей из подчиненного справочника Проживающие, воспользуемся методом ИспользоватьВладельца.


// Создаем объект подчиненного справочника
СпрДети = СоздатьОбъект("Справочник.Проживающие");

// Устанавливаем фильтр по владельцу
СпрДети.ИспользоватьВладельца(ВыбранныйРодитель);

// Начинаем выборку элементов
СпрДети.ВыбратьЭлементы();

// Перебираем элементы в цикле
Пока СпрДети.ПолучитьЭлемент() = 1 Цикл
    // Добавляем новую строку в нашу таблицу значений
    ТЗ.НоваяСтрока();
    
    // Заполняем колонки данными из текущего элемента выборки
    ТЗ.Родитель = ВыбранныйРодитель;
    ТЗ.Ребенок = СпрДети.ТекущийЭлемент();
    
    // Если в справочнике есть дополнительные реквизиты, записываем и их
    ТЗ.ДатаРождения = СпрДети.ДатаРождения;
КонецЦикла;

Важно помнить: метод ИспользоватьВладельца сбрасывает текущую позицию справочника, поэтому его нужно вызывать строго перед ВыбратьЭлементы. Если вы хотите получить данные сразу по всем родителям, этот блок кода необходимо поместить внутрь внешнего цикла по родителям.

Метод 2: Получение данных через объект Запрос

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

Текст запроса в 7.7 пишется на встроенном языке описания запросов и позволяет сразу сгруппировать данные по владельцам.


// Описываем текст запроса
ТекстЗапроса = "
|ТекущийЭлемент = Справочник.Проживающие.ТекущийЭлемент;
|Владелец = Справочник.Проживающие.Владелец;
|Группировка Владелец без групп;
|Группировка ТекущийЭлемент без групп;
|";

Запрос = СоздатьОбъект("Запрос");
Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
    Возврат;
КонецЕсли;

// Выгружаем результат запроса напрямую в Таблицу Значений
Запрос.Выгрузить(ТЗ, 0, 0);

Метод Выгрузить у объекта Запрос — это один из самых быстрых способов наполнения ТаблицыЗначений. Система автоматически создаст необходимые колонки и заполнит их данными. Однако стоит учитывать, что имена колонок в ТЗ будут соответствовать именам переменных в запросе (в нашем примере — Владелец и ТекущийЭлемент).

Нюансы и типичные ошибки

Рассмотрим ситуацию, упомянутую в обсуждении: справочник Проживающие подчинен справочнику Клиенты, а не ФизЛица напрямую. В таком случае крайне важно передавать в метод ИспользоватьВладельца именно элемент справочника-владельца. Если вы попытаетесь передать ссылку на ФизЛицо, когда справочник ожидает Клиента, выборка будет пустой.

Проанализируем также метод ВыбратьЭлементы. У него есть параметры, которые могут быть полезны:

  1. Способ иерархии: Если в подчиненном справочнике есть группы, используйте ВыбратьЭлементы(0), чтобы получить линейный список без учета иерархии (только элементы).
  2. Работа с удаленными: По умолчанию удаленные элементы (помеченные на удаление) не попадают в выборку Запроса, но попадают в ВыбратьЭлементы. Если вам нужно исключить их в цикле, добавьте проверку Спр.ПометкаУдаления() = 0.

Важный совет: При заполнении ТаблицыЗначений в цикле (как в Методе 1), если вы работаете с очень большим объемом данных, рекомендуется отключать автоматический пересчет и обновление экранных форм (если ТЗ выведена на форму), это ускорит процесс заполнения.

Оптимизация производительности (Direct SQL)

Выясним причину, по которой стандартные методы могут работать медленно. 1С 7.7 при каждом вызове ПолучитьЭлемент() делает отдельное обращение к базе данных (проблема N+1). Для профессиональной разработки в среде 7.7 часто применяют внешнюю компоненту 1С++. Она позволяет написать прямой SQL-запрос к таблицам справочников.

Пример логики SQL-запроса (в терминах 1С++):


// Пример схематичного SQL-запроса через 1С++
ТекстSQL = "
|SELECT 
|   child.ID as [Ребенок $Справочник.Проживающие],
|   child.PARENTEXT as [Родитель $Справочник.Клиенты]
|FROM 
|   $Справочник.Проживающие as child
|WHERE 
|   child.PARENTEXT IN (SELECT ID FROM $Справочник.Клиенты WHERE ...)
|";

Такой подход позволяет получить тысячи записей за доли секунды, что критично для крупных систем ЖКХ или кадрового учета, где количество "проживающих" или "детей" может исчисляться десятками тысяч.

Подводя итог, выбор метода зависит от вашей задачи. Если нужно быстро "набросать" код для вывода детей одного родителя — используйте ИспользоватьВладельца. Если нужно собрать данные для отчета по всей базе — используйте объект Запрос или прямые запросы SQL.

← На главную