В процессе разработки на платформе 1С 7.7 часто возникает задача проверки табличной части документа на наличие повторяющихся данных. Особенно это актуально при работе с торговым оборудованием, например, когда при сканировании штрихкодов или кодов маркировки (DataMatrix) один и тот же товар может по ошибке попасть в документ несколько раз. В этой статье мы подробно разберем несколько способов поиска дублей, проанализируем ошибки начинающих разработчиков и выясним, как оптимизировать этот процесс.
Прежде чем приступать к поиску уже существующих дублей, рассмотрим самый эффективный способ — предотвращение их попадания в табличную часть. Если ваша задача связана со сканированием штрихкодов, логичнее всего выполнять проверку в процедуре ОбработкаВнешнегоСобытия. Это позволяет мгновенно оповестить пользователя о повторном сканировании и не замусоривать документ.
Проанализируем пример кода, который проверяет наличие штрихкода перед добавлением новой строки:
// В модуле формы документа
Процедура ОбработкаВнешнегоСобытия(Источник, Событие, Данные)
Перем НомСтр;
Штрихкод = СокрЛП(Данные);
// Пытаемся найти штрихкод в уже заполненной табличной части
Если НайтиЗначение(Штрихкод, НомСтр, "КодМаркировки") = 1 Тогда
Предупреждение("Данный код маркировки уже считан в строке № " + НомСтр);
Возврат;
КонецЕсли;
// Если не нашли — добавляем новую строку
НоваяСтрока();
КодМаркировки = Штрихкод;
// ... заполнение остальных реквизитов
КонецПроцедуры
Этот подход избавляет нас от необходимости последующей свертки или перебора строк, так как база данных остается «чистой» в режиме реального времени.
Если данные уже находятся в табличной части и нам нужно программно выявить все повторяющиеся позиции, воспользуемся мощным инструментом 1С 7.7 — объектом ТаблицаЗначений. Основная идея заключается в том, чтобы выгрузить ТЧ, добавить техническую колонку для подсчета и использовать метод Свернуть.
Разберем этот алгоритм по шагам:
ТаблицаЗначений и выгружаем в него данные.Повтор числового типа.КодМаркировки) с суммированием колонки Повтор.Посмотрим на программную реализацию этого метода:
ИтогТЗ = СоздатьОбъект("ТаблицаЗначений");
ВыгрузитьТабличнуюЧасть(ИтогТЗ);
ИтогТЗ.НоваяКолонка("Повтор", "Число");
// Используем быстрый метод заполнения вместо цикла
ИтогТЗ.Заполнить(1, 1, ИтогТЗ.КоличествоСтрок(), "Повтор");
// Группируем по коду и суммируем единицы
ИтогТЗ.Свернуть("КодМаркировки", "Повтор");
// Проходим по результату и ищем строки, где сумма больше 1
ИтогТЗ.ВыбратьСтроки();
Пока ИтогТЗ.ПолучитьСтроку() = 1 Цикл
Если ИтогТЗ.Повтор > 1 Тогда
Сообщить("Код " + ИтогТЗ.КодМаркировки + " встречается " + ИтогТЗ.Повтор + " раз(а)");
КонецЕсли;
КонецЦикла;
Важный технический нюанс: при использовании метода Свернуть в 1С 7.7 все колонки, не указанные в параметрах метода, будут удалены из таблицы. Поэтому, если вам нужно сохранить информацию о товаре, его артикуле или цене, обязательно перечислите эти колонки в первом параметре (группировка).
Иногда разработчики сталкиваются с проблемой, когда метод НайтиЗначение возвращает только первую найденную строку. Это происходит из-за неправильной передачи параметров. Выясним, как заставить этот метод работать в цикле для поиска всех дублей конкретного значения.
Метод НайтиЗначение(Значение, Стр, Колон) работает следующим образом: он начинает поиск со строки, номер которой передан во втором параметре. Если значение найдено, функция возвращает 1, а в переменную Стр записывается номер найденной строки. Чтобы найти следующий дубль, в следующей итерации нужно передать Стр + 1.
Рассмотрим правильный пример кода для поиска всех строк с конкретным штрихкодом:
ТЗ = СоздатьОбъект("ТаблицаЗначений");
ВыгрузитьТабличнуюЧасть(ТЗ);
НужныйШтрихкод = "123456789";
НомСтр = 0;
Пока ТЗ.НайтиЗначение(НужныйШтрихкод, НомСтр, "КодМаркировки") = 1 Цикл
Сообщить("Дубль найден в строке: " + НомСтр);
// Увеличиваем индекс для поиска следующего вхождения
НомСтр = НомСтр + 1;
Если НомСтр > ТЗ.КоличествоСтрок() Тогда
Прервать;
КонецЕсли;
КонецЦикла;
Для больших табличных частей (сотни и тысячи строк) метод с вложенными циклами или многократным вызовом НайтиЗначение может работать медленно. Проанализируем более производительный алгоритм:
ТЗ.Сортировать("КодМаркировки");.Этот способ требует всего одного цикла, что значительно экономит ресурсы системы.
Разберем типичную ошибку: "Операции сравнения на больше-меньше допустимы только над значениями совпадающих базовых типов". В контексте поиска дублей это обычно происходит в двух случаях:
ТаблицыЗначений или добавлении колонки не указан тип (например, "Число" или "Строка"), 1С может поместить туда значение EmptyValue, которое конфликтует при сравнении с числами.СокрЛП() для строк или Число() для числовых данных.При поиске дублей именно кодов маркировки в 1С 7.7 важно помнить о следующих вещах:
Регистрозависимость: По умолчанию 1С 7.7 может различать большие и маленькие буквы. Коды маркировки чувствительны к регистру. Для корректного поиска всегда используйте функции ВРег() или НРег(), если не уверены в источнике данных.
Спецсимволы (GS1): В кодах DataMatrix часто присутствует непечатный символ разделителя групп (ASCII 29). При выгрузке в таблицу значений или сравнении строк убедитесь, что ваш сканер и драйвер передают этот символ единообразно, иначе визуально одинаковые коды будут считаться системой разными.
Длина строки: Код маркировки может быть очень длинным (более 100 символов). При создании колонки в ТЗ вручную не забывайте указывать достаточную длину, например: ТЗ.НоваяКолонка("КодМаркировки", "Строка", 255);.
Используя предложенные методы, вы сможете не только эффективно находить дубли в существующих документах, но и предотвращать их появление, обеспечивая высокую скорость работы системы и чистоту данных в вашей базе 1С 7.7.