Как найти и обработать дублирующиеся строки в табличной части документа 1С 7.7?

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

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

Метод 1. Предотвращение появления дублей (архитектурно верный подход)

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

Проанализируем пример кода, который проверяет наличие штрихкода перед добавлением новой строки:


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

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

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

Если данные уже находятся в табличной части и нам нужно программно выявить все повторяющиеся позиции, воспользуемся мощным инструментом 1С 7.7 — объектом ТаблицаЗначений. Основная идея заключается в том, чтобы выгрузить ТЧ, добавить техническую колонку для подсчета и использовать метод Свернуть.

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

  1. Создаем объект ТаблицаЗначений и выгружаем в него данные.
  2. Добавляем колонку Повтор числового типа.
  3. Заполняем эту колонку единицей в каждой строке.
  4. Выполняем свертку таблицы по ключевому полю (например, КодМаркировки) с суммированием колонки Повтор.

Посмотрим на программную реализацию этого метода:


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

// Используем быстрый метод заполнения вместо цикла
ИтогТЗ.Заполнить(1, 1, ИтогТЗ.КоличествоСтрок(), "Повтор");

// Группируем по коду и суммируем единицы
ИтогТЗ.Свернуть("КодМаркировки", "Повтор");

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

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

Метод 3. Поиск всех вхождений через НайтиЗначение

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

Метод НайтиЗначение(Значение, Стр, Колон) работает следующим образом: он начинает поиск со строки, номер которой передан во втором параметре. Если значение найдено, функция возвращает 1, а в переменную Стр записывается номер найденной строки. Чтобы найти следующий дубль, в следующей итерации нужно передать Стр + 1.

Рассмотрим правильный пример кода для поиска всех строк с конкретным штрихкодом:


ТЗ = СоздатьОбъект("ТаблицаЗначений");
ВыгрузитьТабличнуюЧасть(ТЗ);
НужныйШтрихкод = "123456789";
НомСтр = 0;

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

Метод 4. Оптимизация поиска через сортировку

Для больших табличных частей (сотни и тысячи строк) метод с вложенными циклами или многократным вызовом НайтиЗначение может работать медленно. Проанализируем более производительный алгоритм:

  1. Сортируем таблицу значений по проверяемой колонке: ТЗ.Сортировать("КодМаркировки");.
  2. Одним проходом сравниваем текущую строку со следующей.
  3. Если значения совпадают — перед нами дубликат.

Этот способ требует всего одного цикла, что значительно экономит ресурсы системы.

Почему возникают ошибки при сравнении?

Разберем типичную ошибку: "Операции сравнения на больше-меньше допустимы только над значениями совпадающих базовых типов". В контексте поиска дублей это обычно происходит в двух случаях:

  1. Нетипизированные колонки: Если при создании ТаблицыЗначений или добавлении колонки не указан тип (например, "Число" или "Строка"), 1С может поместить туда значение EmptyValue, которое конфликтует при сравнении с числами.
  2. Разные типы данных в ТЧ: В колонке «КодМаркировки» могут случайно оказаться как строки, так и числа. Перед сверткой или сравнением убедитесь, что все данные приведены к одному типу, используя функции СокрЛП() для строк или Число() для числовых данных.

Специфика кодов маркировки («Честный ЗНАК»)

При поиске дублей именно кодов маркировки в 1С 7.7 важно помнить о следующих вещах:

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

Спецсимволы (GS1): В кодах DataMatrix часто присутствует непечатный символ разделителя групп (ASCII 29). При выгрузке в таблицу значений или сравнении строк убедитесь, что ваш сканер и драйвер передают этот символ единообразно, иначе визуально одинаковые коды будут считаться системой разными.

Длина строки: Код маркировки может быть очень длинным (более 100 символов). При создании колонки в ТЗ вручную не забывайте указывать достаточную длину, например: ТЗ.НоваяКолонка("КодМаркировки", "Строка", 255);.

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

← На главную