Узнать номер позиции из списка значений в которой сработала команда Принадлежит()

1. Harry_udm 2 25.01.23 11:57 Сейчас в теме
Имеется список значений с группами справочника Номенклатура - СпГруппТоваров.

	ВыбратьСтроки();
	Пока ПолучитьСтроку() = 1 Цикл
		Если СпГруппТоваров.Принадлежит(Товар) = 1 Тогда
			// Собственно вопрос: как узнать номер позиции в СпГруппТоваров где сработало Принадлежит()?
		КонецЕсли;
	КонецЦикла;


Штатно никак. Может кто-то знает способ через внешние компоненты?
По теме из базы знаний
Найденные решения
34. user856012 13 25.01.23 15:37 Сейчас в теме
(33)
Реализовано через так
Слово "так" надо заменить на другое, из (24). ;-P

Потому что перебирать весь справочник для каждой строки ТЧ - г...внокод.

Первое, что просится - установить в справочнике СкидкиПоГруппамТоваров сортировку по реквизиту "Товар" и использовать НайтиПоРеквизиту().
Остальные ответы
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
2. ZergKRSK 129 25.01.23 12:19 Сейчас в теме
(1) НомерПозиции = СпГруппТоваров.НайтиЗначение(Товар);
4. Harry_udm 2 25.01.23 12:30 Сейчас в теме
(2) Не сработает, т.к. в списке группы
7. ZergKRSK 129 25.01.23 12:38 Сейчас в теме
(4) какое количество уровней иерархии справочника ?
8. Harry_udm 2 25.01.23 12:39 Сейчас в теме
9. ZergKRSK 129 25.01.23 12:41 Сейчас в теме
(8) в списке только группы?
10. Harry_udm 2 25.01.23 12:43 Сейчас в теме
(9) Нет. Есть как группы, так и отдельные элементы. Но по элементам всё понятно. Там через НайтиЗначение() сработает.
11. ZergKRSK 129 25.01.23 12:45 Сейчас в теме
(10) лень писать весь код
Подскажу только как найти корневого родителя для группы
Папа = Товар.Родитель;
Пока ПустоеЗначение(Папа.Родитель) = 0 Цикл
Папа = Папа.Родитель;
КонецЦикла;
user856012; +1 Ответить
12. Harry_udm 2 25.01.23 12:47 Сейчас в теме
(11) Что это дает? Родители данного элемента справочника (Товара из документа) мне не интересны.
13. user856012 13 25.01.23 12:50 Сейчас в теме
(5)
Через переменную Ном, вы получаете номер строки документа. Мне он не интересен.
Ну, звыняйте - телепалка с утра барахлит.
(12)
Родители данного элемента справочника (Товара из документа) мне не интересны.
Неужели? А в СпГруппТоваров что? Не родители?
27. ZergKRSK 129 25.01.23 13:56 Сейчас в теме
(12) это даёт всех родителей одной конкретной позиции. Подставляя родителя в СпГруппТоваров.НайтиЗначение( ... ) найдется и номер позиции.
14. user856012 13 25.01.23 12:57 Сейчас в теме
(11)
Подскажу только как найти корневого родителя для группы
Вангую: через десяток-другой сообщений автора выяснится, что в СпГруппТоваров есть как элементы, так и группы разных уровней.

Поэтому ваш код, безусловно, правильный, только надо (автору!) вставить в цикл поиск родителя текущего уровня.

Но это, опять-таки, телепатия, которая сегодня у меня сбоит. ;-)
16. Harry_udm 2 25.01.23 13:06 Сейчас в теме
(14) Не важно есть ли там элементы. Важно, что там есть группы товаров.
Есть факт, что Товар из текущей строки документа Принадлежит() списку значений. В какой позиции Принадлежит()?
21. user856012 13 25.01.23 13:09 Сейчас в теме
(16) Вам уже все разжевали и в рот положили код написали. Проглотить самостоятельно сможете?
23. Harry_udm 2 25.01.23 13:13 Сейчас в теме
24. user856012 13 25.01.23 13:29 Сейчас в теме
(23)
Место разжевывания?
Мнэээ... афедрон! Или чем вы там думаете при вашей постановке задачи незнакомым людям. :-P
25. Harry_udm 2 25.01.23 13:43 Сейчас в теме
(24) А вас просят лезть в каждое узкое горлышко и вставлять свое "авторитетное" мнение? Нечего ответить - не отвечайте. А хамить не надо.
18. user1880116 25.01.23 13:07 Сейчас в теме
(10) Ручками перебирай элементы списка и для каждого ПринадлежитГруппе или равен в зависимости от ЭтоГруппа.

