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

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

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

Причины ошибки: почему выборку нельзя поместить в реквизит формы

Проанализируем архитектурные ограничения платформы 1С:Предприятие 8.3:

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

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

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

Разберем по шагам правильный алгоритм рефакторинга:

  1. Отказ от выборки в пользу запроса: Метод Выбрать() считывает из базы абсолютно все поля объектов. Используем объект Запрос, чтобы выбрать только необходимые поля (например, Ссылка, Код, Наименование) и при возможности ограничить выборку условием ГДЕ.
  2. Перенос строкового разбора на сервер: Подготовку ключевых слов и сравнение строк не следует делать на клиенте перед отправкой. Всю процедуру анализа запускаем на сервере.
  3. Хранение результата в таблице формы: Если пользователю нужно показать найденные похожие элементы, на форме создается реквизит с типом ТаблицаЗначений, который на сервере заполняется с помощью метода ЗначениеВРеквизитФормы() или прямым заполнением строк коллекции ДанныеФормыКоллекция.
  4. Инициализация данных до открытия: Вместо вызова серверных процедур из клиентского события ПриОткрытии переносим первичный расчет в обработчик ПриСозданииНаСервере, что исключает лишние клиент-серверные вызовы.

Пример реализации поиска дубликатов и похожих записей

Посмотрим на пример правильной организации серверной процедуры поиска дубликатов без использования выборки на клиенте:


&НаСервере
Процедура ПроверитьДубликатыНаСервере(ИмяСправочника, ПроверяемоеНаименование, ТекущаяСсылка)
    
    // Очищаем таблицу результатов на форме
    ТаблицаПохожихЗначений.Очистить();
    
    // Используем запрос для получения только нужных полей
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   Спр.Ссылка КАК Ссылка,
        |   Спр.Код КАК Код,
        |   Спр.Наименование КАК Наименование
        |ИЗ
        |   Справочник." + ИмяСправочника + " КАК Спр
        |ГДЕ
        |   Спр.Ссылка <> &ТекущаяСсылка
        |   И НЕ Спр.ПометкаУдаления";
    
    Запрос.УстановитьПараметр("ТекущаяСсылка", ТекущаяСсылка);
    
    РезультатЗапроса = Запрос.Выполнить();
    Выборка = РезультатЗапроса.Выбрать();
    
    ЭталонСтрока = ВРег(СокрЛП(ПроверяемоеНаименование));
    
    Пока Выборка.Следующий() Цикл
        СравниваемаяСтрока = ВРег(СокрЛП(Выборка.Наименование));
        
        // Проверка на точный дубликат
        Если СравниваемаяСтрока = ЭталонСтрока Тогда
            ВызватьИсключение "В справочнике уже имеется элемент с наименованием """ + ПроверяемоеНаименование + """ (Код: " + Выборка.Код + ")";
        КонецЕсли;
        
        // Вычисление процента совпадения через серверную функцию
        Процент = ВспомФункцииУФСервер.НечеткоеСравнениеСтрок(СравниваемаяСтрока, ЭталонСтрока);
        
        Если Процент > 60 Тогда
            НоваяСтрока = ТаблицаПохожихЗначений.Добавить();
            НоваяСтрока.Ссылка = Выборка.Ссылка;
            НоваяСтрока.Код = Выборка.Код;
            НоваяСтрока.Наименование = Выборка.Наименование;
            НоваяСтрока.ПроцентСовпадения = Процент;
        КонецЕсли;
    КонецЦикла;
    
    // Сортировка таблицы на форме
    ТаблицаПохожихЗначений.Сортировать("ПроцентСовпадения Убыв");
    
КонецПроцедуры

Альтернативные способы поиска дубликатов в 1С

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

  1. Встроенный полнотекстовый поиск: Метод ПолнотекстовыйПоиск.СоздатьСписок() с использованием оператора нечеткости ~ выполняет поиск похожих строк средствами СУБД по предварительно построенному индексу, что работает значительно быстрее цикла по всей таблице.
  2. Подсистема БСП «Поиск и удаление дублей»: В типовых конфигурациях рекомендуется использовать готовые функции Библиотеки стандартных подсистем. Они содержат оптимизированные алгоритмы сравнения с учетом синонимов, перестановок слов и опечаток.
← На главную