Как исправить ошибку «Не найден внешний набор данных» в СКД 1С?

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

Использование внешних наборов данных (например, объект типа ТаблицаЗначений) в Системе компоновки данных (СКД) — это стандартный и мощный инструмент разработчика 1С. Однако при его реализации часто возникает досадная ошибка: «Не найден внешний набор данных "ИмяНабора"». При этом отчет может отлично работать в других базах или казаться абсолютно верным с точки зрения структуры кода.

В этой статье мы подробно разберем, почему возникает эта ошибка, проанализируем ключевые причины сбоя и рассмотрим по шагам правильные варианты программного вывода отчета СКД с внешним источником данных.

Причина №1. Использование настроек схемы по умолчанию

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

Если в вашем коде используется следующая строка для получения настроек:

Настройки = СхемаКомпоновкиДанных.НастройкиПоУмолчанию;

Система компоновки берет жестко заданную структуру из XML-схемы, игнорируя текущий контекст формы и компоновщика. В результате при формировании макета связь с переданным внешним набором данных теряется.

Правильное решение: всегда получайте настройки напрямую из компоновщика настроек формы отчета:

Настройки = КомпоновщикНастроек.ПолучитьНастройки();

Это позволяет системе использовать актуальные настройки пользователя (включая быстрые отборы, параметры и выбранные поля) и сопоставить их с вашим внешним источником данных.

Причина №2. Не отключена стандартная обработка формирования отчета

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

Для этого в модуле объекта отчета в предопределенной процедуре ПриКомпоновкеРезультата первым делом необходимо установить флаг отключения стандартного вывода:


Процедура ПриКомпоновкеРезультата(РезультатИдентификатор, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Ложь; // Отключаем авто-вывод платформы
    
    // Далее идет наш программный код формирования
    ...
КонецПроцедуры

Если этого не сделать, платформа попытается сформировать отчет дважды: сначала автоматически (где она не найдет вашу таблицу, так как та еще не передана), а затем программно. На первом же автоматическом шаге пользователь увидит ошибку отсутствия внешнего набора.

Причина №3. Полный шаблон правильного программного вывода отчета

Рассмотрим подробнее и разберем по шагам готовый шаблон кода для модуля объекта отчета. Этот алгоритм гарантирует корректную передачу внешнего набора данных ТаблицаДанных в процессор компоновки:


Процедура ПриКомпоновкеРезультата(РезультатИдентификатор, СтандартнаяОбработка)
	
	СтандартнаяОбработка = Ложь;
	
	// 1. Получаем саму схему и настройки
	СхемаКомпоновкиДанных = ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
	Настройки = КомпоновщикНастроек.ПолучитьНастройки();
	
	// 2. Формируем внешние данные (в реальной задаче здесь будет ваш запрос или алгоритм)
	ТаблицаДанных = Новый ТаблицаЗначений;
	ТаблицаДанных.Колонки.Добавить("Ссылка", Новый ОписаниеТипов("ДокументСсылка.ПриобретениеТоваровИУслуг"));
	ТаблицаДанных.Колонки.Добавить("СуммаРозн", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 2)));
	
	// Пример заполнения строки
	НоваяСтрока = ТаблицаДанных.Добавить();
	НоваяСтрока.Ссылка = Справочники.Номенклатура.ПустаяСсылка(); // или реальная ссылка
	НоваяСтрока.СуммаРозн = 100;

	// 3. Создаем структуру для передачи внешних наборов
	// Ключ структуры должен СТРОГО совпадать с полем "Имя объекта, содержащего данные" в СКД!
	ВнешниеНаборыДанных = Новый Структура;
	ВнешниеНаборыДанных.Вставить("ТаблДок", ТаблицаДанных);
	
	// 4. Инициализируем макет компоновки
	КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
	МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки, РезультатИдентификатор);
	
	// 5. Инициализируем процессор компоновки и передаем туда наши внешние наборы
	ПроцессорКомпоновкиДанных = Новый ПроцессорКомпоновкиДанных;
	ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпоновки, ВнешниеНаборыДанных);
	
	// 6. Выводим результат в табличный документ формы
	ДокументРезультат = Новый ТабличныйДокумент;
	ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
	ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
	ПроцессорВывода.Вывести(ПроцессорКомпоновкиДанных);
	
КонецПроцедуры

Причина №4. Несоответствие имен и регистра символов

Обратите особое внимание на инициализацию структуры внешних наборов данных. Платформа 1С крайне чувствительна к регистру символов и точному соответствию имен.

В схеме компоновки данных на вкладке «Наборы данных» для вашего набора типа «Объект» задается свойство «Имя объекта, содержащего данные». Если там написано значение "ТаблДок", то в коде ключ структуры должен выглядеть точно так же:

Причина №5. Ошибки контекста выполнения (Фоновые задания)

В современных конфигурациях (например, УТ 11.4, ERP, КА) отчеты по умолчанию могут формироваться асинхронно — в фоновом режиме на сервере. При этом фоновое задание не имеет прямого доступа к таблице значений, которая была сформирована в контексте клиентского сеанса.

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

Способы обхода проблемы:

  1. Отключить фоновое формирование отчета в настройках формы или модуля менеджера (отчет будет формироваться в основном сеансе).
  2. Передавать сформированную на клиенте таблицу на сервер через временное хранилище с помощью метода ПоместитьВоВременноеХранилище(), а уже в серверном коде фонового задания извлекать таблицу и передавать ее в СКД.

Альтернативный подход: Передача таблицы в запрос в качестве параметра

Если вам кажется, что механизм внешних наборов данных СКД слишком громоздкий или вы продолжаете сталкиваться с трудностями при интерактивных отборах или расшифровках, существует прекрасный альтернативный вариант.

Мы можем использовать стандартный набор данных типа «Запрос», а нашу готовую таблицу значений передать внутрь запроса как параметр.

Посмотрим на пример реализации данного подхода:


// 1. Создаем таблицу значений и строго типизируем ее колонки
ТабДок = Новый ТаблицаЗначений;
ОписаниеЧисла = Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 2));
ОписаниеСтроки = Новый ОписаниеТипов("Строка", Новый КвалификаторыСтроки(100));

ТабДок.Колонки.Добавить("Ссылка", Новый ОписаниеТипов("ДокументСсылка.ПриобретениеТоваровИУслуг"));
ТабДок.Колонки.Добавить("Номер", ОписаниеСтроки);
ТабДок.Колонки.Добавить("СуммаРозн", ОписаниеЧисла);

// 2. В СКД пишем обычный запрос, где используем параметр &ТабДок
// Схема компоновки сама поймет структуру, если мы опишем ее в запросе:
Выбрать
	ТабДок.Ссылка КАК Ссылка,
	ТабДок.Номер КАК Номер,
	ТабДок.СуммаРозн КАК СуммаРозн
ПОМЕСТИТЬ ВТ_ТаблицаДанных
ИЗ
	&ТабДок КАК ТабДок
;
//////////////////////////////////////////
Выбрать
	ВТ.Ссылка,
	ВТ.Номер,
	ВТ.СуммаРозн
ИЗ
	ВТ_ТаблицаДанных КАК ВТ

При таком подходе вам не нужно программно настраивать связи наборов данных в СКД — все связи и соединения таблиц будут выполняться внутри одного стандартного запроса на уровне СУБД, что значительно упрощает дальнейшую поддержку и исключает ошибки инициализации внешних источников.

← На главную