1с как найти дубли в табличной части

Проверка на наличие дублирующихся строк в табличных частях

Время прочтения — 7 мин.

Получить бесплатную консультацию

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


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



Рассмотрим следующие ситуации:


1) Проверка на наличие дублирующихся строк на уровне есть/нет.
Реализация ее будет выглядеть следующим образом:

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

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

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

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

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

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

|УПОРЯДОЧИТЬ ПО 
| НомерСтроки 
|ИТОГИ ПО 
| Качество, 
| Номенклатура, 
| СерияНоменклатуры, 
| Склад»;
РезЗапроса = Запрос.Выполнить(); 
Если Не РезЗапроса.Пустой() Тогда 
Выб_Качество = РезЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам); 
Пока Выб_Качество.Следующий() Цикл 
Выб_Номенклатура = Выб_Качество.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам); 
Пока Выб_Номенклатура.Следующий() Цикл 
Выб_СерияНоменклатуры = Выб_Номенклатура.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам); 
Пока Выб_СерияНоменклатуры.Следующий() Цикл 
Выб_Склад = Выб_СерияНоменклатуры.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам); 
Пока Выб_Склад.Следующий() Цикл 
Выборка = Выб_Склад.Выбрать(); 
ТекстСообщения = «»; 
Пока Выборка.Следующий() Цикл 
ТекстСообщения = ТекстСообщения + ?(ПустаяСтрока(ТекстСообщения), «», «, «) + Выборка.НомерСтроки; 
КонецЦикла; 
ТекстСообщения = «Обнаружено дублирование строк: » + ТекстСообщения; Сообщить(ТекстСообщения); 
КонецЦикла; 
КонецЦикла; 
КонецЦикла; 
КонецЦикла; 

КонецЕсли

Здесь все тоже не слишком сложно. Обратились к данным табличной части документа, поместили их во временную таблицу. Далее работаем со временной таблицей. Обращаемся к ней, отбираем те данные, по которым есть дубли (условие с использованием вложенного запроса). А далее, для того, чтобы сохранить все множество значений номеров строк, нам необходимо по ключевым полям объявить итоги. В таком случае в результате запроса, при использовании механизма итогов, появляются дополнительные строки, в которых хранится итог для того, или иного поля, а сам результат принимает иерархический вид, или вид дерева. Для того, чтобы вывести пользователю сообщение, нам нужно обойти результат запроса, и по каждому набору ключевых полей скомпоновать текст сообщения, и выдать его пользователю.


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


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

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

|УПОРЯДОЧИТЬ ПО 
| НомерСтроки 
|ИТОГИ ПО 
| Качество, 
| Номенклатура, 
| СерияНоменклатуры,
| Склад, 
| ХарактеристикаНоменклатуры, 
| ЕдиницаИзмерения»;
РезЗапроса = Запрос.Выполнить(); 
Если Не РезЗапроса.Пустой() Тогда 
Выб_Качество = РезЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам); 
Пока Выб_Качество.Следующий() Цикл 
Выб_Номенклатура = Выб_Качество.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам); 
Пока Выб_Номенклатура.Следующий() Цикл 
Выб_СерияНоменклатуры = Выб_Номенклатура.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам); 
Пока Выб_СерияНоменклатуры.Следующий() Цикл 
Выб_Склад = Выб_СерияНоменклатуры.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам); 
Пока Выб_Склад.Следующий() Цикл 
Выб_ХарактеристикаНоменклатуры = Выб_Склад.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам); 
Пока Выб_ХарактеристикаНоменклатуры.Следующий() Цикл 
Выб_ЕдиницаИзмерения=Выб_ХарактеристикаНоменклатуры.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам); 
Пока Выб_ЕдиницаИзмерения.Следующий() Цикл 
ТекстСообщения = «»; 
Выборка = Выб_ЕдиницаИзмерения.Выбрать(); 
Пока

Подпишитесь на дайджест!

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

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

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

ШаблонОшибки = «Табличная часть ‘Товары’: по реквизитам ‘Качество, Номенклатура, СерияНоменклатуры, Склад, ХарактеристикаНоменклатуры’ обнаружено дублирование строк ‘%1′»; 
Запрос = Новый Запрос; 
Запрос.УстановитьПараметр(«Ссылка», Объект.Ссылка); 
Запрос.Текст
«ВЫБРАТЬ
| ТабЧасть.Ссылка, 
| МИНИМУМ(ТабЧасть.НомерСтроки) КАК МинНомерСтроки, 
| ТабЧасть.Качество, 
| ТабЧасть.Номенклатура, 
| ТабЧасть.СерияНоменклатуры, 
| ТабЧасть.Склад, 
| ТабЧасть.ХарактеристикаНоменклатуры 
|ПОМЕСТИТЬ ВТ_ТабЧасть 
|ИЗ 
| Документ.РеализацияТоваровУслуг.Товары КАК ТабЧасть 
|ГДЕ 
| ТабЧасть.Ссылка = &Ссылка 

