Имя: Пароль:
1C
1С v8
Поиск дублей в табличной части документа
0 RasuLL
 
23.12.12
22:35
Документ записан. Как проверить есть ли в табличной части документа дубли, если есть то удалить и сообщить? Обшарила форумы ничего подходящего не нашла. Заранее благодарна за помощь.
1 DrShad
 
23.12.12
22:36
запросом?
2 RasuLL
 
23.12.12
22:37
(1) Запрос.Текст = "ВЫБРАТЬ
       |    Товары.Код
       |ИЗ
       |    ДокПоступление.Товары КАК Товары
       |
       |СГРУППИРОВАТЬ ПО
       |    Товары.Код";
?
3 H A D G E H O G s
 
23.12.12
22:39
(2) Фотку?
4 DrShad
 
23.12.12
22:45
да, без фотки никак
5 RasuLL
 
23.12.12
22:46
какая еще фотка?
6 H A D G E H O G s
 
23.12.12
22:46
Пол: Женский

Какая, какая... Твоя.
7 Armando
 
23.12.12
22:46
(5) с такими вопросами как (0) только топлес
8 ОбычныйЧеловек
 
23.12.12
22:47
(5) месяц на форуме а обычи так и не узнала )
9 Torquader
 
23.12.12
22:50
(2) Посчитать количество различных и выбрать те, которые больше 1.
10 RasuLL
 
23.12.12
22:50
да тут одни джентльмены!
11 DrShad
 
23.12.12
22:51
(10) что не по-джентельменски?
12 RasuLL
 
23.12.12
22:51
(9) можете привести пример?
13 alexei366
 
23.12.12
22:53
Модам, вы неверно хотите это проверять перед записью документа?
14 RasuLL
 
23.12.12
22:54
(13) нет, после записи
15 ERWINS
 
23.12.12
22:55
"ВЫБРАТЬ
   |    Контрагенты.Код,
   |ИЗ
   |    Справочник.Контрагенты КАК Контрагенты
   |
   |СГРУППИРОВАТЬ ПО
   |    Контрагенты.Код
   |
   |ИМЕЮЩИЕ
   |    СУММА(1) > 1"
нечто
16 alexei366
 
23.12.12
22:55
это не принципиально, то есть это должно выполняться в интерфейсе и пользователя сразу оповещать?
17 RasuLL
 
23.12.12
22:57
(15) мне нужно проверить в таб. части, а это не то
18 Torquader
 
23.12.12
22:57
После записи - смысл этой проверки ?
Или это будет проверяться потом, чтобы "зверям отвесить по полной" ?
19 ERWINS
 
23.12.12
22:58
(16) думаю что  ОбработкаПроверкиЗаполнения
20 Torquader
 
23.12.12
22:58
(17) А что мешает выбирать из табличной части ?
Открыли конструктор запросов и мышкуем по нужным полям.
21 Torquader
 
23.12.12
23:00
(19) Если в ОбработкаПроверкаЗаполнения, то выгрузить табличную часть, добавить колонку - проставить единицу в неё, свернуть табличную часть, суммируя по колонке с единицей - ну и перебрать потом, чтобы пользователю сообщить, где он не прав.
22 RasuLL
 
23.12.12
23:00
(20) знания, не знаю как это сделать...
23 DrShad
 
23.12.12
23:02
(21) какой изврат
24 RasuLL
 
23.12.12
23:03
(21)Запрос = Новый Запрос;
       Запрос.Текст = "ВЫБРАТЬ
       |    Товары.Код
       |ИЗ
       |    НовыйДокПоступление.Товары КАК Товары
       |
       |СГРУППИРОВАТЬ ПО
       |    Товары.Код";
       Результат = Запрос.Выполнить();
       ТЗ = Новый ТаблицаЗначений;
       Результат.Выгрузить(ТЗ);
       
       ТЗ.ВыбратьСтроки();
       Пока ТЗ.ПолучитьСтроку()=1 Цикл
       ВыбратьСтроки();
       Пока ПолучитьСтроку()=1 Цикл
           Если (ТЗ.Код = Код)
           И (ТЗ.НомерСтроки<>НомерСтроки) Тогда
               Сообщить ("В строке №"+НомерСтроки+" имеется одинаковый код");
           КонецЕсли;
         КонецЦикла;
       КонецЦикла;
