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

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

В процессе разработки часто возникает задача интеграции с внешними системами через COM-соединение или HTTP-запросы. Полученные данные обычно помещаются в ТаблицуЗначений (ТЗ), и перед разработчиком встает вопрос: как удобно и правильно предоставить пользователю возможность выбора строк из этой таблицы для дальнейшей обработки в основной форме? Рассмотрим подробные механизмы реализации этой задачи в среде 1С:Предприятие 8.3 на управляемых формах.

Метод 1: Использование специализированной формы подбора

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

Шаг 1. Подготовка данных и открытие формы

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


&НаКлиенте
Процедура КомандаПодбор(Команда)
    
    // Помещаем таблицу во временное хранилище
    АдресДанных = ПоместитьДанныеВоВременноеХранилищеНаСервере();
    
    ПараметрыПодбора = Новый Структура;
    ПараметрыПодбора.Вставить("АдресДанных", АдресДанных);
    
    ОткрытьФорму("Обработка.МояОбработка.Форма.ФормаПодбора", 
                 ПараметрыПодбора, 
                 ЭтаФорма, 
                 Истина, , , 
                 Новый ОписаниеОповещения("ПослеЗакрытияПодбора", ЭтаФорма));
                 
КонецПроцедуры

&НаСервере
Функция ПоместитьДанныеВоВременноеХранилищеНаСервере()
    // Объект.ТЗВнешниеДанные - реквизит формы типа ТаблицаЗначений
    Возврат ПоместитьВоВременноеХранилище(Объект.ТЗВнешниеДанные.Выгрузить(), ЭтаФорма.УникальныйИдентификатор);
КонецФункции

Шаг 2. Инициализация формы подбора

В форме подбора создадим реквизит СписокДляВыбора с типом ТаблицаЗначений. В обработчике ПриСозданииНаСервере загрузим данные.


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    АдресДанных = Параметры.АдресДанных;
    Если ЗначениеЗаполнено(АдресДанных) Тогда
        ТЗ = ПолучитьИзВременногоХранилища(АдресДанных);
        ЗначениеВРеквизитФормы(ТЗ, "СписокДляВыбора");
    КонецЕсли;
    
КонецПроцедуры

Шаг 3. Обработка выбора пользователя

Разберем, как вернуть выбранное значение. Если нам нужно выбрать одну строку, используем событие Выбор элемента формы «Таблица».


&НаКлиенте
Процедура СписокДляВыбораВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Ложь;
    ТекущиеДанные = Элемент.ТекущиеДанные;
    
    // Формируем структуру с данными для возврата
    Результат = Новый Структура;
    Результат.Вставить("GUID", ТекущиеДанные.GUID);
    Результат.Вставить("Наименование", ТекущиеДанные.Наименование);
    
    ОповеститьОВыборе(Результат);
    
КонецПроцедуры

Метод 2: Асинхронный выбор через ПоказатьОтметкуЭлементов

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

Выясним, как это работает на практике:

  1. Преобразуем нашу ТЗ в СписокЗначений.
  2. Вызываем метод оповещения.
  3. В процедуре обратного вызова обрабатываем массив выбранных элементов.

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

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

Технические нюансы работы с COM-соединением

Рассмотрим критически важный момент: объекты, полученные через COM-соединение, являются прокси-объектами. Если вы закроете соединение, попытка обратиться к ТекущиеДанные.Наименование, где данные ссылаются на COM-объект, вызовет ошибку «Объект не найден».

Рекомендация: При получении данных из COM-базы всегда выполняйте полное копирование данных в «родную» для текущей базы ТаблицуЗначений. Используйте примитивные типы (строка, число) или создавайте ссылки по GUID сразу при загрузке.

Проанализируем пример функции конвертации GUID в ссылку 1С:


&НаСервереБезКонтекста
Функция ПолучитьСсылкуПоУид(Знач СтрУид)
    
    Попытка
        Уид = Новый УникальныйИдентификатор(СтрУид);
        Ссылка = Справочники.Номенклатура.ПолучитьСсылку(Уид);
        
        // Проверяем существование объекта в нашей базе
        Если Ссылка.ПолучитьОбъект() = Неопределено Тогда
            Возврат Справочники.Номенклатура.ПустаяСсылка();
        КонецЕсли;
        
        Возврат Ссылка;
    Исключение
        Возврат Справочники.Номенклатура.ПустаяСсылка();
    КонецПопытки;
    
КонецФункции

Оптимизация поиска в больших таблицах

Если внешняя таблица содержит тысячи строк, стандартный метод НайтиСтроки() может работать медленно. Посмотрим на альтернативный вариант с использованием объекта Соответствие.

При загрузке данных из COM создайте соответствие, где ключом будет уникальный идентификатор, а значением — структура данных или индекс строки. Поиск в Соответствии выполняется мгновенно вне зависимости от объема данных, так как использует механизм хеш-таблиц.

Использование механизма ОповеститьОВыборе

Разберем, почему важно использовать ОповеститьОВыборе вместо прямого обращения к ВладелецФормы. Обращение напрямую к реквизитам другой формы (например, ВладелецФормы.Объект.Товары.Добавить()) создает жесткую зависимость между формами. Это нарушает принципы инкапсуляции.

Правильный путь — форма подбора «выбрасывает» событие выбора, а основная форма ловит его в обработчике ОбработкаВыбора. Таким образом, одну и ту же форму подбора можно использовать в разных документах и справочниках без переписывания кода.


&НаКлиенте
Процедура ОбработкаВыбора(ВыбранноеЗначение, ИсточникВыбора)
    
    // Проверяем тип пришедших данных
    Если ТипЗнч(ВыбранноеЗначение) = Тип("Структура") Тогда
        // Обрабатываем GUID и добавляем в ТЧ
        НоваяСтрока = Объект.Товары.Добавить();
        НоваяСтрока.Номенклатура = ПолучитьСсылкуПоУид(ВыбранноеЗначение.GUID);
    КонецЕсли;
    
КонецПроцедуры

Вызов экспортных функций модуля объекта из формы

Иногда логика обработки данных скрыта в модуле объекта (например, в модуле внешней обработки). Чтобы вызвать ее из формы подбора, воспользуемся методом РеквизитФормыВЗначение.


&НаСервере
Процедура ВызватьМетодОбработки()
    
    // "Объект" - это реквизит формы, ссылающийся на ВнешнююОбработку
    ОбъектОбработки = РеквизитФормыВЗначение("Объект");
    ТаблицаРезультат = ОбъектОбработки.ПолучитьВнешниеДанныеЧерезCOM();
    
    ЗначениеВРеквизитФормы(ТаблицаРезультат, "СписокДляВыбора");
    
КонецПроцедуры

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

← На главную