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

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

При работе с файлами Excel в среде 1С:Предприятие часто возникает задача программного изменения структуры документа: удаления лишних строк, очистки данных или переформирования реестров. Особенно остро этот вопрос стоит при работе на серверах под управлением Linux, где мы лишены возможности использовать привычные COM-объекты (библиотеки Excel.Application). В таких случаях единственным надежным инструментом остается объект ТабличныйДокумент.

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

Метод 1: Прямое удаление строк через УдалитьОбласть

Самый очевидный способ удалить строку — воспользоваться встроенным методом УдалитьОбласть. Однако здесь кроется главная ловушка для начинающих разработчиков: изменение индексов строк в процессе обхода. Рассмотрим ситуацию подробнее.

Когда мы удаляем, например, 10-ю строку, 11-я строка тут же становится 10-й, 12-я — 11-й и так далее. Если наш цикл идет «сверху вниз» (от 1 к 100), то после удаления 10-й строки счетчик перейдет к 11-й, но на самом деле это будет бывшая 12-я строка. В результате мы пропустим одну строку для проверки.

Правильное решение: всегда выполнять обход коллекции с конца (в обратном порядке). Разберем по шагам, как это реализовать в коде.


// Предположим, табДок уже прочитан из файла Excel
КоличествоСтрок = табДок.ВысотаТаблицы;

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

Проанализируем параметры метода УдалитьОбласть. Вторым параметром крайне важно передать системное перечисление ТипСмещенияТабличногоДокумента.ПоВертикали. Это гарантирует, что нижние строки «подтянутся» вверх, заполняя образовавшееся пустое пространство, а не просто очистят содержимое ячеек.

Метод 2: Оптимизация через пакетное удаление

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

Выясним причину замедления: при каждом удалении 1С обновляет связи всех ячеек, форматов и именованных областей. Если мы знаем, что нам нужно удалить диапазон с 10-й по 50-ю строку, гораздо эффективнее сделать это одним вызовом:


// Удаление диапазона строк с 10 по 50 включительно
ОбластьДиапазон = табДок.Область(10, , 50, );
табДок.УдалитьОбласть(ОбластьДиапазон, ТипСмещенияТабличногоДокумента.ПоВертикали);

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

Метод 3: Создание нового документа (Метод копирования)

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

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

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

ТабДокИсточник = Новый ТабличныйДокумент;
ТабДокИсточник.Прочитать(ПутьКФайлу);

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

КоличествоСтрок = ТабДокИсточник.ВысотаТаблицы;

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

// Сохраняем результат
ТабДокРезультат.Записать(ПутьКФайлу, ТипФайлаТабличногоДокумента.XLSX);

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

Особенности работы на Linux-серверах

Поскольку автор вопроса упомянул работу на Linux, важно учитывать специфику платформы 1С при работе с файлами:

Сравнение производительности

Проанализируем ситуацию: какой метод выбрать? Если в документе 100-500 строк, разница между УдалитьОбласть и Вывести будет незаметна. Однако на реестрах в 10 000 строк и более:

1. УдалитьОбласть: работает медленно из-за постоянной перестройки индексов. Время выполнения растет в геометрической прогрессии от количества строк.
2. Вывести (Копирование): работает линейно и стабильно быстро. Это предпочтительный метод для высоконагруженных систем.

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

← На главную