|СГРУППИРОВАТЬ ПО 
| ТабЧасть.Ссылка, 
| ТабЧасть.Качество, 
| ТабЧасть.Номенклатура, 
| ТабЧасть.СерияНоменклатуры, 
| ТабЧасть.Склад, 
| ТабЧасть.ХарактеристикаНоменклатуры 
| |ИМЕЮЩИЕ 
| КОЛИЧЕСТВО(ТабЧасть.НомерСтроки) > 1 
|; 

|//////////////////////////////////////////////////////////////////////////////// 
|ВЫБРАТЬ 
| ТабЧасть.Ссылка, 
| ТабЧасть.Качество, 
| ТабЧасть.Номенклатура, 
| ТабЧасть.СерияНоменклатуры, 
| ТабЧасть.Склад, 
| ТабЧасть.ХарактеристикаНоменклатуры, 
| Док.Товары.( 
| НомерСтроки, 
| Качество, 
| Номенклатура, 
| СерияНоменклатуры, 
| Склад, 
| ХарактеристикаНоменклатуры 
| ) КАК ДублиСтрок 
|ИЗ 
| (ВЫБРАТЬ 
| Док.Товары.( 
| НомерСтроки, 
| Качество, 
| Номенклатура, 
| СерияНоменклатуры, 
| Склад, 
| ХарактеристикаНоменклатуры 
| ) КАК Товары 
| ИЗ 
| Документ.РеализацияТоваровУслуг КАК Док 
| ГДЕ 
| Док.Ссылка = &Ссылка 
| И (Док.Товары.Качество, Док.Товары.Номенклатура, Док.Товары.СерияНоменклатуры, Док.Товары.Склад, Док.Товары.ХарактеристикаНоменклатуры) В 
| (ВЫБРАТЬ 
| ВТ.Качество, 
| ВТ.Номенклатура, 
| ВТ.СерияНоменклатуры, 
| ВТ.Склад, 
| ВТ.ХарактеристикаНоменклатуры 
| ИЗ 
| ВТ_ТабЧасть КАК ВТ)) КАК Док 
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_ТабЧасть КАК ТабЧасть 
| ПО (ИСТИНА) 
|ГДЕ 
| Док.Товары.Качество = ТабЧасть.Качество 
| И Док.Товары.Номенклатура = ТабЧасть.Номенклатура 
| И Док.Товары.СерияНоменклатуры = ТабЧасть.СерияНоменклатуры 
| И Док.Товары.Склад = ТабЧасть.Склад 
| И Док.Товары.ХарактеристикаНоменклатуры = ТабЧасть.ХарактеристикаНоменклатуры 

|УПОРЯДОЧИТЬ ПО 
| ТабЧасть.МинНомерСтроки, 
| Док.Товары.НомерСтроки»;
ТЗ_Результат = Запрос.Выполнить().Выгрузить(); 
Для Каждого СтрТЗ Из ТЗ_Результат Цикл 
Сообщить(СтрШаблон(ШаблонОшибки, СтрСоединить(СтрТЗ.ДублиСтрок.ВыгрузитьКолонку(«НомерСтроки»), «, «))); 
КонецЦикла;

Главное отличие от предыдущего варианта: обход результата запроса осуществляется линейным способом. Т.е. при изменении состава ключевых полей меняется только текст запроса.

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

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

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

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

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

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

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

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

1.png

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

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

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

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

2.png

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

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

Автор статьи:


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

 +7 

   

Распечатать

Универсальная процедура проверки на дубли строк в табличной части документа

Код 1C v 8.2 УП

 //Процедура проверяет наличие в ТЧ дублей строк по указанным реквизитам
//ДокументСсылка - ссылка на проверяемый документ
//ИмяТабЧасти - имя проверяемой табличной части (строка)
//ПроверяемыеРеквизиты - перечень проверяемых реквизитов (строка, реквизиты разделяются запятой)
Процедура ПроверимДублиСтрок(ДокументСсылка,ИмяТабЧасти,ПроверяемыеРеквизиты,Отказ)

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

ТаблицаДокумента.Свернуть(ПроверяемыеРеквизиты,"КвоПроверкаДублей");

Для Каждого ТекущаяСтрока Из ТаблицаДокумента Цикл
Если ТекущаяСтрока.КвоПроверкаДублей > 1 Тогда
РеквизитыДляСообщения = "";
Стр = СокрЛП(ПроверяемыеРеквизиты);
Пока Найти(Стр,",") > 0 Цикл
НаимРеквизита = СокрЛП(Лев(Стр,Найти(Стр,",") - 1));
Стр = Прав(Стр,СтрДлина(Стр) - Найти(Стр,","));
РеквизитыДляСообщения = РеквизитыДляСообщения+ТекущаяСтрока[НаимРеквизита]+", ";
КонецЦикла;
РеквизитыДляСообщения = РеквизитыДляСообщения+ТекущаяСтрока[СокрЛП(Стр)];

