При разработке отчетов и механизмов интеграции в платформе 1С:Предприятие 7.7 разработчики нередко сталкиваются с ситуацией: при выполнении запроса по иерархическому справочнику у детальных записей (элементов) наименование выводится корректно, а у строк, представляющих группы (папки), поле Наименование оказывается пустым.
Разберем причины такого поведения платформы 1С 7.7 и рассмотрим практические способы решения этой проблемы.
Проанализируем механику работы встроенного языка запросов платформы 1С 7.7 (так называемых «чёрных запросов»). При формировании выборки платформа выполняет следующие действия:
Наименование, Код, так и пользовательские реквизиты), считываются только для найденных элементов.Посмотрим на пример текста запроса, в котором проявляется данная проблема:
Запрос = СоздатьОбъект("Запрос");
ТекстЗапроса = "
|Ссылка = Справочник.Проекты.ТекущийЭлемент;
|Родитель = Справочник.Проекты.Родитель;
|Наименование = Справочник.Проекты.Наименование;
|Группировка Ссылка Без упорядочивания Все;
|";
Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
Предупреждение("Ошибка выполнения запроса!");
Возврат;
КонецЕсли;
ТабЗнач = СоздатьОбъект("ТаблицаЗначений");
Запрос.Выгрузить(ТабЗнач, 1, 0);
В выгруженной таблице значений колонка Наименование для строк, где значение колонки Ссылка является группой, будет пустой строкой.
Если требуется сохранить структуру выгрузки таблицы значений через запрос (например, при передаче данных через OLE/COM-соединение во внешнее приложение), наиболее простым решением является обход результирующей таблицы и заполнение пустых значений через обращение к свойствам объекта.
Рассмотрим по шагам реализацию постобработки:
ТабЗнач = СоздатьОбъект("ТаблицаЗначений");
Запрос.Выгрузить(ТабЗнач, 1, 0);
ТабЗнач.ВыбратьСтроки();
Пока ТабЗнач.ПолучитьСтроку() = 1 Цикл
// Проверяем, заполнено ли наименование
Если ПустоеЗначение(ТабЗнач.Наименование) = 1 Тогда
Если ПустоеЗначение(ТабЗнач.Ссылка) = 0 Тогда
// Получаем наименование напрямую из ссылки на объект
ТабЗнач.Наименование = ТабЗнач.Ссылка.Наименование;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Этот подход позволяет гарантированно заполнить наименования для всех уровней иерархии без изменения структуры запроса.
Если для задачи не требуется сложный механизм агрегации итогов, встроенный запрос часто бывает избыточным. При интеграциях через COM или обработке данных внутри базы значительно быстрее и надежнее использовать прямое сканирование справочника с помощью метода ВыбратьЭлементы().
В объектной модели 1С 7.7 реквизиты Наименование и Код считываются одинаково корректно как для элементов, так и для папок.
Разберем пример обхода справочника с заполнением таблицы значений:
ТабЗнач = СоздатьОбъект("ТаблицаЗначений");
ТабЗнач.НоваяКолонка("Ссылка");
ТабЗнач.НоваяКолонка("Родитель");
ТабЗнач.НоваяКолонка("Наименование", "Строка");
ТабЗнач.НоваяКолонка("ЭтоГруппа", "Число");
Спр = СоздатьОбъект("Справочник.Проекты");
// Выбираем все элементы с учетом иерархии
Спр.ВыбратьЭлементы(1);
Пока Спр.ПолучитьЭлемент() = 1 Цикл
ТабЗнач.НоваяСтрока();
ТабЗнач.Ссылка = Спр.ТекущийЭлемент();
ТабЗнач.Родитель = Спр.Родитель;
ТабЗнач.Наименование = Спр.Наименование;
ТабЗнач.ЭтоГруппа = Спр.ЭтоГруппа(); // 1 - папка, 0 - элемент
КонецЦикла;
Преимущества данного метода:
Если в результирующем наборе папки справочника не нужны, а требуются только конечные элементы для дальнейших расчетов, достаточно модифицировать строку группировки в тексте запроса, добавив параметр Без Групп.
Посмотрим на пример:
ТекстЗапроса = "
|Ссылка = Справочник.Проекты.ТекущийЭлемент;
|Родитель = Справочник.Проекты.Родитель;
|Наименование = Справочник.Проекты.Наименование;
|Группировка Ссылка Без упорядочивания Без Групп;
|";
В этом случае платформа полностью исключит виртуальные группировочные строки, а в таблице останутся только элементы с корректно заполненными наименованиями.
В случаях, когда 1С 7.7 работает на базе данных MS SQL Server, а выгрузка выполняется через внешние компоненты прямого доступа или ADO, встроенные платформенные ограничения можно обойти прямым SQL-запросом к таблице справочника.
В структуре таблиц 1С 7.7 справочники хранятся в таблицах с префиксом SC. Поле ISFOLDER определяет тип записи (1 — группа, 2 — элемент), а поля DESCR (наименование) и CODE (код) присутствуют во всех строках таблицы одинаково.
Пример прямого запроса:
SELECT
ID as [Ссылка],
DESCR as [Наименование],
CODE as [Код],
PARENTID as [Родитель],
ISFOLDER as [ЭтоГруппа]
FROM SC1234 (NOLOCK)
WHERE ISMARK = 0
Прямой запрос выполняется значительно быстрее и исключает проблему незаполненных наименований на уровне архитектуры СУБД.