При разработке расширений в системе 1С:Предприятие 8.3 программисты часто сталкиваются с необходимостью изменить структуру данных, например, увеличить точность числового поля (разрядность дробной части) с 1 знака до 3. Ситуация осложняется, когда элементы формы или сами реквизиты создаются программно в коде расширения или заимствованной формы. В такой ситуации простого изменения в дереве метаданных расширения бывает недостаточно, так как программный код может переопределять типы данных "на лету". Для этой задачи можно использовать методику динамического изменения управляемых форм в расширении.
В этой статье мы подробно разберем, как правильно изменить разрядность числа, почему возникают ошибки при попытке прямого изменения свойств типа и как корректно инициализировать программные реквизиты с новыми квалификаторами.
Рассмотрим стандартную ситуацию: у нас есть документ, добавленный в расширение. Мы увеличили точность реквизита в основной конфигурации и в расширении, добились того, чтобы расширение подключалось без ошибок (соответствие типов соблюдено), но в режиме "1С:Предприятие" точность в табличной части осталась прежней. Проанализируем причину: это происходит потому, что реквизиты формы или элементы интерфейса создаются динамически через метод ИзменитьРеквизиты().
Когда реквизит создается программно, в его конструктор передается объект ОписаниеТипов. Если этот объект берется из существующего реквизита объекта (который еще не обновился в памяти или имеет свои особенности заимствования), то он сохраняет старые квалификаторы (например, 1 знак после запятой вместо 3).
Типичная ошибка начинающего разработчика — попытка обратиться к свойствам типа напрямую и перезаписать их. Посмотрим на этот пример кода:
Если Реквизит.Имя = "Количество" Или Реквизит.Имя = "КоличествоСклад" Тогда
// Попытка прямого изменения — вызовет ошибку "Поле объекта не доступно для записи"
Реквизит.Тип.КвалификаторыЧисла.РазрядностьДробнойЧасти = 3;
КонецЕсли;
Важно помнить: объекты ОписаниеТипов и КвалификаторыЧисла в 1С являются неизменяемыми после создания. Вы не можете просто зайти в свойство существующего типа и поменять его параметры. Единственный верный способ — создать новый объект ОписаниеТипов с нужными параметрами и заменить им старый при создании реквизита формы.
Разберем правильный алгоритм действий. Для того чтобы изменить точность программно создаваемого реквизита, нам нужно выполнить следующие шаги:
ОписаниеТипов на основе этих квалификаторов.РеквизитФормы.Рассмотрим реализацию в коде. Обратите внимание на синтаксис конструктора КвалификаторыЧисла: параметры передаются через запятую, а не через точку.
// 1. Создаем квалификаторы числа: общая длина 15, точность 3, только положительное
НовыеКвалификаторы = Новый КвалификаторыЧисла(15, 3, ДопустимыйЗнак.Неотрицательный);
// 2. Формируем новое описание типов
ТипЧисло = Новый ОписаниеТипов("Число", , , НовыеКвалификаторы);
// 3. Добавляем в массив реквизитов для метода ИзменитьРеквизиты
МассивРеквизитов = Новый Массив;
Если Реквизит.Имя = "Количество" Тогда
// Используем созданный нами ТипЧисло вместо стандартного Реквизит.Тип
МассивРеквизитов.Добавить(Новый РеквизитФормы(Реквизит.Имя, ТипЧисло, "ВашПутьКДанным", "Синоним"));
Иначе
МассивРеквизитов.Добавить(Новый РеквизитФормы(Реквизит.Имя, Реквизит.Тип, "ВашПутьКДанным", "Синоним"));
КонецЕсли;
// Применяем изменения на форме
ЭтаФорма.ИзменитьРеквизиты(МассивРеквизитов);
Даже если тип данных в реквизите формы теперь позволяет хранить 3 знака после запятой, само ПолеФормы (визуальный элемент) может быть настроено на отображение только одного знака. Выясним, как это исправить программно при создании элемента формы:
// Создаем элемент формы
НовыйЭлемент = Элементы.Добавить("Количество", Тип("ПолеФормы"), ГруппаРодитель);
НовыйЭлемент.Вид = ВидПоляФормы.ПолеВвода;
НовыйЭлемент.ПутьКДанным = "Объект.Товары.Количество";
// Устанавливаем формат отображения и редактирования
// ЧЦ (Число цифр) = 15, ЧДЦ (Число десятичных цифр) = 3
НовыйЭлемент.Формат = "ЧЦ=15; ЧДЦ=3";
НовыйЭлемент.ФорматРедактирования = "ЧЦ=15; ЧДЦ=3";
Без установки свойств Формат и ФорматРедактирования платформа может использовать настройки по умолчанию из метаданных, что приведет к визуальному округлению значения при вводе, даже если сам реквизит поддерживает большую точность.
В некоторых случаях, если вы меняете тип уже существующего на форме реквизита (через удаление и добавление), полезно принудительно привести текущее значение к новому типу, чтобы избежать конфликтов при записи данных в объект.
// Пример приведения значения
ТипЧисло = Новый ОписаниеТипов("Число",,, Новый КвалификаторыЧисла(10, 3));
Элементы.Реквизит1.ОграничениеТипа = ТипЧисло;
Объект.Реквизит1 = ТипЧисло.ПривестиЗначение(Объект.Реквизит1);
Метод ПривестиЗначение() гарантирует, что переменная будет содержать число именно с теми квалификаторами, которые мы задали, отсекая лишние знаки или дополняя их нулями.
Проанализировав ситуацию, можно сделать вывод: при работе в расширениях 1С всегда проверяйте, как именно создаются реквизиты. Если они заимствованы визуально — меняйте свойства в дереве метаданных расширения. Если они создаются в коде (особенно в процедурах типа ПриСозданииНаСервере) — используйте создание нового объекта ОписаниеТипов.
Основные правила:
КвалификаторыЧисла у существующего типа — они только для чтения.Новый КвалификаторыЧисла(Длина, Точность).Формат у элементов формы, иначе пользователь не увидит введенные сотые и тысячные доли.Следуя этим шагам, вы сможете гибко управлять точностью данных в расширениях 1С, избегая ошибок совместимости и проблем с отображением информации в интерфейсе.