При разработке сложных отчетов на платформе 1С программисты часто сталкиваются с необходимостью предварительной обработки данных перед их выводом в компоновку. Стандартная схема «Запрос в СКД» заменяется на программное формирование ТаблицыЗначений, которая затем передается в схему как внешний набор данных. Именно на этом этапе часто возникает неприятная ошибка: «Ошибка при вызове метода контекста (Инициализировать): Ошибка компоновки данных: Ошибка инициализации: Не найдено поле замены "Ссылка"». Разберем подробно, почему это происходит и как правильно настроить передачу данных.
Ошибка инициализации процессора компоновки данных обычно происходит в момент выполнения метода Инициализировать() объекта ПроцессорКомпоновкиДанных. В этот момент система пытается сопоставить описание полей в схеме (СКД) с реальными колонками, которые мы передаем в структуре внешних наборов данных. Проанализируем ситуацию: если в настройках отчета (группировках, выбранных полях или условном оформлении) фигурирует поле с именем Ссылка, но в переданной ТаблицеЗначений система не может его однозначно идентифицировать, возникает конфликт.
Важный нюанс: Поле Ссылка является для платформы 1С системным. При использовании внешних наборов данных механизм «полей замены» может давать сбой, если имя поля совпадает с ключевыми словами или если нарушена типизация. Рассмотрим основные способы решения этой проблемы.
Одной из самых частых причин ошибки является конфликт имен. Рассмотрим ситуацию, когда в запросе мы выбираем поле Ссылка. Проанализируем, как лучше изменить код, чтобы избежать двусмысленности для процессора компоновки.
Вместо стандартного именования в запросе рекомендуется использовать уникальный псевдоним (алиас), который точно не будет конфликтовать с системными полями:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| РеализацияТоваровУслуг.Ссылка КАК ДокументРеализации,
| ижЗаказы.ZAK_POTR КАК НомерЗаказа,
| "" "" КАК Сканы
|ИЗ
| Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
|... ";
После изменения текста запроса необходимо выполнить следующие действия в конструкторе СКД (поможет консоль отладки запросов и СКД):
Ссылка на ДокументРеализации.Ссылка во всех группировках и выбранных полях на новое поле ДокументРеализации.Выясним причину, связанную с программным кодом вызова. Часто ошибка «поле замены не найдено» является следствием того, что процессор компоновки вообще не видит вашу таблицу данных из-за опечатки в названии набора. Посмотрим на пример типичной ошибки:
// В СКД имя набора данных указано как "ДанныеСканы"
НаборДанных = Новый Структура("ДанныеСканы", ТаблицаРезультат);
ПроцессорКомпоновкиДанных = Новый ПроцессорКомпоновкиДанных;
// Ошибка будет здесь, если в структуре передано неверное имя ключа
ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпоновки, НаборДанных, ДанныеРасшифровки);
Проанализируем ситуацию подробнее: ключ в объекте Структура, который передается вторым параметром в метод Инициализировать, должен символ в символ совпадать с именем набора данных в схеме компоновки. Если в схеме вы назвали набор НаборДанных1, а в коде передаете ДанныеСканы, система не найдет соответствия и выдаст ошибку о полях замены, так как для нее все поля схемы останутся «пустыми».
Разберем ситуацию, когда типы данных в ТаблицеЗначений после выгрузки из запроса становятся «грязными». При выгрузке результата запроса в таблицу (Запрос.Выполнить().Выгрузить()), колонки часто получают составной тип данных, включающий NULL. СКД при работе с внешними источниками иногда крайне чувствительна к таким моментам.
Посмотрим, как можно программно очистить типы колонок, чтобы СКД корректно их восприняла:
Данные = Запрос.Выполнить().Выгрузить();
Для Каждого Колонка Из Данные.Колонки Цикл
// Вычитаем тип NULL из описания типов колонки
Колонка.ТипЗначения = Новый ОписаниеТипов(Колонка.ТипЗначения, , "NULL");
КонецЦикла;
Этот прием позволяет оставить в колонке только конкретные ссылочные или примитивные типы, что помогает процессору компоновки правильно сопоставить поля макета и данные таблицы.
Иногда решение проблемы кроется не в коде, а в поведении платформы. Рассмотрим сценарий: вы изменили имя поля в конфигураторе (например, со Ссылка на Реализация), сохранили отчет, но ошибка сохраняется. Проанализируем, почему это происходит.
Система 1С сохраняет настройки отчетов для пользователей. Если вы ранее открывали отчет, в ваших сохраненных настройках (в базе данных) всё еще может числиться поле Ссылка. Когда процессор компоновки пытается выполнить отчет с вашими старыми настройками, он ищет поле Ссылка, которого в новом макете уже нет.
Рекомендация: При любых изменениях состава полей во внешнем наборе данных в режиме «1С:Предприятие» необходимо выполнить следующие действия:
Подведем итог и соберем воедино правильный код процедуры ПриКомпоновкеРезультата, учитывающий все разобранные нами нюансы. Проанализируем этот пример как эталонный:
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
// 1. Формируем данные
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ Ссылка КАК РеализацияСсылка, ... ИЗ Документ.РеализацияТоваровУслуг";
ТаблицаДанных = Запрос.Выполнить().Выгрузить();
// Дополнительная обработка таблицы (например, заполнение путей к файлам)
// ...
// 2. Получаем схему и настройки
СКД = ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
Настройки = КомпоновщикНастроек.ПолучитьНастройки();
// 3. Подготавливаем расшифровку и макет
ДанныеРасшифровки = Новый ДанныеРасшифровкиКомпоновкиДанных;
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СКД, Настройки, ДанныеРасшифровки);
// 4. Инициализируем процессор компоновки
// Важно: Имя "ВнешнийНаборДанных" должно совпадать с именем в СКД!
ВнешниеНаборы = Новый Структура("ВнешнийНаборДанных", ТаблицаДанных);
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, ВнешниеНаборы, ДанныеРасшифровки);
// 5. Вывод результата
ДокументРезультат.Очистить();
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
КонецПроцедуры
Соблюдение этих правил: уникальные имена полей, строгое соответствие имен наборов и очистка типов данных — гарантирует стабильную работу отчетов СКД с внешними источниками данных без ошибок инициализации.