К статье
Практический материал

Разработка и Конфигурация · 11 мин

1С: как передать текущую строку на сервер

Как передать текущую строку табличной части или динамического списка с клиента на сервер в 1С: ДанныеФормыСтруктура, сериализация, типичные ошибки и примеры кода.

Клиент-серверное разделение в управляемых формах 1С часто ставит разработчика перед задачей: на клиенте выбрана строка таблицы, а обработать её нужно на сервере — например, пересчитать связанные данные, обратиться к базе или выполнить запрос. Напрямую передать объект ДанныеФормыЭлементКоллекции нельзя: такие объекты не сериализуются и не переживают границу клиент-серверного вызова.

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

Ниже разобраны рабочие подходы с примерами кода, ограничения каждого способа и типичные ошибки, из-за которых строка «теряется» при передаче.

Почему строку формы нельзя передать напрямую

Данные управляемой формы существуют в двух экземплярах — клиентском и серверном, а платформа синхронизирует их сама по своим правилам. Объект типа ДанныеФормыЭлементКоллекции, который вы получаете через Элементы.Товары.ТекущиеДанные, — это обёртка, привязанная к контексту формы. Она не относится к сериализуемым типам.

При попытке передать такой объект параметром в серверную процедуру вы получите либо ошибку преобразования данных, либо неявное копирование с непредсказуемым результатом. Платформа допускает передачу между клиентом и сервером только примитивных типов (число, строка, дата, булево), ссылок, структур, массивов и некоторых системных объектов вроде ДанныеФормыСтруктура.

Способ 1. Передать идентификатор строки и найти её на сервере

Самый простой и надёжный вариант для табличных частей и таблиц значений на форме. На клиенте берёте идентификатор текущей строки, передаёте его числом, а на сервере находите строку методом НайтиПоИдентификатору().

&НаКлиенте

Процедура ТоварыПриАктивизацииСтроки(Элемент)

ТекущаяСтрока = Элементы.Товары.ТекущиеДанные;

Если ТекущаяСтрока = Неопределено Тогда

Возврат;

КонецЕсли;

ОбработатьСтрокуНаСервере(ТекущаяСтрока.ПолучитьИдентификатор());

КонецПроцедуры

&НаСервере

Процедура ОбработатьСтрокуНаСервере(ИдентификаторСтроки)

СтрокаТаблицы = Объект.Товары.НайтиПоИдентификатору(ИдентификаторСтроки);

Если СтрокаТаблицы = Неопределено Тогда

Возврат;

КонецЕсли;

// работа со строкой: СтрокаТаблицы.Сумма = ...

КонецПроцедуры

Преимущество подхода в том, что на сервере вы работаете с той же самой строкой данных формы: все изменения автоматически отразятся на клиенте после завершения вызова. Не нужно ничего возвращать и синхронизировать вручную.

Важный нюанс: идентификатор строки действителен только в рамках текущего сеанса работы формы. После перечитывания объекта или перезаполнения таблицы идентификаторы могут измениться, поэтому хранить их «про запас» и использовать позже нельзя без повторной проверки.

Способ 2. Динамический список: передать ссылку или ключ записи

Если таблица на форме — динамический список (список документов, регистра сведений, справочника), понятия «строка данных формы» там нет в привычном смысле. Свойство Элементы.Список.ТекущаяСтрока возвращает ссылку на объект или ключ записи регистра — и это уже сериализуемое значение, которое можно передать на сервер как есть.

&НаКлиенте

Процедура СписокПриАктивизацииСтроки(Элемент)

ТекущаяСсылка = Элементы.Список.ТекущаяСтрока;

Если ТекущаяСсылка = Неопределено Тогда

Возврат;

КонецЕсли;

ДополнительныеДанные = ПолучитьДанныеНаСервере(ТекущаяСсылка);

КонецПроцедуры

&НаСервереБезКонтекста

Функция ПолучитьДанныеНаСервере(Ссылка)

Запрос = Новый Запрос("ВЫБРАТЬ Сумма ИЗ Документ.Реализация ГДЕ Ссылка = &Ссылка");

Запрос.УстановитьПараметр("Ссылка", Ссылка);

// ...

КонецФункции

Для регистров сведений ТекущаяСтрока вернёт объект типа РегистрСведенийКлючЗаписи — он тоже передаётся на сервер без преобразований. Для списков с произвольным запросом и основной таблицей убедитесь, что ключевое поле присутствует в выборке, иначе текущая строка будет неопределённой.

Способ 3. Преобразовать строку в структуру

Когда искать строку на сервере негде (таблица не связана с объектом, либо серверная процедура без контекста формы), строку упаковывают в структуру. Универсальный приём — пройтись по колонкам таблицы значений и скопировать значения:

&НаКлиенте

Функция СтрокаВСтруктуру(ТекущаяСтрока)

Результат = Новый Структура;

Для Каждого Колонка Из Элементы.ТаблицаДанных.ПодчиненныеЭлементы Цикл

ИмяПоля = Колонка.Имя;

Результат.Вставить(ИмяПоля, ТекущаяСтрока[ИмяПоля]);

КонецЦикла;

Возврат Результат;

КонецФункции

Более надёжный вариант — явно перечислить нужные поля через Новый Структура("Номенклатура,Количество,Цена") и ЗаполнитьЗначенияСвойств(Результат, ТекущаяСтрока). Так вы не зависите от состава колонок элемента формы и не тащите на сервер лишнее.

Помните об ограничении: в структуре допустимы только сериализуемые значения. Если в колонке лежит, например, ХранилищеЗначения или несериализуемый объект, передача завершится ошибкой. Ссылки на объекты базы передаются нормально.

Сравнение вариантов

Идентификатор строки