По другому никак - твоя хотелка противоречит назначению оптимизации метода Принадлежит, там оно под капотом все за один запрос пытается выполнится, а тебе разные нужны.
22. Harry_udm 2 25.01.23 13:10 Сейчас в теме
(18) Сейчас так и делается. Но! 8 номенклатурных позиций проходят эту проверку за от 5 до 20 секунд. В зависимости от вложенности по уровням. Вот и встал вопрос об оптимизации кода.
3. user856012 13 25.01.23 12:22 Сейчас в теме
(1)
Может кто-то знает способ через внешние компоненты?
А тупо создать переменную и инкрементировать ее в цикле - религия не позволяет?
    НомерПозиции = 0;
    Ном = 0;
    ВыбратьСтроки();
    Пока ПолучитьСтроку() = 1 Цикл
        Ном = Ном + 1;
        Если СпГруппТоваров.Принадлежит(Товар) = 1 Тогда
            // Собственно вопрос: как узнать номер позиции в СпГруппТоваров где сработало Принадлежит()?
            НомерПозиции = Ном;
        КонецЕсли;
    КонецЦикла;
Показать

Надеюсь. не оскорбил ваши религиозные чувства?
5. Harry_udm 2 25.01.23 12:32 Сейчас в теме
(3) Ничуть. Через переменную Ном, вы получаете номер строки документа. Мне он не интересен.
6. Harry_udm 2 25.01.23 12:38 Сейчас в теме
Напишу чуть подробнее.

Например, в переменной СпГруппТоваров есть 3 значения.
1. Группа номенклатуры "Хлеб"
2. Группа номенклатуры "Стройматериалы"
3. Группа номенклатуры "Автозапчасти"

Выбираем строки документа.
В строке №1 документа в реквизите "Номенклатура" записан элемент справочника "Гвозди 2.5х50", который находится в группе "Гвозди строительные", которая находится в группе "Метизы", которая находится в группе "Стройматериалы".

СпГруппТоваров.Принадлежит(Товар) даст результат 1.
Но как мне узнать, что эта 1 (единица) из-за того, что гвозди сработали во второй позиции списка значений?
15. CheBurator 3119 25.01.23 13:00 Сейчас в теме
Папа = Товар.Родитель;
поз = СпГруппТоваров.НайтиЗначение(Папа);
Пока поз = 0 Цикл
Папа = Папа.Родитель;
поз = СпГруппТоваров.НайтиЗначение(Папа);
КонецЦикла;
Сообщить("Товар "+Товар +" найден в позиции "+поз+", по группе "+Папа);
user1880116; +1 Ответить
17. user856012 13 25.01.23 13:06 Сейчас в теме
(15) Вот-вот, именно это я и имел в виду. Но надо пару строк в начало добавить - см. (10)
19. Harry_udm 2 25.01.23 13:08 Сейчас в теме
(15) Тут тогда проще сделать так:
1) Выбрать значения из списка СпГруппТоваров
2) Для каждого значения применить Принадлежит() и, если 1, то вот оно
26. Westonline82 25.01.23 13:45 Сейчас в теме
(19)
ВыбратьСтроки();

    Пока ПолучитьСтроку() = 1 Цикл
        Если СпГруппТоваров.Принадлежит(Товар) = 1 Тогда
			Для Каждого ГруппаТоваров Из СпГруппТоваров Цикл
				Сч = 0;
				Если Товар.ПринадлежитЭлементу(ГруппаТоваров) Тогда
				     Сообщение = Новый СообщениеПользователю;
					 Сообщение.Текст = Сч;
					 Сообщение.Сообщить();
				КонецЕсли;
				Сч = Сч+1;
			КонецЦикла;
        КонецЕсли;
    КонецЦикла;
