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