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

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

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

Анализ проблемы: почему области «теряются»

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

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

Метод 1. Создание копии отчета и изменение вывода

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

  1. Копирование объекта: Создадим копию внешнего отчета или создадим новый отчет в конфигурации, скопировав макет и модуль объекта оригинального отчета.
  2. Корректировка алгоритма: Найдем в модуле место, где происходит цикл вывода областей. Обычно это выглядит так:

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

В этом блоке мы можем добавить условие, которое просто не будет выводить ненужные нам строки или шапки. Чтобы понять, какие данные и условия для фильтрации использовать, на этапе анализа бывает полезно выполнить исходный запрос в удобной консоли запросов. Это исключит необходимость в будущем «парсить» готовый документ и искать в нем данные.

Метод 2. Поиск областей по ключевому тексту

Если же мы вынуждены работать с уже сформированным документом, нам необходимо найти координаты строк для удаления. Разберем, как использовать метод НайтиТекст() для поиска повторяющихся областей. Мы можем запустить цикл, который будет искать заголовки «ОбластьШапка» по всему документу.

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


НайденнаяОбласть = Неопределено;
СтартоваяЯчейка = ТабДок.Область(1, 1);

Пока Истина Цикл
    НайденнаяОбласть = ТабДок.НайтиТекст("ИскомыйЗаголовокШапки", СтартоваяЯчейка, ТабДок.Область(), Истина, Истина, Истина, Ложь);
    
    Если НайденнаяОбласть = Неопределено Тогда
        Прервать;
    КонецЕсли;
    
    // Сохраняем номер строки найденной шапки
    НомерСтроки = НайденнаяОбласть.Верх;
    // Логика пометки строки на удаление или обработка данных
    
    // Перемещаем точку старта поиска ниже найденной области
    СтартоваяЯчейка = ТабДок.Область(НомерСтроки + 1, 1);
КонецЦикла;

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

Метод 3. Использование расшифровки для идентификации строк

Выясним причину, по которой использование Расшифровка считается более надежным методом. Часто разработчики при выводе строк заполняют свойство Расшифровка ячейки уникальным идентификатором или специальной строкой-маркером (например, «Тип_Строки_Шапка»).

Рассмотрим, как проверить строки через расшифровку:


Для НомерСтроки = 1 По ТабДок.ВысотаТаблицы Цикл
    ТекОбласть = ТабДок.Область(НомерСтроки, 1); // Проверяем первую колонку
    Если ТекОбласть.Расшифровка = "НужнаяНамМетка" Тогда
        // Мы нашли нужную строку
    КонецЕсли;
КонецЦикла;

Критически важное правило: Удаление строк снизу вверх

Теперь разберем самую частую ошибку начинающих программистов — удаление строк в цикле «сверху вниз». Проанализируем ситуацию: если вы удаляете строку №5, то бывшая строка №6 тут же становится строкой №5. Ваш счетчик цикла переходит к индексу 6, и в итоге вы пропускаете строку, которая только что сместилась вверх.

Правильное решение: всегда выполняйте удаление с конца документа к началу. Посмотрим на пример кода:


Высота = ТабДок.ВысотаТаблицы;
Для Счетчик = -Высота По -1 Цикл
    ТекущийНомерСтроки = -Счетчик;
    // Проверяем условие удаления для строки ТекущийНомерСтроки
    Если НужноУдалитьСтроку(ТекущийНомерСтроки) Тогда
        ТабДок.УдалитьОбласть(ТабДок.Область(ТекущийНомерСтроки, , ТекущийНомерСтроки, ), ТипСмещенияТабличногоДокумента.ПоВертикали);
    КонецЕсли;
КонецЦикла;

Или более лаконичный вариант с использованием шага -1:


Для НомерСтроки = ТабДок.ВысотаТаблицы По 1 Шаг -1 Цикл
    Если ОбнаруженПризнакУдаления(НомерСтроки) Тогда
        ТабДок.УдалитьОбласть(ТабДок.Область(НомерСтроки, 1, НомерСтроки, ), ТипСмещенияТабличногоДокумента.ПоВертикали);
    КонецЕсли;
КонецЦикла;

Метод 4. Сборка нового документа методом копирования

Вместо того чтобы «вырезать» лишнее, иногда проще «собрать» нужное. Этот метод особенно хорош, когда из огромного отчета нужно вытащить всего две-три таблицы. Проанализируем алгоритм:

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

// Пример копирования блока со строки 10 по 20
НужныйБлок = ИсходныйТабДок.ПолучитьОбласть(10, , 20, );
НовыйТабДок.Вывести(НужныйБлок);

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

Рекомендации по оптимизации

В завершение разберем несколько советов, которые помогут сделать код надежнее:

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

← На главную