Как на управляемой форме реализовать таблицу со списком документов с возможностью редактирования

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

При разработке интерфейсов на управляемых формах 1С программисты часто сталкиваются с задачей: нужно вывести список документов не просто для просмотра, а с возможностью быстрого редактирования прямо в строке. Чаще всего это касается смены статусов, установки пометок или изменения ответственных. Стандартный механизм Динамического списка (ДинамическийСписок) по своей природе предназначен только для отображения данных, считываемых из базы SQL-запросом, и не поддерживает прямое редактирование ячеек "как в Excel".

В этой статье мы подробно разберем, как обойти это ограничение, рассмотрим различные архитектурные подходы и выберем наиболее эффективные методы реализации задачи.

Метод 1. Использование Динамического списка с перехватом события выбора

Этот метод является наиболее предпочтительным, так как он сохраняет все преимущества динамического списка: быструю подгрузку данных порциями, встроенные отборы, поиск и группировки. Чтобы реализовать "псевдо-редактирование", мы будем программно вызывать форму выбора значения при клике на ячейку.

Рассмотрим пошаговый алгоритм реализации:

  1. Разместим на форме таблицу, путь к данным которой указывает на реквизит типа ДинамическийСписок.
  2. Для колонки, которую нужно "редактировать" (например, "Статус"), установим свойство Режим редактирования в значение "Вход в ячейку".
  3. Создадим обработчик события Выбор для таблицы.

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


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

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

На сервере необходимо реализовать непосредственную запись объекта. Важно помнить, что любая запись документа — это ресурсозатратная операция, поэтому стоит предусмотреть необходимые проверки.


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

Метод 2. Использование Таблицы значений (ТЗ)

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

Выясним причину, почему это иногда удобнее: в ТЗ ячейки являются полностью редактируемыми по умолчанию. Мы можем включить флажки (булево), текстовые поля и списки выбора без написания сложных перехватов событий.

Однако у этого метода есть существенные недостатки, которые мы должны учитывать:

Разберем реализацию загрузки в ТЗ:


&НаСервере
Процедура ЗагрузитьДокументыВТаблицу()
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   РеализацияТоваровУслуг.Ссылка КАК Документ,
        |   РеализацияТоваровУслуг.Статус КАК Статус,
        |   РеализацияТоваровУслуг.СуммаДокумента КАК Сумма
        |ИЗ
        |   Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
        |ГДЕ
        |   РеализацияТоваровУслуг.Дата МЕЖДУ &НачалоПериода И &КонецПериода";
    
    Запрос.УстановитьПараметр("НачалоПериода", Объект.Период.ДатаНачала);
    Запрос.УстановитьПараметр("КонецПериода", Объект.Период.ДатаОкончания);
    
    Результат = Запрос.Выполнить().Выгрузить();
    Объект.ТаблицаДокументов.Загрузить(Результат);
КонецПроцедуры

Метод 3. Групповое изменение через командную панель

Часто пользователь просит "редактирование в списке", когда на самом деле ему нужно установить один и тот же статус для 50 документов. В этом случае наиболее правильным с точки зрения UX (пользовательского опыта) будет использование кнопок действий на командной панели над динамическим списком.

Проанализируем ситуацию: вместо того чтобы заставлять пользователя щелкать в каждую строку, мы предлагаем ему выделить нужные строки (используя Ctrl или Shift) и нажать одну кнопку "Установить статус -> Выполнен".

Пример кода для групповой обработки:


&НаКлиенте
Процедура КомандаУстановитьСтатусВыполнен(Команда)
    
    ВыделенныеСтроки = Элементы.СписокДокументов.ВыделенныеСтроки;
    Если ВыделенныеСтроки.Количество() = 0 Тогда
        ПоказатьПредупреждение(, "Выберите хотя бы один документ!");
        Возврат;
    КонецЕсли;
    
    ОписаниеОповещения = Новый ОписаниеОповещения("ПодтверждениеЗавершение", ЭтаФорма);
    ПоказатьВопрос(ОписаниеОповещения, "Изменить статус для " + ВыделенныеСтроки.Количество() + " документов?", РежимДиалогаВопрос.ДаНет);
    
КонецПроцедуры

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

Важные рекомендации по оптимизации

При реализации любого из этих методов следует учитывать несколько критически важных моментов:

  1. Оповещение об изменении: Всегда используйте метод ОповеститьОбИзменении(). Это гарантирует, что динамические списки во всех открытых окнах (включая текущее) обновят данные автоматически.
  2. Блокировки: При записи объекта из списка помните, что документ может быть открыт и заблокирован другим пользователем. Обязательно используйте конструкцию Попытка...Исключение.
  3. Фоновое выполнение: Если групповая обработка затрагивает сотни документов и включает проведение, рассмотрите возможность запуска этой операции в фоновом задании. Это позволит пользователю продолжать работу с формой, пока система меняет статусы.
  4. Условное оформление: Чтобы пользователю было проще ориентироваться, настройте Условное оформление формы. Например, документы со статусом "Отклонен" можно выделять серым цветом, а "На утверждении" — жирным шрифтом.

Выбор конкретного метода зависит от бизнес-задачи. Для оперативной работы с большими массивами данных лучше всего подходит Метод 1 (перехват события выбора в динамическом списке), так как он наиболее технологичен и масштабируем.

← На главную