Сообщить("Информация "+РеквизитыДляСообщения+" введена несколько раз в табличную часть, проведение невозможно!");
Отказ = Истина;
КонецЕсли;
КонецЦикла;

КонецПроцедуры

Пример обращения к процедуре проверки

Код 1C v 8.2 УП

 // Процедура - обработчик события ОбработкаПроверкиЗаполнения объекта.
//
Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)

Если Запасы.Количество() = 0 Тогда
Возврат;
КонецЕсли;

ПроверимДублиСтрок(Ссылка, "Запасы", "Номенклатура, АлгоритмФормированияШК,Регион", Отказ);

КонецПроцедуры

Да, в списке реквизитов добавленные случайно пробелы игнорируются )
Процедуру можно добавить в общий модуль и обращаться к ней из любого документа

Поиск дублей в табличной части документа

Я
   RasuLL

23.12.12 — 22:35

Документ записан. Как проверить есть ли в табличной части документа дубли, если есть то удалить и сообщить? Обшарила форумы ничего подходящего не нашла. Заранее благодарна за помощь.

   DrShad

1 — 23.12.12 — 22:36

запросом?

   RasuLL

2 — 23.12.12 — 22:37

(1) Запрос.Текст = «ВЫБРАТЬ

       |    Товары.Код

       |ИЗ

       |    ДокПоступление.Товары КАК Товары

       |

       |СГРУППИРОВАТЬ ПО

       |    Товары.Код»;

?

   H A D G E H O G s

3 — 23.12.12 — 22:39

(2) Фотку?

   DrShad

4 — 23.12.12 — 22:45

да, без фотки никак

   RasuLL

5 — 23.12.12 — 22:46

какая еще фотка?

   H A D G E H O G s

6 — 23.12.12 — 22:46

Пол: Женский

Какая, какая… Твоя.

   Armando

7 — 23.12.12 — 22:46

(5) с такими вопросами как (0) только топлес

   ОбычныйЧеловек

8 — 23.12.12 — 22:47

(5) месяц на форуме а обычи так и не узнала )

   Torquader

9 — 23.12.12 — 22:50

(2) Посчитать количество различных и выбрать те, которые больше 1.

   RasuLL

10 — 23.12.12 — 22:50

да тут одни джентльмены!

   DrShad

11 — 23.12.12 — 22:51

(10) что не по-джентельменски?

   RasuLL

12 — 23.12.12 — 22:51

(9) можете привести пример?

   alexei366

13 — 23.12.12 — 22:53

Модам, вы неверно хотите это проверять перед записью документа?

   RasuLL

14 — 23.12.12 — 22:54

(13) нет, после записи

   ERWINS

15 — 23.12.12 — 22:55

«ВЫБРАТЬ

   |    Контрагенты.Код,

   |ИЗ

   |    Справочник.Контрагенты КАК Контрагенты

   |

   |СГРУППИРОВАТЬ ПО

   |    Контрагенты.Код

   |

   |ИМЕЮЩИЕ

   |    СУММА(1) > 1″

нечто

   alexei366

16 — 23.12.12 — 22:55

это не принципиально, то есть это должно выполняться в интерфейсе и пользователя сразу оповещать?

   RasuLL

17 — 23.12.12 — 22:57

(15) мне нужно проверить в таб. части, а это не то

   Torquader

18 — 23.12.12 — 22:57

После записи — смысл этой проверки ?

Или это будет проверяться потом, чтобы «зверям отвесить по полной» ?

   ERWINS

19 — 23.12.12 — 22:58

(16) думаю что  ОбработкаПроверкиЗаполнения

   Torquader

20 — 23.12.12 — 22:58

(17) А что мешает выбирать из табличной части ?

Открыли конструктор запросов и мышкуем по нужным полям.

   Torquader

21 — 23.12.12 — 23:00

(19) Если в ОбработкаПроверкаЗаполнения, то выгрузить табличную часть, добавить колонку — проставить единицу в неё, свернуть табличную часть, суммируя по колонке с единицей — ну и перебрать потом, чтобы пользователю сообщить, где он не прав.

   RasuLL

22 — 23.12.12 — 23:00

(20) знания, не знаю как это сделать…

   DrShad

23 — 23.12.12 — 23:02

(21) какой изврат

   RasuLL

