В процессе разработки на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с необходимостью передать данные конкретной строки таблицы (тип ДанныеФормыЭлементКоллекции) с клиента на сервер. Основная сложность заключается в том, что этот тип данных тесно связан с контекстом формы и не может быть передан напрямую во внеконтекстные серверные методы (&НаСервереБезКонтекста). Кроме того, ручное перечисление всех колонок в структуре при большом их количестве становится трудоемкой задачей. Рассмотрим подробно, как автоматизировать этот процесс и какие методы являются наиболее эффективными.
Проанализируем самый производительный и правильный с точки зрения архитектуры 1С способ. Вместо того чтобы передавать на сервер тяжелый объект или вручную созданную структуру, мы передаем только уникальный идентификатор строки. Этот метод идеально подходит для контекстных вызовов (&НаСервере).
Рассмотрим по шагам, как это реализовать:
ПолучитьИдентификатор().НайтиПоИдентификатору().Посмотрим на пример кода:
&НаКлиенте
Процедура ТаблицаПриИзменении(Элемент)
ДанныеСтроки = Элементы.Таблица.ТекущиеДанные;
Если ДанныеСтроки = Неопределено Тогда
Возврат;
КонецЕсли;
ИдентификаторСтроки = ДанныеСтроки.ПолучитьИдентификатор();
ОбработатьСтрокуНаСервере(ИдентификаторСтроки);
КонецПроцедуры
&НаСервере
Процедура ОбработатьСтрокуНаСервере(ИдентификаторСтроки)
// Восстанавливаем строку из реквизита формы (например, Объект.Товары)
СтрокаКоллекции = Объект.Товары.НайтиПоИдентификатору(ИдентификаторСтроки);
Если СтрокаКоллекции <> Неопределено Тогда
// Теперь у нас есть доступ ко всем полям строки
СтрокаКоллекции.Цена = 100;
// Сумма пересчитается, так как мы работаем в контексте формы
КонецЕсли;
КонецПроцедуры
Важный нюанс: Этот метод работает максимально быстро, так как платформа не выполняет лишнюю сериализацию данных. Мы просто передаем одно число (ID), а сервер обращается к уже имеющимся в памяти данным формы.
Если же вам необходимо вызвать внеконтекстный метод (&НаСервереБезКонтекста), передать идентификатор не получится, так как вне контекста сервер не "видит" реквизиты формы. В этом случае данные нужно упаковать в Структура. Чтобы не прописывать имена всех колонок вручную, воспользуемся программным обходом реквизитов.
Разберем ситуацию: нам нужно считать все имена колонок программно. Для этого используется метод формы ПолучитьРеквизиты(). Выясним причину, почему это лучше делать один раз: получение состава реквизитов — операция относительно тяжелая, поэтому список имен колонок стоит кэшировать или получать при создании формы.
Пример функции для динамического создания структуры из строки таблицы:
&НаКлиенте
Функция ПолучитьСтруктуруИзСтроки(ТаблицаИмя, ТекущиеДанные)
Результат = Новый Структура;
// Получаем список имен колонок (имена реквизитов этой таблицы на форме)
СписокКолонок = ПолучитьИменаКолонокСервер(ТаблицаИмя);
Для Каждого ИмяКолонки Из СписокКолонок Цикл
Результат.Вставить(ИмяКолонки, ТекущиеДанные[ИмяКолонки]);
КонецЦикла;
Возврат Результат;
КонецФункции
&НаСервере
Функция ПолучитьИменаКолонокСервер(ПутьКДаннымТаблицы)
МассивИмен = Новый Массив;
// Получаем массив объектов РеквизитФормы, принадлежащих таблице
РеквизитыТаблицы = ЭтаФорма.ПолучитьРеквизиты(ПутьКДаннымТаблицы);
Для Каждого Реквизит Из РеквизитыТаблицы Цикл
МассивИмен.Добавить(Реквизит.Имя);
КонецЦикла;
Возврат МассивИмен;
КонецФункции
В этом примере мы используем ПутьКДанным (например, "Объект.Товары"), чтобы сервер точно определил, какие колонки принадлежат коллекции. Это позволяет избежать ошибок, если на форме есть элементы, не связанные с данными.
Рассмотрим еще один практичный способ, который часто применяется в типовых конфигурациях. Если вы заранее знаете, какие поля вам нужны, или их список совпадает с полями какой-то структуры, используйте встроенную функцию ЗаполнитьЗначенияСвойств. Она умеет работать с ДанныеФормыЭлементКоллекции как с источником данных.
&НаКлиенте
Процедура ПередатьДанныеЧерезЗаполнение()
ТекДанные = Элементы.Товары.ТекущиеДанные;
Если ТекДанные = Неопределено Тогда Возврат; КонецЕсли;
// Создаем структуру с именами нужных полей
ДанныеДляСервера = Новый Структура("Номенклатура, Количество, Цена, Сумма");
// Магия платформы: свойства автоматически перенесутся из ДФЭК в структуру
ЗаполнитьЗначенияСвойств(ДанныеДляСервера, ТекДанные);
ВызватьСервернуюОбработку(ДанныеДляСервера);
КонецПроцедуры
Преимущество этого метода: Скорость разработки и читаемость кода. Вы явно указываете, какие данные уходят на сервер, используя принципы модели объекта, что упрощает отладку.
Многие разработчики забывают, что в рамках контекстного вызова (&НаСервере) объект ДанныеФормыЭлементКоллекции доступен для использования в качестве параметра процедур и функций. Платформа сама управляет передачей ссылки на этот объект.
Проанализируем ситуацию: в типовых решениях (например, БСП) часто встречаются общие модули, функции которых принимают ТекущаяСтрока. Вы можете просто передать Элементы.ИмяТаблицы.ТекущиеДанные в серверный метод. Внутри метода 1С будет обращаться к этому объекту так же, как если бы это была структура.
&НаКлиенте
Процедура РасчитатьСкидку(Элемент)
// Передаем весь объект строки целиком
РасчитатьНаСервере(Элементы.Товары.ТекущиеДанные);
КонецПроцедуры
&НаСервере
Процедура РасчитатьНаСервере(СтрокаДанных)
// СтрокаДанных здесь имеет тип ДанныеФормыЭлементКоллекции
// Мы можем проверять наличие свойств через Свойство()
Если СтрокаДанных.Количество > 10 Тогда
СтрокаДанных.Скидка = 5;
КонецЕсли;
КонецПроцедуры
Выясним, какой метод выбрать в зависимости от задачи:
ТекущиеДанные в контекстные процедуры (Метод 4).Важное предостережение: Помните, что данные в ТекущиеДанные на сервере могут не содержать изменений, которые пользователь только что внес в ячейку, если фокус еще не покинул поле ввода. Перед вызовом сервера рекомендуется использовать метод ПроверитьЗаполнение() или дождаться события ПриИзменении, которое гарантирует фиксацию данных в коллекции.
Таким образом, мы разобрали все основные способы взаимодействия с элементами коллекций форм. Выбор конкретного инструмента зависит от требований к контексту и необходимости универсальности кода. Использование НайтиПоИдентификатору остается самым надежным способом для 90% задач при разработке в управляемом приложении.