Как получить список строк, найденных пользователем в таблице управляемой формы 1С после интерактивного поиска?

Программист 1С v8.3 (Управляемые формы)
← На главную

При работе с управляемыми формами в 1С:Предприятии часто возникает ситуация, когда пользователь интерактивно использует встроенный механизм поиска в табличной части формы. Это удобная функция, позволяющая быстро отфильтровать данные по заданному критерию прямо на форме. Однако, если нам как разработчикам потребуется программно получить список именно тех строк, которые остались видимыми после такого интерактивного поиска, задача может показаться нетривиальной.

Стандартные механизмы платформы не предоставляют прямого доступа к критериям интерактивного поиска, особенно когда речь идет об элементе формы типа Таблица, связанном с данными типа ТаблицаЗначений. Свойство ОтборСтрок элемента формы предназначено для программной установки отбора, а не для чтения уже примененного пользователем интерактивного поиска. В данной статье мы подробно рассмотрим несколько подходов и обходных путей, которые позволят нам решить эту задачу и получить желаемый список строк. В качестве альтернативного готового решения можно использовать универсальную форму отбора и сортировки для любых таблиц значений, реализующую гибкую фильтрацию средствами СКД.

Метод 1: Использование метода ПроверитьСтроку()

Один из наиболее эффективных и подтвержденных на практике способов получить список видимых строк после интерактивного поиска — это использование метода ПроверитьСтроку(), доступного для элементов формы типа Таблица. Этот метод позволяет нам определить, отображается ли конкретная строка в таблице формы с учетом всех текущих отборов, включая интерактивный поиск пользователя.

Давайте разберем, как мы можем применить этот метод шаг за шагом:

  1. Суть метода: Метод Элементы.<ИмяТаблицы>.ПроверитьСтроку(ИдентификаторСтроки) возвращает значение Истина, если строка с указанным идентификатором отображается на форме (то есть она прошла все отборы, включая интерактивный поиск). Если строка скрыта, метод вернет Ложь.
  2. Получение идентификатора строки: Для того чтобы проверить каждую строку, нам потребуется получить ее уникальный идентификатор. Каждая строка в коллекции типа ТаблицаЗначений имеет свой идентификатор, который можно получить методом ПолучитьИдентификатор().
  3. Итерация по исходной таблице: Поскольку нам нужно проверить все строки на предмет их видимости, мы должны будем проитерировать по всей исходной ТаблицеЗначений, которая является источником данных для нашей табличной части на форме.
  4. Создание списка найденных строк: В процессе итерации мы будем формировать новый список (например, Массив или новую ТаблицуЗначений), куда будем добавлять только те строки, для которых ПроверитьСтроку() вернула Истина.

Рассмотрим пример кода, который демонстрирует этот подход:


&НаКлиенте
Процедура ПолучитьНайденныеСтрокиВТЧ()
    // Предположим, что наша табличная часть на форме называется "Товары"
    // и ее данные привязаны к реквизиту формы "Объект.Товары" (типа ТаблицаЗначений)
    
    // Создадим новый массив, в который будем собирать найденные строки
    ПеременнаяНайденныеСтроки = Новый Массив;
    
    // Получим ссылку на элемент формы "Товары"
    ЭлементТаблицы = Элементы.Товары;
    
    // Получим саму ТаблицуЗначений, которая является источником данных для элемента формы
    // Важно: если реквизит формы объектный (например, "Объект"), то его надо предварительно
    // преобразовать в значение. Если это реквизит формы коллекции (например, "Товары"),
    // то можно обращаться напрямую
    ИсходнаяТаблицаЗначений = Объект.Товары;
    
    // Проитерируем по каждой строке исходной таблицы
    Для Каждого СтрокаТЗ Из ИсходнаяТаблицаЗначений Цикл
        // Получим идентификатор текущей строки
        ИдентификаторСтроки = СтрокаТЗ.ПолучитьИдентификатор();
        
        // Проверим, отображается ли эта строка в элементе формы с учетом отборов
        Если ЭлементТаблицы.ПроверитьСтроку(ИдентификаторСтроки) Тогда
            // Если строка отображается, добавляем ее в наш список найденных строк
            ПеременнаяНайденныеСтроки.Добавить(СтрокаТЗ);
        КонецЕсли;
    КонецЦикла;
    
    // Теперь переменная "ПеременнаяНайденныеСтроки" содержит массив тех строк,
    // которые видны пользователю в табличной части формы
    
    // Пример использования: можно вывести количество найденных строк
    Сообщить("Найдено видимых строк: " + ПеременнаяНайденныеСтроки.Количество());
    
    // Далее вы можете работать с этим массивом: перебирать, выводить в другую таблицу и т.д.