24 — 23.12.12 — 23:03

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

       Запрос.Текст = «ВЫБРАТЬ

       |    Товары.Код

       |ИЗ

       |    НовыйДокПоступление.Товары КАК Товары

       |

       |СГРУППИРОВАТЬ ПО

       |    Товары.Код»;

       Результат = Запрос.Выполнить();

       ТЗ = Новый ТаблицаЗначений;

       Результат.Выгрузить(ТЗ);

       
       ТЗ.ВыбратьСтроки();

       Пока ТЗ.ПолучитьСтроку()=1 Цикл

       ВыбратьСтроки();

       Пока ПолучитьСтроку()=1 Цикл

           Если (ТЗ.Код = Код)

           И (ТЗ.НомерСтроки<>НомерСтроки) Тогда

               Сообщить («В строке №»+НомерСтроки+» имеется одинаковый код»);

           КонецЕсли;

         КонецЦикла;

       КонецЦикла;

   alexei366

25 — 23.12.12 — 23:03

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

   RasuLL

26 — 23.12.12 — 23:04

(25) все верно)

   alexei366

27 — 23.12.12 — 23:05

Вот моя умничка, я знал что вы никогда не скажите что хотите

   alexei366

28 — 23.12.12 — 23:05

Ну чтож пример кода придумать или сама?

   RasuLL

29 — 23.12.12 — 23:06

цель проверять на коды, если в строке имеются одинаковые коды элементов, то удалить их и сообщить об этих строках

   DrShad

30 — 23.12.12 — 23:06

(27) а не проще сворачивать по-умолчанию?

   RasuLL

31 — 23.12.12 — 23:07

(28) не получается у меня…((

   alexei366

32 — 23.12.12 — 23:09

DrShad эт идея, ток надо не сварачивать а в событии таблицы ОкончаниеРедактирования проверять на совпадение с другими строками , если да удалять эту и сообщить пользователю что он дурак

   alexei366

33 — 23.12.12 — 23:09

Модмозель, вы определитесь пока с вариантом исполнения, а примеры кода после фотографии (не всёж на халяву)

   alexei366

34 — 23.12.12 — 23:19

Мужики я сделал это!!!!!))))))))))))))

   DrShad

35 — 23.12.12 — 23:23

что ты сделал?

   alexei366

36 — 23.12.12 — 23:24

DrShad ты опоздал, фотка висела пару минут

   alexei366

37 — 23.12.12 — 23:27

Эх походу кто-то обиделся и примеры кода не нужны, ладно ещё 3 минуты посмотрю потом закрою страничку.

   ERWINS

38 — 23.12.12 — 23:29

Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)

   ТЗ=Товары.Выгрузить();

   ТЗ.Сортировать(«Товар, НомерСтроки»);

   тов=неопределено;

   ст=»»;

   нтов=ложь;

   для каждого стр из ТЗ Цикл

       Если стр.Товар=тов тогда

           ст=ст+»,»+строка(стр.НомерСтроки);

           нтов=истина;

       Иначе

           Если нтов тогда

               Сообщение = Новый СообщениеПользователю;

               Сообщение.Текст = тов.Наименование+» содержиться в нескольких строках «+ст;

               Сообщение.Сообщить();

               отказ = истина;

           КонецЕсли;

           ст=строка(стр.НомерСтроки);

           нтов=Ложь;

           тов=стр.Товар;

       КонецЕсли;

       
   КонецЦикла;

   
   Если нтов тогда

       Сообщение = Новый СообщениеПользователю;

       Сообщение.Текст = тов.Наименование+» содержиться в нескольких строках «+ст;

       Сообщение.Сообщить();

       отказ = истина;

   КонецЕсли;

   
КонецПроцедуры

   DrShad

39 — 23.12.12 — 23:32

(38) за такой код, человек его написавший уже бы не работал у нас, ничего личного, но не стоит учить плохому начинающих

   alexei366

40 — 23.12.12 — 23:33

ERWINS есть одно но, небудет подсветки на ошибочную строку если в модуле объекта.

   ОбычныйЧеловек

41 — 23.12.12 — 23:34

(38) а не проще выгрузить только колонку товары, добавить числовую колонку — запонить ее единичкой потом свернуть и там гле будет больше единицы вывести на экран…код в 3 строчки.

   ERWINS

42 — 23.12.12 — 23:35

(39) и чем плохо кроме имен переменных?

(40) тогда делать по другому, тоже не сложно

   DrShad

43 — 23.12.12 — 23:35

(41) зачем!? не проще сделать тоже самое запросом к ТЧ?

   Noroving

44 — 23.12.12 — 23:35

(32) Помоему самый верный вариант… зачем писать замудроватые запросы и усложнять запись документа… проще сразу проверять внесенные данные…

   DrShad

45 — 23.12.12 — 23:36

(42) например выгрузка в ТЗ и обход по ТЗ, а не сразу же по ТЧ

   alexei366

46 — 23.12.12 — 23:36

DrShad а как запрос делать к незаписанному объекту?

   ОбычныйЧеловек

47 — 23.12.12 — 23:36

(43) запрос будет работать при условии, что документ уже записан.

   ERWINS

48 — 23.12.12 — 23:36

(45) там вообще то сортировка…

сортировать табличную часть????

   DrShad

49 — 23.12.12 — 23:42

