При разработке на управляемых формах 1С (УФ) программисты часто сталкиваются с необходимостью обработать данные текущей строки таблицы именно на стороне сервера. Основная сложность заключается в том, что привычное свойство ТекущиеДанные доступно только в клиентском контексте. В этой статье мы подробно разберем, как правильно передать управление на сервер и получить доступ к нужной строке, используя идентификаторы и особенности коллекций данных формы.
Для начала проанализируем архитектуру управляемой формы. На форме всегда присутствуют два связанных объекта:
ДанныеФормыКоллекция) — это сами данные, которые хранятся на сервере и отображаются на клиенте.ТаблицаФормы) — это визуальное представление данных, которое отвечает за отображение, выделение строк и взаимодействие с пользователем.Разберем ситуацию: когда пользователь выбирает строку в таблице, визуальный элемент "знает", какая строка активна. Это значение хранится в свойстве Элементы.ИмяВашейТаблицы.ТекущаяСтрока. Важно понимать, что это свойство возвращает не саму строку, а её внутренний идентификатор (ID) — уникальное числовое значение.
Этот способ является наиболее правильным и эффективным. Мы используем идентификатор строки, который доступен на сервере через коллекцию элементов формы, и находим по нему данные в реквизите. Рассмотрим пример кода, где ТЗ — это имя реквизита формы (ваша таблица), а Элементы.ТЗ — визуальный элемент.
&НаСервере
Процедура ОбработатьТекущуюСтрокуНаСервере()
// Получаем идентификатор текущей строки из элемента формы
ИдентификаторСтроки = Элементы.ТЗ.ТекущаяСтрока;
Если ИдентификаторСтроки <> Неопределено Тогда
// Находим строку в коллекции данных формы по её ID
ТекущаяСтрокаДанных = ТЗ.НайтиПоИдентификатору(ИдентификаторСтроки);
Если ТекущаяСтрокаДанных <> Неопределено Тогда
// Теперь нам доступны все колонки строки
Сообщить("Выбрана строка с реквизитом: " + ТекущаяСтрокаДанных.ИмяКолонки);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Проанализируем этот код: метод НайтиПоИдентификатору ищет строку именно по внутреннему ID, который не меняется при сортировке или фильтрации таблицы. Это принципиальное отличие от индекса строки, который может измениться, если пользователь нажмет на заголовок колонки для сортировки.
Хорошей практикой считается явная передача параметров при вызове серверных процедур с клиента. Это делает код более читаемым и позволяет избежать лишних обращений к объекту Элементы на сервере, что положительно сказывается на чистоте кода. Для реализации классических сценариев на управляемой форме, таких как обновление связанных списков при смене строки, можно использовать готовый механизм для связывания главной и подчиненной таблиц.
&НаКлиенте
Процедура КомандаОбработать(Команда)
ИдСтроки = Элементы.Заказы.ТекущаяСтрока;
Если ИдСтроки = Неопределено Тогда
Возврат;
КонецЕсли;
СервернаяФункцияОбработки(ИдСтроки);
КонецПроцедуры
&НаСервере
Функция СервернаяФункцияОбработки(ВыбранныйИдентификатор)
// Работаем напрямую с реквизитом формы "Заказы"
СтрокаЗаказа = Заказы.НайтиПоИдентификатору(ВыбранныйИдентификатор);
Если СтрокаЗаказа <> Неопределено Тогда
// Выполняем необходимые действия
СтрокаЗаказа.Статус = "Обработано";
КонецЕсли;
КонецФункции
Выясним причину, почему это работает: объект Заказы на сервере имеет тип ДанныеФормыКоллекция. У этого типа есть встроенный метод НайтиПоИдентификатору(), который позволяет мгновенно получить доступ к нужной строке памяти сервера. При решении более сложных задач, когда требуется не просто найти строку, а динамически сформировать весь интерфейс, будет полезен инструмент для программного вывода произвольной таблицы значений на управляемую форму.
Рассмотрим важный нюанс, который часто приводит к ошибкам. Если вы решите преобразовать данные формы в обычную таблицу значений с помощью метода РеквизитФормыВЗначение("Заказы"), вы потеряете внутренние идентификаторы строк.
В обычной ТаблицеЗначений нет метода НайтиПоИдентификатору. Если вы планируете сложную обработку данных через выгрузку в объект ТаблицаЗначений, вам придется заранее позаботиться о наличии уникальной колонки (например, НомерСтроки или собственный УникальныйИдентификатор), чтобы найти соответствие. Посмотрим на пример, как делать не рекомендуется, если можно обойтись работой с данными формы:
&НаСервере
Процедура ОпасныйМетод()
// ТЗ_Объект - это уже не ДанныеФормыКоллекция, а обычная ТаблицаЗначений
ТЗ_Объект = РеквизитФормыВЗначение("Заказы");
// ОШИБКА: У ТЗ_Объект нет метода НайтиПоИдентификатору!
// Строка = ТЗ_Объект.НайтиПоИдентификатору(Элементы.Заказы.ТекущаяСтрока);
КонецПроцедуры
Совет: старайтесь изменять данные напрямую в реквизите формы (тип ДанныеФормыКоллекция), тогда платформа автоматически синхронизирует изменения с интерфейсом пользователя без полной перезагрузки таблицы.
Иногда требуется получить данные не одной текущей строки, а всех строк, которые пользователь выделил мышкой (удерживая Ctrl или Shift). В этом случае свойство ТекущаяСтрока вернет только одну (активную) строку, а для получения всех остальных нужно использовать коллекцию ВыделенныеСтроки.
Проанализируем пример обработки группы строк:
&НаСервере
Процедура ОбработатьВыделенныеНаСервере()
Для Каждого ИдСтроки Из Элементы.ТЗ.ВыделенныеСтроки Цикл
СтрокаДанных = ТЗ.НайтиПоИдентификатору(ИдСтроки);
Если СтрокаДанных <> Неопределено Тогда
// Обрабатываем каждую выделенную строку
СтрокаДанных.Пометка = Истина;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Подведем итог нашему разбору. Для эффективной работы с текущей строкой на сервере придерживайтесь следующих правил:
Элементы.ИмяТаблицы.ТекущаяСтрока для получения уникального идентификатора.НайтиПоИдентификатору() у соответствующего реквизита формы.ТекущиеДанные — это "клиентский" объект, и на сервере он всегда будет возвращать ошибку.Неопределено перед поиском данных.РеквизитФормыВЗначение, если вам нужно просто поменять значения в текущей строке.Соблюдение этих правил позволит вам писать быстрый и стабильный код для управляемого интерфейса 1С, избегая лишних конвертаций данных и ошибок контекста.