КонецПроцедуры

Важные нюансы и дополнительные сведения:

  1. Где вызывать процедуру: Эту процедуру можно вызывать по кнопке "Получить найденные" или, например, в обработчике события, которое происходит после изменения отбора, хотя напрямую отловить интерактивный поиск без сторонних механизмов довольно сложно. Если требуется максимально оперативно реагировать на изменение видимости, можно рассмотреть вызов в обработчике события ПриАктивизацииСтроки, но это будет проверять только активированную строку. Для получения всего списка видимых строк после интерактивного поиска пользователем, оптимальным решением является добавление отдельной кнопки.
  2. Доступ к данным строки: Если ПроверитьСтроку() вернула Истина, вы уже имеете саму строку (СтрокаТЗ в примере), из которой можете получить значения всех реквизитов. Если вам нужен доступ к значениям реквизитов формы, относящихся к этой строке, и вы используете индекс, то можно использовать синтаксис Объект.ИмяТЧ[ИндексСтроки].Реквизит, но в нашем случае СтрокаТЗ уже является нужным объектом.

Метод 2: Получение выделенных строк через ВыделенныеСтроки (интерактивный обходной путь)

Если мы готовы немного изменить пользовательский сценарий и можем попросить пользователя выполнить дополнительное действие, то можем использовать свойство ВыделенныеСтроки элемента формы. Этот подход основан на том, что пользователь после выполнения интерактивного поиска вручную выделит все найденные строки.

Разберем последовательность действий:

  1. Действие пользователя: Пользователь выполняет интерактивный поиск в табличной части. После того как в таблице останутся только нужные строки, пользователь нажимает комбинацию клавиш Ctrl+A (для выделения всех видимых строк) или вручную выделяет нужные строки.
  2. Программное получение выделенных строк: Мы можем получить массив идентификаторов этих выделенных строк с помощью свойства Элементы.<ИмяТаблицы>.ВыделенныеСтроки.
  3. Получение объектов строк: Имея идентификаторы, мы можем использовать метод НайтиПоИдентификатору() у исходной ТаблицыЗначений, чтобы получить сами объекты строк.

Пример кода для этого подхода:


&НаКлиенте
Процедура ПолучитьВыделенныеСтроки()
    // Предположим, что наша табличная часть на форме называется "Товары"
    // и ее данные привязаны к реквизиту формы "Объект.Товары"
    
    // Создадим новый массив, в который будем собирать строки
    ПеременнаяНайденныеСтроки = Новый Массив;
    
    // Получим массив идентификаторов выделенных строк
    МассивИдентификаторов = Элементы.Товары.ВыделенныеСтроки;
    
    // Получим саму ТаблицуЗначений, которая является источником данных
    ИсходнаяТаблицаЗначений = Объект.Товары;
    
    // Проитерируем по идентификаторам и найдем соответствующие строки
    Для Каждого ИдентификаторСтроки Из МассивИдентификаторов Цикл
        СтрокаТЗ = ИсходнаяТаблицаЗначений.НайтиПоИдентификатору(ИдентификаторСтроки);
        Если СтрокаТЗ <> Неопределено Тогда
            ПеременнаяНайденныеСтроки.Добавить(СтрокаТЗ);
        КонецЕсли;
    КонецЦикла;
    
    Сообщить("Найдено (выделено) строк: " + ПеременнаяНайденныеСтроки.Количество());
    // Далее работаем с ПеременнаяНайденныеСтроки
КонецПроцедуры

Этот метод является простым в реализации, но требует активного участия пользователя. Он может быть полезен в сценариях, где интерактивное взаимодействие с пользователем не является проблемой.

Метод 3: Реализация собственного механизма поиска

Если нам требуется полный контроль над процессом поиска и его результатами, а также не хочется полагаться на интерактивные действия пользователя или особенности платформы, мы можем реализовать собственный механизм поиска. Этот подход является более трудоемким, но предоставляет максимальную гибкость. Для создания более продвинутого поискового алгоритма можно задействовать компоненту нечеткого поиска, которая позволяет вычислять коэффициент похожести и сопоставлять текстовые данные.

