При разработке на платформе 1С:Предприятие 8.3 начинающие разработчики часто сталкиваются с проблемой взаимодействия между клиентской и серверной частью приложения. Типичная ситуация: на клиенте собраны данные в объект Структура, и их необходимо добавить в объект ТаблицаЗначений, который находится на сервере. Однако при попытке прямой передачи возникают ошибки вроде "Переменная не определена" или данные просто "теряются".
В этой статье мы подробно разберем, как правильно организовать этот процесс, выясним причины типичных ошибок и рассмотрим несколько эффективных способов решения задачи.
Проанализируем ситуацию, описанную в первом сообщении темы. Автор пытается обратиться к структуре, созданной на клиенте, внутри серверной процедуры так, будто она доступна там автоматически. Это основное заблуждение. Процедура с директивой &НаСервере "видит" только три категории данных:
Если вы создали переменную МояСтруктура в клиентском обработчике нажатия кнопки, серверная процедура не будет знать о её существовании, пока вы не передадите её как аргумент. Именно поэтому возникает ошибка "Переменная не определена".
Если ваша задача — накапливать данные, введенные пользователем, и отображать их в таблице на форме, то использование программного объекта ТаблицаЗначений на сервере часто является избыточным. Платформа предлагает специальный тип данных — ДанныеФормыКоллекция.
Рассмотрим алгоритм работы через реквизит формы:
ТаблицаЗначений (назовем его ТЗДанные) и добавим в него нужные колонки.Посмотрим на пример кода, который выполняет эту задачу без лишних серверных вызовов:
&НаКлиенте
Процедура ДобавитьДанныеВТаблицу(Команда)
// Подготовим данные из реквизитов формы (например, ФИО и Возраст)
НоваяСтрока = ТЗДанные.Добавить();
НоваяСтрока.ФИО = Объект.ФИО_Реквизит;
НоваяСтрока.Возраст = Объект.Возраст_Реквизит;
// Данные уже в таблице и будут переданы на сервер автоматически при записи
КонецПроцедуры
Этот способ оптимален, так как ДанныеФормыКоллекция доступны и на клиенте, и на сервере. Вам не нужно писать функции преобразования.
Иногда требуется обработать данные именно в объекте ТаблицаЗначений (например, для использования в запросе или сложного поиска). В этом случае нам нужно передать структуру на сервер и там заполнить таблицу.
Выясним, как правильно передать параметры. Рассмотрим пример вызова серверной процедуры:
&НаКлиенте
Процедура КнопкаДобавитьНаСервер(Команда)
// 1. Формируем структуру на клиенте
ДанныеДляПередачи = Новый Структура;
ДанныеДляПередачи.Вставить("ФИО", Объект.ФИО);
ДанныеДляПередачи.Вставить("Частота", Объект.Частота);
// 2. Вызываем серверную процедуру, ПЕРЕДАВАЯ структуру в параметрах
ДобавитьВТаблицуНаСервере(ДанныеДляПередачи);
КонецПроцедуры
&НаСервере
Процедура ДобавитьВТаблицуНаСервере(СтруктураСКлиента)
// Здесь мы создаем или получаем ТЗ.
// Помните: локальная ТЗ в этой процедуре удалится после завершения работы!
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("ФИО");
ТЗ.Колонки.Добавить("Частота");
НоваяСтрока = ТЗ.Добавить();
// Используем универсальный метод заполнения
ЗаполнитьЗначенияСвойств(НоваяСтрока, СтруктураСКлиента);
// Дальнейшая логика (например, поиск или сохранение в БД)
КонецПроцедуры
Если данных много, эффективнее передавать не одну структуру, а массив структур. Разберем продвинутый метод создания таблицы значений с динамическим созданием колонок и типизацией.
Проанализируем следующий код:
&НаСервере
Функция ПреобразоватьМассивВТаблицуЗначений(МассивСтруктур)
Таблица = Новый ТаблицаЗначений;
Если МассивСтруктур.Количество() = 0 Тогда
Возврат Таблица;
КонецЕсли;
// Создадим колонки динамически по первой структуре
ПерваяСтруктура = МассивСтруктур[0];
Для Каждого Свойство Из ПерваяСтруктура Цикл
// Важно: типизируем колонку для стабильной работы
ТипЗначения = ТипЗнч(Свойство.Значение);
Таблица.Колонки.Добавить(Свойство.Ключ, Новый ОписаниеТипов(ТипЗначения));
КонецЦикла;
// Заполняем таблицу данными
Для Каждого ТекущаяСтруктура Из МассивСтруктур Цикл
НоваяСтрока = Таблица.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, ТекущаяСтруктура);
КонецЦикла;
Возврат Таблица;
КонецФункции
Важный нюанс: при добавлении колонок через Таблица.Колонки.Добавить крайне рекомендуется использовать ОписаниеТипов. Если этого не сделать, колонки будут иметь тип "Произвольный", что может вызвать ошибки при выводе этой таблицы в интерфейс или при выполнении запросов к ней.
В сообщении 5 форума прозвучала важная мысль: "ТЗ не может храниться на сервере". Это означает, что переменная типа ТаблицаЗначений, созданная внутри серверной процедуры, уничтожается сразу после слова КонецПроцедуры. Если вам нужно сохранить данные между нажатиями кнопок, у вас есть два пути:
АдресХранилища = ПоместитьВоВременноеХранилище(МояТЗ, УникальныйИдентификатор);
При следующем вызове вы сможете получить её обратно по этому адресу.Если ваша таблица будет содержать сотни или тысячи строк (например, список сотрудников), и вы планируете искать в ней данные по ФИО, как упоминалось в сообщении 12, обязательно используйте индексацию. Это значительно ускорит работу серверного кода.
Рассмотрим пример создания индекса:
&НаСервере
Процедура НайтиДанныеВТЗ(ИскомоеФИО)
// Предположим, ТЗ уже заполнена
ТЗ.Индексы.Добавить("ФИО");
ПараметрыПоиска = Новый Структура("ФИО", ИскомоеФИО);
НайденныеСтроки = ТЗ.НайтиСтроки(ПараметрыПоиска);
Если НайденныеСтроки.Количество() > 0 Тогда
// Обработка результата
КонецЕсли;
КонецПроцедуры
Для успешной передачи данных из структуры на клиенте в таблицу на сервере мы должны придерживаться следующих правил:
ТаблицаЗначений — создавать его на сервере и заполнять через ЗаполнитьЗначенияСвойств.Соблюдение этих архитектурных принципов платформы 1С позволит вам избежать ошибок неопределенных переменных и обеспечит высокую производительность вашего кода.