Как передать текущую активную строку из формы списка в параметры запроса

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

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

Разбор основной проблемы и типичных ошибок

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

Выясним причину ошибки: в управляемом приложении объект ТекущаяСтрока для динамического списка возвращает ссылку на объект (или идентификатор строки), а не сам объект с его реквизитами. Кроме того, на сервере состав объекта Элементы ограничен. Попытка прочитать Наименование напрямую из элемента формы приводит к ошибке "Поле объекта не обнаружено".

Решение №1: Использование ТекущиеДанные и передача ссылки

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

На стороне клиента мы используем свойство ТекущиеДанные. Оно содержит структуру всех колонок, отображаемых в данный момент в строке. Нам оттуда нужна только Ссылка. Проанализируем следующий код:


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

Теперь рассмотрим серверную часть. Здесь мы принимаем ссылку и устанавливаем её в качестве параметра запроса. Важно понимать, что в запросе мы сравниваем ссылки, а не строки с наименованиями.


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

Решение №2: Использование ТекущаяСтрока (прямая ссылка)

Если нам не нужны никакие дополнительные данные из колонок списка, а требуется только ссылка на объект, можно использовать свойство Элементы.Список.ТекущаяСтрока. В динамическом списке это свойство сразу возвращает ссылку на элемент справочника или документа.

Посмотрим на пример упрощенного вызова:


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

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

Анализ ошибок типизации в запросах

Иногда при выполнении запроса возникает ошибка: "Неверные параметры в операции сравнения. Нельзя сравнивать поля несовместимых типов". Это происходит в двух случаях:

  1. Несоответствие типов: В параметр запроса &Автобус передается строка (например, "Mercedes-Benz"), а в базе данных поле Автобус имеет тип СправочникСсылка.Автобусы. 1С не умеет автоматически сравнивать строку и ссылку в запросе.
  2. Пустые значения: Если переменная, передаваемая в параметр, имеет значение Неопределено или Null, и это не предусмотрено логикой запроса.

Всегда проверяйте тип передаваемого значения в отладчике. Значение должно иметь тип СправочникСсылка, а не Строка или УникальныйИдентификатор.

Расширение задачи: Множественный выбор

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

Вместо этого воспользуемся свойством ВыделенныеСтроки. Оно возвращает массив ссылок. Рассмотрим, как изменить код для работы с массивом:


&НаКлиенте
Процедура ПечатьГруппы(Команда)
    
    МассивСсылок = Элементы.Список.ВыделенныеСтроки;
    
    Если МассивСсылок.Количество() = 0 Тогда
        Возврат;
    КонецЕсли;
    
    ТабДок = Новый ТабличныйДокумент;
    ПечатьМассиваНаСервере(ТабДок, МассивСсылок);
    ТабДок.Показать();
    
КонецПроцедуры

&НаСервере
Процедура ПечатьМассиваНаСервере(ТабДок, МассивАвтобусов)
    
    Запрос = Новый Запрос;
    // Используем оператор В для работы с массивом
    Запрос.Текст = 
        "ВЫБРАТЬ * ИЗ РегистрСведений.СведенияОбАвтобусе 
        |ГДЕ Автобус В (&МассивАвтобусов)";
    
    Запрос.УстановитьПараметр("МассивАвтобусов", МассивАвтобусов);
    
    // Далее стандартный вывод в таблицу...
КонецПроцедуры

Подведем итоги

Для корректной передачи текущей строки из формы списка в запрос необходимо придерживаться следующих правил:

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

Соблюдение этих принципов позволит вам создавать стабильные и быстрые механизмы печати и обработки данных в управляемом приложении 1С.

← На главную