Почему метод ТаблицаЗначений.ВыбратьСтроку() не работает в управляемом приложении и как это исправить?

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

Многие начинающие разработчики 1С при переходе с обычных форм на управляемые сталкиваются с ситуацией, когда привычный метод ВыбратьСтроку() для объекта ТаблицаЗначений просто перестает вызывать диалоговое окно. Код «пролетает» мимо, выполнение не останавливается, и пользователь ничего не видит. Разберем подробно, почему так происходит, и какие современные механизмы 1С 8.3 нужно использовать вместо этого устаревшего метода.

Причина проблемы: Ограничения платформы

Первое, что нам необходимо проанализировать — это синтакс-помощник. Если мы заглянем в описание метода ВыбратьСтроку(), то увидим важное ограничение в графе «Доступность»: он предназначен исключительно для Толстого клиента.

В современных конфигурациях на платформе 1С 8.3 (таких как ERP, УТ 11, БП 3.0) используется Управляемое приложение. В этом режиме работа разделена на Клиент (Тонкий клиент или Веб-клиент) и Сервер. Объект ТаблицаЗначений — это сугубо серверный объект. Его не существует на стороне клиента. Следовательно, платформа физически не может вызвать визуальное окно выбора из объекта, которого нет в памяти клиентского приложения.

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

Рассмотрим несколько эффективных способов реализации интерактивного выбора в управляемых формах.

Решение №1: Использование СпискаЗначений (для простых данных)

Если вам нужно, чтобы пользователь просто выбрал один элемент из списка (например, только наименование товара или строку «Товар — Цена»), самым простым и быстрым способом будет использование объекта СписокЗначений и его асинхронного метода ПоказатьВыборЭлемента().

Разберем алгоритм по шагам:

  1. На сервере подготовим данные и заполним СписокЗначений.
  2. Передадим этот список на клиент.
  3. На клиенте вызовем окно выбора.

Пример кода реализации:


&НаКлиенте
Процедура ПодобратьАналог(Команда)
    // Получаем данные с сервера
    СписокАналогов = ПолучитьСписокАналоговНаСервере(Объект.Товар);
    
    // Создаем описание оповещения (куда вернется результат выбора)
    Оповещение = Новый ОписаниеОповещения("ПослеВыбораАналога", ЭтотОбъект);
    
    // Показываем окно выбора (немодально)
    СписокАналогов.ПоказатьВыборЭлемента(Оповещение, "Выберите аналог для " + Объект.Товар);
КонецПроцедуры

&НаСервере
Функция ПолучитьСписокАналоговНаСервере(Товар)
    Список = Новый СписокЗначений;
    
    // Здесь ваш запрос к базе данных
    Запрос = Новый Запрос("ВЫБРАТЬ Номенклатура, Цена ИЗ РегистрСведений.Цены...");
    // ... заполнение запроса параметрами ...
    
    Выборка = Запрос.Выполнить().Выбрать();
    Пока Выборка.Следующий() Цикл
        Представление = Строка(Выборка.Номенклатура) + " (Цена: " + Выборка.Цена + ")";
        Список.Добавить(Выборка.Номенклатура, Представление);
    КонецЦикла;
    
    Возврат Список;
КонецФункции

&НаКлиенте
Процедура ПослеВыбораАналога(ВыбранныйЭлемент, ДополнительныеПараметры) Экспорт
    Если ВыбранныйЭлемент <> Неопределено Тогда
        // Здесь мы получаем само значение (ссылку на номенклатуру)
        Объект.Аналог = ВыбранныйЭлемент.Значение;
    КонецЕсли;
КонецПроцедуры

Решение №2: Создание вспомогательной формы выбора (для таблиц с колонками)

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

Проанализируем ситуацию: нам нужно передать таблицу с сервера на клиент и отобразить ее. Напрямую передать ТаблицаЗначений нельзя. Рассмотрим правильную архитектуру решения:

Шаг 1: Создание формы выбора.

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

Шаг 2: Вызов формы из основного кода.

Для передачи данных лучше всего использовать Временное хранилище. Посмотрим, как выглядит код вызова:


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

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

Шаг 3: Прием данных в форме выбора.

В модуле формы выбора (которую мы открываем) пропишем логику получения данных:


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

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

Решение №3: Метод ПоказатьВыборИзМеню

Если данных немного (до 10-15 строк), и вы хотите сделать интерфейс более современным («как в Такси»), воспользуйтесь методом ПоказатьВыборИзМеню(). Это создаст выпадающий список прямо возле кнопки или поля, где инициирован выбор. Это выглядит эстетичнее, чем отдельное всплывающее окно.

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


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

Важные замечания по методу Выгрузить()

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

Метод Выгрузить() доступен у объекта РезультатЗапроса или у ТабличнойЧасти документа/справочника. Если же вы пытаетесь вызвать его у переменной, которая уже является ТаблицейЗначений или ДаннымиФормыКоллекция (реквизит таблицы на управляемой форме), возникнет ошибка.

Чтобы скопировать одну ТаблицуЗначений в другую на сервере, используйте метод Скопировать():

НоваяТЗ = СтараяТЗ.Скопировать();

Резюме

Для исправления неработающего кода ВыбратьСтроку() необходимо:

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

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

← На главную