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

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

При разработке в среде управляемых форм 1С программисты часто сталкиваются с задачей: пользователь настроил отбор или воспользовался строкой поиска в таблице формы, и теперь эти отфильтрованные строки необходимо передать на сервер для дальнейшей обработки (например, проведения документов, заполнения регистров или массового пересчета). Попытка напрямую передать коллекцию отфильтрованных строк вызывает затруднения. Разберем причины такого поведения платформы и рассмотрим правильные варианты решения этой задачи.

Проанализируем сначала особенности клиент-серверной архитектуры управляемых форм:

  1. Метод ПроверитьСтроку() принадлежит объекту интерфейса ТаблицаФормы и доступен исключительно на клиенте. На сервере платформе неизвестно текущее состояние интерактивного поиска пользователя (например, фильтрация по Ctrl+F или через панель поиска).
  2. Объект ДанныеФормыЭлементКоллекции (отдельная строка таблицы формы) не является сериализуемым типом и не может передаваться в качестве параметра из клиентской процедуры в серверную.
  3. Сама коллекция ДанныеФормыКоллекция хранится как реквизит формы и уже синхронизирована между клиентом и сервером. Поэтому передавать сами строки целиком нет никакой необходимости — достаточно указать серверу, какие именно строки были отобраны.

Способ 1. Сбор массива идентификаторов на клиенте и поиск на сервере (Рекомендуемый)

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

Посмотрим на пример клиентской и серверной части кода:


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

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

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

Способ 2. Получение интерактивно выделенных строк

Если пользователю требуется обработать не все отфильтрованные строки, а только те, которые он выделил мышью или комбинацией клавиш Shift/Ctrl в таблице, обходить коллекцию циклом с вызовом ПроверитьСтроку() не нужно. Свойство таблицы ВыделенныеСтроки уже содержит массив идентификаторов.

Разберем реализацию этого сценария:


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

&НаСервере
Процедура ОбработатьВыделенныеСтрокиНаСервере(МассивВыделенных)
    
    Для Каждого ИД Из МассивВыделенных Цикл
        СтрокаТаблицы = Договоры.НайтиПоИдентификатору(ИД);
        Если СтрокаТаблицы <> Неопределено Тогда
            // Прикладная обработка строки
        КонецЕсли;
    КонецЦикла;
    
КонецПроцедуры

Способ 3. Программная фильтрация на сервере через таблицу значений

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

Рассмотрим, как преобразовать реквизит формы в объект ТаблицаЗначений для быстрого поиска:


&НаСервере
Процедура НайтиИОбработатьСтрокиНаСервере(СтруктураОтбора)
    
    // Преобразуем данные формы в прикладной объект ТаблицаЗначений
    ТаблицаДанных = РеквизитФормыВЗначение("Договоры");
    
    // Выполняем поиск строк по структуре критериев
    НайденныеСтроки = ТаблицаДанных.НайтиСтроки(СтруктураОтбора);
    
    Для Каждого СтрТЗ Из НайденныеСтроки Цикл
        // Обработка строк во временной таблице значений
        СтрТЗ.Сумма = СтрТЗ.Сумма * 1.1;
    КонецЦикла;
    
    // Загружаем обновленные значения обратно в реквизит формы
    ЗначениеВРеквизитФормы(ТаблицаДанных, "Договоры");
    
КонецПроцедуры

Способ 4. Проверка фиксированного отбора таблицы на сервере

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

Посмотрим на пример функции проверки:


&НаСервере
Функция СтрокаСоответствуетОтбору(ТаблицаФормыЭлемент, СтрокаКоллекции)
    
    Если ТаблицаФормыЭлемент.ОтборСтрок = Неопределено Тогда
        Возврат Истина;
    КонецЕсли;
    
    Для Каждого КлючИЗначение Из ТаблицаФормыЭлемент.ОтборСтрок Цикл
        Если СтрокаКоллекции[КлючИЗначение.Ключ] <> КлючИЗначение.Значение Тогда
            Возврат Ложь;
        КонецЕсли;
    КонецЦикла;
    
    Возврат Истина;
    
КонецФункции

В большинстве практических задач рекомендуется применять Способ 1: фильтрация на клиенте методом ПроверитьСтроку(), сбор массива идентификаторов и их последующий поиск на сервере через НайтиПоИдентификатору(). Это сохраняет производительность и гарантирует полное соответствие видимого пользователем результата серверной обработке.

← На главную