При разработке интерфейсов на управляемых формах 1С программисты часто сталкиваются с задачей: нужно вывести список документов не просто для просмотра, а с возможностью быстрого редактирования прямо в строке. Чаще всего это касается смены статусов, установки пометок или изменения ответственных. Стандартный механизм Динамического списка (ДинамическийСписок) по своей природе предназначен только для отображения данных, считываемых из базы SQL-запросом, и не поддерживает прямое редактирование ячеек "как в Excel".
В этой статье мы подробно разберем, как обойти это ограничение, рассмотрим различные архитектурные подходы и выберем наиболее эффективные методы реализации задачи.
Этот метод является наиболее предпочтительным, так как он сохраняет все преимущества динамического списка: быструю подгрузку данных порциями, встроенные отборы, поиск и группировки. Чтобы реализовать "псевдо-редактирование", мы будем программно вызывать форму выбора значения при клике на ячейку.
Рассмотрим пошаговый алгоритм реализации:
ДинамическийСписок.Выбор для таблицы.Проанализируем программный код, который позволит нам организовать выбор статуса и его сохранение в базу данных без открытия основной формы документа:
&НаКлиенте
Процедура СписокДокументовВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
// Проверяем, что пользователь нажал именно на колонку со статусом
Если Поле.Имя = "Статус" Тогда
СтандартнаяОбработка = Ложь; // Отменяем открытие формы документа
// Получаем текущие данные строки
ТекущиеДанные = Элементы.СписокДокументов.ТекущиеДанные;
Если ТекущиеДанные = Неопределено Тогда
Возврат;
КонецЕсли;
// Формируем список возможных статусов (можно выгрузить из перечисления)
СписокВыбора = Новый СписокЗначений;
СписокВыбора.Добавить(ПредопределенноеЗначение("Перечисление.СтатусыДокументов.Согласован"));
СписокВыбора.Добавить(ПредопределенноеЗначение("Перечисление.СтатусыДокументов.Отклонен"));
СписокВыбора.Добавить(ПредопределенноеЗначение("Перечисление.СтатусыДокументов.НаУтверждении"));
// Описываем оповещение о завершении выбора
ПараметрыВыбора = Новый Структура;
ПараметрыВыбора.Вставить("ДокументСсылка", ТекущиеДанные.Ссылка);
ОписаниеОповещения = Новый ОписаниеОповещения("ВыборСтатусаЗавершение", ЭтаФорма, ПараметрыВыбора);
// Вызываем выпадающее меню выбора
ПоказатьВыборИзСписка(ОписаниеОповещения, СписокВыбора, Элемент);
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ВыборСтатусаЗавершение(ВыбранныйЭлемент, ДополнительныеПараметры) Экспорт
Если ВыбранныйЭлемент <> Неопределено Тогда
// Вызываем серверный метод для записи документа
ИзменитьСтатусДокументаНаСервере(ДополнительныеПараметры.ДокументСсылка, ВыбранныйЭлемент.Значение);
// Сообщаем платформе, что данные изменились, чтобы динамический список обновил строку
ОповеститьОбИзменении(Тип("ДокументСсылка.ВашТипДокумента"));
КонецЕсли;
КонецПроцедуры
На сервере необходимо реализовать непосредственную запись объекта. Важно помнить, что любая запись документа — это ресурсозатратная операция, поэтому стоит предусмотреть необходимые проверки.
&НаСервереБезКонтекста
Процедура ИзменитьСтатусДокументаНаСервере(Ссылка, НовыйСтатус)
ОбъектДокумента = Ссылка.ПолучитьОбъект();
Если ОбъектДокумента.Статус <> НовыйСтатус Тогда
ОбъектДокумента.Статус = НовыйСтатус;
Попытка
ОбъектДокумента.Записать(РежимЗаписиДокумента.Запись);
Исключение
ВызватьИсключение "Не удалось обновить статус: " + ОписаниеОшибки();
КонецПопытки;
КонецЕсли;
КонецПроцедуры
Если предполагается, что документов в списке будет немного (до нескольких сотен), а пользователю нужно массово и быстро редактировать данные в нескольких колонках одновременно, мы можем рассмотреть вариант с Таблицей значений.
Выясним причину, почему это иногда удобнее: в ТЗ ячейки являются полностью редактируемыми по умолчанию. Мы можем включить флажки (булево), текстовые поля и списки выбора без написания сложных перехватов событий.
Однако у этого метода есть существенные недостатки, которые мы должны учитывать:
ПостроительЗапроса или программные фильтры ТЗ).Разберем реализацию загрузки в ТЗ:
&НаСервере
Процедура ЗагрузитьДокументыВТаблицу()
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| РеализацияТоваровУслуг.Ссылка КАК Документ,
| РеализацияТоваровУслуг.Статус КАК Статус,
| РеализацияТоваровУслуг.СуммаДокумента КАК Сумма
|ИЗ
| Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
|ГДЕ
| РеализацияТоваровУслуг.Дата МЕЖДУ &НачалоПериода И &КонецПериода";
Запрос.УстановитьПараметр("НачалоПериода", Объект.Период.ДатаНачала);
Запрос.УстановитьПараметр("КонецПериода", Объект.Период.ДатаОкончания);
Результат = Запрос.Выполнить().Выгрузить();
Объект.ТаблицаДокументов.Загрузить(Результат);
КонецПроцедуры
Часто пользователь просит "редактирование в списке", когда на самом деле ему нужно установить один и тот же статус для 50 документов. В этом случае наиболее правильным с точки зрения UX (пользовательского опыта) будет использование кнопок действий на командной панели над динамическим списком.
Проанализируем ситуацию: вместо того чтобы заставлять пользователя щелкать в каждую строку, мы предлагаем ему выделить нужные строки (используя Ctrl или Shift) и нажать одну кнопку "Установить статус -> Выполнен".
Пример кода для групповой обработки:
&НаКлиенте
Процедура КомандаУстановитьСтатусВыполнен(Команда)
ВыделенныеСтроки = Элементы.СписокДокументов.ВыделенныеСтроки;
Если ВыделенныеСтроки.Количество() = 0 Тогда
ПоказатьПредупреждение(, "Выберите хотя бы один документ!");
Возврат;
КонецЕсли;
ОписаниеОповещения = Новый ОписаниеОповещения("ПодтверждениеЗавершение", ЭтаФорма);
ПоказатьВопрос(ОписаниеОповещения, "Изменить статус для " + ВыделенныеСтроки.Количество() + " документов?", РежимДиалогаВопрос.ДаНет);
КонецПроцедуры
&НаКлиенте
Процедура ПодтверждениеЗавершение(Результат, ДополнительныеПараметры) Экспорт
Если Результат = КодВозвратаДиалога.Да Тогда
МассивСсылок = Новый Массив;
Для Каждого Строка ИЗ Элементы.СписокДокументов.ВыделенныеСтроки Цикл
МассивСсылок.Добавить(Строка);
КонецЦикла;
ВыполнитьГрупповоеИзменениеНаСервере(МассивСсылок);
ОповеститьОбИзменении(Тип("ДокументСсылка.РеализацияТоваровУслуг"));
КонецЕсли;
КонецПроцедуры
При реализации любого из этих методов следует учитывать несколько критически важных моментов:
ОповеститьОбИзменении(). Это гарантирует, что динамические списки во всех открытых окнах (включая текущее) обновят данные автоматически.Попытка...Исключение.Выбор конкретного метода зависит от бизнес-задачи. Для оперативной работы с большими массивами данных лучше всего подходит Метод 1 (перехват события выбора в динамическом списке), так как он наиболее технологичен и масштабируем.