25 alexei366
 
23.12.12
23:03
Я так думаю что ей нужно в событии формы "ПередЗаписьюНаСервер" организовать обход строк табличной части, в этом обходе данные текущей строки сравниваются с данными строк где номер строки больше текущего, и при совпадении создавать СообщениеПользователю в котором ссылаться на текущую строку, таким образом мы не только не запишем ошибочный документ, но и тыкнем пользователя носом.
26 RasuLL
 
23.12.12
23:04
(25) все верно)
27 alexei366
 
23.12.12
23:05
Вот моя умничка, я знал что вы никогда не скажите что хотите
28 alexei366
 
23.12.12
23:05
Ну чтож пример кода придумать или сама?
29 RasuLL
 
23.12.12
23:06
цель проверять на коды, если в строке имеются одинаковые коды элементов, то удалить их и сообщить об этих строках
30 DrShad
 
23.12.12
23:06
(27) а не проще сворачивать по-умолчанию?
31 RasuLL
 
23.12.12
23:07
(28) не получается у меня...((
32 alexei366
 
23.12.12
23:09
DrShad эт идея, ток надо не сварачивать а в событии таблицы ОкончаниеРедактирования проверять на совпадение с другими строками , если да удалять эту и сообщить пользователю что он дурак
33 alexei366
 
23.12.12
23:09
Модмозель, вы определитесь пока с вариантом исполнения, а примеры кода после фотографии (не всёж на халяву)
34 alexei366
 
23.12.12
23:19
Мужики я сделал это!!!!!))))))))))))))
35 DrShad
 
23.12.12
23:23
что ты сделал?
36 alexei366
 
23.12.12
23:24
DrShad ты опоздал, фотка висела пару минут
37 alexei366
 
23.12.12
23:27
Эх походу кто-то обиделся и примеры кода не нужны, ладно ещё 3 минуты посмотрю потом закрою страничку.
38 ERWINS
 
23.12.12
23:29
Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
   ТЗ=Товары.Выгрузить();
   ТЗ.Сортировать("Товар, НомерСтроки");
   тов=неопределено;
   ст="";
   нтов=ложь;
   для каждого стр из ТЗ Цикл
       Если стр.Товар=тов тогда
           ст=ст+","+строка(стр.НомерСтроки);
           нтов=истина;
       Иначе
           Если нтов тогда
               Сообщение = Новый СообщениеПользователю;
               Сообщение.Текст = тов.Наименование+" содержиться в нескольких строках "+ст;
               Сообщение.Сообщить();
               отказ = истина;
           КонецЕсли;
           ст=строка(стр.НомерСтроки);
           нтов=Ложь;
           тов=стр.Товар;
       КонецЕсли;
       
   КонецЦикла;
   
   Если нтов тогда
       Сообщение = Новый СообщениеПользователю;
       Сообщение.Текст = тов.Наименование+" содержиться в нескольких строках "+ст;
       Сообщение.Сообщить();
       отказ = истина;
   КонецЕсли;
   
КонецПроцедуры
39 DrShad
 
23.12.12
23:32
(38) за такой код, человек его написавший уже бы не работал у нас, ничего личного, но не стоит учить плохому начинающих
40 alexei366
 
23.12.12
23:33
ERWINS есть одно но, небудет подсветки на ошибочную строку если в модуле объекта.
41 ОбычныйЧеловек
 
23.12.12
23:34
(38) а не проще выгрузить только колонку товары, добавить числовую колонку - запонить ее единичкой потом свернуть и там гле будет больше единицы вывести на экран...код в 3 строчки.
42 ERWINS
 
