Как обратиться к определенной строке динамического списка и изменить значение реквизита в 1С

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

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

Алгоритм работы с динамическим списком

Для того чтобы изменить данные объекта, отображаемого в списке, нам необходимо выполнить три последовательных шага. Рассмотрим их подробнее:

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

Проанализируем стандартный шаблон кода, который часто используется для решения этой задачи:


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

&НаСервере
Процедура ИзменитьРеквизитНаСервере(ВыбраннаяСсылка)
    
    // Получаем объект для редактирования
    ОбъектСсылка = ВыбраннаяСсылка.ПолучитьОбъект();
    
    Если ОбъектСсылка <> Неопределено Тогда
        ОбъектСсылка.Наименование = "Новое наименование"; // Пример изменения
        ОбъектСсылка.Записать();
    КонецЕсли;
    
КонецПроцедуры

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

Часто при попытке обратиться к ТекущиеДанные.Ссылка система выдает ошибку. Выясним причину такого поведения. Это происходит в двух случаях:

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

2. Поле не включено в запрос: Если вы используете произвольный запрос, убедитесь, что поле Ссылка явно выбрано в тексте запроса. Чтобы оно было доступно в ТекущиеДанные, даже если колонка не выведена на форму, в свойствах этого поля в конфигураторе нужно установить флаг Использовать всегда.

Разница между ТекущаяСтрока и ТекущиеДанные

Важно различать два свойства элемента формы «Таблица», отображающего динамический список:

Рассмотрим более лаконичный и правильный вариант кода, используя ТекущаяСтрока:


&НаКлиенте
Процедура ИзменитьДанные(Команда)
    
    СсылкаНаОбъект = Элементы.Список.ТекущаяСтрока;
    
    Если ЗначениеЗаполнено(СсылкаНаОбъект) Тогда
        ВыполнитьЗаписьНаСервере(СсылкаНаОбъект);
    КонецЕсли;
    
КонецПроцедуры

Проблема «Элемент не выбран» при вызове ПолучитьОбъект()

Если на сервере вы получаете ошибку при вызове ПолучитьОбъект(), проанализируем ситуацию. Это часто связано с тем, что в переменную, передаваемую на сервер, попадает не ссылка, а строка или пустое значение. Рассмотрим типичные причины:

  1. Неправильный тип реквизита формы: Если вы сохраняете ссылку в промежуточный реквизит формы, убедитесь, что его тип установлен как СправочникСсылка.ИмяСправочника, а не Строка.
  2. Пустая ссылка: Перед вызовом серверного метода всегда проверяйте ссылку функцией ЗначениеЗаполнено().

Посмотрим на пример правильной обработки на сервере с проверкой прав и блокировок:


&НаСервере
Процедура ВыполнитьЗаписьНаСервере(ВыбраннаяСсылка)
    
    // Проверяем, не является ли ссылка пустой (на всякий случай)
    Если ВыбраннаяСсылка.Пустая() Тогда
        Возврат;
    КонецЕсли;

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

Обновление данных в интерфейсе

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

Элементы.Список.Обновить();

Этот метод принудительно пересчитывает данные списка, учитывая последние изменения в базе данных. Также хорошей практикой является использование метода ОповеститьОбИзменении(ВыбраннаяСсылка), который уведомляет все открытые формы в системе о том, что данный объект был изменен.

Работа с несколькими строками

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


&НаКлиенте
Процедура ОбработатьВыделенные(Команда)
    
    МассивСсылок = Элементы.Список.ВыделенныеСтроки;
    
    Для Каждого СсылкаИзСписка Из МассивСсылок Цикл
        // Здесь можно либо вызывать серверный метод для каждой ссылки, 
        // либо (что правильнее) передать весь массив на сервер сразу
    КонецЦикла;
    
КонецПроцедуры

Передача массива на сервер одним вызовом гораздо эффективнее с точки зрения производительности системы, так как минимизирует количество клиент-серверных вызовов.

Резюмируем: Для успешной работы со строкой динамического списка всегда проверяйте настройки "Основной таблицы", используйте ТекущаяСтрока для получения ссылки и не забывайте обновлять визуальные данные после завершения серверных операций. Это обеспечит стабильную работу вашего кода и корректное отображение данных пользователю.

← На главную