Как это сделать:

  1. Добавление элементов управления: Мы добавляем на форму текстовое поле для ввода поискового запроса (например, ПолеВводаПоиска) и кнопку "Найти" (например, КомандаНайти).
  2. Программная обработка поиска: В обработчике команды "Найти" мы получаем текст из поля ввода и применяем его к исходной ТаблицеЗначений.
  3. Формирование новой таблицы и обновление данных: Мы создаем новую ТаблицуЗначений, наполняем ее только теми строками из исходной таблицы, которые соответствуют нашему поисковому запросу, и затем присваиваем эту новую отфильтрованную таблицу в качестве источника данных для элемента формы Таблица.

Пример реализации собственного поиска:


&НаКлиенте
Перем РезультатПоиска ТаблицаЗначений; // Для хранения отфильтрованных данных

&НаКлиенте
Процедура КомандаНайти(Команда)
    ТекстПоиска = Элементы.ПолеВводаПоиска.Значение;
    
    Если ЗначениеЗаполнено(ТекстПоиска) Тогда
        // Создаем новую ТаблицуЗначений для результатов поиска
        РезультатПоиска = Новый ТаблицаЗначений;
        
        // Копируем колонки из исходной таблицы
        Для Каждого Колонка Из Объект.Товары.Колонки Цикл
            РезультатПоиска.Колонки.Добавить(Колонка.Имя, Колонка.ТипЗначения, Колонка.Заголовок);
        КонецЦикла;
        
        // Итерируем по исходной таблице и ищем совпадения
        Для Каждого СтрокаТЗ Из Объект.Товары Цикл
            // Пример простого текстового поиска по всем строковым реквизитам
            // Можно реализовать более сложную логику поиска
            НайденоВСтроке = Ложь;
            Для Каждого Колонка Из СтрокаТЗ.Метаданные().Свойства() Цикл
                Если Колонка.Тип.Строка() И СтрокаТЗ[Колонка.Имя] Тогда
                    Если СтрНайти(НижРег(СтрокаТЗ[Колонка.Имя]), НижРег(ТекстПоиска)) > 0 Тогда
                        НайденоВСтроке = Истина;
                        Прервать;
                    КонецЕсли;
                КонецЕсли;
            КонецЦикла;
            
            Если НайденоВСтроке Тогда
                // Если строка соответствует условию, добавляем ее в результат
                РезультатПоиска.Добавить().Заполнить(СтрокаТЗ);
            КонецЕсли;
        КонецЦикла;
        
        // Присваиваем отфильтрованную таблицу элементу формы
        Элементы.Товары.ИзменитьНаполнение(РезультатПоиска);
        
    Иначе
        // Если поле поиска пустое, возвращаем исходную таблицу
        Элементы.Товары.ИзменитьНаполнение(Объект.Товары);
    КонецЕсли;
КонецПроцедуры

Этот подход дает нам полный контроль над алгоритмом поиска и гарантирует, что мы всегда будем иметь программный доступ к списку найденных строк, так как мы сами их формируем.

Метод 4: Использование вспомогательного реквизита для отбора

Еще один обходной путь, который позволяет использовать механизм отбора элемента формы, но при этом иметь программный контроль над тем, какие строки отображаются, это добавление вспомогательного реквизита в исходную ТаблицуЗначений.

Разберем этот метод:

  1. Добавление вспомогательной колонки: Добавьте в исходную ТаблицуЗначений новую булеву колонку, например, с именем ВидимаяСтрока.
  2. Программное обновление колонки: Когда пользователь (или вы по команде) выполняет поиск, вы итерируете по всем строкам исходной ТаблицыЗначений и устанавливаете значение колонки ВидимаяСтрока в Истина для тех строк, которые соответствуют условию поиска, и в Ложь для остальных.
  3. Применение отбора к элементу формы: После обновления этой колонки вы применяете программный отбор к элементу формы Таблица по этому булеву реквизиту.

Пример использования вспомогательного реквизита:


