Как исправить ошибку «Не найден внешний набор данных» и связать таблицу значений в СКД

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

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

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

Анализ ошибки инициализации: почему «исчезает» внешний набор данных

Рассмотрим ситуацию, с которой столкнулся автор темы. В процедуре вывода отчета подготавливается внешняя таблица значений, которая затем передается в структуру для инициализации компоновщика. Однако при формировании отчета система выдает ошибку: «Не найден внешний набор данных».

Давайте внимательно изучим фрагмент кода, содержащий критическую ошибку:


пПериод = Настройки.ПараметрыДанных.Элементы.Найти("Период");
Если пПериод <> Неопределено Тогда
    ТабКолУб = ПолучитьТЗКолУбыли(пПериод.Значение);
    ВнешнийНаборДанных = Новый Структура("ТабКолУб", ТабКолУб); 
    ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных; 
    ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, ВнешнийНаборДанных);
Иначе
    ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных; 
    ПроцессорКомпоновки.Инициализировать(МакетКомпоновки);
КонецЕсли;

// КРИТИЧЕСКАЯ ОШИБКА:
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных; 
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки);

Выясним причину сбоя. В блоке Если ... КонецЕсли логика написана верно: если параметр периода найден, то создается структура ВнешнийНаборДанных, которая передается в метод Инициализировать объекта ПроцессорКомпоновкиДанных.

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

Правильный шаблон программного вывода отчета СКД с внешним набором данных

Чтобы избежать подобных ошибок, напишем чистый и надежный шаблон для вывода отчета. Обратите внимание, что мы должны четко контролировать наполнение структуры внешних наборов данных и инициализировать процессор компоновки строго один раз.


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

Разбор ошибки: «Не найдено поле замены [ИмяПоля]»

Вторая проблема, описанная автором: при попытке добавить в связь наборов или в выводимые поля числовой показатель (в данном случае — Количество) возникает ошибка «Не найдено поле замены Количество».

Давайте детально проанализируем причины этой ошибки и способы ее локализации:

  1. Отключенное автозаполнение (Автозаполнение = Ложь) в СКД. Когда для внешнего набора данных снят флаг автозаполнения, система компоновки не пытается автоматически сопоставить поля таблицы значений с полями схемы. Вы обязаны вручную добавить каждое поле (включая ресурсы и поля связи) на вкладке «Наборы данных» и настроить их параметры. Если вы добавили колонку в таблицу значений в коде, но забыли описать ее в полях набора данных СКД, возникнет ошибка компоновки.
  2. Несовпадение имен колонок. Имена колонок во внешней таблице значений чувствительны к регистру и должны символ в символ совпадать с именами полей, объявленными во внешнем наборе в СКД. Если в схеме написано Количество, а в коде колонка таблицы значений создана как количество или КОЛИЧЕСТВО, СКД выдаст ошибку отсутствия поля замены.
  3. Жесткая («Обязательная») связь между наборами. Перейдем на вкладку «Связи наборов данных». По умолчанию при создании связи СКД может установить флаг «Обязательная связь». Если во внешнем наборе данных по какой-то причине нет строк (таблица пустая) либо значения в ключевых полях связи (Организация, Контрагент, Период) не сопоставляются, обязательная связь приводит к фатальному сбою компоновки макета. Снимите флаг «Обязательная» в строке связи наборов — это сделает соединение аналогичным левому соединению (Left Join) в SQL, и отчет сформируется без ошибок, даже если внешние данные пусты.
  4. Отсутствие типизации колонок в Таблице Значений. Для полей внешнего набора в СКД критически важно задавать типы данных. Если в коде при создании таблицы значений вы не определили тип для колонки (например, написали просто Таблица.Колонки.Добавить("Количество")), система может передать туда значения типа Неопределено или типы, не поддающиеся сравнению, что приведет к краху алгоритмов сопоставления полей связи в СКД.

Чек-лист для проверки связи с внешним набором данных

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

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

← На главную