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

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

Как передать табличную часть на сервер в 1С

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

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

Основных подхода три: выгрузка табличной части в массив структур, передача всей коллекции через ДанныеФормыКоллекция с преобразованием на сервере и работа с объектом целиком через реквизит формы типа ДанныеФормыСтруктура. Каждый вариант имеет свои условия применения, ограничения и подводные камни.

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

Почему табличную часть нельзя передать «как есть»

В управляемой форме табличная часть документа представлена реквизитом типа ДанныеФормыКоллекция. Это специальный объект платформы, привязанный к контексту формы. При вызове серверной процедуры с директивой &НаСервере контекст формы туда не передаётся: серверная процедура в модуле формы видит реквизиты формы только если вызывается из формы и форма пересоздаётся на сервере, а в общем модуле контекста формы нет вовсе.

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

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

Способ 1. Выгрузка в массив структур на клиенте

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

Пример клиентской процедуры:

&НаКлиенте

Процедура РассчитатьНаСервере(Команда)

МассивСтрок = Новый Массив;

Для Каждого СтрокаТЧ Из Объект.Товары Цикл

СтруктураСтроки = Новый Структура;

СтруктураСтроки.Вставить("Номенклатура", СтрокаТЧ.Номенклатура);

СтруктураСтроки.Вставить("Количество", СтрокаТЧ.Количество);

СтруктураСтроки.Вставить("Цена", СтрокаТЧ.Цена);

МассивСтрок.Добавить(СтруктураСтроки);

КонецЦикла;

Результат = РассчитатьСуммыНаСервере(МассивСтрок);

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

Серверная функция в общем модуле (с признаком «Сервер») принимает массив и обрабатывает его как обычную коллекцию:

Функция РассчитатьСуммыНаСервере(МассивСтрок) Экспорт

ИтоговаяСумма = 0;

Для Каждого Строка Из МассивСтрок Цикл

ИтоговаяСумма = ИтоговаяСумма + Строка.Количество * Строка.Цена;

КонецЦикла;

Возврат ИтоговаяСумма;

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

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

Способ 2. Преобразование ДанныеФормыКоллекция в таблицу значений на сервере

Если серверная обработка выполняется в модуле самой формы (директива &НаСервере), выгружать данные на клиенте не нужно. В серверной процедуре формы доступен реквизит Объект, и табличную часть можно преобразовать в таблицу значений штатными средствами.

&НаСервере

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

ТаблицаТоваров = Объект.Товары.Выгрузить();

Для Каждого СтрокаТЗ Из ТаблицаТоваров Цикл

// серверная обработка строки

КонецЦикла;

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

Метод Выгрузить() у коллекции данных формы возвращает таблицу значений со всеми колонками табличной части. Дальше таблицу значений можно передать в общий серверный модуль — этот тип сериализуется платформой без ограничений по составу колонок, если в колонках лежат допустимые типы.

Обратная загрузка выполняется методом Загрузить(): после серверной обработки таблицу значений можно вернуть в форму и перезаписать табличную часть. Это удобно для сценариев «заполнить по кнопке», «пересчитать всё», «подобрать товары».

&НаСервере

Процедура ЗагрузитьРезультат(ТаблицаРезультата)

Объект.Товары.Загрузить(ТаблицаРезультата);

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

Порядок действий при работе через форму
  1. 1
    На клиенте вызовите серверную процедуру модуля формы (&НаСервере)
  2. 2
    В ней выполните Объект.Товары.Выгрузить() и получите таблицу значений
  3. 3
    Передайте таблицу в общий серверный модуль для расчётов
  4. 4
    Полученную таблицу загрузите обратно: Объект.Товары.Загрузить(Таблица)
  5. 5
    Убедитесь, что форма обновилась и пользователь видит изменённые строки

Способ 3. Работа с объектом целиком без передачи табличной части

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

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

&НаСервере

Процедура ЗаписатьСОбработкойНаСервере()

ДокументОбъект = РеквизитФормыВЗначение("Объект");

Для Каждого СтрокаТЧ Из ДокументОбъект.Товары Цикл

СтрокаТЧ.Сумма = СтрокаТЧ.Количество * СтрокаТЧ.Цена;

