Как вывести задолженность в форме списка справочника 1С и исправить ошибку «Поле объекта не обнаружено (Ссылка)»

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

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

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

Причина ошибки «Поле объекта не обнаружено (Ссылка)»

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


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

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

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

Вариант 1. Программный расчет задолженности в событии ПриАктивизацииСтроки

Разберем базовый программный способ получения данных. При смене выбранной строки в таблице списка срабатывает событие ПриАктивизацииСтроки. На клиенте мы получаем значение текущей ссылки, передаем ее на сервер, выполняем запрос к регистру накопления и обновляем заголовок элемента формы.

Посмотрим на рабочий пример реализации:


&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
    
    ТекПациент = Элементы.Список.ТекущаяСтрока;
    Если ТекПациент = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    СуммаЗадолженности = ПолучитьСуммуЗадолженностиПациента(ТекПациент);
    
    Если СуммаЗадолженности = 0 Тогда
        Элементы.ЗадолженностьПациента.ЦветТекстаЗаголовка = WebЦвета.Синий;
        Элементы.ЗадолженностьПациента.Заголовок = "У пациента нет задолженности";
    ИначеЕсли СуммаЗадолженности > 0 Тогда
        Элементы.ЗадолженностьПациента.ЦветТекстаЗаголовка = WebЦвета.Красный;
        Элементы.ЗадолженностьПациента.Заголовок = "Задолженность пациента составляет: " + Строка(СуммаЗадолженности);
    Иначе
        Элементы.ЗадолженностьПациента.ЦветТекстаЗаголовка = WebЦвета.Синий;
        Элементы.ЗадолженностьПациента.Заголовок = "Задолженность перед пациентом составляет: " + Строка(-СуммаЗадолженности);
    КонецЕсли;

КонецПроцедуры

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

КонецФункции

Оптимизация клиент-серверных вызовов через обработчик ожидания

Обратите внимание: событие ПриАктивизацииСтроки вызывает серверную функцию при каждом нажатии клавиш вверх/вниз на клавиатуре. Если пользователь быстро пролистывает список, это создает высокую нагрузку на сервер и может приводить к «подвисанию» интерфейса.

Для предотвращения частых запросов рекомендуется использовать механизм ПодключитьОбработчикОжидания. Вызов сервера будет происходить только после того, как пользователь остановит курсор на строке на заданное время (например, 0.3 секунды):


&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
    ОтключитьОбработчикОжидания("ОбновитьЗадолженностьПослеПаузы");
    ПодключитьОбработчикОжидания("ОбновитьЗадолженностьПослеПаузы", 0.3, Истина);
КонецПроцедуры

&НаКлиенте
Процедура ОбновитьЗадолженностьПослеПаузы()
    // Здесь выполняем получение ТекущаяСтрока и вызов сервера
КонецПроцедуры

Вариант 2. Оптимальное решение без кода: Настройка динамического списка

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

Рассмотрим, как это реализовать по шагам:

  1. В свойствах динамического списка формы установите флаг «Произвольный запрос».
  2. В тексте запроса свяжите справочник с виртуальной таблицей остатков регистра накопления с помощью левого соединения:
    
    ВЫБРАТЬ
        Пациенты.Ссылка КАК Ссылка,
        Пациенты.Наименование КАК Наименование,
        ЕСТЬНУЛЛ(ОплатыОстатки.СуммаОстаток, 0) КАК Задолженность
    ИЗ
        Справочник.Пациенты КАК Пациенты
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ОплатыПриемов.Остатки КАК ОплатыОстатки
        ПО ОплатыОстатки.Прием.Пациент = Пациенты.Ссылка
    
  3. Выведите колонку Задолженность в таблицу формы. Платформа 1С будет автоматически и порционно подгружать остатки только для видимых на экране строк.
  4. Для изменения цвета текста (например, подсветить должников красным цветом) используйте механизм Условное оформление динамического списка без написания кода.
← На главную