Почему при использовании метода Присоединить в табличном документе 1С происходит смещение данных?

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

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

Суть проблемы и анализ исходного кода

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


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

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

Технические причины "бага" при использовании метода Присоединить

Разберем по шагам, что происходит "под капотом" платформы 1С при выполнении такого кода:

  1. Конфликт сеток колонок: Когда вы создаете Новый ТабличныйДокумент, он имеет стандартную ширину колонок. Если в итоговом документе ширина колонок была изменена, то при выполнении Присоединить платформа пытается совместить две разные геометрии. Это неизбежно приводит к визуальным искажениям и "сдвигам".
  2. Расчет точки вставки: Метод Присоединить ищет крайнюю правую заполненную ячейку в текущей строке вывода. Если вы передаете целый объект ТабличныйДокумент, система не всегда может корректно определить его границы, особенно если в нем есть объединенные ячейки.
  3. Объединенные ячейки: Это самый критичный момент. Если макеты карточек (например, КарточкаСерединаВниз) содержат объединение ячеек по горизонтали или вертикали, то при попытке горизонтального присоединения 1С может "сломать" сетку, пытаясь втиснуть объединенную область в структуру колонок итогового документа. Это выглядит как "дырка" в отчете или смещение на одну колонку в сторону.
  4. Пустые области: Если по какому-то условию временный ТабличныйДокумент остался пустым, выполнение Присоединить(ПустойДокумент) может сбить внутренний курсор вывода, из-за чего следующая итерация начнется не с той позиции.

Решение проблемы: переход на работу с областями макета

Для исправления ситуации необходимо отказаться от создания промежуточных объектов ТабличныйДокумент внутри цикла. Вместо этого следует использовать области макета (ТабличныйДокументОбласть). Этот метод считается "золотым стандартом" разработки в 1С, так как он гарантирует сохранение единой геометрии документа. Рассмотрим, как переписать код правильно.

Проанализируем шаги для реализации корректного вывода:

  1. Получаем макет один раз перед началом циклов.
  2. Используем метод ПолучитьОбласть() для извлечения нужных фрагментов (карточек).
  3. Заполняем параметры области.
  4. Используем метод Вывести() для начала новой строки и Присоединить() для добавления данных справа в ту же строку.

Разберем пример правильного построения цикла:


// Инициализируем итоговый документ и макет
ТабДокИтог = Новый ТабличныйДокумент;
Макет = ПолучитьМакет("МакетКарточек");

// Основной цикл формирования структуры
Для каждого Стр Из ТЗ Цикл
    // Сначала выводим заголовок строки или левую часть через Вывести()
    ОбластьЗаголовок = Макет.ПолучитьОбласть("ЗаголовокВетки");
    // ... заполнение параметров ...
    ТабДокИтог.Вывести(ОбластьЗаголовок); 
    
    // Вложенный цикл для горизонтального вывода подчиненных
    Для каждого нСтр Из Подчиненные Цикл
        // Определяем, какую карточку выводить
        ИмяОбласти = ?(ЭтоПоследний, "КарточкаКонецВниз", "КарточкаСерединаВниз");
        ОбластьКарточка = Макет.ПолучитьОбласть(ИмяОбласти);
        
        // Заполнение параметров области напрямую
        ОбластьКарточка.Параметры.Сотрудник = нСтр.Сотрудник;
        ОбластьКарточка.Параметры.Должность = нСтр.Должность;
        
        // ВАЖНО: Присоединяем ОБЛАСТЬ, а не документ
        ТабДокИтог.Присоединить(ОбластьКарточка);
    КонецЦикла;
КонецЦикла;

Почему работа с областями решает проблему?

Когда мы используем ОбластьКарточка = Макет.ПолучитьОбласть(...), объект ОбластьКарточка не является самостоятельным табличным документом в полном смысле слова. Он хранит в себе информацию о структуре ячеек макета-донора. При выполнении метода Присоединить(ОбластьКарточка) платформа 1С:

Важный совет: Если вы строите сложную схему, где карточки должны выравниваться "в шахматном порядке" или иметь разную высоту, следите за тем, чтобы высота (количество строк) во всех присоединяемых областях была одинаковой. Если КарточкаСерединаВниз занимает 5 строк, а КарточкаКонецВниз — 4 строки, визуально нижняя граница "поплывет". В таких случаях рекомендуется добавлять пустые строки в макет для выравнивания высоты всех областей.

Резюме и рекомендации

Выяснив причину смещения, мы можем сформулировать основные правила работы с Присоединить:

  1. Никогда не присоединяйте один ТабличныйДокумент к другому в цикле. Это ресурсоемко и ведет к ошибкам позиционирования.
  2. Используйте единый макет. Все области, участвующие в построении формы, должны находиться в одном макете. Это обеспечит единство сетки колонок.
  3. Контролируйте "Вывести" и "Присоединить". Метод Вывести всегда создает переход на новую строку (опускает виртуальный курсор вниз). Метод Присоединить добавляет колонки справа в текущей строке. Смещение часто происходит из-за того, что программист случайно вызывает Вывести там, где нужно было Присоединить.
  4. Проверяйте заполненность областей. Прежде чем присоединять область, убедитесь, что она содержит данные. Присоединение пустой области с объединением ячеек может привести к тому, что следующая карточка "перескочит" через несколько колонок.

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

← На главную