Запрос = Новый Запрос ;
Запрос.УстановитьПараметр ( "Ссылка" , Ссылка );
Запрос.Текст =
"ВЫБРАТЬ
| ТабЧасть.Качество,
| ТабЧасть.Номенклатура,
| ТабЧасть.СерияНоменклатуры,
| ТабЧасть.Склад,
| ТабЧасть.ХарактеристикаНоменклатуры,
| КОЛИЧЕСТВО(ТабЧасть.НомерСтроки) КАК КоличествоДублей
|ИЗ
| Документ.РеализацияТоваровУслуг.Товары КАК ТабЧасть
|ГДЕ
| ТабЧасть.Ссылка = &Ссылка
|
|СГРУППИРОВАТЬ ПО
| ТабЧасть.Качество,
| ТабЧасть.Номенклатура,
| ТабЧасть.СерияНоменклатуры,
| ТабЧасть.Склад,
| ТабЧасть.ХарактеристикаНоменклатуры
|
|ИМЕЮЩИЕ
| КОЛИЧЕСТВО(ТабЧасть.НомерСтроки) > 1" ;
РезЗапроса = Запрос.Выполнить ();
Если Не РезЗапроса.Пустой () Тогда
Сообщить ( "Имеются дубли строк. " );
КонецЕсли;

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

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

Запрос = Новый Запрос ;

Запрос.УстановитьПараметр ( "Ссылка" , Ссылка );

Запрос.Текст =
"ВЫБРАТЬ
| ТабЧасть.Качество,
| ТабЧасть.Номенклатура,
| ТабЧасть.СерияНоменклатуры,
| ТабЧасть.Склад,
| ТабЧасть.ХарактеристикаНоменклатуры,
| ТабЧасть.НомерСтроки КАК НомерСтроки
|ПОМЕСТИТЬ ВТ_ТабЧасть
|ИЗ
| Документ.РеализацияТоваровУслуг.Товары КАК ТабЧасть
|ГДЕ
| ТабЧасть.Ссылка = &Ссылка
|;
| |////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ТабЧасть.Качество КАК Качество,
| ТабЧасть.Номенклатура КАК Номенклатура,
| ТабЧасть.СерияНоменклатуры КАК СерияНоменклатуры,
| ТабЧасть.Склад КАК Склад,
| ТабЧасть.ХарактеристикаНоменклатуры КАК ХарактеристикаНоменклатуры,
| ТабЧасть.НомерСтроки КАК НомерСтроки
|ИЗ
| ВТ_ТабЧасть КАК ТабЧасть
|ГДЕ
| (ТабЧасть.Качество, ТабЧасть.Номенклатура, ТабЧасть.СерияНоменклатуры, ТабЧасть.Склад, ТабЧасть.ХарактеристикаНоменклатуры) В
| (ВЫБРАТЬ
| ВТ.Качество,
| ВТ.Номенклатура,
| ВТ.СерияНоменклатуры,
| ВТ.Склад,
| ВТ.ХарактеристикаНоменклатуры
| ИЗ
| ВТ_ТабЧасть КАК ВТ
| СГРУППИРОВАТЬ ПО
| ВТ.Качество,
| ВТ.Номенклатура,
| ВТ.СерияНоменклатуры,
| ВТ.Склад,
| ВТ.ХарактеристикаНоменклатуры
| ИМЕЮЩИЕ
| КОЛИЧЕСТВО(ВТ.НомерСтроки) > 1)
|
|УПОРЯДОЧИТЬ ПО
| НомерСтроки
|ИТОГИ ПО
| Качество,
| Номенклатура,
| СерияНоменклатуры,
| Склад";
РезЗапроса = Запрос.Выполнить () ;
Если Не РезЗапроса.Пустой () Тогда
Выб_Качество = РезЗапроса.Выбрать ( ОбходРезультатаЗапроса.ПоГруппировкам );
Пока Выб_Качество.Следующий () Цикл
Выб_Номенклатура = Выб_Качество.Выбрать ( ОбходРезультатаЗапроса.ПоГруппировкам );
Пока Выб_Номенклатура.Следующий () Цикл
Выб_СерияНоменклатуры = Выб_Номенклатура.Выбрать ( ОбходРезультатаЗапроса.ПоГруппировкам );
Пока Выб_СерияНоменклатуры.Следующий () Цикл
Выб_Склад = Выб_СерияНоменклатуры.Выбрать ( ОбходРезультатаЗапроса.ПоГруппировкам );
Пока Выб_Склад.Следующий() Цикл
Выборка = Выб_Склад.Выбрать ();
ТекстСообщения = "" ;
Пока Выборка.Следующий () Цикл
ТекстСообщения = ТекстСообщения + ?( ПустаяСтрока ( ТекстСообщения ) , "" , ", " ) + Выборка.НомерСтроки ;
КонецЦикла;
ТекстСообщения = "Обнаружено дублирование строк: " + ТекстСообщения ; Сообщить(ТекстСообщения);
КонецЦикла;
КонецЦикла;
КонецЦикла;
КонецЦикла;