КонецЦикла;

ДокументОбъект.Записать();

ЗначениеВРеквизитФормы(ДокументОбъект, "Объект");

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

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

Сравнение способов и критерии выбора

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

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

Массив структур с клиента

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

Выгрузить() в серверной процедуре формы

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

РеквизитФормыВЗначение и работа с объектом

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

Передача только ссылки на документ

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

КритерийМассив структурВыгрузить() в формеОбъект целиком
Нужен общий серверный модульДа, напрямуюЧерез таблицу значенийЧерез объект или ссылку
Риск потери колонокВысокийНетНет
Запись документаНе предназначенНе предназначенОсновной сценарий
Трафик клиент–серверЗависит от полейОдин серверный вызовМинимальный
Маршрут решения

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

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

Типичные ошибки и как их избежать

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

Вторая группа ошибок связана с директивами компиляции. Код, написанный в &НаКлиенте, не имеет доступа к запросам, менеджерам объектов и РеквизитФормыВЗначение. Обратная ситуация — попытка обратиться к элементам формы из &НаСервереБезКонтекста, где реквизит Объект недоступен. Проверяйте директивы до отладки логики.

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

Типичные ошибки
01
Передача ДанныеФормыКоллекция в общий модуль — ошибка сериализации; сначала выгрузите в таблицу значений или массив структур
02
Серверный вызов на каждое событие ПриИзменении строки — форма тормозит; накапливайте изменения и вызывайте сервер один раз
03
Загрузить() с неполным набором колонок — остальные колонки табличной части очищаются
04
Использование &НаСервереБезКонтекста и обращение к Объект — недоступно; выберите &НаСервере или передавайте данные параметром
05
Забытое новое поле в структуре выгрузки — значение колонки молча теряется при передаче

Проверка результата и ограничения

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

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

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

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

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

Количество строк на сервере
Норма

Совпадает с числом строк табличной части в форме

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

Строк меньше — часть данных потеряна при выгрузке

Значения всех колонок
Норма

Каждое поле в серверной таблице заполнено как в форме

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

Отдельные колонки пустые — поле не включено в структуру или не совпало имя

Форма после обратной загрузки
Норма

Все колонки табличной части сохранили значения

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

Часть колонок очистилась — Загрузить() получил неполную таблицу

Время отклика при большой таблице
Норма

Вызов выполняется без видимой задержки

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

Форма подвисает — нужен перенос обработки на сервер целиком

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

Можно ли передать табличную часть в процедуру &НаСервереБезКонтекста?

Напрямую нет — в такой процедуре недоступен реквизит Объект. Передайте данные параметром: массив структур, собранный на клиенте, или таблицу значений, подготовленную в контекстной серверной процедуре формы, которая уже вызовет метод без контекста.

Что быстрее: массив структур или таблица значений?

Для небольших объёмов разница незаметна, выбирайте по удобству кода. На больших таблицах таблица значений обычно предпочтительнее: она компактнее при сериализации и удобнее для серверной обработки запросами и свёртками.

Как передать табличную часть внешней обработки на сервер?

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

Почему после Загрузить() пропали значения части колонок?

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

Можно ли изменить табличную часть на сервере без возврата в форму?

Да, если документ уже записан: получите объект по ссылке в серверном модуле, измените табличную часть и вызовите Записать(). Но учтите, что открытая у пользователя форма покажет старые данные, пока её не обновят или не перечитают.

Передаётся ли табличная часть при обычном вызове &НаСервере в модуле формы?

Формально данные формы доступны в серверной процедуре модуля формы, потому что платформа пересоздаёт контекст формы на сервере. Отдельно «передавать» табличную часть не нужно — работайте с Объект.Товары напрямую в этой процедуре.

Итог

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

ДанныеФормыКоллекция напрямую на сервер не передаётся: преобразуйте её в массив структур на клиенте или в таблицу значений через Выгрузить() в серверной процедуре формы. Для записи и проведения работайте с объектом целиком через РеквизитФормыВЗначение. Проверяйте состав колонок при обратной загрузке и не делайте серверный вызов на каждое изменение строки.