Как исправить ошибку «Поле объекта не обнаружено (ТекущийИсполнитель)» и программно изменить данные в списке 1С?

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

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

Почему возникает ошибка «Поле объекта не обнаружено»?

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

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

Для решения проблемы с доступностью поля в динамическом списке, нам необходимо зайти в конфигуратор, открыть настройки динамического списка и в списке полей установить галочку «Использовать всегда» для поля ТекущийИсполнитель. Это гарантирует, что данные будут переданы с сервера на клиент, даже если соответствующая колонка скрыта пользователем.

Разбираем правильный доступ к данным текущей строки

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


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

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

Проблема изменения данных: Динамический список vs Объект

Выясним важный архитектурный нюанс: свойство ТекущиеДанные в динамическом списке предназначено только для чтения. Если мы просто напишем ТекДанные.ТекущийИсполнитель = НовыйИсполнитель;, это не приведет к изменению данных в базе данных, так как динамический список — это всего лишь отображение результата запроса к БД.

Чтобы изменить исполнителя, мы должны выполнить следующие шаги:

  1. Получить ссылку на объект из текущих данных.
  2. Передать эту ссылку на сервер.
  3. На сервере получить объект по ссылке, изменить реквизит и записать его.
  4. Обновить динамический список на клиенте, чтобы пользователь увидел изменения.

Реализация назначения исполнителя с использованием асинхронных вызовов

В современных версиях платформы (8.3.15+) рекомендуется отказываться от модальных окон (функция Вопрос()) в пользу асинхронных методов. Рассмотрим, как правильно реализовать процедуру назначения себя исполнителем с использованием метода ПоказатьВопрос().

Проанализируем комплексное решение задачи:


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

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

&НаСервереБезКонтекста
Процедура УстановитьИсполнителяНаСервере(СсылкаНаОбъект)
    
    // Получаем объект для редактирования
    ОбъектДок = СсылкаНаОбъект.ПолучитьОбъект();
    ОбъектДок.ТекущийИсполнитель = ПараметрыСеанса.ТекущийПользователь;
    
    Попытка
        ОбъектДок.Записать(РежимЗаписиДокумента.Запись);
    Исключение
        ВызватьИсключение "Не удалось назначить исполнителя: " + ОписаниеОшибки();
    КонецПопытки;
    
КонецПроцедуры

&НаСервереБезКонтекста
Функция ПолучитьТекущегоПользователяНаСервере()
    Возврат ПараметрыСеанса.ТекущийПользователь;
КонецФункции

Разберем ключевые моменты этого кода

Во-первых, мы использовали &НаСервереБезКонтекста для функций получения пользователя и записи объекта. Это оптимизирует работу системы, так как при вызове таких процедур на сервер не передается контекст всей формы (все её реквизиты и данные), что значительно ускоряет отклик интерфейса.

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

В-третьих, при открытии формы документа мы передаем структуру с ключом Ключ. Это стандартный механизм платформы: если передать в параметрах формы структуру с полем Ключ, содержащим ссылку на объект, 1С автоматически откроет форму именно этого существующего объекта.

Советы по отладке подобных ошибок

Если вы все же сталкиваетесь с ошибкой Поле объекта не обнаружено, воспользуйтесь следующей методикой:

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

← На главную