23.12.12
23:35
(39) и чем плохо кроме имен переменных?
(40) тогда делать по другому, тоже не сложно
43 DrShad
 
23.12.12
23:35
(41) зачем!? не проще сделать тоже самое запросом к ТЧ?
44 Noroving
 
23.12.12
23:35
(32) Помоему самый верный вариант... зачем писать замудроватые запросы и усложнять запись документа... проще сразу проверять внесенные данные...
45 DrShad
 
23.12.12
23:36
(42) например выгрузка в ТЗ и обход по ТЗ, а не сразу же по ТЧ
46 alexei366
 
23.12.12
23:36
DrShad а как запрос делать к незаписанному объекту?
47 ОбычныйЧеловек
 
23.12.12
23:36
(43) запрос будет работать при условии, что документ уже записан.
48 ERWINS
 
23.12.12
23:36
(45) там вообще то сортировка...
сортировать табличную часть????
49 DrShad
 
23.12.12
23:42
(48) а ее обязательно сортировать, чтоб найти дубли? имхо клюшечный код в снеговике
50 alexei366
 
23.12.12
23:43
ERWINS а как твой код отработает, если две совпадающие строки будут в конце таблицы?
51 ERWINS
 
23.12.12
23:44
(49) что бы найти номера строк обязательно
52 alexei366
 
23.12.12
23:44
а всё не посмотрел сначала.
53 ERWINS
 
23.12.12
23:44
(50) да, проверил
54 DrShad
 
23.12.12
23:45
(53) если уж ты получил ТЗ, то скорми ее запросу и получи все дубли в результат
55 ERWINS
 
23.12.12
23:51
(54) зачем?
56 kokamoonga
 
23.12.12
23:51
(48) извините за вопрос немного не по теме.
а почему нельзя сортировать табличную часть? судя по количеству вопросительных знаков в конце вашего возмущенного вопроса речь идет о чем-то предельно порочном и некрасивом...
57 DrShad
 
23.12.12
23:52
(55) потому что сортировка ТЗ тормознутый метод
потому что дублей может и не быть, а цикл пройдет всю ТЗ и это тоже время
потому что так кошернее
58 DrShad
 
23.12.12
23:53
(56) ее потом с оригиналом не удобно сверять, к примеру ввод ПТиУ
59 ERWINS
 
23.12.12
23:56
(56) потому что я не знаю, можно ли произвольно в документе менять порядок строк.
Иногда это бывает черевато
60 kokamoonga
 
23.12.12
23:57
(58) ну это первое и единственное, что пришло мне в голову да. просто такое количество вопросительных знаков... думал может за этим кроется что-то еще
61 ERWINS
 
23.12.12
23:59
(60) просто я один раз так сделал, а потом объяснялся с лдьми из росалкоголя
62 kokamoonga
 
23.12.12
23:59
(59) документ в котором нельзя меня порядок строк в табличной части это какой-то плохой документ как мне кажется. что-то есть неправильное в таком документе
63 kokamoonga
 
24.12.12
00:02
(61) бред какой-то... но вобщем наши регулирующие органы никогда не были средоточием здравого смысла
64 Noroving
 
24.12.12
00:20
модуль формы перед записью на сервере
ТЗДок = ТекущийОбъект.Товары.Выгрузить();

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

Пока Выборка.Следующий() Цикл
Если Выборка.КоличествоДублей>1 Тогда
   Отбор = Новый Структура("Код", Выборка.Код);
НайденыеСтроки = ТекущийОбъект.Товары.НайтиСтроки(Отбор);
Если НайденыеСтроки.Количество()>0 Тогда
  Для Сч=1 По НайденыеСтроки.Количество()-1 Цикл
  Сообщение = Новый СообщениеПользователю;
  Сообщение.Текст = "Удалена строка с номенклатурой"+НайденыеСтроки[Сч].Номенклатура;
  Сообщение.Сообщить();

ТекущийОбъект.Товары.Удалить(НайденыеСтроки[Сч]);
КонецЦикла;
КонецЕсли;
КонецЕсли;
КонецЦикла;
65 Snovy
 
