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