(48) а ее обязательно сортировать, чтоб найти дубли? имхо клюшечный код в снеговике

   alexei366

50 — 23.12.12 — 23:43

ERWINS а как твой код отработает, если две совпадающие строки будут в конце таблицы?

   ERWINS

51 — 23.12.12 — 23:44

(49) что бы найти номера строк обязательно

   alexei366

52 — 23.12.12 — 23:44

а всё не посмотрел сначала.

   ERWINS

53 — 23.12.12 — 23:44

(50) да, проверил

   DrShad

54 — 23.12.12 — 23:45

(53) если уж ты получил ТЗ, то скорми ее запросу и получи все дубли в результат

   ERWINS

55 — 23.12.12 — 23:51

(54) зачем?

   kokamoonga

56 — 23.12.12 — 23:51

(48) извините за вопрос немного не по теме.

а почему нельзя сортировать табличную часть? судя по количеству вопросительных знаков в конце вашего возмущенного вопроса речь идет о чем-то предельно порочном и некрасивом…

   DrShad

57 — 23.12.12 — 23:52

(55) потому что сортировка ТЗ тормознутый метод

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

потому что так кошернее

   DrShad

58 — 23.12.12 — 23:53

(56) ее потом с оригиналом не удобно сверять, к примеру ввод ПТиУ

   ERWINS

59 — 23.12.12 — 23:56

(56) потому что я не знаю, можно ли произвольно в документе менять порядок строк.

Иногда это бывает черевато

   kokamoonga

60 — 23.12.12 — 23:57

(58) ну это первое и единственное, что пришло мне в голову да. просто такое количество вопросительных знаков… думал может за этим кроется что-то еще

   ERWINS

61 — 23.12.12 — 23:59

(60) просто я один раз так сделал, а потом объяснялся с лдьми из росалкоголя

   kokamoonga

62 — 23.12.12 — 23:59

(59) документ в котором нельзя меня порядок строк в табличной части это какой-то плохой документ как мне кажется. что-то есть неправильное в таком документе

   kokamoonga

63 — 24.12.12 — 00:02

(61) бред какой-то… но вобщем наши регулирующие органы никогда не были средоточием здравого смысла

   Noroving

64 — 24.12.12 — 00:20

модуль формы перед записью на сервере

ТЗДок = ТекущийОбъект.Товары.Выгрузить();

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

       Запрос.Текст = «ВЫБРАТЬ

       |    Товары.Код

       |    КОЛИЧЕСТВО(Товары.Номенклатура) КАК КоличествоДублей

       |ИЗ

       |    &ТабличканяЧастьДок КАК Товары

       |

       |СГРУППИРОВАТЬ ПО

       |    Товары.Код»;

Запрос.УстановитьПараметр(«ТабличканяЧастьДок»,ТЗДок);

       Результат = Запрос.Выполнить();

     
Выборка = Результат.Выбрать();

Пока Выборка.Следующий() Цикл

Если Выборка.КоличествоДублей>1 Тогда

   Отбор = Новый Структура(«Код», Выборка.Код);

НайденыеСтроки = ТекущийОбъект.Товары.НайтиСтроки(Отбор);

Если НайденыеСтроки.Количество()>0 Тогда

  Для Сч=1 По НайденыеСтроки.Количество()-1 Цикл

  Сообщение = Новый СообщениеПользователю;

  Сообщение.Текст = «Удалена строка с номенклатурой»+НайденыеСтроки[Сч].Номенклатура;

  Сообщение.Сообщить();

ТекущийОбъект.Товары.Удалить(НайденыеСтроки[Сч]);

КонецЦикла;

КонецЕсли;

КонецЕсли;

КонецЦикла;

   Snovy

65 — 24.12.12 — 00:27

(0) Выгрузить ТЧ в ТЗ, свернуть ТЗ по колонкам, где могут быть дубли, сравнить количество строк свернутой ТЗ и оригинальной ТЧ. Если разошлись количества строк — значит есть дубли. А вот уже потом искать любыми производительными способами дубли и сообщать о них пользователю.

А то часто видел код проверки на дубли, который очень долго ищет их там, где их нет…

   Max Street

66 — 24.12.12 — 00:30

(0) Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)

   Для Каждого ТекСтрока Из ТЧ Цикл

       ТекНоменклатура = ТекСтрока.Номенклатура;

       НомерСтрк = ТекСтрока.НомерСтроки;

       Для Каждого Стрк ИЗ ТЧ Цикл

           Если Стрк.Номенклатура = ТекНоменклатура И Стрк.НомерСтроки <> НомерСтрк Тогда

               ТЧ.Удалить(Стрк);

               Сообщение = Новый СообщениеПользователю;

               Сообщение.Текст = «дубли строк очищены»;

               Сообщение.Сообщить();

           КонецЕсли;    

       КонецЦикла;        

   КонецЦикла;

КонецПроцедуры

   ERWINS

