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

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) если еще подумать, то еще можно ускорить наверняка. если подробно в задачу посмотреть. другой вопрос - надо ли...
Оставьте свое сообщение
Вакансии
1С аналитик
Москва
зарплата от 210 000 руб.
Полный день

Руководитель направления 1С
Москва
зарплата от 350 000 руб.
Полный день

1С Программист
Москва
зарплата от 180 000 руб.
Полный день

Программист 1С
Москва
зарплата от 180 000 руб. до 220 000 руб.
Полный день

Аналитик 1С / Бизнес-аналитик
Нижний Новгород
зарплата от 100 000 руб. до 250 000 руб.
Временный (на проект)