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

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

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

Особенности клиент-серверного взаимодействия

Прежде чем писать код, необходимо четко понимать границы контекстов. Код, помеченный директивой &НаКлиенте, выполняется в тонком клиенте и имеет доступ только к визуальным элементам формы и локальным переменным. Он не может напрямую обратиться к базе данных или изменить структуру метаданных.

Для выполнения логики на сервере используется контекст &НаСервере. Данные между этими мирами передаются через механизм сериализации. Это означает, что сложные объекты преобразуются в поток байтов, передаются по сети и восстанавливаются в новом контексте.

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

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

Методы вызова серверных процедур

Существует несколько способов инициировать выполнение кода на сервере из клиента. Выбор конкретного метода зависит от того, нужно ли вам ждать результата выполнения и какие параметры вы планируете передать.

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

📊 Какой метод вызова сервера вы используете чаще всего?
&ВызовСервера
Асинхронные вызовы
Фоновые задания
Команды формы

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

Рассмотрим синтаксис объявления такой процедуры. Она должна быть объявлена в модуле формы с указанием контекста выполнения:

&НаСервере

Процедура ОбработатьСтрокуНаСервере(ПараметрыСтроки)

А вызов этой процедуры из клиентского кода будет выглядеть как обычный вызов функции, но с обязательным указанием контекста вызова.

Подготовка данных для передачи

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

Частая ошибка — попытка передать сам объект строки табличной части напрямую. Хотя платформа позволяет это делать в некоторых случаях, надежнее и правильнее передавать структуру данных, например, ТаблицуЗначений или структуру с ключевыми полями.

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

💡

Используйте метод ТабличнаяЧасть.ПолучитьЭлементы().Выгрузить() для быстрого создания копии данных, если нужно передать несколько строк сразу.

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

Алгоритм передачи строки

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

☑️ Алгоритм передачи данных

Выполнено: 0 / 1

В коде клиента это выглядит следующим образом. Мы обращаемся к элементу формы, представляющему табличную часть, и получаем текущую строку.

&НаКлиенте

Процедура КнопкаПередатьНаСервер(Команда)

// Получаем текущую строку

ТекущаяСтрока = Объект.Товары.ТекущаяСтрока;

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

Сообщить("Не выбрана строка для передачи");

Возврат;

КонецЕсли;

// Формируем параметры для передачи

ПараметрыПередачи = Новый Структура;

ПараметрыПередачи.Вставить("Номенклатура", ТекущаяСтрока.Номенклатура);

ПараметрыПередачи.Вставить("Количество", ТекущаяСтрока.Количество);

ПараметрыПередачи.Вставить("Цена", ТекущаяСтрока.Цена);

// Вызываем сервер

ОбработатьДанныеНаСервере(ПараметрыПередачи);

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

Обратите внимание, что мы не передаем всю строку объекта целиком, а выгружаем только необходимые поля в структуру. Это делает код более явным и устойчивым к изменениям в структуре метаданных.

Обработка данных на стороне сервера

На сервере полученная структура или таблица значений становится обычным объектом языка 1С. Здесь вы можете выполнять любые операции: проводить расчеты, делать выборки из базы данных, записывать изменения.

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

⚠️ Внимание: Не пытайтесь обращаться к объектам формы (например, Элементы.ИмяЭлемента) внутри серверной процедуры. Они там не существуют, и код выдаст ошибку выполнения.

Пример серверной процедуры, принимающей данные:

&НаСервере

Процедура ОбработатьДанныеНаСервере(Параметры)

// Параметры.Номенклатура уже содержит ссылку на объект

// Можно выполнить запрос или прямое чтение

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Цены.ВидЦены КАК ВидЦены,

| Цены.Цена КАК Цена

|ИЗ

| РегистрСведений.ЦеныНоменклатуры КАК Цены

|ГДЕ

| Цены.Номенклатура = &Номенклатура";

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

Результат = Запрос.Выполнить();

// Дальнейшая логика обработки

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

Использование параметризированных запросов, как показано выше, является лучшей практикой для защиты от SQL-инъекций и оптимизации планов выполнения запросов.

Оптимизация и работа с большими данными

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

Платформа 1С позволяет передавать объекты типа ТаблицаЗначений между клиентом и сервером достаточно эффективно. Вы можете выгрузить всю табличную часть документа в таблицу значений и передать её одним параметром.

Для анализа производительности используйте технологический журнал или встроенные инструменты мониторинга. Они покажут время сериализации и время передачи по сети.

Метод передачи Объем данных Нагрузка на сеть Рекомендация
По одной строке Малый Высокая (много вызовов) Только для редких операций
Таблица значений Средний Средняя Оптимально для документов
Структура с ключами Минимальный Низкая Для справочной информации
Серийная передача Большой Высокая Избегать, использовать пакеты

Критически важным фактором является размер сериализуемого объекта: превышение лимита в 1 ГБ (настройка сервера) приведет к аварийному завершению сеанса.

Лимиты передачи данных

По умолчанию в 1С нет жесткого ограничения на размер передаваемых данных в коде, но есть ограничения на уровне протокола и настроек сервера. Обычно безопасный лимит — до 10-50 МБ за один вызов. Для больших файлов используйте работу с файловой системой или потоками.

Частые ошибки и способы их устранения

Разработчики часто сталкиваются с ошибкой "Неверный тип аргумента" или "Невозможно сериализовать объект". Это происходит, когда в передаваемую структуру попадает объект, который не поддерживает сериализацию, например, ссылка на элемент формы или менеджер объекта.

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

⚠️ Внимание: Интерфейс и возможности платформы 1С могут обновляться. Проверяйте документацию к вашей конкретной версии платформы (8.3.x), так как некоторые методы сериализации могли измениться.

Для отладки используйте команду Сообщить() на клиенте перед вызовом и на сервере в начале процедуры, чтобы убедиться, что данные дошли в ожидаемом виде. Также полезно проверять заполненность полей перед передачей.

💡

Всегда проверяйте типы передаваемых данных и избегайте передачи лишних объектов. Чем "чище" структура параметров, тем стабильнее работает система.

Можно ли передать строку табличной части без создания структуры?

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

Что делать, если сервер не видит изменений, внесенных на клиенте?

Убедитесь, что вы вызываете серверную процедуру после того, как данные были записаны в объект формы. Если вы меняли данные только в элементах формы, но не в объекте, сервер увидит старые данные.

Как передать данные асинхронно?

Используйте аннотацию &Асинх для клиентских процедур и вызывайте серверные методы с ожиданием. Это позволит интерфейсу оставаться отзывчивым во время длительных вычислений на сервере.

Влияет ли режим совместимости на передачу данных?

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

Можно ли передать картинку или файл из строки табличной части?

Да, если в строке есть поле типа ХранилищеЗначения, оно успешно сериализуется и передается на сервер. Однако учитывайте размер файла при передаче по сети.