24.12.12
00:27
(0) Выгрузить ТЧ в ТЗ, свернуть ТЗ по колонкам, где могут быть дубли, сравнить количество строк свернутой ТЗ и оригинальной ТЧ. Если разошлись количества строк - значит есть дубли. А вот уже потом искать любыми производительными способами дубли и сообщать о них пользователю.

А то часто видел код проверки на дубли, который очень долго ищет их там, где их нет...
66 Max Street
 
24.12.12
00:30
(0) Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
   Для Каждого ТекСтрока Из ТЧ Цикл
       ТекНоменклатура = ТекСтрока.Номенклатура;
       НомерСтрк = ТекСтрока.НомерСтроки;
       Для Каждого Стрк ИЗ ТЧ Цикл
           Если Стрк.Номенклатура = ТекНоменклатура И Стрк.НомерСтроки <> НомерСтрк Тогда
               ТЧ.Удалить(Стрк);
               Сообщение = Новый СообщениеПользователю;
               Сообщение.Текст = "дубли строк очищены";
               Сообщение.Сообщить();
           КонецЕсли;    
       КонецЦикла;        
   КонецЦикла;
КонецПроцедуры
67 ERWINS
 
24.12.12
00:34
&НаКлиенте
перем ЕстьДубликаты;

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

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


&НаКлиенте
Процедура ТоварыПриИзменении(Элемент)
   ПроверкаДубликатов()
КонецПроцедуры

&НаКлиенте
Процедура ПриОткрытии(Отказ)
   ПроверкаДубликатов()
КонецПроцедуры

&НаКлиенте
Процедура ПередЗаписью(Отказ, ПараметрыЗаписи)
   Если ЕстьДубликаты тогда
       Сообщение = Новый СообщениеПользователю;
       Сообщение.Текст = "В табличной части Товары есть дубликаты";
       Сообщение.Сообщить();
       отказ=истина;
   КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура ПриПовторномОткрытии()
   ПроверкаДубликатов()
КонецПроцедуры
68 DrShad
 
24.12.12
00:34
(66) больше никому это не показывай
69 ERWINS
 
24.12.12
00:35
(68) почему?
70 Noroving
 
24.12.12
00:36
(66) Представляю что будет с таб частью в 50 строк... Можно записать документ и пойти пообедать)))
71 DrShad
 
24.12.12
00:40
(69) во-первых двойной цикл
во-вторых удаление строк с нарушением выборки
72 ERWINS
 
24.12.12
00:41
(71) где ты видишь удаление строк????
какой двойной цикл?
73 Noroving
 
24.12.12
00:44
(71) Таки да, если это и будет работать, то только при обратном обходе.
(72) Не тупи, мы коментируем не твой код.
74 ERWINS
 
24.12.12
00:46
(73) понял, извини
удаление строк в двойном цикле это минное поле
75 DrShad
 
24.12.12
00:46
(74) иди уже отдыхать :)
76 Dethmont
 
24.12.12
03:47
(64) Пока самый близкий вариант... Но опять же обход всей Табличной части (а если нету дублей?)
77 Dethmont
 
24.12.12
03:50
Тоже самое но с условием в запросе
ТЗДок = ТекущийОбъект.Товары.Выгрузить();

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

Пока Выборка.Следующий() Цикл
   Отбор = Новый Структура("Код", Выборка.Код);
   НайденыеСтроки = ТекущийОбъект.Товары.НайтиСтроки(Отбор);
Если НайденыеСтроки.Количество()>0 Тогда
  Для Сч=1 По НайденыеСтроки.Количество()-1 Цикл
  Сообщение = Новый СообщениеПользователю;
  Сообщение.Текст = "Удалена строка с номенклатурой"+НайденыеСтроки[Сч].Номенклатура;
  Сообщение.Сообщить();

ТекущийОбъект.Товары.Удалить(НайденыеСтроки[Сч]);
КонецЦикла;
КонецЕсли;
КонецЦикла;
78 Dethmont
 
