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

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

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

Метод 1: Использование промежуточной Таблицы Значений и метода Свернуть

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

Шаг 1. Преобразование табличного документа в Таблицу Значений

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


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

Шаг 2. Удаление дублей с помощью метода Свернуть

После того как данные получены в объект ТаблицаЗначений, мы можем применить метод Свернуть(). Выясним причину его эффективности: этот метод группирует строки по указанным колонкам и суммирует значения в остальных. Если нам нужно просто оставить уникальные записи, мы указываем ключевую колонку (например, "Имейл"), а колонки для суммирования оставляем пустыми.


// Предположим, ТЗ уже получена
ТЗ.Свернуть("Имейл"); 
// Теперь в ТЗ остались только уникальные адреса

Шаг 3. Перезаполнение табличного поля на форме

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


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

Метод 2: Прямое удаление строк «Снизу Вверх»

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

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

Алгоритм действий:

  1. Создаем вспомогательный массив или соответствие для хранения уже встреченных значений.
  2. Запускаем цикл по строкам от ВысотаТаблицы до 1 (с шагом -1).
  3. Читаем значение ячейки через Область(НомерСтроки, НомерКолонки).Текст.
  4. Если значение уже есть в нашем списке — удаляем строку методом УдалитьОбласть().

ПоследняяСтрока = ТабДокумент.ВысотаТаблицы;
СписокУникальных = Новый Соответствие;

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

Как избежать ошибки «Индекс находится за границами массива»

При реализации подобных алгоритмов программисты часто сталкиваются с ошибкой индексации. Разберем, почему это происходит. В сообщениях темы упоминалось обращение к КлючиЗапроса[0] без проверки. Выясним причину: программа пытается получить доступ к первому элементу коллекции, которая в данный момент может быть пуста (например, если поиск не дал результатов).

Золотое правило: прежде чем обращаться к элементу массива или таблицы по индексу, всегда проверяйте количество элементов.


Если КлючиЗапроса.Количество() > 0 Тогда
    МассивКлючейЗапроса.Добавить(КлючиЗапроса[0]);
Иначе
    // Обработка ситуации, когда данных нет
    Сообщить("Список ключей пуст, операция прервана.");
    Возврат;
КонецЕсли;

Полезные советы по оптимизации

Работа с визуальными компонентами, такими как ТабличныйДокумент, может быть медленной, если строк больше тысячи. Чтобы ускорить процесс чистки, рекомендуем:

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

← На главную