Внимание! Тема закрыта. Добавлять сообщения в закрытую тему запрещено.
Дано:
Двухуровневое дерево:
Родитель1
ПотомокР1.1
ПотомокР1.2
ПотомокР1.3
ПотомокР1.N
Родитель2
ПотомокР2.1
ПотомокР2.2
ПотомокР2.3
ПотомокР2.N
РодительN
ПотомокРN.1
ПотомокРN.2
ПотомокРN.3
ПотомокРN.N
Пользователь задает несколько условий на значения потомков (Реквизит1Потомка Равно ЗначениеРеквизита1; Реквизит2Потомка НЕ Равно ЗначениеРеквизита2 и т.д.) добавляя условия в ТЧ. Между условиями может быть И/ИЛИ
Найти:
Алгоритм проверки соответствия потомков списку введенных условий.
Есть какие-нибудь идеи?
Двухуровневое дерево:
Родитель1
ПотомокР1.1
ПотомокР1.2
ПотомокР1.3
ПотомокР1.N
Родитель2
ПотомокР2.1
ПотомокР2.2
ПотомокР2.3
ПотомокР2.N
РодительN
ПотомокРN.1
ПотомокРN.2
ПотомокРN.3
ПотомокРN.N
Пользователь задает несколько условий на значения потомков (Реквизит1Потомка Равно ЗначениеРеквизита1; Реквизит2Потомка НЕ Равно ЗначениеРеквизита2 и т.д.) добавляя условия в ТЧ. Между условиями может быть И/ИЛИ
Найти:
Алгоритм проверки соответствия потомков списку введенных условий.
Есть какие-нибудь идеи?
По теме из базы знаний
Найденные решения
Для Каждого Стр из ТЗУсловий Цикл
ЭлементДерева = ДеревоЭлементов.Найти(Стр.Потомок,,Истина);
Если ЭлементДерева <> Неопределено Тогда
РезультатВыполнения = Вычислить(ЭлементДерева[Строка(Стр.Реквизит)]+Стр.Условие+Стр.ЗначениеРеквизита);
КонецЕсли;
КонецЦикла;
условия задавать общепринятыми обозначениями, <,>,<>,=,НЕ.
ЭлементДерева = ДеревоЭлементов.Найти(Стр.Потомок,,Истина);
Если ЭлементДерева <> Неопределено Тогда
РезультатВыполнения = Вычислить(ЭлементДерева[Строка(Стр.Реквизит)]+Стр.Условие+Стр.ЗначениеРеквизита);
КонецЕсли;
КонецЦикла;
условия задавать общепринятыми обозначениями, <,>,<>,=,НЕ.
Остальные ответы
Подписаться на ответы
Инфостарт бот
Сортировка:
Древо развёрнутое
Свернуть все
(2) M.Shalimov, На выходе должно получиться дерево, очищенное от потомков, не удовлетворяющих условиям.
Список условий заранее не известен.
Это может быть что-то типа: Потомок.Поставщик = ЗначениеПоставщик И (Потомок.Цена = ЗначениеЦена1 ИЛИ Потомок.Цена = ЗначениеЦена2) и т.д.
Список условий получаем из ТЧ выражения И/ИЛИ оттуда же.
Список условий заранее не известен.
Это может быть что-то типа: Потомок.Поставщик = ЗначениеПоставщик И (Потомок.Цена = ЗначениеЦена1 ИЛИ Потомок.Цена = ЗначениеЦена2) и т.д.
Список условий получаем из ТЧ выражения И/ИЛИ оттуда же.
(5) mozz,
Второй вариант, в любом удобоном для Вас виде организовать хранение отбора.
Сделать рекурсивную функцию по обратному обходу строк дерева, с обходом вложенных строк.
Третий вариант, обойти дерево (рекурсия, ибо количество подчиненных строк неизвестно), во время обхода преобразовать к таблице значений, ролдителей строк добавить в строки ТЗ.
Дальше пишите запрос к ТЗ, помещаете во временную таблицу и дьяволически пишите условия для выборки.
Полученную ТЗ обртно преобразуетет к дереву.
Второй вариант, в любом удобоном для Вас виде организовать хранение отбора.
Сделать рекурсивную функцию по обратному обходу строк дерева, с обходом вложенных строк.
Третий вариант, обойти дерево (рекурсия, ибо количество подчиненных строк неизвестно), во время обхода преобразовать к таблице значений, ролдителей строк добавить в строки ТЗ.
Дальше пишите запрос к ТЗ, помещаете во временную таблицу и дьяволически пишите условия для выборки.
Полученную ТЗ обртно преобразуетет к дереву.
в свое время перебирал дерво таким образом:
Для каждого СтрокаПервогоУровня из ДеревоЗаказы.Строки цикл
Для каждого СтрокаВторогоУровня Из СтрокаПервогоУровня.Строки Цикл
Если ЭлементыФормы.Заказы.ТекущаяСтрока.НомерЗаказ = СтрокаВторогоУровня.НомерЗаказ тогда
Если СтрокаВторогоУровня.Формула = Формула тогда
Если СтрокаВторогоУровня.ФормулаВыбран тогда
БылаИстина = истина;
Иначе
БылаЛожь = истина;
КонецЕсли;
Если БылаИстина и БылаЛожь тогда
возврат 2;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЦикла;
тут проверяется дерево на тот факт что: "совпадает ли формула в конкретных заказах", я думаю легко под свои цели переделаеш
Для каждого СтрокаПервогоУровня из ДеревоЗаказы.Строки цикл
Для каждого СтрокаВторогоУровня Из СтрокаПервогоУровня.Строки Цикл
Если ЭлементыФормы.Заказы.ТекущаяСтрока.НомерЗаказ = СтрокаВторогоУровня.НомерЗаказ тогда
Если СтрокаВторогоУровня.Формула = Формула тогда
Если СтрокаВторогоУровня.ФормулаВыбран тогда
БылаИстина = истина;
Иначе
БылаЛожь = истина;
КонецЕсли;
Если БылаИстина и БылаЛожь тогда
возврат 2;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЦикла;
тут проверяется дерево на тот факт что: "совпадает ли формула в конкретных заказах", я думаю легко под свои цели переделаеш
Для Каждого Стр из ТЗУсловий Цикл
ЭлементДерева = ДеревоЭлементов.Найти(Стр.Потомок,,Истина);
Если ЭлементДерева <> Неопределено Тогда
РезультатВыполнения = Вычислить(ЭлементДерева[Строка(Стр.Реквизит)]+Стр.Условие+Стр.ЗначениеРеквизита);
КонецЕсли;
КонецЦикла;
условия задавать общепринятыми обозначениями, <,>,<>,=,НЕ.
ЭлементДерева = ДеревоЭлементов.Найти(Стр.Потомок,,Истина);
Если ЭлементДерева <> Неопределено Тогда
РезультатВыполнения = Вычислить(ЭлементДерева[Строка(Стр.Реквизит)]+Стр.Условие+Стр.ЗначениеРеквизита);
КонецЕсли;
КонецЦикла;
условия задавать общепринятыми обозначениями, <,>,<>,=,НЕ.
Если юзвери будут задавать условие буквами символами или любым другим нативным способом, то без Вычислить() так или иначе обойтись не удастся. Значение реквизита доступно как Элемент[ИмяРеквизита]. В чем сложность в цикле поискать элементы дерева(для которых указаны условия) по строковому, ссылочному или любому другому соответствию, а потом проверить выполнение условия, не понимаю.
(11) mymyka, Как отработает такое Вычислить(Справочник.Контрагенты.ПустаяСсылка()+"="+Справочник.Контрагенты.КакойтоКонтрагент)
?
У меня на такое пишет что "Преобразование к типу число не может быть выполнено".
Если из ссылок сделаем строки то будет так:
Вычислить(""+"="+"КакойтоКонтрагент")
На это пишет "Ошибка компиляции при вычислении выражения или выполнения фрагмента кода"
?
У меня на такое пишет что "Преобразование к типу число не может быть выполнено".
Если из ссылок сделаем строки то будет так:
Вычислить(""+"="+"КакойтоКонтрагент")
На это пишет "Ошибка компиляции при вычислении выражения или выполнения фрагмента кода"
Решил задачу монструозно:
Не очень красиво, но работает...
&НаСервере
Процедура ФильтроватьДеревоНаСервере()
Дерево = ДанныеФормыВЗначение(ТаблицаАнализ, Тип("ДеревоЗначений"));
ТзУдаляемых = Новый ТаблицаЗначений;
ТзУдаляемых.Колонки.Добавить("Строки");
ТзУдаляемых.Колонки.Добавить("СтрокиУд");
Для Каждого СтрокаПервогоУровня Из Дерево.Строки Цикл
Для каждого СтрокаВторогоУровня Из СтрокаПервогоУровня.Строки Цикл
Если НЕ ПодходитПоФильтрам(СтрокаВторогоУровня) тогда
Новая = ТзУдаляемых.Добавить();
Новая.Строки = СтрокаПервогоУровня.Строки;
Новая.СтрокиУд = СтрокаВторогоУровня;
КонецЕсли;
КонецЦикла;
КонецЦикла;
Для каждого стр Из ТзУдаляемых Цикл
стр.Строки.Удалить(стр.СтрокиУд);
КонецЦикла;
ЗначениеВДанныеФормы(Дерево, ТаблицаСФильтром);
КонецПроцедуры
&НаСервере
Функция ПодходитПоФильтрам(СтрокаДерева)
ТЗУсловий = ДанныеФормыВЗначение(НастройкиФильтров, Тип("ТаблицаЗначений"));
РезультатПроверки = Истина;
Добавочное = Ложь;
Для каждого Стр Из ТЗУсловий Цикл
Если Стр.ИИЛИ = "ИЛИ" тогда
Если Стр.ВидСравнения = "Равно" тогда
Если СтрокаДерева[Строка(Стр.ФильтрПо)] = Стр.ПравоеЗначение тогда
Добавочное = Истина;
Иначе
Добавочное = Ложь;
КонецЕсли;
РезультатПроверки = РезультатПроверки ИЛИ Добавочное;
Иначе
Если СтрокаДерева[Строка(Стр.ФильтрПо)] <> Стр.ПравоеЗначение тогда
Добавочное = Истина;
Иначе
Добавочное = Ложь;
КонецЕсли;
РезультатПроверки = РезультатПроверки ИЛИ Добавочное;
КонецЕсли;
Иначе
Если Стр.ВидСравнения = "Равно" тогда
Если СтрокаДерева[Строка(Стр.ФильтрПо)] = Стр.ПравоеЗначение тогда
Добавочное = Истина;
Иначе
Добавочное = Ложь;
КонецЕсли;
РезультатПроверки = РезультатПроверки И Добавочное;
Иначе
Если СтрокаДерева[Строка(Стр.ФильтрПо)] <> Стр.ПравоеЗначение тогда
Добавочное = Истина;
Иначе
Добавочное = Ложь;
КонецЕсли;
РезультатПроверки = РезультатПроверки И Добавочное;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Возврат РезультатПроверки;
КонецФункции // ПодходитПоФильтрам()
Не очень красиво, но работает...
&НаСервере
Процедура ФильтроватьДеревоНаСервере()
Дерево = ДанныеФормыВЗначение(ТаблицаАнализ, Тип("ДеревоЗначений"));
ТзУдаляемых = Новый ТаблицаЗначений;
ТзУдаляемых.Колонки.Добавить("Строки");
ТзУдаляемых.Колонки.Добавить("СтрокиУд");
Для Каждого СтрокаПервогоУровня Из Дерево.Строки Цикл
Для каждого СтрокаВторогоУровня Из СтрокаПервогоУровня.Строки Цикл
Если НЕ ПодходитПоФильтрам(СтрокаВторогоУровня) тогда
Новая = ТзУдаляемых.Добавить();
Новая.Строки = СтрокаПервогоУровня.Строки;
Новая.СтрокиУд = СтрокаВторогоУровня;
КонецЕсли;
КонецЦикла;
КонецЦикла;
Для каждого стр Из ТзУдаляемых Цикл
стр.Строки.Удалить(стр.СтрокиУд);
КонецЦикла;
ЗначениеВДанныеФормы(Дерево, ТаблицаСФильтром);
КонецПроцедуры
&НаСервере
Функция ПодходитПоФильтрам(СтрокаДерева)
ТЗУсловий = ДанныеФормыВЗначение(НастройкиФильтров, Тип("ТаблицаЗначений"));
РезультатПроверки = Истина;
Добавочное = Ложь;
Для каждого Стр Из ТЗУсловий Цикл
Если Стр.ИИЛИ = "ИЛИ" тогда
Если Стр.ВидСравнения = "Равно" тогда
Если СтрокаДерева[Строка(Стр.ФильтрПо)] = Стр.ПравоеЗначение тогда
Добавочное = Истина;
Иначе
Добавочное = Ложь;
КонецЕсли;
РезультатПроверки = РезультатПроверки ИЛИ Добавочное;
Иначе
Если СтрокаДерева[Строка(Стр.ФильтрПо)] <> Стр.ПравоеЗначение тогда
Добавочное = Истина;
Иначе
Добавочное = Ложь;
КонецЕсли;
РезультатПроверки = РезультатПроверки ИЛИ Добавочное;
КонецЕсли;
Иначе
Если Стр.ВидСравнения = "Равно" тогда
Если СтрокаДерева[Строка(Стр.ФильтрПо)] = Стр.ПравоеЗначение тогда
Добавочное = Истина;
Иначе
Добавочное = Ложь;
КонецЕсли;
РезультатПроверки = РезультатПроверки И Добавочное;
Иначе
Если СтрокаДерева[Строка(Стр.ФильтрПо)] <> Стр.ПравоеЗначение тогда
Добавочное = Истина;
Иначе
Добавочное = Ложь;
КонецЕсли;
РезультатПроверки = РезультатПроверки И Добавочное;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Возврат РезультатПроверки;
КонецФункции // ПодходитПоФильтрам()
Для получения уведомлений об ответах подключите телеграм бот:
Инфостарт бот