67 — 24.12.12 — 00:34

&НаКлиенте

перем ЕстьДубликаты;

&НаКлиенте

Функция ПроверкаДубликатов()

   для каждого стр из Объект.Товары цикл

       стр.ДублирующаяСтрока=ложь;

   конецЦикла;

   
   МассивПервый=новый Массив;

   МассивВторой=новый Массив;

   
   для каждого стр из Объект.Товары цикл

       Если МассивПервый.Найти(стр.Товар)=неопределено тогда

           МассивПервый.Добавить(стр.Товар);

       иначеЕсли МассивВторой.Найти(стр.Товар)=неопределено тогда

           МассивВторой.Добавить(стр.Товар);

       КонецЕсли

   конецЦикла;

   
   для каждого стр из Объект.Товары цикл

       стр.ДублирующаяСтрока=не (МассивВторой.Найти(стр.Товар)=неопределено);

   КонецЦикла;

   
   ЕстьДубликаты=МассивВторой.Количество()>0;

   возврат ЕстьДубликаты;

КонецФункции // ПроверкаДубликатов()

&НаКлиенте

Процедура ТоварыПриИзменении(Элемент)

   ПроверкаДубликатов()

КонецПроцедуры

&НаКлиенте

Процедура ПриОткрытии(Отказ)

   ПроверкаДубликатов()

КонецПроцедуры

&НаКлиенте

Процедура ПередЗаписью(Отказ, ПараметрыЗаписи)

   Если ЕстьДубликаты тогда

       Сообщение = Новый СообщениеПользователю;

       Сообщение.Текст = «В табличной части Товары есть дубликаты»;

       Сообщение.Сообщить();

       отказ=истина;

   КонецЕсли;

КонецПроцедуры

&НаКлиенте

Процедура ПриПовторномОткрытии()

   ПроверкаДубликатов()

КонецПроцедуры

   DrShad

68 — 24.12.12 — 00:34

(66) больше никому это не показывай

   ERWINS

69 — 24.12.12 — 00:35

(68) почему?

   Noroving

70 — 24.12.12 — 00:36

(66) Представляю что будет с таб частью в 50 строк… Можно записать документ и пойти пообедать)))

   DrShad

71 — 24.12.12 — 00:40

(69) во-первых двойной цикл

во-вторых удаление строк с нарушением выборки

   ERWINS

72 — 24.12.12 — 00:41

(71) где ты видишь удаление строк????

какой двойной цикл?

   Noroving

73 — 24.12.12 — 00:44

(71) Таки да, если это и будет работать, то только при обратном обходе.

(72) Не тупи, мы коментируем не твой код.

   ERWINS

74 — 24.12.12 — 00:46

(73) понял, извини

удаление строк в двойном цикле это минное поле

   DrShad

75 — 24.12.12 — 00:46

(74) иди уже отдыхать :)

   Dethmont

76 — 24.12.12 — 03:47

(64) Пока самый близкий вариант… Но опять же обход всей Табличной части (а если нету дублей?)

   Dethmont

77 — 24.12.12 — 03:50

Тоже самое но с условием в запросе

ТЗДок = ТекущийОбъект.Товары.Выгрузить();

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

       Запрос.Текст = «ВЫБРАТЬ

       |    Товары.Код

       |    КОЛИЧЕСТВО(Товары.Номенклатура) КАК КоличествоДублей

       | Поместить ВТ

       |ИЗ

       |    &ТабличканяЧастьДок КАК Товары

       |

       |СГРУППИРОВАТЬ ПО

       |    Товары.Код»;

       |;

       | Выбрать ВТ.Код

       |ИЗ ВТ КАК ВТ

       |ГДЕ ВТ.КоличествоДублей > 1

Запрос.УстановитьПараметр(«ТабличканяЧастьДок»,ТЗДок);

       Результат = Запрос.Выполнить();

     
Выборка = Результат.Выбрать();

Пока Выборка.Следующий() Цикл

   Отбор = Новый Структура(«Код», Выборка.Код);

   НайденыеСтроки = ТекущийОбъект.Товары.НайтиСтроки(Отбор);

Если НайденыеСтроки.Количество()>0 Тогда

  Для Сч=1 По НайденыеСтроки.Количество()-1 Цикл

  Сообщение = Новый СообщениеПользователю;

  Сообщение.Текст = «Удалена строка с номенклатурой»+НайденыеСтроки[Сч].Номенклатура;

  Сообщение.Сообщить();

ТекущийОбъект.Товары.Удалить(НайденыеСтроки[Сч]);

КонецЦикла;

КонецЕсли;

КонецЦикла;

   Dethmont

78 — 24.12.12 — 03:59

Или же примитив:

ТЗДок = ТекущийОбъект.Товары.Выгрузить();

ТЗДок.Колонки.Добавить(«КоличествоДублей»);

ТЗДок.ЗаполнитьЗначения(1,»КоличествоДублей»);

