Как найти и отметить одинаковые строки в таблице значений 1С 7.7

Программист 1С v7.7
← На главную

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

Метод 1: Сортировка и последовательный обход

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

Проанализируем алгоритм действий:

  1. Добавим в таблицу значений новую колонку (например, ФлагДубля), куда будем записывать результат.
  2. Отсортируем таблицу по тем колонкам, которые определяют "одинаковость" элементов.
  3. Пройдем по таблице в цикле, сравнивая значения в текущей строке со значениями в предыдущей.

Рассмотрим пример кода, реализующий этот подход:


// Предположим, ТЗ уже заполнена данными
ТЗ.НоваяКолонка("ФлагДубля", "Число", 1);
// Сортируем по ключевым колонкам
ТЗ.Сортировать("Договор, Объект");

// Переменные для хранения значений предыдущей строки
ПредДоговор = "";
ПредОбъект = "";

ТЗ.ВыбратьСтроки();
Пока ТЗ.ПолучитьСтроку() = 1 Цикл
    Если (ТЗ.Договор = ПредДоговор) И (ТЗ.Объект = ПредОбъект) Тогда
        // Нашли дубль
        ТЗ.ФлагДубля = 1;
    Иначе
        // Это первое вхождение или уникальная строка
        ТЗ.ФлагДубля = 0;
        // Запоминаем текущие значения для следующего шага
        ПредДоговор = ТЗ.Договор;
        ПредОбъект = ТЗ.Объект;
    КонецЕсли;
КонецЦикла;

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

Метод 2: Использование метода Свернуть

Метод Свернуть() — один из самых мощных инструментов в 1С 7.7 для работы с агрегированными данными. Мы можем использовать его, чтобы быстро определить, какие комбинации значений встречаются более одного раза.

Разберем этот способ по шагам:

  1. Создаем вспомогательную таблицу значений — копию основной.
  2. Добавляем в нее колонку Количество и заполняем её единицами.
  3. Сворачиваем копию по ключевым полям, суммируя колонку Количество.
  4. Возвращаемся к основной таблице и для каждой строки проверяем значение счетчика в свернутой таблице.

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


// 1. Подготовка основной ТЗ
ТЗ.НоваяКолонка("ФлагДубля", "Число");

// 2. Создание вспомогательной ТЗ
ТЗ_Копия = СоздатьОбъект("ТаблицаЗначений");
ТЗ.Выгрузить(ТЗ_Копия);
ТЗ_Копия.НоваяКолонка("Количество", "Число");
ТЗ_Копия.ВыбратьСтроки();
Пока ТЗ_Копия.ПолучитьСтроку() = 1 Цикл
    ТЗ_Копия.Количество = 1;
КонецЦикла;

// 3. Сворачивание
ТЗ_Копия.Свернуть("Договор, Объект", "Количество");

// 4. Проставление отметок в основной ТЗ
ТЗ.ВыбратьСтроки();
Пока ТЗ.ПолучитьСтроку() = 1 Цикл
    НомСтроки = 0;
    // Ищем комбинацию в свернутой таблице
    Если ТЗ_Копия.НайтиЗначение(ТЗ.Договор, НомСтроки, "Договор") = 1 Тогда
        ТЗ_Копия.ПолучитьСтрокуПоНомеру(НомСтроки);
        // Проверяем еще и объект (так как НайтиЗначение ищет только по одной колонке)
        Если (ТЗ_Копия.Объект = ТЗ.Объект) И (ТЗ_Копия.Количество > 1) Тогда
            ТЗ.ФлагДубля = 1;
        КонецЕсли;
    КонецЕсли;
КонецЦикла;

Обратите внимание, что штатный метод НайтиЗначение() в 7.7 ищет только по одной колонке. Для поиска по нескольким колонкам в свернутой таблице лучше использовать предварительную сортировку и метод НайтиПараметры или конкатенацию ключей в одну строковую колонку.

Метод 3: Оптимизация через Scripting.Dictionary (COM-объект)

Если таблица значений содержит десятки тысяч строк, штатные методы перебора могут работать медленно. В таких случаях программисты часто прибегают к использованию объекта Scripting.Dictionary (словарь), который обеспечивает поиск со скоростью O(1).

Выясним, как применить словарь для нашей задачи:

  1. Создаем объект Словарь = СоздатьОбъект("Scripting.Dictionary");.
  2. В первом цикле формируем уникальный ключ (например, через строковое представление ID договора и объекта).
  3. Записываем в словарь количество вхождений каждого ключа.
  4. Во втором цикле проверяем значение по ключу в словаре: если оно больше 1, значит, перед нами дубль.

Этот метод считается одним из самых быстрых для "семерки", так как он заменяет вложенные циклы или тяжелые операции поиска внутри ТЗ на эффективное хеширование.

Метод 4: Индексированная таблица (внешняя компонента 1С++)

Для тех, кто использует в своей работе расширение 1С++, задача упрощается максимально. Объект ИндексированнаяТаблица позволяет создавать индексы по любым колонкам, что делает поиск дублей мгновенным.

Проанализируем возможности этого объекта:

Рекомендации по выбору решения

Выбор метода зависит от объема данных и ваших условий работы:

Важный совет: Перед сравнением объектов (договоров, контрагентов) убедитесь, что они имеют одинаковый тип. В 1С 7.7 иногда в одну колонку могут попасть как ссылки на справочник, так и их строковые представления, что приведет к неверному результату при поиске дублей.

← На главную