Как передать данные из структуры на клиенте в таблицу значений на сервере в 1С?

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

При разработке на платформе 1С:Предприятие 8.3 начинающие разработчики часто сталкиваются с проблемой взаимодействия между клиентской и серверной частью приложения. Типичная ситуация: на клиенте собраны данные в объект Структура, и их необходимо добавить в объект ТаблицаЗначений, который находится на сервере. Однако при попытке прямой передачи возникают ошибки вроде "Переменная не определена" или данные просто "теряются".

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

Разбор основной ошибки: Область видимости и контекст

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

  1. Реквизиты формы (если процедура контекстная).
  2. Параметры, которые были явно переданы в процедуру при её вызове.
  3. Глобальные переменные серверных модулей (что используется редко).

Если вы создали переменную МояСтруктура в клиентском обработчике нажатия кнопки, серверная процедура не будет знать о её существовании, пока вы не передадите её как аргумент. Именно поэтому возникает ошибка "Переменная не определена".

Решение №1: Использование реквизитов формы (рекомендуемый способ)

Если ваша задача — накапливать данные, введенные пользователем, и отображать их в таблице на форме, то использование программного объекта ТаблицаЗначений на сервере часто является избыточным. Платформа предлагает специальный тип данных — ДанныеФормыКоллекция.

Рассмотрим алгоритм работы через реквизит формы:

  1. Создадим в редакторе формы реквизит с типом ТаблицаЗначений (назовем его ТЗДанные) и добавим в него нужные колонки.
  2. Вынесем эту таблицу на форму, чтобы пользователь видел результат.
  3. На клиенте будем добавлять данные напрямую в этот реквизит.

Посмотрим на пример кода, который выполняет эту задачу без лишних серверных вызовов:


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

Этот способ оптимален, так как ДанныеФормыКоллекция доступны и на клиенте, и на сервере. Вам не нужно писать функции преобразования.

Решение №2: Передача структуры как параметра и создание ТЗ на сервере

Иногда требуется обработать данные именно в объекте ТаблицаЗначений (например, для использования в запросе или сложного поиска). В этом случае нам нужно передать структуру на сервер и там заполнить таблицу.

Выясним, как правильно передать параметры. Рассмотрим пример вызова серверной процедуры:


&НаКлиенте
Процедура КнопкаДобавитьНаСервер(Команда)
    
    // 1. Формируем структуру на клиенте
    ДанныеДляПередачи = Новый Структура;
    ДанныеДляПередачи.Вставить("ФИО", Объект.ФИО);
    ДанныеДляПередачи.Вставить("Частота", Объект.Частота);
    
    // 2. Вызываем серверную процедуру, ПЕРЕДАВАЯ структуру в параметрах
    ДобавитьВТаблицуНаСервере(ДанныеДляПередачи);
    
КонецПроцедуры

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

Решение №3: Массовое преобразование (Массив структур в ТЗ)

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

Проанализируем следующий код:


&НаСервере
Функция ПреобразоватьМассивВТаблицуЗначений(МассивСтруктур)
    
    Таблица = Новый ТаблицаЗначений;
    
    Если МассивСтруктур.Количество() = 0 Тогда
        Возврат Таблица;
    КонецЕсли;
    
    // Создадим колонки динамически по первой структуре
    ПерваяСтруктура = МассивСтруктур[0];
    Для Каждого Свойство Из ПерваяСтруктура Цикл
        // Важно: типизируем колонку для стабильной работы
        ТипЗначения = ТипЗнч(Свойство.Значение);
        Таблица.Колонки.Добавить(Свойство.Ключ, Новый ОписаниеТипов(ТипЗначения));
    КонецЦикла;
    
    // Заполняем таблицу данными
    Для Каждого ТекущаяСтруктура Из МассивСтруктур Цикл
        НоваяСтрока = Таблица.Добавить();
        ЗаполнитьЗначенияСвойств(НоваяСтрока, ТекущаяСтруктура);
    КонецЦикла;
    
    Возврат Таблица;
    
КонецФункции

Важный нюанс: при добавлении колонок через Таблица.Колонки.Добавить крайне рекомендуется использовать ОписаниеТипов. Если этого не сделать, колонки будут иметь тип "Произвольный", что может вызвать ошибки при выводе этой таблицы в интерфейс или при выполнении запросов к ней.

Как хранить таблицу значений на сервере?

В сообщении 5 форума прозвучала важная мысль: "ТЗ не может храниться на сервере". Это означает, что переменная типа ТаблицаЗначений, созданная внутри серверной процедуры, уничтожается сразу после слова КонецПроцедуры. Если вам нужно сохранить данные между нажатиями кнопок, у вас есть два пути:

  1. Временное хранилище: Вы можете поместить ТЗ в хранилище и передать адрес на клиент. АдресХранилища = ПоместитьВоВременноеХранилище(МояТЗ, УникальныйИдентификатор); При следующем вызове вы сможете получить её обратно по этому адресу.
  2. Реквизит формы: Как мы уже обсуждали, это самый надежный способ для работы в рамках одной формы. Данные в реквизитах формы сохраняются на протяжении всей жизни формы.

Оптимизация: Использование индексов

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

Рассмотрим пример создания индекса:


&НаСервере
Процедура НайтиДанныеВТЗ(ИскомоеФИО)
    // Предположим, ТЗ уже заполнена
    ТЗ.Индексы.Добавить("ФИО"); 
    
    ПараметрыПоиска = Новый Структура("ФИО", ИскомоеФИО);
    НайденныеСтроки = ТЗ.НайтиСтроки(ПараметрыПоиска);
    
    Если НайденныеСтроки.Количество() > 0 Тогда
        // Обработка результата
    КонецЕсли;
КонецПроцедуры

Подведем итоги

Для успешной передачи данных из структуры на клиенте в таблицу на сервере мы должны придерживаться следующих правил:

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

← На главную