Как правильно работать с запросами, контекстом формы и типами данных в 1С 8.3?

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

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

Ошибка 1: Отсутствие итерации по результату запроса

Рассмотрим типичную ситуацию: вы написали запрос, установили параметры и выполнили его. Однако при попытке получить данные в отладчике вы видите сообщение «Ошибка чтения значения». Проанализируем пример кода:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |    СостояниеТранспортногоСредства.Наименование КАК Наименование,
    |    СостояниеТранспортногоСредства.СостояниеТС КАК СостояниеТС
    |ИЗ
    |    РегистрСведений.СостояниеТранспортногоСредства КАК СостояниеТранспортногоСредства
    |ГДЕ
    |    СостояниеТранспортногоСредства.Наименование = &Наименование";

Запрос.УстановитьПараметр("Наименование", Наименование);
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДСостояниеТС = РезультатЗапроса.Выбрать();

Проблема заключается в том, что объект ВыборкаИзРезультатаЗапроса — это лишь курсор, который указывает на начало данных, но еще не «стоит» ни на одной конкретной записи. Чтобы получить доступ к полям Наименование или СостояниеТС, необходимо обязательно вызвать метод Следующий().

Разберем правильный алгоритм работы с выборкой:

  1. Метод Выполнить() исполняет запрос на стороне СУБД.
  2. Метод Выбрать() подготавливает данные для обхода.
  3. Метод Следующий() перемещает указатель на следующую строку. Если строк больше нет, функция возвращает Ложь.

Совет: Чтобы не забывать про обход результата, рекомендуем использовать в конфигураторе «Конструктор запроса с обработкой результата». Он автоматически создаст правильный шаблон цикла Пока Выборка.Следующий() Цикл ... КонецЦикла;.

Ошибка 2: Обращение к элементам формы на сервере

Часто возникает вопрос: почему код Запрос.УстановитьПараметр("Контрагент", Элементы.Контрагент) выдает ошибку, если он написан в процедуре с директивой &НаСервере? Выясним причину.

В системе «1С:Предприятие 8» нужно четко разделять данные и визуальные элементы:

Следовательно, на сервере мы должны обращаться к реквизиту данных. Правильный вариант:


// Вместо Элементы.Контрагент используем данные реквизита
Запрос.УстановитьПараметр("Контрагент", Объект.Контрагент);

Ошибка 3: Управление видимостью и жизненный цикл формы

Проанализируем попытку изменить свойство видимости в модуле формы:


&НаСервере
Процедура ПриОткрытииНаСервере()
    Объект.ДобавитьГСМ.Видимость = Ложь; // ОШИБКА!
КонецПроцедуры

Здесь допущены сразу две важные ошибки. Во-первых, свойство Видимость относится к элементу формы (тому, что видит пользователь), а не к данным объекта. Во-вторых, процедура ПриОткрытии выполняется на клиенте, и вызывать из нее серверную процедуру для настройки интерфейса — неэффективно.

Рассмотрим, как сделать правильно:

  1. Для настройки интерфейса при создании формы используйте стандартный обработчик ПриСозданииНаСервере. Это экономит время, так как форма еще не передана клиенту.
  2. Обращайтесь к коллекции Элементы.

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    // Управляем визуальным элементом формы
    Элементы.ГруппаДобавитьГСМ.Видимость = Ложь;
    
    // Работаем с данными
    Объект.ВидТС = Объект.Родитель;
КонецПроцедуры

Ошибка 4: Ссылка против Строки в параметрах запроса

Рассмотрим ситуацию, когда при изменении автомобиля нужно подтянуть его госномер. Если вы передаете в запрос наименование (строку), а в базе ищете соответствие ссылке, запрос ничего не найдет.

Посмотрим на пример ошибочного кода:


|ГДЕ
|    ТранспортныеСредства.Наименование = &Наименование";
...
Запрос.УстановитьПараметр("Наименование", Объект.Автомобиль); // В параметре ссылка, а в условии строка!

В 1С крайне не рекомендуется работать с данными через Наименование, так как названия могут дублироваться или меняться. Всегда используйте Ссылка. Проанализируем исправленный вариант:


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

Оптимизация работы через &НаСервереБезКонтекста

Обратите внимание на использование директивы &НаСервереБезКонтекста. Это мощный инструмент оптимизации. Рассмотрим, почему это важно:

Внутри таких методов нельзя писать Объект.Наименование, так как самого Объекта там нет. Все необходимые данные должны передаваться через параметры функции.

Итоги

Для успешной разработки в управляемом приложении 1С 8.3 придерживайтесь следующих правил:

  1. Всегда используйте Выборка.Следующий() перед чтением данных из результата запроса.
  2. Помните, что Элементы — это интерфейс, а Объект — это данные. Элементы недоступны на сервере.
  3. Используйте ПриСозданииНаСервере для начальной настройки формы.
  4. В запросах всегда отдавайте предпочтение поиску по полю Ссылка, а не по строковым реквизитам.
  5. Для простых вычислений и получения данных из справочников используйте &НаСервереБезКонтекста.
← На главную