Как разбить результат запроса на две колонки в табличном документе 1С

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

При формировании печатных форм часто возникает задача компактного размещения информации: вместо одного длинного вертикального списка необходимо вывести данные в две параллельные колонки (например, слева строки с 1 по 10, а справа — с 11 по 20). При реализации такого алгоритма разработчики нередко сталкиваются с ошибками типизации и неправильной работой с объектами выборки. Разберем по шагам, почему возникают эти ошибки и какими способами можно правильно вывести данные в две колонки.

Анализ типичных ошибок при работе с выборкой запроса

Рассмотрим, с какими трудностями чаще всего сталкиваются при попытке разделить данные на две части непосредственно в процессе обхода выборки:

  1. Попытка обращения к полям выборки до начала обхода. Код вида КолВо = ВыборкаДетальныеЗаписи.КолВоСтр;, написанный до первого вызова ВыборкаДетальныеЗаписи.Следующий(), возвращает значение Неопределено. Позиционирование на первой записи происходит только после выполнения метода Следующий(). При попытке выполнить математическую операцию (например, деление на 2) система выдает исключение: «Преобразование значения к типу Число не может быть выполнено».
  2. Подсчет общего количества через агрегатные функции запроса. Использование функции КОЛИЧЕСТВО(...) с группировкой по всем полям возвращает единицу для каждой отдельной строки, а не общее количество строк в выборке. Общее число записей выборки следует получать встроенной функцией ВыборкаДетальныеЗаписи.Количество().
  3. Ограничения однонаправленного курсора. Объект ВыборкаИзРезультатаЗапроса является однонаправленным курсором. По нему нельзя произвольно переходить по индексам назад или «перепрыгивать» в середину списка, чтобы параллельно читать первую и вторую половины выборки.

Способ 1. Выгрузка в Таблицу Значений и доступ по индексам (рекомендуемый)

Наиболее надежный и простой способ сформировать две колонки сверху вниз — выгрузить результат запроса в объект ТаблицаЗначений. Это позволяет мгновенно узнать общее количество строк и обращаться к произвольным строкам по их числовому индексу.

Разберем по шагам логику расчета:

  1. Выгружаем результат запроса в таблицу значений методом РезультатЗапроса.Выгрузить().
  2. Рассчитываем высоту печатной таблицы (количество строк для вывода). Для корректного учета нечетного количества элементов используем округление вверх: Цел((ВсегоСтрок + 1) / 2).
  3. В цикле от 0 до расчетной высоты таблицы берем элемент для левой колонки по индексу НомерСтроки, а для правой — со смещением НомерСтроки + ВысотаТаблицы.

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


ТаблицаСертификатов = РезультатЗапроса.Выгрузить();
ВсегоСтрок = ТаблицаСертификатов.Количество();

Если ВсегоСтрок > 0 Тогда
    ВысотаТаблицы = Цел((ВсегоСтрок + 1) / 2);
    
    ОбластьШапка = Макет.ПолучитьОбласть("ШапкаСертификаты");
    ТабДок.Вывести(ОбластьШапка);
    
    ОбластьСтрока = Макет.ПолучитьОбласть("СтрокаСертификаты");
    
    Для НомерСтроки = 0 По ВысотаТаблицы - 1 Цикл
        // Заполняем левую колонку
        СтрокаЛево = ТаблицаСертификатов[НомерСтроки];
        ОбластьСтрока.Параметры.СертификатыКод = СтрокаЛево.Код;
        ОбластьСтрока.Параметры.СертификатыНаименование = СтрокаЛево.Номенклатура;
        
        // Заполняем правую колонку, проверяя наличие элемента
        ИндексПраво = НомерСтроки + ВысотаТаблицы;
        Если ИндексПраво < ВсегоСтрок Тогда
            СтрокаПраво = ТаблицаСертификатов[ИндексПраво];
            ОбластьСтрока.Параметры.СертификатыКод2 = СтрокаПраво.Код;
            ОбластьСтрока.Параметры.СертификатыНаименование2 = СтрокаПраво.Номенклатура;
        Иначе
            ОбластьСтрока.Параметры.СертификатыКод2 = "";
            ОбластьСтрока.Параметры.СертификатыНаименование2 = "";
        КонецЕсли;
        
        ТабДок.Вывести(ОбластьСтрока);
    КонецЦикла;
КонецЕсли;

Способ 2. Чередующийся вывод при обходе выборки («змейка»)

Если бизнес-логика допускает заполнение таблицы слева направо (1-я запись слева, 2-я запись справа, 3-я слева и т. д.), можно обойтись без промежуточной выгрузки в память и обойти выборку напрямую.

Рассмотрим реализацию пошагового обхода:


Выборка = РезультатЗапроса.Выбрать();
ОбластьСтрока = Макет.ПолучитьОбласть("СтрокаСертификаты");

Пока Выборка.Следующий() Цикл
    // Заполняем левую часть строки
    ОбластьСтрока.Параметры.СертификатыКод = Выборка.Код;
    ОбластьСтрока.Параметры.СертификатыНаименование = Выборка.Номенклатура;
    
    // Пытаемся получить данные для правой части
    Если Выборка.Следующий() Тогда
        ОбластьСтрока.Параметры.СертификатыКод2 = Выборка.Код;
        ОбластьСтрока.Параметры.СертификатыНаименование2 = Выборка.Номенклатура;
    Иначе
        ОбластьСтрока.Параметры.СертификатыКод2 = "";
        ОбластьСтрока.Параметры.СертификатыНаименование2 = "";
    КонецЕсли;
    
    ТабДок.Вывести(ОбластьСтрока);
КонецЦикла;

Способ 3. Построчный вывод с помощью метода Присоединить()

Проанализируем ситуацию, когда макет разделен на две отдельные вертикальные области: ОбластьЛево и ОбластьПраво. При использовании метода Присоединить() табличного документа важно помнить: он добавляет колонки строго вправо от текущей последней выведенной строки.

Разберем пример правильного вывода с параллельным присоединением:


ТаблицаДанных = РезультатЗапроса.Выгрузить();
Всего = ТаблицаДанных.Количество();
ВысотаТаблицы = Цел((Всего + 1) / 2);

ОбластьЛево = Макет.ПолучитьОбласть("КолонкаЛево");
ОбластьПраво = Макет.ПолучитьОбласть("КолонкаПраво");

Для Стр = 0 По ВысотаТаблицы - 1 Цикл
    // Выводим левую ячейку вниз
    ОбластьЛево.Параметры.Заполнить(ТаблицаДанных[Стр]);
    ТабДок.Вывести(ОбластьЛево);
    
    // Присоединяем правую ячейку в ту же строку справа
    ИндексПраво = Стр + ВысотаТаблицы;
    Если ИндексПраво < Всего Тогда
        ОбластьПраво.Параметры.Заполнить(ТаблицаДанных[ИндексПраво]);
        ТабДок.Присоединить(ОбластьПраво);
    КонецЕсли;
КонецЦикла;

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

← На главную