Как реализовать изменение данных напрямую в динамическом списке 1С?

Программист IT и автоматизация бизнеса
← На главную

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

Понимание природы динамического списка

Прежде чем переходить к кодингу, проанализируем ситуацию: почему в динамическом списке нельзя просто «включить» редактирование в ячейке? Дело в том, что ДС — это, по сути, визуализированный SQL-запрос, который порционно подгружает данные из базы. Когда пользователь видит строку в списке, перед ним не сам объект, а результат запроса. Чтобы изменить данные, нам нужно физически записать новое значение в объект базы данных (документ, справочник или регистр) и заставить список «перечитать» это изменение.

Способ 1. Использование команд и групповой обработки

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

Алгоритм реализации следующий:

  1. Создаем команду формы (например, УстановитьСтатусВыполнен).
  2. В обработчике команды на клиенте получаем массив выделенных строк через Элементы.ИмяСписка.ВыделенныеСтроки.
  3. Передаем этот массив на сервер.
  4. На сервере в цикле открываем объекты, меняем реквизит и записываем их.
  5. Используем метод ОповеститьОбИзменении(), чтобы список на всех клиентах обновил данные.

Разберем пример кода для такой обработки:


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

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

Способ 2. Интерактивное изменение через событие «НачалоВыбора»

Если стоит задача сделать процесс максимально похожим на редактирование ячейки (как в Excel), мы можем использовать событие НачалоВыбора для конкретного поля списка. Выясним причину популярности этого метода: он позволяет перехватить клик пользователя по ячейке и вместо стандартного выбора (который для ДС заблокирован) вызвать свой программный код.

Выполним следующие шаги:

  1. В свойствах элемента формы (колонки списка) устанавливаем флаг КнопкаВыбора = Да и Редактирование = Да.
  2. Создаем обработчик события НачалоВыбора.
  3. Внутри обработчика устанавливаем СтандартнаяОбработка = Ложь.
  4. Вызываем форму выбора или выпадающее меню программно.

Пример программного вызова списка значений:


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

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

Нюансы свойства «Основная таблица» и обновления списка

Проанализируем важный технический аспект: как список понимает, что данные в базе изменились? Если у динамического списка заполнено свойство ОсновнаяТаблица, то вызов метода ОповеститьОбИзменении(Тип("...")) автоматически инициирует обновление всех открытых списков данного типа у всех пользователей в рамках одного сеанса (и через систему оповещений — в других).

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

Работа с блокировками и оптимизация

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

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

Для улучшения User Experience (UX) можно использовать технику фоновых заданий, если перезапись объекта инициирует тяжелые регламентные операции (например, проведение по регистрам). В этом случае в ячейке списка можно временно отображать картинку «в обработке» с помощью условного оформления, пока фоновое задание не завершит работу и не обновит статус в базе.

Альтернативный подход: Поле ввода над списком

Рассмотрим еще один вариант, который часто применяется в типовых конфигурациях (например, в «Текущих делах ЭДО»). Вместо редактирования внутри списка, над ним размещается вспомогательная панель с полем выбора. Пользователь выделяет одну или несколько строк, выбирает значение в поле над списком и нажимает кнопку «Применить». Это избавляет разработчика от необходимости перехватывать события каждой ячейки и делает интерфейс более предсказуемым.

Подведем итог:

Такой комплексный подход позволит вам создать современный и отзывчивый интерфейс, сохраняя при этом все преимущества динамического списка в части скорости отображения больших объемов данных.

← На главную