Как передать табличную часть с клиента на сервер в управляемых формах 1С

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Понимание типов данных: ДанныеФормыКоллекция vs ТаблицаЗначений

Прежде чем мы перейдем к коду, проанализируем фундаментальное различие. На клиенте и в контексте формы сервер оперирует типом ДанныеФормыКоллекция. Это специальный объект-обертка, который платформа использует для визуализации данных на форме. На сервере же (вне контекста формы или в общих модулях) мы привыкли работать с ТаблицаЗначений.

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

Способ 1. Контекстный серверный вызов (самый простой)

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

Рассмотрим пример, когда нам нужно рассчитать итоги или проверить данные перед выполнением клиентской логики:


&НаКлиенте
Процедура ОбработатьДанныеТЧ()
    // Вызываем контекстный серверный метод
    РезультатОбработки = ОбработатьТЧНаСервере();
    
    Если РезультатОбработки Тогда
        Сообщить("Данные успешно проверены!");
    КонецЕсли;
КонецПроцедуры

&НаСервере
Функция ОбработатьТЧНаСервере()
    // ТЧ доступна напрямую через Объект.ИмяТЧ
    Для Каждого СтрокаТЧ Из Объект.Товары Цикл
        // Производим необходимые вычисления
        Если СтрокаТЧ.Количество > 100 Тогда
            СтрокаТЧ.Цена = СтрокаТЧ.Цена * 0.9; // Применяем скидку
        КонецЕсли;
    КонецЦикла;
    
    Возврат Истина;
КонецФункции

Плюсы: Простота реализации, автоматическая обратная синхронизация изменений с клиентом.

Минусы: Передается весь контекст формы (все реквизиты, а не только ТЧ), что создает нагрузку на сеть при больших объемах данных.

Способ 2. Внеконтекстный серверный вызов и сериализация

Если мы хотим написать максимально производительный код, следует использовать &НаСервереБезКонтекста. Но в этом случае Объект недоступен, а тип ДанныеФормыКоллекция нельзя передать напрямую в параметры такой функции, так как он не является сериализуемым.

Разберем алгоритм решения через массив структур:

  1. На клиенте обходим табличную часть и заполняем массив структур (каждая структура — это строка ТЧ).
  2. Передаем массив на сервер.
  3. На сервере работаем с массивом или загружаем его в ТаблицаЗначений.

&НаКлиенте
Процедура ПередатьТЧБезКонтекста()
    МассивДанных = Новый Массив;
    
    Для Каждого СтрокаТЧ Из Объект.Товары Цикл
        СтруктураСтроки = Новый Структура("Номенклатура, Количество, Цена");
        ЗаполнитьЗначенияСвойств(СтруктураСтроки, СтрокаТЧ);
        МассивДанных.Добавить(СтруктураСтроки);
    КонецЦикла;
    
    // Передаем только нужные данные
    Результат = ОбработатьМассивНаСервере(МассивДанных);
КонецПроцедуры

&НаСервереБезКонтекста
Функция ОбработатьМассивНаСервере(ДанныеТЧ)
    // Здесь ДанныеТЧ — это Массив, содержащий Структуры
    // При необходимости можно создать таблицу значений
    ТЗ = Новый ТаблицаЗначений;
    ТЗ.Колонки.Добавить("Номенклатура", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));
    ТЗ.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число"));
    
    Для Каждого СтрИзМассива Из ДанныеТЧ Цикл
        НоваяСтр = ТЗ.Добавить();
        ЗаполнитьЗначенияСвойств(НоваяСтр, СтрИзМассива);
    КонецЦикла;
    
    // Выполняем бизнес-логику (запросы к ТЗ, свертку и т.д.)
    Возврат ТЗ.Итог("Количество");
КонецФункции

Способ 3. Преобразование ДанныеФормыВЗначение (Работа с объектом)

Часто на сервере требуется выполнить действия, доступные только для прикладных объектов (например, методы РассчитатьСумму(), определенные в модуле документа). Для этого внутри контекстного серверного вызова мы используем преобразование реквизитов формы в реальный объект базы данных (в памяти).

Выясним причину, почему это важно: ДанныеФормыКоллекция не имеет методов Свернуть(), НайтиСтроки() или Скопировать(). Если вам нужны эти функции, делайте так:


&НаСервере
Процедура ВыполнитьСложнуюОбработкуНаСервере()
    // 1. Конвертируем данные формы в объект документа
    ДокОбъект = РеквизитФормыВЗначение("Объект");
    
    // 2. Теперь ДокОбъект.Товары — это полноценная ТаблицаЗначений
    ДокОбъект.Товары.Свернуть("Номенклатура", "Количество, Сумма");
    
    // 3. Вызываем методы модуля объекта, если нужно
    ДокОбъект.РассчитатьСчетаУчета();
    
    // 4. Возвращаем изменения обратно на форму
    ЗначениеВРеквизитФормы(ДокОбъект, "Объект");
КонецПроцедуры

Анализируем типичную ошибку: «Нельзя изменять поле, содержащее объект данных формы»

Проанализируем ситуацию, описанную в сообщениях форума. Автор пытался передать Объект.ТабличнаяЧасть как параметр в серверную функцию и получил ошибку. Почему это происходит?

Когда вы передаете ДанныеФормыКоллекция в качестве параметра серверной процедуры, 1С пытается передать его «по ссылке». Если внутри сервера вы попытаетесь изменить этот параметр или присвоить ему новое значение, система заблокирует операцию, так как этот объект жестко связан с интерфейсным контекстом.

Решение: Всегда используйте ключевое слово Знач в описании параметров функции, если передаете туда коллекции данных формы.


&НаСервере
Функция МояПроверка(Знач ТаблицаПараметр) // Используем Знач!
    // Теперь внутри функции ТаблицаПараметр — это копия, 
    // и ошибка изменения поля не возникнет.
    Возврат ТаблицаПараметр.Количество() > 0;
КонецФункции

Практические советы по оптимизации

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

← На главную