Почему ПроцессорКомпоновкиДанных не выводит результат в ТаблицуЗначений в 1С?

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

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

Анализируем исходную проблему: пустая таблица значений при программном выводе СКД

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

Давайте рассмотрим исходный код, с которым столкнулся разработчик:


КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;

СхемаСКД = ПолучитьМакет("ВыгрузкаНоменклатуры");

НовоеПоле = КомпоновщикСхемы.Настройки.ПараметрыДанных.Элементы.Найти("Узел");
НовоеПоле.Использование = Истина;
НовоеПоле.Значение = ПланОбмена;

НовоеПоле = КомпоновщикСхемы.Настройки.ПараметрыДанных.Элементы.Найти("НеОтборИзменениями");
НовоеПоле.Использование = Истина;
НовоеПоле.Значение = НЕ ВыгружатьИзменения;

ОсновнаяГруппировка = КомпоновщикСхемы.Настройки.Структура.Добавить(Тип("ГруппировкаКомпоновкиДанных"));
ОсновнаяГруппировка.Выбор.Элементы.Добавить(Тип("АвтоВыбранноеПолеКомпоновкиДанных"));

МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаСКД, КомпоновщикСхемы.Настройки,,, Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки);

Результат = Новый ТаблицаЗначений;

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

Для каждого СтрокаТовараДляОбработки Из Результат Цикл
    // ... обработка строк ...
КонецЦикла;

В этом коде есть несколько нюансов, которые могут привести к нежелательному результату.

Выясняем причины: ключевые аспекты работы с СКД программно

Давайте разберем основные моменты, которые влияют на корректность вывода данных из СКД в коллекцию значений:

  1. Некорректная инициализация КомпоновщикНастроекКомпоновкиДанных.

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

  2. Отсутствие загрузки настроек по умолчанию.

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

  3. Отсутствие или неверная структура вывода.

    Чтобы ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений мог вывести данные, в настройках СКД должна быть определена структура вывода. Это могут быть детальные записи, группировки или и то, и другое, а также явно выбранные поля. Если в Настройки.Структура ничего нет или выбраны поля, которые не соответствуют запросу, таблица значений останется пустой. В исходном коде попытка добавления группировки была, но могла быть перекрыта или не учтена из-за других ошибок в цепочке.

  4. Неправильная передача параметров.

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

  5. Особенности ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений.

    Этот процессор выводит данные только в ТаблицаЗначений или ДеревоЗначений. Он игнорирует условное оформление, папки в выбранных полях и некоторые другие элементы, ориентированные на визуальное представление отчета.