А теперь попробуем оценить перспективу доработки. Допустим, у нас изменился состав ключевых полей в сторону увеличения их количества: добавились ЕдиницаИзмерения и ЗаказПокупателя. Чтобы контроль дублей строк не перестал работать, нам нужно доработать запрос и обход результата запроса следующим образом:

Запрос = Новый Запрос ;
Запрос.УстановитьПараметр ( "Ссылка" , Ссылка );
Запрос.Текст =
" ВЫБРАТЬ
| ТабЧасть.ЕдиницаИзмерения,
| ТабЧасть.ЗаказПокупателя,
| ТабЧасть.Качество,
| ТабЧасть.Номенклатура,
| ТабЧасть.СерияНоменклатуры,
| ТабЧасть.Склад,
| ТабЧасть.ХарактеристикаНоменклатуры,
| ТабЧасть.НомерСтроки КАК НомерСтроки
|ПОМЕСТИТЬ ВТ_ТабЧасть
|ИЗ
| Документ.РеализацияТоваровУслуг.Товары КАК ТабЧасть
|ГДЕ
| ТабЧасть.Ссылка = &Ссылка
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ТабЧасть.ЕдиницаИзмерения КАК ЕдиницаИзмерения,
| ТабЧасть.ЗаказПокупателя КАК ЗаказПокупателя,
| ТабЧасть.Качество КАК Качество,
| ТабЧасть.Номенклатура КАК Номенклатура,
| ТабЧасть.СерияНоменклатуры КАК СерияНоменклатуры,
| ТабЧасть.Склад КАК Склад,
| ТабЧасть.ХарактеристикаНоменклатуры КАК ХарактеристикаНоменклатуры,
| ТабЧасть.НомерСтроки КАК НомерСтроки
|ИЗ
| ВТ_ТабЧасть КАК ТабЧасть
|ГДЕ
| (ТабЧасть.ЕдиницаИзмерения, ТабЧасть.ЗаказПокупателя, ТабЧасть.Качество, ТабЧасть.Номенклатура, ТабЧасть.СерияНоменклатуры, ТабЧасть.Склад, ТабЧасть.ХарактеристикаНоменклатуры) В
| (ВЫБРАТЬ
| ВТ.ЕдиницаИзмерения,
| ВТ.ЗаказПокупателя,
| ВТ.Качество,
| ВТ.Номенклатура,
| ВТ.СерияНоменклатуры,
| ВТ.Склад,
| ВТ.ХарактеристикаНоменклатуры
| ИЗ
| ВТ_ТабЧасть КАК ВТ
| СГРУППИРОВАТЬ ПО
| ВТ.ЕдиницаИзмерения,
| ВТ.ЗаказПокупателя,
| ВТ.Качество,
| ВТ.Номенклатура,
| ВТ.СерияНоменклатуры,
| ВТ.Склад,
| ВТ.ХарактеристикаНоменклатуры
| ИМЕЮЩИЕ
| КОЛИЧЕСТВО(ВТ.НомерСтроки) > 1)
|
|УПОРЯДОЧИТЬ ПО
| НомерСтроки
|ИТОГИ ПО
| Качество,
| Номенклатура,
| СерияНоменклатуры,
| Склад,
| ХарактеристикаНоменклатуры,
| ЕдиницаИзмерения" ;
РезЗапроса = Запрос.Выполнить ();
Если Не РезЗапроса.Пустой () Тогда
Выб_Качество = РезЗапроса.Выбрать ( ОбходРезультатаЗапроса.ПоГруппировкам );
Пока Выб_Качество.Следующий () Цикл
Выб_Номенклатура = Выб_Качество.Выбрать ( ОбходРезультатаЗапроса.ПоГруппировкам );
Пока Выб_Номенклатура.Следующий () Цикл
Выб_СерияНоменклатуры = Выб_Номенклатура.Выбрать ( ОбходРезультатаЗапроса.ПоГруппировкам );
Пока Выб_СерияНоменклатуры.Следующий () Цикл
Выб_Склад = Выб_СерияНоменклатуры.Выбрать ( ОбходРезультатаЗапроса.ПоГруппировкам );
Пока Выб_Склад.Следующий () Цикл
Выб_ХарактеристикаНоменклатуры = Выб_Склад.Выбрать ( ОбходРезультатаЗапроса.ПоГруппировкам );
Пока Выб_ХарактеристикаНоменклатуры.Следующий () Цикл
Выб_ЕдиницаИзмерения = Выб_ХарактеристикаНоменклатуры.Выбрать ( ОбходРезультатаЗапроса.ПоГруппировкам );
Пока Выб_ЕдиницаИзмерения.Следующий () Цикл
ТекстСообщения = "" ;
Выборка = Выб_ЕдиницаИзмерения.Выбрать ();
Пока Выборка.Следующий () Цикл
ТекстСообщения = ТекстСообщения + ?( ПустаяСтрока ( ТекстСообщения ), " " , ", " ) + Выборка.НомерСтроки ;
КонецЦикла;
ТекстСообщения = "Обнаружено дублирование строк: " + ТекстСообщения ;
Сообщить ( ТекстСообщения );
КонецЦикла;
КонецЦикла;
КонецЦикла;
КонецЦикла;
КонецЦикла;
КонецЦикла;