24.12.12
03:59
Или же примитив:
ТЗДок = ТекущийОбъект.Товары.Выгрузить();
ТЗДок.Колонки.Добавить("КоличествоДублей");
ТЗДок.ЗаполнитьЗначения(1,"КоличествоДублей");

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

ТекущийОбъект.Товары.Удалить(НайденыеСтроки[Сч]);
КонецЦикла;
КонецЕсли;
КонецЦикла;
79 Infsams654
 
24.12.12
09:14
В типовой БГУ в ОбщегоНазначения есть Функция ЭтоСтрокаДубль(ТабЧасть, СтрокаТабЧасти, СтруктураРеквизитов)
80 Serg_1960
 
24.12.12
09:40
(64) и (78) Прежде чем искать чёрную кошку в тёмной комнате хотелось бы убедиться, что она там есть.

ТЗ = ЭтотОбъект.Товары.Выгрузить();
ТЗ.ЗаполнитьЗначения(1,"НомерСтроки");
ТЗ.Свернуть("Номенклатура","НомерСтроки");

Если ЭтотОбъект.Товары.Количество() <> ТЗ.Количество() Тогда
  Собщить("Мадам, я дико извеняюсь, но у вас таки всё-таки есть проблема с дублями строк");
  Отказ = Истина;
  ...
КонецЕсли;
81 Noroving
 
24.12.12
09:48
(77) Писал на ходу без отладок... так что уж извините...
А нащет этого  |ГДЕ ВТ.КоличествоДублей > 1
может я и ошибаюсь, но помоему сначало срабатывает отбор, а потом групировка, не???
82 Ns33
 
24.12.12
10:58
ВЫБРАТЬ РАЗЛИЧНЫЕ
   ПоступлениеТоваровТовары.НомерСтроки КАК НомерСтроки,
   ПоступлениеТоваровТовары.Номенклатура
ИЗ
   Документ.ПоступлениеТоваров.Товары КАК ПоступлениеТоваровТовары
       ЛЕВОЕ СОЕДИНЕНИЕ Документ.ПоступлениеТоваров.Товары КАК ПоступлениеТоваровТовары1
       ПО ПоступлениеТоваровТовары.Номенклатура = ПоступлениеТоваровТовары1.Номенклатура
ГДЕ
   ПоступлениеТоваровТовары.Ссылка = &Ссылка
   И ПоступлениеТоваровТовары1.Ссылка = &Ссылка
   И ПоступлениеТоваровТовары.НомерСтроки <> ПоступлениеТоваровТовары1.НомерСтроки

УПОРЯДОЧИТЬ ПО
   НомерСтроки

Единственно, нужно сначала ТЧ во временную таблицу кинуть, чтобы 2 раза не читать, но для краткости пока без ВТ.
83 ERWINS
 
24.12.12
11:20
(82) квадратичная зависимость... жесть, так нельзя
84 ERWINS
 
24.12.12
11:23
Каждый раз гонять данные на скл и обратно не есть гуд, это дополнительная нагрузка и значительные задержки, правда практически константные, лучше уж делать только на одном уровне трехзвенки (случай ошибок особый)
85 Ns33
 
24.12.12
11:26
(83) Конечно нельзя, ведь правильно это делать циклами и без запросов, и для полного счастья всё это на клиенте.
86 ERWINS
 
24.12.12
11:32
(85) смотри (67)
87 Ns33
 
24.12.12
11:35
(86) Так я про это и писал.
88 ERWINS
 
24.12.12
11:36
(87) на мой взгляд лучший  вариант....
89 Ns33
 
24.12.12
11:43
(88) А вот давай попросим знающих людей выбрать наилучший вариант из предложенных в данной теме. Если они сюда зайдут, конечно.
90 ERWINS
 
24.12.12
11:45
(89) хотелось бы
91 МихаилМ
 
24.12.12
12:11
(0)
вот эффективный алгоритм поиска дублей
Задача на поиск в массиве