Как сохранить тип СправочникСсылка при выгрузке из ДанныеФормыКоллекция в ТаблицуЗначений?

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

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

Рассмотрим детально, почему это происходит, и разберем правильные подходы к решению этой задачи.

Анализ основной ошибки: коварство метода Выгрузить()

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


ВТ = Новый ТаблицаЗначений;
НоменклатураТип = Новый ОписаниеТипов("СправочникСсылка.Номенклатура");
ВТ.Колонки.Добавить("Наименование", НоменклатураТип, "Наименование (у поставщика)");

На первый взгляд, все верно. Однако далее следует строка кода, которая полностью перечеркивает предыдущие действия:

ВТ = ВыборВЗаказ.Выгрузить(,"Наименование,Цена,Выбран");

Разберем, что здесь происходит с точки зрения платформы. Метод Выгрузить() для объекта ДанныеФормыКоллекция (которым является таблица на форме) не заполняет существующий объект, переданный в переменную, а создает новый экземпляр типа ТаблицаЗначений. В момент выполнения присваивания ВТ = ... ссылка на ту таблицу, которую мы так тщательно типизировали, теряется. Вместо нее в переменную ВТ записывается новая таблица, структура которой полностью определяется метаданными реквизита формы ВыборВЗаказ.

Если в реквизитах формы колонка "Наименование" имела тип Строка, то и в выгруженной таблице она будет строкой. Именно поэтому предварительное создание колонок в данном контексте бесполезно.

Проверка метаданных исходных данных

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

Важный момент: Если в колонке на форме отображается название номенклатуры, это еще не значит, что там хранится ссылка. Проверьте свойства реквизита формы (в дереве реквизитов, а не в элементах формы). Если там указана Строка, то метод Выгрузить() всегда будет возвращать строку.

Чтобы исправить это на уровне интерфейса:

  1. Найдите соответствующий реквизит формы (коллекцию).
  2. Выберите нужную колонку.
  3. В свойстве "Тип" установите СправочникСсылка.Номенклатура вместо Строка.

Корректная передача таблицы значений в запрос

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


Запрос = Новый Запрос;
// Выгружаем только нужные колонки сразу в параметр запроса
Запрос.УстановитьПараметр("Таблица", ВыборВЗаказ.Выгрузить(, "Наименование, Цена, Выбран"));

Запрос.Текст = 
"ВЫБРАТЬ
|	Таблица.Наименование КАК Наименование,
|	Таблица.Цена КАК Цена,
|	Таблица.Выбран КАК Выбран
|ПОМЕСТИТЬ ВТ_Данные
|ИЗ
|	&Таблица КАК Таблица
|;
|// Дальнейшая работа с временной таблицей";

При таком подходе платформа автоматически создаст временную таблицу с типами, которые соответствуют типам колонок в ДанныеФормыКоллекция.

Что делать, если изменить тип на форме невозможно?

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

Проанализируем алгоритм «ручного» переноса с приведением типов:


// 1. Создаем таблицу с жесткой типизацией
ВТ = Новый ТаблицаЗначений;
НоменклатураТип = Новый ОписаниеТипов("СправочникСсылка.Номенклатура");
ВТ.Колонки.Добавить("Номенклатура", НоменклатураТип);
ВТ.Колонки.Добавить("Цена", Новый ОписаниеТипов("Число"));

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

// 3. Теперь ВТ можно смело передавать в запрос
Запрос.УстановитьПараметр("Таблица", ВТ);

Этот способ более трудозатратный для сервера, но он гарантирует, что в запрос попадет именно СправочникСсылка, а не текст.

Особенности типизации для временных таблиц

Посмотрим на ситуацию со стороны СУБД. Когда мы используем конструкцию ПОМЕСТИТЬ во временную таблицу, передавая туда таблицу значений, 1С должна создать реальную таблицу в базе данных (SQL). Для этого ей нужно точно знать длину строк, точность чисел и типы ссылок.

Если в колонке ТЗ будет содержаться составной тип или тип ЛюбаяСсылка, выполнение запроса может завершиться ошибкой или привести к крайне низкой производительности. Поэтому хорошей практикой считается:

Использование метода ДанныеФормыВЗначение

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

Разберем пример:


// Допустим, Объект - это реквизит формы с типом ДокументОбъект
ДокументОбъект = ДанныеФормыВЗначение(Объект, Тип("ДокументОбъект.ЗаказПокупателя"));
ТаблицаДляЗапроса = ДокументОбъект.Товары.Выгрузить();
// В ТаблицаДляЗапроса все типы колонок будут соответствовать метаданным документа

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

Краткие выводы и рекомендации

Подведем итог нашему разбору. Чтобы не "терять" ссылки при работе с таблицами значений на управляемых формах:

  1. Проверьте первоисточник: убедитесь, что в реквизитах формы у колонки установлен тип СправочникСсылка, а не Строка.
  2. Не переприсваивайте объект: помните, что ТЗ = Коллекция.Выгрузить() создает новую таблицу. Старая переменная со всеми настройками типов будет затерта.
  3. Используйте прямую передачу: если типы верны, передавайте результат Выгрузить() прямо в параметр запроса.
  4. Приводите типы вручную: если данные на форме — это строки, преобразуйте их в ссылки (через поиск или GUID) перед помещением в таблицу для запроса.

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

← На главную