Показать
28. Harry_udm 2 25.01.23 13:58 Сейчас в теме
(26) Вы тут языки объединили, но принцип я понял. Так и сделано. Но в момент выполнения строки с кодом
Если Товар.ПринадлежитГруппе(ГруппаТоваров) = 1 Тогда
по замеру времени уходит от 5 до 20 секунд (в зависимости от уровня товара). Вот эту строку и пытаюсь оптимизировать.
29. CheBurator 3119 25.01.23 14:13 Сейчас в теме
(28) возможно, надо посмотреть не на текущую реализацию, а на задачу - которая потребовала текущей реализации - под другим углом?
.
СЗ.НайтиЗначение - самый быстрый метод.
ю
может быть - окажется что притекущей реализации вариант в (15) для каждого товара из ТЧ суммарно окажется менее затратным чем Принадлежит и потом (15). По сути применение (15) полностью покрывает задачу "принадлежности" и СЗ.Принадлежит можно не использовать вообще.
30. user856012 13 25.01.23 15:04 Сейчас в теме
(29)
может быть - окажется
...окажется, что в СпГруппТоваров есть и "Гвозди строительные", и "Метизы", и "Стройматериалы" (см.6).

И спрашивается - на какую из этих строк должен указать поиск "Гвозди 2.5х50" при таком ТЗ?
31. CheBurator 3119 25.01.23 15:09 Сейчас в теме
(30) а хз.. это уже от частностей задачи зависит.
при применении (15) - укажет на БЛИЖАЙШУЮ родительскую группу (Гвозди строительные). Мне кажется это логичным в общем случае. В частном - хз что ТС надо...
32. Harry_udm 2 25.01.23 15:16 Сейчас в теме
(30) Любое срабатывание Принадлежит(). Вот где сработало, ту позицию и надо.
20. user1880116 25.01.23 13:08 Сейчас в теме
(15) О, или так.
Собака, съеденная Злопом =)
33. Harry_udm 2 25.01.23 15:28 Сейчас в теме
Давайте пойдем не от Списка значений, а от справочников.

Имеем:
1) Справочник Номенклатура
2) Справочник Контрагенты
Это всё типовое, для ТиС 9.2

Также имеем:
3) справочник СкидкиПоГруппамТоваров, подчиненный справочнику Контрагенты.
Реквизиты справочника:
Товар - справочник Номенклатура
ПроцОпт - Число.

В Накладной расходной после завершения подбора товара надо все подобранные товары прогнать по справочнику СкидкиПоГруппамТоваров и, если товары входят в какую-то из групп, то применить скидку для этой группы товаров.

Реализовано через так:
	ВыбратьСтроки();
	Пока ПолучитьСтроку() = 1 Цикл
		СкидкиПоГруппамТоваров.ВыбратьЭлементы();
		Пока СкидкиПоГруппамТоваров.ПолучитьЭлемент() = 1 Цикл
			Если Товар.ПринадлежитГруппе(СкидкиПоГруппамТоваров.Товар) = 1 Тогда
				ПроцентСкидки = СкидкиПоГруппамТоваров.ПроцОпт;
				Прервать;
			КонецЕсли;
		КонецЦикла;
	КонецЦикла;
Показать


И вот тут строка с кодом
Если Товар.ПринадлежитГруппе(СкидкиПоГруппамТоваров.Товар) = 1 Тогда

выполняется очень долго. Последний замер - для трех номенклатурных позиций, включенных в подбор, время выполнения этой строки 4 секунды.

Попытка закинуть все группы товаров и их скидок в Таблицу значений, а ту в Список значений привела меня в тупик. Как выйти на скидку из Списка значений?
Принадлежит() срабатывает быстро. Но в Списке значений нет скидок. А в Таблице значений только группы товаров. И как в ней найти ту самую строку?
34. user856012 13 25.01.23 15:37 Сейчас в теме
(33)
Реализовано через так
Слово "так" надо заменить на другое, из (24). ;-P

Потому что перебирать весь справочник для каждой строки ТЧ - г...внокод.

Первое, что просится - установить в справочнике СкидкиПоГруппамТоваров сортировку по реквизиту "Товар" и использовать НайтиПоРеквизиту().
36. Harry_udm 2 25.01.23 17:07 Сейчас в теме
(34) Так там группы товаров. А ищем элемент.
48. Harry_udm 2 26.01.23 16:57 Сейчас в теме
(34) В итоге так и сделал. Сортировку по реквизиту в справочнике установил. А далее в коде уже сделал цикл прохода по Родителям и поиск через НайтиПоРеквизиту()
35. user856012 13 25.01.23 15:56 Сейчас в теме
(33)
Но в Списке значений нет скидок.
М-да. Кто мешает в качестве представления записать строку из значения скидки?