3) Альтернативный вариант.

Реализация предыдущего варианта другим способом. Предлагаю использовать особенность запросов 1С, позволяющих обращаться к данным табличных частей, как к обычным полям выборки. Ну все-таки не совсем обычным, но все же полям выборки. Кроме того, нам придётся использовать не самый оптимальный способ соединения данных — декартово произведение. Почему так — опишу ниже.

Несколько комментариев по поводу запроса.

Работа с табличными частями в качестве полей выборки накладывает ряд ограничений на выполнение запросов. Во-первых, это работа с временными таблицами. Т.е. нельзя помещать такие объекты во временные таблицы, но никто не мешает использовать вложенные запросы. Во-вторых, это соединения таблиц. Мне требовалось написать такой запрос, который бы возвратил мне наборы ключевых полей по которым имеются дубли, и многострочный объект, содержащий все строки с таким же набором ключевых полей. Обычные соединения (ВНУТРЕННЕЕ, ЛЕВОЕ, ПРАВОЕ, ПОЛНОЕ) возвращают всю табличную часть, что, в общем, правильно – для части объекта условие соединения же выполняется? Выполняется. Ну тогда и получите всю табличную часть. Искомый результат, как оказалось, достигается декартовым произведением. Мне как-то претит видеть в тексте запроса перечисление таблиц через запятую, поэтому я все декартовы произведения всегда реализую через «. СОЕДИНЕНИЕ . ПО (ИСТИНА)». Чтобы ограничить мсье Декарта в аппетитах (и повысить производительность), применяются дополнительные ограничения.

Теперь о производительности. Производились тестовые замеры каждого из вариантов на документе с большим количеством строк в табличной части. Количество строк в тестируемом документе: 47 817, 4 комбинации ключевых полей с дублями по 2, 2, 3 и 4 строки. Результаты замеров:

Вариант 1) 0:00:00.078 сек.

Вариант 2) 0:00:00.265 сек.

Вариант 3) 0:00:01.513 сек.

Как видим, третий вариант, как и ожидалось, самый медленный, но он же является самым удобным в перспективе модификации.

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

1) Выбираем вид объекта: Документ или Справочник.

2) Выбираем тип объекта: Какой именно документ или справочник.

3) Выбираем табличную часть объекта.

4) Определяем состав ключевых полей в специальном диалоге

5) Если мы хотим, то можем указать ссылку на объект, чтобы проверить его на наличие дублей.

6) Если активен флажок «Сгенерировать и показать код для проверки на дубли», то будет сгенерирован программный код для выполнения проверки на дубли строк с имеющимися настройками.

Эксперт по технологическим вопросам ООО ЦБР ИнфоСофт

Как найти дубли в справочнике (элементы совпадающие по названию) при помощи запроса в 1С?
Для этого необходимо получить выборку из этого справочника с названием и ссылкой.

Следующим шагом Вы группируете данную выборку по названию, а к полю «Ссылка» применяете функцию «Количество».
Тем самым вы узнаете, сколько с таким названием элементов справочника.
Но нас не интересуют «одиночные» элементы, т.е. те названия у которых одна ссылка. Поэтому необходимо использовать оператор «Имеющие», который применяем к функции «Количество», ставя условие что результат этой функции больше одного.

