При разработке внешних обработок на платформе «1С:Предприятие 8.3» программисты часто сталкиваются с задачей массового редактирования данных. Типичный сценарий: пользователь выбирает несколько строк в таблице, нажимает кнопку, и программа должна изменить определенное значение во всех этих строках. Несмотря на кажущуюся простоту, здесь есть важные нюансы, связанные с архитектурой управляемых форм.
В этой статье мы подробно разберем, как правильно работать с выделенными строками, почему стандартные ссылки здесь не помогут и как написать эффективный код для решения этой задачи.
Первое, с чем сталкивается разработчик — это понимание того, что именно возвращает платформа при обращении к выделенным строкам. Рассмотрим ситуацию: у нас есть таблица на форме, связанная с табличной частью объекта (Объект.Товары). Когда мы обращаемся к свойству Элементы.Товары.ВыделенныеСтроки, мы получаем массив.
Важно понимать: этот массив содержит не сами строки и не ссылки на объекты базы данных, а идентификаторы строк. Идентификатор — это внутреннее числовое значение, которое уникально для строки в рамках текущего сеанса работы с формой. Попытка напрямую обратиться к реквизиту через этот идентификатор, например, Идентификатор.Количество = 10, приведет к ошибке выполнения, так как у числа нет свойства Количество.
Проанализируем ситуацию, описанную в сообщениях форума. Пользователь пытался передать эти строки в типовую обработку «Групповое изменение реквизитов». Это не сработало, так как типовая обработка ожидает массив ссылок (AnyRef), которые существуют в базе данных постоянно. Строки же внешней обработки живут только «в памяти» формы и ссылок в понимании объектов БД не имеют.
Рассмотрим подробнее правильный алгоритм действий. Для того чтобы изменить данные, нам нужно пройти по цепочке: от элемента формы к данным объекта. Разберем по шагам, как это реализовать в модуле управляемой формы.
Во-первых, нам необходимо получить коллекцию выделенных строк. Во-вторых, для каждого идентификатора из этой коллекции нужно найти соответствующую ему «физическую» строку в данных объекта. В-третьих, произвести необходимые манипуляции с реквизитами.
Посмотрим на пример кода, который реализует эту логику на стороне клиента:
&НаКлиенте
Процедура ИзменитьВыделенные(Команда)
// 1. Получаем массив идентификаторов выделенных строк
МассивИдентификаторов = Элементы.СписокНоменклатуры.ВыделенныеСтроки;
// 2. Организуем цикл по всем выделенным элементам
Для Каждого ИдентификаторСтроки Из МассивИдентификаторов Цикл
// 3. Получаем непосредственно строку данных из объекта
СтрокаДанных = Объект.СписокНоменклатуры.НайтиПоИдентификатору(ИдентификаторСтроки);
// 4. Проверяем, что строка была найдена (защита от ошибок)
Если СтрокаДанных <> Неопределено Тогда
// Изменяем нужные нам реквизиты
СтрокаДанных.Цена = 100;
СтрокаДанных.СтавкаНДС = ПредопределенноеЗначение("Перечисление.СтавкиНДС.НДС20");
КонецЕсли;
КонецЦикла;
КонецПроцедуры
В данном примере мы используем метод НайтиПоИдентификатору, который является ключевым инструментом. Он позволяет связать визуальный элемент (строку в таблице на экране) с программным объектом (строкой в оперативной памяти).
Часто возникает вопрос: почему нельзя использовать метод Элементы.Таблица.ДанныеСтроки(Идентификатор)? Давайте выясним причину. Метод ДанныеСтроки возвращает структуру, предназначенную в основном для чтения данных на клиенте. Хотя в некоторых случаях через него можно попытаться что-то изменить, правильным и надежным способом изменения данных в 1С считается работа непосредственно с коллекцией Объект.ТабличнаяЧасть.
При использовании НайтиПоИдентификатору вы получаете объект типа ДанныеФормыЭлементКоллекции. Любые изменения в этом объекте мгновенно отражаются в интерфейсе пользователя без дополнительных команд обновления формы. Это происходит благодаря механизму связей (биндингу) между реквизитами формы и элементами управления.
Если в процессе изменения строк требуется выполнять сложные расчеты, обращаться к запросам или проверять остатки на складах, выполнение кода &НаКлиенте может быть неэффективным. В таких случаях лучше передать массив идентификаторов на сервер.
Рассмотрим, как это реализовать:
&НаКлиенте
Процедура КомандаИзменитьНаСервере(Команда)
// Собираем идентификаторы в массив
Выделенные = Элементы.ТаблицаТовары.ВыделенныеСтроки;
// Вызываем серверный метод
ИзменитьРеквизитыНаСервере(Выделенные);
КонецПроцедуры
&НаСервере
Процедура ИзменитьРеквизитыНаСервере(МассивИдентификаторов)
Для Каждого ТекИдентификатор Из МассивИдентификаторов Цикл
СтрокаТЧ = Объект.Товары.НайтиПоИдентификатору(ТекИдентификатор);
Если СтрокаТЧ <> Неопределено Тогда
// Выполняем сложную серверную логику
СтрокаТЧ.Сумма = СтрокаТЧ.Количество * СтрокаТЧ.Цена;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Важный момент: на сервере нам доступен весь контекст Объекта, поэтому мы можем использовать полные возможности языка, включая запросы к базе данных, которые недоступны на клиенте.
Стоит отметить, что поведение свойства ВыделенныеСтроки меняется, если ваша таблица на форме — это не Табличная часть, а Динамический список. В случае с динамическим списком (например, если вы вывели список документов во внешней обработке), массив ВыделенныеСтроки будет содержать Ссылки (уникальные идентификаторы из БД), а не числовые идентификаторы строк формы.
Проанализируем разницу в коде для Динамического списка:
Идентификатор (Число) -> Объект.ТЧ.НайтиПоИдентификатору().Ссылка (ДокументСсылка/СправочникСсылка) -> Работа через ПолучитьОбъект() (если нужно менять данные в базе) или использование ссылки в запросах.Когда мы программно меняем данные в таблице внешней обработки, система автоматически устанавливает признак Модифицированность для формы. Это означает, что при попытке закрыть обработку 1С может спросить: «Данные были изменены. Сохранить изменения?». Однако у внешней обработки нет встроенной кнопки «Записать», как у документа. Если вы не предполагаете сохранение этих данных в какой-то файл или внешнюю базу, после выполнения цикла изменений можно программно сбросить этот флаг:
ЭтаФорма.Модифицированность = Ложь;
Также убедитесь, что в свойствах таблицы на форме установлен режим выделения Множественный. Если там стоит Одиночный, пользователь просто не сможет выделить несколько строк зажатой клавишей Ctrl или Shift, и ваш массив всегда будет содержать только один элемент.
Подводя итог, можно сказать, что работа с выделенными строками во внешней обработке требует четкого понимания того, где находятся данные (в объекте) и как к ним обратиться через интерфейсные идентификаторы. Использование метода НайтиПоИдентификатору является «золотым стандартом» для решения этой задачи в управляемом приложении.