А после нахождения значения - преобразовать ее в число?
CheBurator; +1 Ответить
37. Harry_udm 2 25.01.23 17:08 Сейчас в теме
(35) Не мешает никто. НО! В списке значений содержатся группы справочника Номенклатура. А ищем элемент справочника.
38. пользователь 25.01.23 19:29
Сообщение было скрыто модератором.
...
40. user856012 13 25.01.23 21:00 Сейчас в теме
(38)
что мешает перебирать СЗ не через конструкцию Для Каждого, а через конструкцию Для НомерСписка = 0
Как минимум, версия платформы. ;-)
39. user856012 13 25.01.23 20:58 Сейчас в теме
(37)
В списке значений содержатся группы справочника Номенклатура. А ищем элемент справочника.
А что такое, по-вашему, родители элемента, нахождение цепочки которых вам продемонстрировали в (15)? Открою секрет: это и есть группы - сюрприз!

Пациент безнадежен...
42. Harry_udm 2 26.01.23 05:23 Сейчас в теме
(39) Я не понимаю, почему при обсуждении какого-то кода, надо обязательно переходить на личности и оскорблять человека? Что это? Завышенное ЧСВ? Или просто характер говеный? Почему вы позволяете себе общаться со мной с высокомерием?
Как рассказывается в анекдоте: "Какой из тебя Наполеон? Ты - жалкий, презренный червь!".

Но идею вашу осознаю. О результатах замеров отпишусь.
41. CheBurator 3119 25.01.23 21:41 Сейчас в теме
Так, восьмерочники! Собрались! А то и так уже ниже плинтуса пал секам...
43. VladimirB 16 26.01.23 08:12 Сейчас в теме
ВыбратьСтроки();
    Пока ПолучитьСтроку() = 1 Цикл
        Если СпГруппТоваров.Принадлежит(Товар) = 1 Тогда
            // Собственно вопрос: как узнать номер позиции в СпГруппТоваров где сработало Принадлежит()?
            _Родитель=Товар;
            Пока ПустоеЗначение(_Родитель)=0 Цикл
                   _Позиция=спГруппТоваров.НайтиЗначение(_Родитель);
                   Если _Позиция>0 Тогда
                         Сообщить(_Позиция);
                         Прервать;
                   КонецЕсли;
                    _Родитель=_Родитель.Родитель;
            КонецЦикла;

        КонецЕсли;
    КонецЦикла;
Показать


Так тоже долго?
45. Harry_udm 2 26.01.23 11:57 Сейчас в теме
(43) Да. Львиная доля времени (более 70%) уходит на выполнение строки
Если СпГруппТоваров.Принадлежит(Товар) = 1 Тогда
46. CheBurator 3119 26.01.23 16:05 Сейчас в теме
(45) условие
Если СпГруппТоваров.Принадлежит(Товар) = 1 Тогда
убрать вообще.
принадлежит или нет - станет известно в результате прохода цикла по родителям.
конкретный результат зависит от соотносшения числа элементов в ТЧ дока и в СЗ.
а то может в ТЧ = 500 строк, в СЗ - 2 значения - это будет "долго", если ТЧ =2 строки, СЗ = 500 значений - это будет "быстро"
47. Harry_udm 2 26.01.23 16:54 Сейчас в теме
(46) Да, вся суть этой ветки в том, чтобы убрать код с Принадлежит()
44. user856012 13 26.01.23 11:11 Сейчас в теме
(42) "Сопли и вопли" (с)

No comments.
49. Harry_udm 2 26.01.23 17:00 Сейчас в теме
Решение:
1) установил в справочнике "СкидкиПоГруппамТоваров" сортировку по реквизиту "Товар".
2) В цикле проходим по Родителям товаров и ищем через НайтиПоРеквизиту().

Замер времени показал ускорение в 4 раза.
50. CheBurator 3119 26.01.23 21:20 Сейчас в теме
(49) если еще подумать, то еще можно ускорить наверняка. если подробно в задачу посмотреть. другой вопрос - надо ли...
Оставьте свое сообщение

Для получения уведомлений об ответах подключите телеграм бот:
Инфостарт бот