Например, как в этом запросе:

Результат его выполнения можно посмотреть на картинке ниже

Если Вы всё еще «плаваете» в конструкциях языка запросов, и у Вас вызывают трудности даже самые простые запросы, то рекомендую вам мой курс «Запросы в 1С от новичка до профи». Где эти и многие другие вопросы рассматриваются более подробно.

В чем особенность этого курса:
• Курс рассчитан на тех, кто не знаком с языком запросов в 1С;
• Учебный материал грамотно скомпонован и прост в освоении;
• Несколько десятков уроков;
• Полезные практические примеры;
• Все уроки изложены понятным и простым языком

Для моих читателей, купон на скидку 25%: hrW0rl9Nnx

Я стараюсь как можно чаще выпускать различные интересные бесплатные статьи и видеоуроки. Поэтому буду очень рад, если Вы поддержите мой проект перечислив любую сумму:

Можете перечислить любую сумму напрямую:
Яндекс.Деньги — 410012882996301
Web Money — R955262494655

Михаил Сайко

При работе с программой 1С может так случиться, что пользователь по ошибке вносит одинаковые элементы в справочники программы. Это создает неудобства в работе и путаницу в данных. Чаще всего подобные накладки случаются со справочниками «Контрагенты» и «Номенклатура». Они достаточно объемные, поэтому в них могут и кроются такие недочеты.

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

Для поиска и удаления дублей, в программе 1С Бухгалтерия 8.3 предусмотрена одноименная обработка. Рассмотрим принцип ее работы.

Обработка поиск и удаление дублей

Открыть обработку можно в разделе меню «Администрирование» — «Обслуживание» перейдя по гиперссылке «Поиск и удаление дублей».

В открывшемся окне необходимо указать область поиска, заполнив поле «Искать в:».

Из предложенного списка выбираем нужную область поиска дублей. В нашем примере проверим сначала справочник «Контрагенты».

Перейдя по гиперссылке в поле «Сравнить», задаем правила поиска дублей для выбранного объекта. По умолчанию установлен поиск по наименованию – по схожим словам. Но пользователь может написать разные наименования, например, полное и сокращенное – ИП или Индивидуальный предприниматель, полные данные контрагента (физического лица) – фамилию, имя, отчество, или указать только инициалы.

В этом случае можно сопоставить элементы по каким-то другим реквизитам. Для справочника «Контрагенты» – это ИНН, КПП, для справочника «Номенклатура» – Артикул и т.п.

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

Элемент с наибольшим количеством записей программа автоматически определяет как оригинал, выделив его синей стрелочкой. Если какой-то из объектов мы обрабатывать не будем, галочку с него надо снять. Или если мы хотим изменить объект, на который будут перенесены все данные с другого объекта при его удалении, то отметим его, нажав кнопку «Отметить как оригинал».

После нажатия кнопки «Удалить дубли» программа перенесет все объекты, где был задействован элемент-двойник, на отмеченный объект-оригинал, тем самым объединив их.

Мы можем закрыть обработку или, нажав кнопку «Новый поиск», повторить поиск дулей в других местах программы.

Для примера найдем дубли элементов в справочнике «Номенклатура», проведя сравнение по артикулу и наименованию.

Аналогично предыдущему описанию ищем и удаляем дубли.

Посмотрим, что же происходит с ними в справочнике. Зайдем в справочник «Контрагенты» (раздел меню «Справочники» — «Покупки и продажи»). Дубль-двойник помечен на удаление. Помимо этого мы видим, что контрагент был внесен дважды, но с разным наименованием. Внимательный пользователь бы заметил, что ИНН у элемента двойника выделен красным цветом. В программе имеется контроль совпадений контрагентов по ИНН.

Перейдя в справочник «Номенклатура» (раздел меню «Справочники» — «Покупки и продажа»), выполним поиск по наименованию, т.к. зрительно похожее название почему-то не отображалось. Что мы видим? У одного из элементов справочника перед названием стоит пробел – именно поэтому пользователь не может увидеть этот элемент в списке, просматривая его в алфавитном порядке. Все символы идут обычно в начале списка. Не найдя этот элемент, пользователь создал новый. Такая ситуация встречается довольно часто.

Так, используя штатный функционал программы, можно очистить справочники от таких элементов-двойников. После установки пометки удаления на них, удаление производится обычным способом, через «Удаление помеченных объектов» в разделе меню «Администрирование» — «Сервис». При больших объемах данных периодически можно проверять справочники во избежание путаницы в учете и захламления информационной базы ненужными элементами.