Как получить ОписаниеТипов и разрядность реквизита управляемой формы

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

В процессе разработки на платформе 1С:Предприятие 8 часто возникает задача: привести значение какой-либо переменной к формату, который задан для конкретного реквизита управляемой формы. Например, у нас есть числовой реквизит с точностью 3 знака после запятой, и мы хотим, чтобы наши промежуточные расчеты на клиенте соответствовали этой точности, не обращаясь каждый раз к серверу и не изменяя само значение реквизита формы. Рассмотрим подробнее, как это реализовать, учитывая архитектурные особенности управляемого приложения.

Почему нельзя получить ОписаниеТипов напрямую на клиенте?

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

Способ 1. Получение данных через перебор реквизитов на сервере

Если нам необходимо получить ОписаниеТипов в конкретный момент времени, мы можем воспользоваться методом ПолучитьРеквизиты(). Этот метод доступен только в серверном контексте и возвращает массив объектов РеквизитФормы. Разберем по шагам, как это работает.

Допустим, у нас есть реквизит с именем Цена. Нам нужно получить его тип и привести произвольное число к этому типу:


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

В данном примере метод ПривестиЗначение() является очень мощным инструментом. Он не просто округляет число, а учитывает все квалификаторы: Разрядность, РазрядностьДробнойЧасти и ДопустимыйЗнак. Если в метаданных указано "Неотрицательное", то отрицательное число превратится в ноль.

Способ 2. Получение конкретных квалификаторов числа

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


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

Способ 3. Оптимальный вариант: Кэширование параметров на клиенте

Постоянные вызовы сервера для получения точности — это плохая практика с точки зрения производительности. Чтобы работать на клиенте максимально быстро, выясним причину необходимости данных и подготовим их заранее. Выясним, как это сделать через кэширование в процедуре ПриСозданииНаСервере.

Шаг 1. Создадим на форме скрытый реквизит ПараметрыРеквизитов с типом Произвольный (на клиенте он станет объектом ФиксированноеСоответствие).

Шаг 2. Заполним его при инициализации формы:


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

Шаг 3. Теперь на клиенте мы можем мгновенно получить точность любого реквизита без серверных вызовов:


&НаКлиенте
Процедура РассчитатьСумму()
    
    ИсходноеЧисло = 125.456789;
    
    // Получаем точность из кэша
    Точность = ПараметрыРеквизитов["Цена"];
    
    Если Точность <> Неопределено Тогда
        Результат = Окр(ИсходноеЧисло, Точность);
        Сообщить("Округленное значение: " + Результат);
    КонецЕсли;
    
КонецПроцедуры

Альтернатива: Работа через метаданные объекта

Если реквизит формы напрямую связан с данными объекта (например, Объект.Количество), мы можем посмотреть настройки непосредственно в конфигурации. Рассмотрим пример получения разрядности дробной части через метаданные (также выполняется на сервере):


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

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

Резюме

Мы проанализировали ситуацию и выяснили, что получить ОписаниеТипов напрямую на клиенте невозможно. Однако, используя серверный контекст, мы можем либо разово вычислить нужные значения методом ПривестиЗначение(), либо (что более правильно) собрать данные о точности при открытии формы и сохранить их в переменную. Это позволит нам выполнять все последующие операции приведения типов на клиенте максимально эффективно и без лишних задержек.

← На главную