Подходит для табличных частей и таблиц значений формы. Изменения на сервере сразу видны на клиенте. Не работает для динамических списков.

Ссылка / ключ записи

Для динамических списков. Минимальный трафик, но на сервере нужно заново читать данные из базы.

Структура со значениями

Универсально, работает без контекста формы. Минус: изменения нужно возвращать и записывать обратно вручную.

Способ 4. Передать всю строку через ДанныеФормыСтруктура

В модуле формы доступна серверная механика преобразования данных формы в значение: строку табличной части можно получить как ДанныеФормыСтруктура и передать между контекстами. Практически это используется реже, чем идентификатор, но полезно, когда серверная процедура должна получить снимок строки, не привязанный к текущему состоянию формы.

На практике чаще встречается обратная задача — вернуть обработанную строку с сервера на клиент. Здесь тот же принцип: серверная функция возвращает структуру, а клиент копирует значения в текущую строку через ЗаполнитьЗначенияСвойств(ТекущаяСтрока, РезультатСервера).

Проверка результата и частые ошибки

После внедрения кода проверьте три вещи: строка находится на сервере (не Неопределено), изменения видны на клиенте сразу после вызова, и повторный вызов не падает при пустой таблице или неактивной строке.

Типичные ошибки
01
Передача ТекущиеДанные напрямую параметром — ошибка преобразования или пустые значения на сервере.
02
Использование НомерСтроки вместо идентификатора: после сортировки или удаления строк номера смещаются, и сервер обрабатывает не ту строку.
03
Обращение к НайтиПоИдентификатору у динамического списка — метод отсутствует, нужна ТекущаяСтрока элемента формы.
04
Забытая проверка ТекущиеДанные = Неопределено — падение при клике по пустой таблице.
05
Вызов серверной процедуры из обработчика ПриАктивизацииСтроки без отложенного вызова — тормоза при каждом перемещении по списку.

Ещё одна ловушка — модифицированность формы. Если серверная процедура изменяет данные объекта, форма помечается модифицированной, и при закрытии пользователь получит вопрос о сохранении. Если изменение служебное и его не нужно сохранять, либо не трогайте объект на сервере, либо осознанно управляйте признаком модифицированности.

Контрольные точки

Как проверить результат

Найденная строка на сервере
Норма

НайтиПоИдентификатору вернул строку, поля заполнены

Тревожный признак

Вернулось Неопределено — идентификатор устарел или таблица перечитана

Отображение на клиенте
Норма

После серверного вызова изменения видны в таблице без переоткрытия формы

Тревожный признак

Данные изменились только в базе, на форме старые значения

Производительность
Норма

При быстрой навигации по строкам форма отвечает без задержек

Тревожный признак

Каждое перемещение вызывает паузу — серверный вызов не защищён задержкой

Рекомендации по выбору подхода

Маршрут решения

Как выбрать действие

Табличная часть документа или справочника, нужно изменить строкуПередайте идентификатор строки и используйте НайтиПоИдентификатору на сервере
Динамический список документов или справочниковПередайте Элементы.Список.ТекущаяСтрока (ссылку) в серверную функцию без контекста
Регистр сведений в динамическом спискеПередайте ключ записи, на сервере создайте менеджер записи по ключу
Серверная процедура общего модуля без контекста формыСоберите структуру с нужными полями на клиенте и передайте её
Нужно вернуть обработанные данные обратно в строкуВерните структуру из серверной функции и примените ЗаполнитьЗначенияСвойств к ТекущиеДанные

В большинстве сценариев достаточно первого способа: идентификатор строки плюс поиск на сервере. Он минимизирует трафик, сохраняет связь с данными формы и не требует ручной синхронизации. Структуры и ссылки оставьте для случаев, где контекст формы недоступен или данные нужно передать за пределы формы — например, в фоновое задание.

Итог

Что важно запомнить

Строка формы (ДанныеФормыЭлементКоллекции) не сериализуется. Передавайте на сервер идентификатор строки, ссылку/ключ записи или структуру со значениями — в зависимости от типа таблицы. Всегда проверяйте ТекущиеДанные на Неопределено и защищайте серверные вызовы в ПриАктивизацииСтроки отложенным обработчиком.

Частые вопросы

Можно ли передать на сервер всю табличную часть целиком?

Да, но не как объект формы. На сервере данные табличной части и так доступны через Объект.ИмяТабличнойЧасти, поэтому передавать её с клиента обычно не нужно. Если процедура без контекста формы, таблицу выгружают в массив структур или передают в виде значения через реквизит формы.

Почему НайтиПоИдентификатору возвращает Неопределено?

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

Чем идентификатор строки отличается от номера строки?

Номер строки — это порядковый индекс в текущем отображении, он меняется при сортировке, удалении и вставке. Идентификатор — уникальный внутренний ключ строки в данных формы, стабильный, пока коллекция не перечитана. Для серверного поиска подходит только идентификатор.

Как передать строку из формы в фоновое задание?

Фоновое задание не имеет доступа к данным формы, поэтому соберите нужные поля строки в структуру с сериализуемыми значениями и передайте её в параметрах метода Выполнить. Ссылки на объекты базы в такой структуре допустимы.

Работает ли передача структуры в тонком и веб-клиенте?

Да, структуры с примитивными типами и ссылками корректно сериализуются во всех клиентах. Ограничение одно: в веб-клиенте недоступны некоторые клиентские типы, но на передачу структуры это не влияет.

Нужно ли что-то делать, чтобы изменения с сервера появились в строке на клиенте?

Если серверная процедура изменила строку через НайтиПоИдентификатору в данных формы — ничего, платформа синхронизирует отображение сама. Если сервер вернул структуру, примените её к текущей строке вручную через ЗаполнитьЗначенияСвойств.