При формировании печатных форм и отчетов нередко возникает задача скорректировать уже сформированный макет: подтянуть нижние строки вверх, перенести блок ячеек или удалить ненужный пустой интервал. Разберем, как правильно реализовать перемещение данных в объекте ТабличныйДокумент, какие методы платформы 1С для этого предназначены и с какими тонкостями можно столкнуться при манипуляциях со строками и областями.
Проанализируем базовый механизм платформы: чтобы поднять нижние строки вверх, самым простым и очевидным действием является удаление мешающего пустого пространства над ними. Для этого у объекта ТабличныйДокумент предусмотрен метод УдалитьОбласть() с указанием типа смещения.
Посмотрим на пример удаления целых строк через числовые координаты:
// Определяем область целых строк: (НачалоСтроки, НачалоКолонки, КонецСтроки, КонецКолонки)
// Если колонки опущены, область охватывает всю ширину таблицы
НомерПервойСтроки = 5;
НомерПоследнейСтроки = 7;
ОбластьУдаления = Результат.Область(НомерПервойСтроки, , НомерПоследнейСтроки);
Результат.УдалитьОбласть(ОбластьУдаления, ТипСмещенияТабличногоДокумента.ПоВертикали);
Разберем важную особенность поведения платформы при работе со смещением:
УдалитьОбласть() передается область, состоящая из целых строк (как в примере выше), платформа всегда выполняет вертикальное смещение снизу вверх. Даже если ошибочно передать ТипСмещенияТабличногоДокумента.ПоГоризонтали, строки все равно подтянутся снизу вверх, так как сместить целую строку по горизонтали физически невозможно.ТипСмещенияТабличногоДокумента.ПоВертикали, вверх поднимутся только ячейки, расположенные непосредственно под удаляемым блоком в пределах тех же колонок. Соседние колонки останутся на месте, что приведет к разрыву строк таблицы.Рассмотрим ситуацию, когда требуется взять определенный блок строк снизу, перенести его выше, а затем очистить исходное местоположение. Посмотрим на алгоритм, который обсуждался участниками темы:
// Запоминаем исходные границы блока
Верх = ОбластьСмещ.Верх;
// Получаем блок строк для переноса (2 строки)
АдресИсходный = "R" + Формат(Верх, "ЧГ=0") + ":R" + Формат(Верх + 1, "ЧГ=0");
ОбластьДляПереноса = Результат.Область(АдресИсходный);
// Вставляем блок выше со смещением по вертикали
АдресПриемника = "R" + Формат(ОбластьВставки.Верх + 1, "ЧГ=0") + ":R" + Формат(ОбластьВставки.Верх + 1, "ЧГ=0");
ОбластьПриемник = Результат.Область(АдресПриемника);
Результат.ВставитьОбласть(ОбластьДляПереноса, ОбластьПриемник, ТипСмещенияТабличногоДокумента.ПоВертикали);
// Удаляем старые строки, сместившиеся вниз
АдресСтарыхСтрок = "R" + Формат(Верх + 2, "ЧГ=0") + ":R" + Формат(Верх + 3, "ЧГ=0");
Результат.УдалитьОбласть(Результат.Область(АдресСтарыхСтрок), ТипСмещенияТабличногоДокумента.ПоВертикали);
Выясним причину возможных ошибок при выполнении такого кода:
Строка(Число) для номеров строк более 999 1С добавляет неразрывный пробел (например, получается строка "R1 000"). Платформа не сможет распознать такой адрес ячейки и вызовет исключение. Поэтому всегда используем Формат(Номер, "ЧГ=0") или XMLСтрока(Номер), либо сразу передаем числовые координаты в метод Область().ВставитьОбласть() выделение области-приемника должно быть совместимо с форматом источника, иначе платформа сообщит об ошибке несоответствия вставляемого блока.Если задача состоит в том, чтобы убрать пустоту между разделами и визуально притянуть нижний блок к верхнему, не обязательно физически удалять ячейки и пересчитывать координаты. Разберем альтернативный вариант с использованием свойства Видимость:
// Скрываем строки с 10 по 15 включительно
Результат.Область(10, , 15).Видимость = Ложь;
У этого подхода есть ряд существенных преимуществ:
УдалитьОбласть() может выдать ошибку пересечения, тогда как изменение свойства Видимость скрывает строки корректно.Видимость доступно для установки только областям, состоящим из целых строк или целых колонок. Прямоугольному диапазону внутри строки скрыть видимость нельзя.Когда в уже заполненном отчете нужно выполнить сложные перестановки нескольких секций, последовательное применение методов вставки и удаления со смещением часто приводит к путанице с индексами строк: после каждой вставки или удаления номера строк нижележащих областей сдвигаются. В таких ситуациях надежнее использовать вспомогательный табличный документ:
ВременныйТабДок = Новый ТабличныйДокумент;
// 1. Копируем нижний блок во временный документ
БлокНиз = Результат.Область(20, , 30);
ВременныйТабДок.Вывести(БлокНиз);
// 2. Копируем верхний блок вслед за ним
БлокВерх = Результат.Область(5, , 15);
ВременныйТабДок.Вывести(БлокВерх);
// 3. При необходимости заменяем содержимое исходного документа
Результат.Очистить();
Результат.Вывести(ВременныйТабДок);
Такой подход полностью исключает риск непреднамеренно повредить соседние ячейки или нарушить форматирование таблицы.