Пошаговое решение: как правильно вывести данные из СКД в ТаблицуЗначений

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

  1. Получение схемы компоновки данных.

    Начнем с получения объекта СхемаКомпоновкиДанных, обычно из макета или временного хранилища.

    
    СхемаКомпоновки = ПолучитьИзВременногоХранилища(ВременноеХранилищеСКД);
    // или:
    // СхемаКомпоновки = ПолучитьМакет("ВыгрузкаНоменклатуры");
    
  2. Инициализация КомпоновщикНастроекКомпоновкиДанных.

    Инициализируем компоновщик настроек, передав ему источник доступных настроек, созданный на основе нашей схемы.

    
    КомпоновщикНастроек = Новый КомпоновщикНастроекКомпоновкиДанных;
    ИсточникНастроек = Новый ИсточникДоступныхНастроекКомпоновкиДанных(СхемаКомпоновки);
    КомпоновщикНастроек.Инициализировать(ИсточникНастроек);
    
  3. Загрузка настроек по умолчанию.

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

    КомпоновщикНастроек.ЗагрузитьНастройки(СхемаКомпоновки.НастройкиПоУмолчанию);
  4. Доступ к текущим настройкам и установка параметров.

    Теперь мы можем получить доступ к текущим настройкам компоновщика и установить значения для необходимых параметров. Не забудьте установить Использование = Истина для каждого параметра.

    
    НастройкиКомпоновщика = КомпоновщикНастроек.Настройки;
    ПараметрыНастройки = НастройкиКомпоновщика.ПараметрыДанных;
    
    // Устанавливаем параметр "Узел"
    ЗначениеПараметра = ПараметрыНастройки.НайтиЗначениеПараметра(Новый ПараметрКомпоновкиДанных("Узел"));
    Если ЗначениеПараметра <> Неопределено Тогда
        ЗначениеПараметра.Значение = ПланОбмена;
        ЗначениеПараметра.Использование = Истина;
    КонецЕсли;
    
    // Устанавливаем параметр "НеОтборИзменениями"
    ЗначениеПараметра = ПараметрыНастройки.НайтиЗначениеПараметра(Новый ПараметрКомпоновкиДанных("НеОтборИзменениями"));
    Если ЗначениеПараметра <> Неопределено Тогда
        ЗначениеПараметра.Значение = НЕ ВыгружатьИзменения;
        ЗначениеПараметра.Использование = Истина;
    КонецЕсли;
    
  5. Проверка и формирование структуры вывода.

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

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

    Важно: Проверьте, что имя поля, указанное в ВыбранноеПолеКомпоновкиДанных, точно соответствует имени поля в запросе или в наборе данных СКД. Использование АвтоВыбранноеПолеКомпоновкиДанных обычно является более универсальным решением, если вам нужны все доступные поля.

  6. Выполнение компоновки макета.

    Теперь, когда настройки полностью готовы, передаем их КомпоновщикуМакетаКомпоновкиДанных для создания исполняемого макета.

    
    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
    МакетКомпоновкиДанных = КомпоновщикМакета.Выполнить(СхемаКомпоновки, НастройкиКомпоновщика, , , Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));
    
  7. Инициализация и выполнение процессора компоновки.

    Создаем и инициализируем ПроцессорКомпоновкиДанных нашим скомпонованным макетом. Этот процессор будет выполнять запрос и собирать данные.

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

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

    
    ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
            
    // Вариант 1: получить новую ТаблицуЗначений как результат
    Результат = ПроцессорВывода.Вывести(ПроцессорКомпоновкиДанных);
            
    // Вариант 2: вывести в предварительно созданную ТаблицуЗначений
    // Результат = Новый ТаблицаЗначений;
    // ПроцессорВывода.УстановитьОбъект(Результат);
    // ПроцессорВывода.Вывести(ПроцессорКомпоновкиДанных, Истина); // Истина - для очистки объекта перед выводом
    

    После выполнения этих шагов ваша ТаблицаЗначений Результат должна быть заполнена данными из СКД.

Полный пример кода для успешного вывода данных СКД

Соберем все описанные шаги в единый, рабочий код:


// Предполагаем, что СхемаКомпоновки уже доступна,
// а также определены переменные ПланОбмена и ВыгружатьИзменения
// Например:
// СхемаКомпоновки = ПолучитьМакет("ВыгрузкаНоменклатуры");
// Или, как в примере из форума:
// СхемаКомпоновки = ПолучитьИзВременногоХранилища(ВременноеХранилищеСКД);


// 1. Инициализация КомпоновщикаНастроекКомпоновкиДанных
КомпоновщикНастроек = Новый КомпоновщикНастроекКомпоновкиДанных;
ИсточникНастроек    = Новый ИсточникДоступныхНастроекКомпоновкиДанных(СхемаКомпоновки);
КомпоновщикНастроек.Инициализировать(ИсточникНастроек);

// 2. Загрузка настроек по умолчанию из схемы
КомпоновщикНастроек.ЗагрузитьНастройки(СхемаКомпоновки.НастройкиПоУмолчанию);

// 3. Доступ к текущим настройкам и установка параметров
НастройкиКомпоновщика = КомпоновщикНастроек.Настройки;
ПараметрыНастройки = НастройкиКомпоновщика.ПараметрыДанных;

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

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

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

// 5. Получаем макет компоновки
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновкиДанных = КомпоновщикМакета.Выполнить(СхемаКомпоновки, НастройкиКомпоновщика, , , Тип("ГенераторМакетаКомпоновкиДанныхДляКоллекцииЗначений"));

// 6. Инициализируем ПроцессорКомпоновкиДанных
ПроцессорКомпоновкиДанных = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпоновкиДанных);

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

Сообщить("Количество строк в ТаблицеЗначений: " + Результат.Количество());

Для каждого СтрокаТовараДляОбработки Из Результат Цикл
    // ... ваша логика обработки полученных данных ...
    // Например:
    // Идентификатор = ВыгрузитьНоменклатуру(СтрокаТовараДляОбработки.Ссылка);
    // ...
КонецЦикла;

Диагностика и отладка: используем Консоль компоновки данных

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

  1. Визуально проверить запрос, который формирует СКД.
  2. Просмотреть доступные поля, параметры, отборы и их значения.
  3. Сформировать отчет с вашими настройками и убедиться, что он выводит ожидаемые данные.

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

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

← На главную