Как избежать потери типа значения и квалификаторов колонки при работе с реквизитами формы

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

При разработке на управляемых формах 1С программисты часто сталкиваются с необходимостью динамического создания колонок в таблицах. Однако стандартные методы ЗначениеВРеквизитФормы и РеквизитФормыВЗначение могут преподнести неприятный сюрприз: после преобразования типы данных в колонках «сбрасываются», а квалификаторы (например, длина строки или разрядность числа) обнуляются. В этой статье мы подробно разберем, почему это происходит и как правильно передавать структуру таблицы, чтобы данные оставались целостными.

В чем заключается суть проблемы?

Рассмотрим типичную ситуацию: у нас есть объект ТаблицаЗначений (ТЗ), созданный программно на сервере. Мы определили в нем колонки, задали типы и ограничения. Затем мы пытаемся отобразить эту таблицу на форме, используя программное создание реквизитов. Проблема проявляется при попытке «вернуть» таблицу из реквизита формы обратно в объект ТаблицаЗначений. Выясняется, что колонка, которая должна была иметь тип Строка(10), превратилась в строку неограниченной длины, а число с точностью 2 знака стало целым числом.

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


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

На первый взгляд код выглядит логичным, но именно здесь кроется причина потери метаданных.

Почему теряются квалификаторы типов?

Разберем по шагам, что происходит в приведенном выше фрагменте. Объект Колонка.ТипЗначения уже является объектом типа ОписаниеТипов. Когда мы добавляем его в массив и передаем в конструктор Новый ОписаниеТипов(МассивТипов), платформа отрабатывает некорректно:

  1. Конструктор ОписаниеТипов ожидает в массиве список объектов типа Тип (например, Тип("Строка")), а не другие объекты ОписаниеТипов.
  2. При передаче «неправильного» массива платформа пытается извлечь типы, но полностью игнорирует вложенные квалификаторы (длину, точность, допустимый знак).
  3. В результате создается новое описание типа с параметрами «по умолчанию». Для строки это означает неограниченную длину, для числа — отсутствие дробной части.

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

Способ 1: Явное пересоздание квалификаторов

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


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

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

Этот метод надежен, но становится очень громоздким, если колонки имеют составные типы (например, когда в одной ячейке может быть и число, и ссылка на справочник).

Способ 2: Копирование ОписанияТипов (Рекомендуемый)

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

Проанализируем упрощенный и наиболее правильный вариант кода:


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

Важный момент: Конструктор Новый ОписаниеТипов(ИсходноеОписаниеТипов) — это самый эффективный способ дублирования метаданных без потери точности.

Особенности работы методов трансформации данных

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

Практические советы для разработчика

1. Проверяйте результат в отладчике. После выполнения ИзменитьРеквизиты посмотрите на свойство ЭтаФорма.ТаблицаДанных. В списке колонок должно быть четко указано ОписаниеТипов с заполненными квалификаторами. Если там стоят значения по умолчанию (0), значит, ошибка произошла на этапе создания РеквизитФормы.

2. Составные типы. Если вы работаете с составными типами, избегайте ручного перебора типов через СодержитТип. Используйте прямое копирование объекта ОписаниеТипов, как показано в Способе 2.

3. Использование БСП. Если в вашей конфигурации подключена Библиотека Стандартных Подсистем, обратите внимание на общие модули для работы с формами. В них часто есть готовые функции для приведения структуры одной таблицы к другой, которые уже учитывают все нюансы платформы.

Подведем итог: потеря типов происходит из-за неправильного использования конструктора ОписаниеТипов. Всегда передавайте либо массив чистых типов с явным указанием квалификаторов, либо копируйте существующее описание типа напрямую. Это обеспечит стабильную работу ваших динамических интерфейсов и сохранность данных при передаче между сервером и формой.

← На главную