&НаКлиенте
Процедура ОбновитьОтборПоиска(Команда)
    ТекстПоиска = Элементы.ПолеВводаПоиска.Значение; // Предположим, есть поле ввода поиска
    
    // Проверим, существует ли колонка "ВидимаяСтрока"
    Если Объект.Товары.Колонки.Найти("ВидимаяСтрока") = Неопределено Тогда
        Объект.Товары.Колонки.Добавить("ВидимаяСтрока", Новый ОписаниеТипов("Булево"));
    КонецЕсли;
    
    // Сбросим текущий отбор, чтобы переприменить его
    Элементы.Товары.ОтборСтрок.Очистить();
    
    // Итерируем по исходной таблице для установки флага видимости
    Для Каждого СтрокаТЗ Из Объект.Товары Цикл
        Если ЗначениеЗаполнено(ТекстПоиска) Тогда
            // Пример логики поиска: проверяем, содержится ли текст поиска в каком-либо строковом поле
            НайденоВСтроке = Ложь;
            Для Каждого Колонка Из СтрокаТЗ.Метаданные().Свойства() Цикл
                Если Колонка.Тип.Строка() И СтрокаТЗ[Колонка.Имя] Тогда
                    Если СтрНайти(НижРег(СтрокаТЗ[Колонка.Имя]), НижРег(ТекстПоиска)) > 0 Тогда
                        НайденоВСтроке = Истина;
                        Прервать;
                    КонецЕсли;
                КонецЕсли;
            КонецЦикла;
            СтрокаТЗ.ВидимаяСтрока = НайденоВСтроке;
        Иначе
            // Если поиск пуст, делаем все строки видимыми
            СтрокаТЗ.ВидимаяСтрока = Истина;
        КонецЕсли;
    КонецЦикла;
    
    // Применяем отбор к элементу формы по нашему вспомогательному реквизиту
    Если ЗначениеЗаполнено(ТекстПоиска) Тогда
        Элементы.Товары.ОтборСтрок.Добавить("ВидимаяСтрока", Истина);
    КонецЕсли;
КонецПроцедуры

Этот метод позволяет вам сохранить исходную ТаблицуЗначений в качестве источника данных, при этом управляя видимостью строк через программный отбор на форме. Недостаток в том, что требуется изменение структуры данных (добавление колонки).

Важное замечание: Отличие ТаблицыЗначений от ДинамическогоСписка

Критически важно понимать, что все вышеописанные сложности в основном касаются элементов формы, привязанных к ТаблицеЗначений. Если же ваш элемент формы представляет собой ДинамическийСписок (например, список справочника или документа), то задача значительно упрощается. У ДинамическогоСписка есть свойство Список.Отбор, которое позволяет программно получить или управлять элементами отбора, в том числе теми, что установил пользователь через строку поиска.

Пример для ДинамическогоСписка:


&НаКлиенте
Процедура ПолучитьОтборДинамическогоСписка()
    // Предположим, что элемент формы называется "СписокДокументов"
    // и он привязан к ДинамическомуСписку
    
    // Получаем коллекцию элементов отбора
    ОтборСписка = Элементы.СписокДокументов.Список.Отбор;
    
    Сообщить("Элементов отбора (включая интерактивный поиск): " + ОтборСписка.Элементы.Количество());
    
    Для Каждого ЭлементОтбора Из ОтборСписка.Элементы Цикл
        Сообщить("Поле: " + ЭлементОтбора.Поле + ", ВидСравнения: " + ЭлементОтбора.ВидСравнения + ", Значение: " + ЭлементОтбора.Значение);
    КонецЦиклов;
КонецПроцедуры

В случае с ДинамическимСписком мы имеем прямой программный доступ к критериям отбора, что значительно упрощает задачу получения "найденных" строк.

Заключение

Как мы видим, в 1С:Предприятии нет единого универсального прямого способа получения критериев интерактивного поиска для ТаблицыЗначений на управляемой форме. Однако мы рассмотрели несколько эффективных методов и обходных путей:

  1. Использование метода ПроверитьСтроку() для итеративной проверки видимости каждой строки. Этот метод является наиболее прямым и рекомендованным для получения списка отображаемых строк.
  2. Применение интерактивного подхода с ВыделенныеСтроки, требующего дополнительного действия от пользователя.
  3. Реализация собственного механизма поиска, дающего полный контроль над процессом и результатами.
  4. Использование вспомогательного булева реквизита для управления видимостью через программный отбор.

Выбор конкретного метода будет зависеть от ваших специфических требований к функциональности, необходимости контроля со стороны разработчика и готовности идти на компромиссы с пользовательским интерфейсом. Всегда анализируйте тип данных, с которым вы работаете (ТаблицаЗначений или ДинамическийСписок), поскольку это существенно влияет на доступные инструменты.

← На главную