При разработке интерфейсов на управляемых формах 1С 8.3 часто возникает задача: выполнить какое-либо действие (например, сформировать печатную форму или отчет) именно для того объекта, на котором в данный момент установлен курсор в списке. Несмотря на кажущуюся простоту, начинающие разработчики часто сталкиваются с ошибками типизации и нарушениями контекста исполнения кода. Рассмотрим подробно, как правильно передать данные текущей строки в запрос на сервере.
Проанализируем ситуацию: пользователь находится в форме списка справочника Автобусы. Ему нужно нажать кнопку и получить печатную форму с данными из регистра сведений, связанного с этим конкретным автобусом. Основная ошибка, которую мы видим в исходном коде, заключается в попытке обратиться к свойствам элементов формы (таких как Наименование) непосредственно на сервере через конструкцию Элементы.Список.ТекущаяСтрока.Наименование.
Выясним причину ошибки: в управляемом приложении объект ТекущаяСтрока для динамического списка возвращает ссылку на объект (или идентификатор строки), а не сам объект с его реквизитами. Кроме того, на сервере состав объекта Элементы ограничен. Попытка прочитать Наименование напрямую из элемента формы приводит к ошибке "Поле объекта не обнаружено".
Рассмотрим наиболее надежный способ получения данных. Для этого нам потребуется разделить логику на две части: клиентскую, которая "знает", где стоит курсор, и серверную, которая выполняет запрос к базе данных. Разберем этот процесс по шагам.
На стороне клиента мы используем свойство ТекущиеДанные. Оно содержит структуру всех колонок, отображаемых в данный момент в строке. Нам оттуда нужна только Ссылка. Проанализируем следующий код:
&НаКлиенте
Процедура КомандаПечатьДанных(Команда)
// Получаем данные текущей строки списка
ДанныеСтроки = Элементы.Список.ТекущиеДанные;
// Обязательная проверка: если список пуст, ДанныеСтроки будут равны Неопределено
Если ДанныеСтроки = Неопределено Тогда
Сообщить("Пожалуйста, выберите строку в списке!");
Возврат;
КонецЕсли;
// Подготавливаем табличный документ
ТабДок = Новый ТабличныйДокумент;
// Вызываем серверную процедуру, передавая Ссылку из текущих данных
СформироватьПечатнуюФормуНаСервере(ТабДок, ДанныеСтроки.Ссылка);
// Выводим результат пользователю
ТабДок.Показать("Информация об автобусе");
КонецПроцедуры
Теперь рассмотрим серверную часть. Здесь мы принимаем ссылку и устанавливаем её в качестве параметра запроса. Важно понимать, что в запросе мы сравниваем ссылки, а не строки с наименованиями.
&НаСервере
Процедура СформироватьПечатнуюФормуНаСервере(ТабДок, ВыбранныйАвтобус)
Макет = Справочники.Автобусы.ПолучитьМакет("Печать");
ОбластьЭлемент = Макет.ПолучитьОбласть("Элемент");
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| СведенияОбАвтобусе.Период КАК Период,
| СведенияОбАвтобусе.КоличествоПассажиров КАК КоличествоПассажиров
|ИЗ
| РегистрСведений.СведенияОбАвтобусе КАК СведенияОбАвтобусе
|ГДЕ
| СведенияОбАвтобусе.Автобус = &Автобус";
// Передаем ссылку в параметр
Запрос.УстановитьПараметр("Автобус", ВыбранныйАвтобус);
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
ОбластьЭлемент.Параметры.Заполнить(Выборка);
ТабДок.Вывести(ОбластьЭлемент);
КонецЦикла;
КонецПроцедуры
Если нам не нужны никакие дополнительные данные из колонок списка, а требуется только ссылка на объект, можно использовать свойство Элементы.Список.ТекущаяСтрока. В динамическом списке это свойство сразу возвращает ссылку на элемент справочника или документа.
Посмотрим на пример упрощенного вызова:
&НаКлиенте
Процедура ПечатьКоротко(Команда)
СсылкаНаОбъект = Элементы.Список.ТекущаяСтрока;
Если СсылкаНаОбъект = Неопределено Тогда
Возврат;
КонецЕсли;
// Передаем ссылку напрямую на сервер
ПечатьНаСервере(СсылкаНаОбъект);
КонецПроцедуры
Важный нюанс: если ваш справочник имеет иерархию (папки), то ТекущаяСтрока может вернуть ссылку на группу. Если ваш запрос рассчитан только на элементы, программа может выдать пустой результат. В таких случаях добавим проверку ЭтоГруппа внутри серверного кода или проверим тип данных.
Иногда при выполнении запроса возникает ошибка: "Неверные параметры в операции сравнения. Нельзя сравнивать поля несовместимых типов". Это происходит в двух случаях:
&Автобус передается строка (например, "Mercedes-Benz"), а в базе данных поле Автобус имеет тип СправочникСсылка.Автобусы. 1С не умеет автоматически сравнивать строку и ссылку в запросе.Неопределено или Null, и это не предусмотрено логикой запроса.Всегда проверяйте тип передаваемого значения в отладчике. Значение должно иметь тип СправочникСсылка, а не Строка или УникальныйИдентификатор.
Проанализируем ситуацию, когда пользователю нужно распечатать данные не по одному, а по нескольким выделенным автобусам. В этом случае свойство ТекущаяСтрока нам не поможет, так как оно возвращает только одну строку, на которой стоит фокус.
Вместо этого воспользуемся свойством ВыделенныеСтроки. Оно возвращает массив ссылок. Рассмотрим, как изменить код для работы с массивом:
&НаКлиенте
Процедура ПечатьГруппы(Команда)
МассивСсылок = Элементы.Список.ВыделенныеСтроки;
Если МассивСсылок.Количество() = 0 Тогда
Возврат;
КонецЕсли;
ТабДок = Новый ТабличныйДокумент;
ПечатьМассиваНаСервере(ТабДок, МассивСсылок);
ТабДок.Показать();
КонецПроцедуры
&НаСервере
Процедура ПечатьМассиваНаСервере(ТабДок, МассивАвтобусов)
Запрос = Новый Запрос;
// Используем оператор В для работы с массивом
Запрос.Текст =
"ВЫБРАТЬ * ИЗ РегистрСведений.СведенияОбАвтобусе
|ГДЕ Автобус В (&МассивАвтобусов)";
Запрос.УстановитьПараметр("МассивАвтобусов", МассивАвтобусов);
// Далее стандартный вывод в таблицу...
КонецПроцедуры
Для корректной передачи текущей строки из формы списка в запрос необходимо придерживаться следующих правил:
Элементы.Список.ТекущиеДанные.Ссылка или ТекущаяСтрока), а выполнение запроса — на сервере.Наименование или Код в качестве основного параметра связи, если можно передать Ссылку. Это обеспечит уникальность данных и быстродействие запроса.ТекущиеДанные, для нескольких — ВыделенныеСтроки.Соблюдение этих принципов позволит вам создавать стабильные и быстрые механизмы печати и обработки данных в управляемом приложении 1С.