В процессе разработки на платформе 1С:Предприятие 8.3 часто возникает задача массового изменения данных непосредственно из формы списка. Типичный пример: пользователь выделяет несколько документов (накладных, заказов или актов) и нажимает кнопку, чтобы сменить их статус, например, выполнить групповое изменение текстовых реквизитов или установить признак «Оплачено». Начинающие разработчики часто сталкиваются с тем, что попытка изменить данные напрямую в строке списка не дает результата или вызывает ошибки. В этой статье мы подробно разберем, как правильно реализовать эту задачу, учитывая архитектуру клиент-серверного взаимодействия.
Рассмотрим типичную ошибку. Разработчик пытается обратиться к данным через Элементы.Список.ДанныеСтроки(ВыделеннаяСтрока) и присвоить значение колонке. Выясним причину, почему это не работает. Динамический список — это всего лишь визуальное представление данных, полученных с помощью запроса из базы данных (по аналогии с тем, как отображает данные универсальный журнал документов). Данные, которые мы видим в ДанныеСтроки, предназначены только для чтения в контексте интерфейса. Чтобы изменить реальный реквизит документа или справочника, нам необходимо обратиться к самому объекту в базе данных, использовать менеджер редактирования данных, изменить его и зафиксировать транзакцию записи.
Для решения задачи нам потребуется выполнить переход с клиента на сервер. Разберем по шагам стандартную процедуру обработки нажатия кнопки.
Шаг 1. Получение списка выделенных строк на клиенте. Сначала мы соберем массив идентификаторов (ссылок), которые выбрал пользователь. Проанализируем пример кода для обработчика команды:
&НаКлиенте
Процедура КомандаЗачетОплаты(Команда)
ВыделенныеСтроки = Элементы.Список.ВыделенныеСтроки;
Если ВыделенныеСтроки.Количество() = 0 Тогда
ПоказатьПредупреждение(, "Не выбрано ни одной строки!");
Возврат;
КонецЕсли;
// Передаем массив ссылок на сервер для обработки
ИзменитьСостояниеОплатыНаСервере(ВыделенныеСтроки);
// Обновляем список, чтобы пользователь увидел изменения
Элементы.Список.Обновить();
КонецПроцедуры
Шаг 2. Обработка данных на сервере. Теперь рассмотрим серверную процедуру. Нам нужно обойти переданный массив, получить для каждой ссылки объект, изменить реквизит и записать его. Если речь идет о документах, важно помнить про режим записи (проведение или простая запись).
&НаСервере
Процедура ИзменитьСостояниеОплатыНаСервере(МассивСсылок)
Для Каждого СсылкаИзСписка Из МассивСсылок Цикл
// Проверяем, что это не группировка, а ссылка на объект
Если ТипЗнч(СсылкаИзСписка) = Тип("ДокументСсылка.Накладная") Тогда
// Получаем объект для редактирования
ОбъектДокумент = СсылкаИзСписка.ПолучитьОбъект();
// Меняем значение реквизита
ОбъектДокумент.СостояниеОплаты = Истина;
Попытка
// Если нужно, чтобы сработали проводки, используем РежимЗаписиДокумента.Проведение
ОбъектДокумент.Записать(РежимЗаписиДокумента.Проведение);
Исключение
ОбщегоНазначенияКлиентСервер.СообщитьПользователю("Не удалось провести документ: " + СсылкаИзСписка);
КонецПопытки;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Если пользователь выделит не 5, а 500 строк, вышеописанный код может работать медленно, так как каждая запись объекта инициирует отдельную транзакцию в базе данных. Проанализируем способы оптимизации:
ПолучитьОбъект() накладывает блокировку. Убедитесь, что вы не блокируете работу всей системы на длительное время.Рассмотрим пример с использованием транзакции:
&НаСервере
Процедура ИзменитьСостояниеОплатыОптимизировано(МассивСсылок)
НачатьТранзакцию();
Попытка
Для Каждого СсылкаИзСписка Из МассивСсылок Цикл
// Логика изменения реквизита...
Объект = СсылкаИзСписка.ПолучитьОбъект();
Объект.СостояниеОплаты = Истина;
Объект.Записать();
КонецЦикла;
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ВызватьИсключение "Ошибка при массовом изменении данных: " + ОписаниеОшибки();
КонецПопытки;
КонецПроцедуры
После того как данные в базе изменены, важно, чтобы динамический список на форме сразу отобразил актуальную информацию. Метод Элементы.Список.Обновить() перечитывает данные только для текущей формы. Если же у пользователя открыты карточки этих документов или другие списки, они могут остаться со старыми данными.
Для решения этой проблемы в системе 1С предусмотрен механизм оповещений. Рассмотрим, как его использовать:
Во-первых, после записи объекта на сервере полезно использовать метод ОповеститьОбИзменении(Ссылка). Это стандартный механизм платформы, который дает сигнал всем открытым формам, связанным с этим типом данных, обновить свое содержимое.
Во-вторых, можно использовать глобальный метод Оповестить(), если нужно передать специфические параметры обновления в другие формы.
Существует продвинутый способ «подменять» данные в списке без немедленной записи в базу данных или для отображения расчетных показателей. Рассмотрим ситуацию, когда нам нужно временно выделить строки цветом или показать статус, который еще не записан в БД. Для этого используется обработчик события динамического списка ПриПолученииДанныхНаСервере.
В этом событии мы получаем доступ к коллекции Строки, которая содержит данные, подготовленные к отправке на клиент. Мы можем программно изменить значения в этих строках. Посмотрим на пример кода:
&НаСервере
Процедура СписокПриПолученииДанныхНаСервере(ИмяЭлемента, Настройки, Строки)
// Допустим, у нас есть список идентификаторов, которые мы хотим пометить как "Оплаченные" виртуально
Для Каждого СтрокаСписка Из Строки Цикл
ТекущиеДанные = СтрокаСписка.Значение; // Получаем данные строки
// Здесь можно изменить оформление или значение колонки,
// если она добавлена в список как произвольное поле
КонецЦикла;
КонецПроцедуры
Важно: Этот метод сложнее в реализации и требует осторожности, так как он вызывается очень часто — при каждой прокрутке списка или обновлении экрана. Используйте его только тогда, когда стандартное изменение через ПолучитьОбъект() не подходит по бизнес-логике.
Если ваша конфигурация построена на базе БСП (например, УТ 11, ERP 2, БП 3.0), вы можете воспользоваться готовыми механизмами группового изменения реквизитов. Это избавляет от написания собственного кода обработки ссылок. Выясним, как это работает: в БСП есть общая форма «Групповое изменение реквизитов», которую можно вызвать программно, передав ей массив ссылок. Это обеспечит корректную проверку прав доступа и запись изменений в журнал регистрации автоматически.
Подводя итоги, закрепим основные правила работы с выделенными строками динамического списка:
ПолучитьОбъект().Записать(РежимЗаписиДокумента.Проведение).Попытка...Исключение для обработки ошибок доступа или логических запретов.Обновить() у элемента формы списка на клиенте после завершения серверной операции.Проанализировав эти подходы, вы сможете создавать надежные и быстрые интерфейсные решения для массовой обработки данных в 1С.