"Задача:
Создать обработку с табличной частью.
Программно удалить только те строк, номера которых пользователь
задал в виде фильтра в шапке обработки. Фильтр универсальный: равно,
список, больше, меньше и т.п."
Коллеги, я иногда задаюсь двумя вопросами:
1.Что за профессор Мориарти делает такие задачи?
2.Может все-таки я слишком усложняю и у подобных задач есть решение?
Идем от фильтра:
"Универсальный отбор" - это как я понимаю Отбор в ОФ и ОтборКомпоновкиДанных в УФ.
в ОФ отбор по номеру строки невозможен. Поэтому всякие акробатические этюды с ПостроителемЗапроса не выйдут.
В УФ ОтборКомпоновкиДанных доступен для Динамического списка и собственно в СКД.
Динамическим списком не обратишься к табличной части Обработки.
Свойство ОтборСтрок это только вид сравнения Равно, там свойством является
Фиксированная Структура. В качестве ключа используется имя реквизита табличной части, а в качестве значения - значение, по которому осуществляется отбор.
Ну и собственно где может быть решение?
Создать собственные элементы "псевдофильтр" в виде значения, списка значений и вида сравнения?
Ну как-бы это не очень стыкуется с "Фильтр универсальный: равно,
список, больше, меньше и т.п."
Может что-то есть еще? Кто подскажет? Помогите пожалуйста.
(1) Можно сделать на основе компоновщика динамического списка. Запрос ДС сформировать на основе имен и типов полей табличной части.
ТЗ = Объект.ТабличнаяЧасть1.Выгрузить();
ПоляЗапроса = Новый Массив;
Для Каждого Колонка Из ТЗ.Колонки Цикл
Если Колонка.Имя = "ИсходныйНомерСтроки" Тогда
Продолжить;
КонецЕсли;
Типы = Колонка.ТипЗначения.Типы();
Если Типы.Количество() > 1 Тогда
ПоляЗапроса.Добавить("Неопределено КАК " + Колонка.Имя);
Продолжить;
КонецЕсли;
ТипКолонки = Типы[0];
Если ТипКолонки = Тип("Строка") Тогда
Длина = Колонка.ТипЗначения.КвалификаторыСтроки.Длина;
Если Длина = 0 Тогда
Длина = 1024;
КонецЕсли;
ПоляЗапроса.Добавить("ВЫРАЗИТЬ("""" КАК СТРОКА(" + XMLСтрока(Длина) + ")) КАК " + Колонка.Имя);
ИначеЕсли ТипКолонки = Тип("Дата") Тогда
ПоляЗапроса.Добавить("ДАТАВРЕМЯ(1,1,1) КАК " + Колонка.Имя);
ИначеЕсли ТипКолонки = Тип("Число") Тогда
Длина = Колонка.ТипЗначения.КвалификаторыЧисла.Разрядность;
Точность = Колонка.ТипЗначения.КвалификаторыЧисла.РазрядностьДробнойЧасти;
ПоляЗапроса.Добавить("ВЫРАЗИТЬ(0 КАК ЧИСЛО(" + Длина + ", " + Точность + ")) КАК " + Колонка.Имя);
ИначеЕсли ТипКолонки = Тип("Булево") Тогда
ПоляЗапроса.Добавить("ИСТИНА КАК " + Колонка.Имя);
Иначе
ОбъектМетаданных = Метаданные.НайтиПоТипу(ТипКолонки);
Если ОбъектМетаданных = Неопределено Тогда
Продолжить
КонецЕсли;
ПоляЗапроса.Добавить("ЗНАЧЕНИЕ( " + ОбъектМетаданных.ПолноеИмя() + ".ПустаяСсылка) КАК " + Колонка.Имя);
КонецЕсли;
КонецЦикла;
ТекстЗапроса = "ВЫБРАТЬ" + Символы.ПС + СтрСоединить(ПоляЗапроса, "," + Символы.ПС);
ДС.ТекстЗапроса = ТекстЗапроса;
(1)Насколько я понял, проблема в том, как сделать интерактивный универсальный отбор? В ОФ посмотрите как это сделано в групповой обработке данных, в УФ - групповая корректировка реквизитов.
(12)Спасибо. Там источник данных Запрос в СКД, передается имя Метаданных в виде параметра. Но мы не можем обратиться к ТабличнойЧасти Обработки через запрос к БД. Буду пробовать через источник данных Объект.
(1) Я бы попробовал программно создать СКД, в качестве источника данных установить туда Таблицу значений, а в качестве отбора -- отбор компоновки данных с формы. Строки, которые вернет результат выполнения СКД удалить из таблицы на форме методом НайтиСтроки()
(26) Ну СКД вернет нам таблицу значений. Если не менять структуру полей, то далее примерно так:
Для каждого Элемент из ТаблицаПослеОтбора Цикл
Отбор = ОбщегоНазначения.СтрокаТаблицыЗначенийВСтруктуру(Элемент);
НайденныеСтроки = ИсходнаяТаблица.НайтиСтроки(Отбор);
Для каждого НайденнаяСтрока Из НайденныеСтроки Цикл
ИсходнаяТаблица.Удалить(НайденнаяСтрока);
КонецЦикла;
КонецЦикла;
(33) Бред. Засовывать строку таблицы в структуру, потом по этой структуре искать эту же строку в исходной таблице, а потом еще зачем то в цикле пытаться её удалить (прекрасно зная, что она там одна).
Проще тогда уже делать копию ТЗ, в цикле её обходить, проверять на условие и тогда уже сносить её в основной таблице.
Но нет, мы не ищем легких путей, нам подавай СКД, потому что без обращения к СУБД мы уже не можем обработать таблицу значений, которая находится в оперативной памяти...
(35) вы попросили пример структуры для отбора -- я привел пример структуры для отбора, а не пример оптимально работающего решения. Об этом не было речи.
Ничего не мешает исключить из полей структуры колонки с типом данных ХранилищеЗначения и заменить удаление в цикле на НайденныеСтроки[0].
Но нет, мы не ищем легких путей, нам подавай СКД
Всё зависит от того, насколько сложный отбор на форме. Если на форме фильтр осуществляется с помощью отбора компоновки данных, то выполнять его придется через СКД, в противном случае для корректного выполнения сложных условий придется городить куда более вырвиглазные костыли.
Ну и в чем проблема? Создать массив удаляемых строк, а потом их удалить в цикле.
Никаких компоновок и отборов - они предназначены только для визуального отображения, а не для изменения состава строк.
Циклом найти нужные строки, добавить в массив, а потом в цикле по массиву - удалять... Первый класс задачка.
Циклом найти нужные строки, добавить в массив, а потом в цикле по массиву - удалять... Первый класс задачка.
номера которых пользователь
задал в виде фильтра в шапке обработки Я понимаю как их удалить, это действительно просто, я не понимаю как стыкуется
именно для визуального отображения. На уровне элемента формы.
(3) Что отображать? Отбор? Строка. С номерами через запятую. В задаче не сказано каким образом пользователь должен вводить отбор? Нет. Значит все на твое усмотрение.
Обычная строка не противоречит условиям задачи.
Ну или список с числами, если уж очень хочется.
В задаче приводится четкое описание на уровне всех сравнений отбора,
мы делаем строку. А, простите, равно, больше или равно. подобно, с /по
мы тоже все в одну строку вместе с значениями?
(8)Во-первых что за тон?
Во-вторых задача не мной создана, и я сюда не издеваться пришел и не троллить.
В-третьих парсить строку ">=6", а тем более диапазоны
полученные парсом строки "C 19 По 21" разве просто?
Там еще условия "Не равно", "Не в списке" и т д
(11)Там Отбор не применишь ни в ОФ, ни в УФ.
НомерСтроки не отбирается в ОФ, в УФ из ДокументСсылка.ТабличнаяЧасть можно дин. списком, а если ОбработкаОбъект.ТабличнаяЧасть никак.
(1) Можно сделать на основе компоновщика динамического списка. Запрос ДС сформировать на основе имен и типов полей табличной части.
ТЗ = Объект.ТабличнаяЧасть1.Выгрузить();
ПоляЗапроса = Новый Массив;
Для Каждого Колонка Из ТЗ.Колонки Цикл
Если Колонка.Имя = "ИсходныйНомерСтроки" Тогда
Продолжить;
КонецЕсли;
Типы = Колонка.ТипЗначения.Типы();
Если Типы.Количество() > 1 Тогда
ПоляЗапроса.Добавить("Неопределено КАК " + Колонка.Имя);
Продолжить;
КонецЕсли;
ТипКолонки = Типы[0];
Если ТипКолонки = Тип("Строка") Тогда
Длина = Колонка.ТипЗначения.КвалификаторыСтроки.Длина;
Если Длина = 0 Тогда
Длина = 1024;
КонецЕсли;
ПоляЗапроса.Добавить("ВЫРАЗИТЬ("""" КАК СТРОКА(" + XMLСтрока(Длина) + ")) КАК " + Колонка.Имя);
ИначеЕсли ТипКолонки = Тип("Дата") Тогда
ПоляЗапроса.Добавить("ДАТАВРЕМЯ(1,1,1) КАК " + Колонка.Имя);
ИначеЕсли ТипКолонки = Тип("Число") Тогда
Длина = Колонка.ТипЗначения.КвалификаторыЧисла.Разрядность;
Точность = Колонка.ТипЗначения.КвалификаторыЧисла.РазрядностьДробнойЧасти;
ПоляЗапроса.Добавить("ВЫРАЗИТЬ(0 КАК ЧИСЛО(" + Длина + ", " + Точность + ")) КАК " + Колонка.Имя);
ИначеЕсли ТипКолонки = Тип("Булево") Тогда
ПоляЗапроса.Добавить("ИСТИНА КАК " + Колонка.Имя);
Иначе
ОбъектМетаданных = Метаданные.НайтиПоТипу(ТипКолонки);
Если ОбъектМетаданных = Неопределено Тогда
Продолжить
КонецЕсли;
ПоляЗапроса.Добавить("ЗНАЧЕНИЕ( " + ОбъектМетаданных.ПолноеИмя() + ".ПустаяСсылка) КАК " + Колонка.Имя);
КонецЕсли;
КонецЦикла;
ТекстЗапроса = "ВЫБРАТЬ" + Символы.ПС + СтрСоединить(ПоляЗапроса, "," + Символы.ПС);
ДС.ТекстЗапроса = ТекстЗапроса;
Почему все уперлись в отбор? Про который нет ни слова в задаче? В задаче есть слово "фильтр". Слово "отбор" придумал ТС, и после этого все пошли по неправильному пути.
Задача - удалить строки, а не показать на экране отбор строк.
Зачем изобретать велосипед?
Элемент со списком видов сравнения и текстовая строка для правого значения. Потом формирование массива удаляемых строк на основании правого значения, потом удаление строк по сформированному массиву.
"Универсальный" <> "платформенный, типовой". Универсальный - это который подходит для всех видов сравнения (на единичное значение и на список). И всё!
(19) Формально задача простая. Думаю, у ТС нет вопросов как добавить поле ввода на форму и прочее для ее решения. Тут скорее повод поговорить об универсальном отборе, непривязанном к отчету. Платформенный станет универсальным, стоит лишь усложнить задачу. И решать ее через свою таблицу отборов со всей обработкой – вот где будет точно велосипед.
Если подходить формализовано, то возникает неоднозначность определения.
Набрал слово "фильтр" в СП, а потом в справке по платформе:
Общие объекты/DOM/ИтераторУзловDOM/Свойства/Фильтр
Общие объекты/DOM/ОбходДереваDOM/Свойства/Фильтр
Общие объекты/XBase/ИндексXBase/Свойства/Фильтр
Общие объекты/Работа с файлами/ДиалогВыбораФайла/Свойства/Фильтр
Общие объекты/Работа с файлами/ПараметрыДиалогаПомещенияФайлов/Свойства/Фильтр
А ежели задача удалить строки, то зачем городить огород в условии и упоминать про универсальность,
виды сравнения?
Это как двумя словами можно обезобразить и усложнить задачу:
"возможность редактирования и добавления новых строк"
"возможность редактирования и добавления новых строк и столбцов"
Или как в фильме "Привидение" с Патриком Суэйзи:
"Поднять стакан воды"
"Поднять стакан воды будучи мертвым"
А не проще было просто взять все таблицу и циклом по ней пройтись снизу-вверх и удалить те строки, которые удовлетворяют уловию? Если я правильно понял то там кода на 10-20 строк максимум
(23)Я думаю, если бы мы делали метод фонового задания, то да. Безусловно.
Но в условии фигурирует Пользователь, он там что-то задает в шапке обработки "и т.п."
(23) Так и я про то же. Все что нужно получить - это массив с номерами строк, которые надо удалить.
То есть это задача, которая вообще никакого отношения ни к отборам, ни к фильтрам не имеет.
Задача просто на умение пользоваться универсальными коллекциями (массивами и таблицами)
(27)Ну пока от вас только слова. Человек обработку работающую приложил.
Я убрал из нее Динамический список и текст запроса-типизатора, взял реквизит формы КомпоновщикНастроек, типизировал набор данных с таблицей одной колонкой, убрал массив для удаления (удаляю сразу в цикле обхода итоговой коллекции), сейчас вся обработка 71 строка. Со всеми видами сравнения. Их если что 10 для типа Число.
Ваш вариант в формате epf где?
(36) Ваш вариант однозначно лаконичнее и оптимальнее, чем мой. Про реквизит формы типа КомпоновщикНастроекКомпоновкиДанных я знал и думал использовать именно его, но не сообразил как правильно инициализировать.
40.
user785225
2631.08.22 18:22 Сейчас в теме+7 $m
(36) как сформировать КомпоновщикНастроекКомпоновкиДанных для САБЖа программно?
цель - отбираться по табличной части документа, дописав всего 2 строки:
- ПриСозданииНаСервере: ИнициализироватьСКД(...)
- КомпоновщикНастроекКомпоновкиДанныхНастройкиОтборПриИзменении: УдалитьСтроки(...)
(не добавляя ручками на форму компоновщик данных - собственно это делалется в одну строчку, получилось;
ЭтаФорма.ИзменитьРеквизиты(Массив(Новый РеквизитФормы("КомпоновщикНастроекКомпоновкиДанных_", Новый ОписаниеТипов("КомпоновщикНастроекКомпоновкиДанных"))))
не вынося ручками элемент с настройками - а вот это не получилось, подчиненные элементы настроек видимо при ручном добавлении инициализируются, а при программном - нет, и их тьма, см. рис.)