ТЗДок.Свернуть(«Номенклатура»,»КоличествоДублей»);

Для каждого Стр Из ТЗДок Цикл

  Если Стр.КоличествоДублей > 1 тогда

     Отбор = Новый Структура(«Номенклатура», Стр.Номенклатура);

   НайденыеСтроки = ТекущийОбъект.Товары.НайтиСтроки(Отбор);

Если НайденыеСтроки.Количество()>0 Тогда

  Для Сч=1 По НайденыеСтроки.Количество()-1 Цикл

  Сообщение = Новый СообщениеПользователю;

  Сообщение.Текст = «Удалена строка с номенклатурой»+НайденыеСтроки[Сч].Номенклатура;

  Сообщение.Сообщить();

ТекущийОбъект.Товары.Удалить(НайденыеСтроки[Сч]);

КонецЦикла;

КонецЕсли;

КонецЦикла;

   Infsams654

79 — 24.12.12 — 09:14

В типовой БГУ в ОбщегоНазначения есть Функция ЭтоСтрокаДубль(ТабЧасть, СтрокаТабЧасти, СтруктураРеквизитов)

   Serg_1960

80 — 24.12.12 — 09:40

(64) и (78) Прежде чем искать чёрную кошку в тёмной комнате хотелось бы убедиться, что она там есть.

ТЗ = ЭтотОбъект.Товары.Выгрузить();

ТЗ.ЗаполнитьЗначения(1,»НомерСтроки»);

ТЗ.Свернуть(«Номенклатура»,»НомерСтроки»);

Если ЭтотОбъект.Товары.Количество() <> ТЗ.Количество() Тогда

  Собщить(«Мадам, я дико извеняюсь, но у вас таки всё-таки есть проблема с дублями строк»);

  Отказ = Истина;

  …

КонецЕсли;

   Noroving

81 — 24.12.12 — 09:48

(77) Писал на ходу без отладок… так что уж извините…

А нащет этого  |ГДЕ ВТ.КоличествоДублей > 1

может я и ошибаюсь, но помоему сначало срабатывает отбор, а потом групировка, не???

   Ns33

82 — 24.12.12 — 10:58

ВЫБРАТЬ РАЗЛИЧНЫЕ

   ПоступлениеТоваровТовары.НомерСтроки КАК НомерСтроки,

   ПоступлениеТоваровТовары.Номенклатура

ИЗ

   Документ.ПоступлениеТоваров.Товары КАК ПоступлениеТоваровТовары

       ЛЕВОЕ СОЕДИНЕНИЕ Документ.ПоступлениеТоваров.Товары КАК ПоступлениеТоваровТовары1

       ПО ПоступлениеТоваровТовары.Номенклатура = ПоступлениеТоваровТовары1.Номенклатура

ГДЕ

   ПоступлениеТоваровТовары.Ссылка = &Ссылка

   И ПоступлениеТоваровТовары1.Ссылка = &Ссылка

   И ПоступлениеТоваровТовары.НомерСтроки <> ПоступлениеТоваровТовары1.НомерСтроки

УПОРЯДОЧИТЬ ПО

   НомерСтроки

Единственно, нужно сначала ТЧ во временную таблицу кинуть, чтобы 2 раза не читать, но для краткости пока без ВТ.

   ERWINS

83 — 24.12.12 — 11:20

(82) квадратичная зависимость… жесть, так нельзя

   ERWINS

84 — 24.12.12 — 11:23

Каждый раз гонять данные на скл и обратно не есть гуд, это дополнительная нагрузка и значительные задержки, правда практически константные, лучше уж делать только на одном уровне трехзвенки (случай ошибок особый)

   Ns33

85 — 24.12.12 — 11:26

(83) Конечно нельзя, ведь правильно это делать циклами и без запросов, и для полного счастья всё это на клиенте.

   ERWINS

86 — 24.12.12 — 11:32

(85) смотри (67)

   Ns33

87 — 24.12.12 — 11:35

(86) Так я про это и писал.

   ERWINS

88 — 24.12.12 — 11:36

(87) на мой взгляд лучший  вариант….

   Ns33

89 — 24.12.12 — 11:43

(88) А вот давай попросим знающих людей выбрать наилучший вариант из предложенных в данной теме. Если они сюда зайдут, конечно.

   ERWINS

90 — 24.12.12 — 11:45

(89) хотелось бы

  

МихаилМ

91 — 24.12.12 — 12:11

(0)

вот эффективный алгоритм поиска дублей

Задача на поиск в массиве

Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)

   Если Товары.Количество() = 0 Тогда
       Возврат;
   КонецЕсли;

   ПроверитьДублиСтрок(Ссылка, «Товары», «Номенклатура, ШтрихКод», Отказ);

КонецПроцедуры

