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

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

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

Анализ программного вывода отчета

Рассмотрим типичный код формирования отчета, который часто становится источником проблем. Разберем пример, представленный в обсуждении, и проанализируем его слабые места:


СтандартнаяОбработка = Ложь;

ТЗ = ПолучитьТаблицуДанных();

Настройки = КомпоновщикНастроек.Настройки;
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки, ДанныеРасшифровки);

ВнешниеНаборыДанных = Новый Структура;
ВнешниеНаборыДанных.Вставить("ТЗ", ТЗ);

ПроцессорКомпоновкиДанных = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпоновки, ВнешниеНаборыДанных, ДанныеРасшифровки);

ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
ПроцессорВывода.Вывести(ПроцессорКомпоновкиДанных);

На первый взгляд код выглядит стандартно, однако в нем кроется фундаментальная проблема взаимодействия с компоновщиком настроек. Когда мы обращаемся напрямую к свойству КомпоновщикНастроек.Настройки, мы получаем текущее состояние настроек «как есть». Проблема заключается в том, что пользовательские изменения (отборы, выбранные поля, группировки) могут находиться в свойстве ПользовательскиеНастройки и не быть окончательно синхронизированы с основным объектом настроек в момент первого запуска.

Решение №1: Всегда используйте метод ПолучитьНастройки(). Этот метод собирает воедино основные и пользовательские настройки, гарантируя, что МакетКомпоновки будет построен на актуальных данных. Исправленная строка должна выглядеть так:

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

Именно поэтому у автора проблемы «нули» исчезали после того, как он заходил в настройки и нажимал «ОК» — это действие принудительно синхронизировало настройки компоновщика.

Важность жесткой типизации колонок Таблицы Значений

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

Рассмотрим, как правильно подготовить таблицу данных для передачи в СКД. Проанализируем пример правильного создания колонок:


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

Если колонка добавлена просто через ТЗ.Колонки.Добавить("Сумма"), то тип колонки будет Неопределено. Даже если вы заполните ее числами, при передаче в ПроцессорКомпоновкиДанных может произойти ошибка интерпретации типа, особенно если первая строка таблицы содержит NULL или 0. Явное описание типов исключает эту неопределенность.

Регистр имен полей и соответствие схеме

Еще одна неочевидная причина появления нулей — несовпадение имен колонок в таблице значений и имен полей в наборе данных СКД. Выясним причину, почему это критично:

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

Роли полей и агрегатные функции

Если поле в СКД выведено как ресурс, проверьте, правильно ли настроено выражение ресурса. Если вы просто выводите поле, не являющееся ресурсом, в область данных, СКД попытается его сгруппировать. Проанализируем настройки полей на вкладке «Наборы данных»:

Для числовых полей, которые не являются ресурсами (например, какой-то коэффициент), важно убедиться, что у них не стоит лишних ролей. Если же это поле должно суммироваться, проверьте вкладку «Ресурсы». Часто бывает, что поле добавлено в ресурсы, но в выражении указано что-то некорректное или оно вовсе не определено для конкретной группировки.

Также обратите внимание на флаг «Игнорировать значения NULL». Если в вашей ТЗ присутствуют значения NULL, а в настройках поля СКД не указано, как их обрабатывать, это может влиять на расчет итогов по группировкам, превращая результат в пустую ячейку (визуально выглядящую как нуль).

Влияние кэша и метаданных сеанса

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

Практические рекомендации по «очистке» ситуации:

  1. Завершите все активные сеансы с данным отчетом.
  2. Используйте очистку временных файлов (папки %AppData%\1C\1cv8).
  3. Если проблема наблюдается в процессе разработки, попробуйте изменить Имя отчета в свойствах объекта (не просто имя файла, а внутренний идентификатор метаданных). Это заставит платформу инициализировать его как совершенно новый объект.

Использование «Данных расшифровки»

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

Рассмотрим правильную схему работы с расшифровкой в управляемом приложении:


// На сервере
АдресДанныхРасшифровки = ПоместитьВоВременноеХранилище(Неопределено, ЭтаФорма.УникальныйИдентификатор);
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки, АдресДанныхРасшифровки);
// ... инициализация и вывод ...
ДанныеРасшифровки = АдресДанныхРасшифровки; // Возвращаем адрес в реквизит формы

Итоги и контрольный список

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

Соблюдение этих правил позволит избежать большинства проблем с отображением данных в сложных отчетах и обеспечит корректную работу механизмов компоновки 1С.

← На главную