//Процедура проверяет наличие в ТЧ дублей строк по указанным реквизитам
//ДокументСсылка       — ссылка на проверяемый документ
//ИмяТабЧасти          — имя проверяемой табличной части (строка)
//ПроверяемРеквизиты — перечень проверяемых реквизитов (строка, реквизиты разделяются запятой)
Процедура ПроверитьДублиСтрок(ДокументСсылка, ИмяТабЧасти, ПроверяемРеквизиты, Отказ)

   ТаблДок = ДокументСсылка[ИмяТабЧасти].Выгрузить();
   ТаблДок.Колонки.Добавить(«КоличПроверкаДублей»);
   ТаблДок.ЗаполнитьЗначения(1, «КоличПроверкаДублей»);
   ТаблДок.Свернуть(ПроверяемРеквизиты,«КоличПроверкаДублей»);

   Для Каждого ТекСтрока Из ТаблДок Цикл
       Если ТекСтрока.КоличПроверкаДублей > 1 Тогда
           ДляСообщения = «»;
           СтрРекв = СокрЛП(ПроверяемРеквизиты);
           Пока Найти(СтрРекв,«,») > 0 Цикл
               НаимРеквизита = СокрЛП(Лев(СтрРекв,Найти(СтрРекв,«,») — 1));
               СтрРекв = Прав(СтрРекв,СтрДлина(СтрРекв) — Найти(СтрРекв,«,»));
               ДляСообщения = ДляСообщения+ТекСтрока[НаимРеквизита]+«, «;
           КонецЦикла;
           ДляСообщения = ДляСообщения+ТекСтрока[СокрЛП(СтрРекв)];

           Сообщение = Новый СообщениеПользователю;
           Сообщение.Текст = «В разделе « + ТекСтрока.Раздел + » одинаковые значения: « + ДляСообщения + «, сохранение невозможно»;
           Сообщение.Сообщить();

           Отказ = Истина;
       КонецЕсли;
   КонецЦикла;

КонецПроцедуры

Поиск дублей в таблице значений или табличном поле

16.05.2017

Проверка любой таблицы на повторяющиеся строки, с выводом сообщения какие строки задублированны, и режимом «Отказ» для проведения документов.

В данной процедуре поиск дублей происходит по всем колонкам строк. Тоесть дублем считается повтор значений в двух строках по всем колонкам.

Если повторяющих строк больше одной, то они все будут показаны в сообщении, с порядковым номером исходной строки и повторяющейся строки.

Данную процедура лучше использовать в общем модуле и вызывать её из процедур «ПриЗаписи» или «ОбработкаПроведения», и т.п. То есть в тех, где можно сделать отказ от выполнения дальнейших дествий
В качестве Таблицы — можно указать «ТаблицуЗначений», либо «ТабличнуюЧасть» документа, Справочника и т.д.

// !!! Павел С.С. 2 июня 2011 г. 17:49:14
// Проверка любой таблицы на повторяющиеся строки
// Данную процедура лучше использовать в процедурах ПриЗаписи, ОбработкаПроведения, и т.п. Тоесть в тех, где можно сделать отказ от выполениядальнейших дествий
// Параметры:
// ТЧ — можно указать «ТаблицуЗначений», либо «ТабличнуюЧасть» документа
// Отказ — параметр «Отказ» или «Истина», «Ложь»
Процедура ПоискДублейСтрокВТабЧасти(ТЧ, Отказ) Экспорт

 Если Тип(ТЧ) = Тип(«ТаблицаЗначений») Тогда
 
ТаблЗнач = ТЧ;
 Иначе
 
ТаблЗнач = ТЧ.Выгрузить();
 КонецЕсли;

 Отбор = Новый Структура();

 Для каждого Стр Из ТаблЗнач Цикл
 
Отбор.Очистить();
  Для каждого
Колонки Из ТаблЗнач.Колонки Цикл
   Если
Колонки.Имя <> «НомерСтроки» Тогда
   
Отбор.Вставить(Колонки.Имя, Стр[Колонки.Имя]);
   КонецЕсли;
  КонецЦикла;

  Строки = ТаблЗнач.НайтиСтроки(Отбор);
  Если
Строки.Количество() > 1 Тогда
   Для каждого
НайденныеСтроки Из Строки Цикл
    Если
Строки.Найти(НайденныеСтроки) > 0 Тогда
    
СтрокаСообщения = «Строка № » + Строки[0].НомерСтроки + » совпадает со строкой № » + НайденныеСтроки.НомерСтроки;
    
СообщитьОбОшибке(СтрокаСообщения, Отказ, «Уберите задвоения строк!»);
    КонецЕсли;
   КонецЦикла;
     КонецЕсли;
 КонецЦикла;
КонецПроцедуры

Понравилась статья? Поделить с друзьями:

Не пропустите также:

  • Как исправить двойной подбородок
  • Как найти даны на человека
  • Как найти массу медного куба
  • Как найти приложения на андройде
  • Как найти свою смерть в арк

  • 0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии