Описание типов 1С — объект ОписаниеТипов: список допустимых типов вместе с ограничениями — разрядностью числа, длиной строки, составом даты. Его возвращает свойство Тип у реквизитов в метаданных, его принимают колонки таблицы значений и реквизиты формы, а метод ПривестиЗначение превращает произвольное значение в значение нужного типа без исключений.
Ниже — оба конструктора, квалификаторы, таблица результатов приведения, составной тип и тип реквизита из метаданных. Проверка типа отдельного значения через ТипЗнч разобрана в статье о типе значения. Код рассчитан на общий модуль с флажком «Сервер», кроме примера формы.
Конструкторов два. Первый принимает типы — строкой или массивом — и квалификаторы. Второй берёт готовое описание и добавляет или вычитает типы. Какой сработает, платформа решает по первому параметру: строка или массив — первый, ОписаниеТипов — второй.
// Общий модуль РаботаСТипамиСервер (флажок «Сервер»)
// Набор описаний типов для обработки загрузки: создаётся один раз и переиспользуется.
Функция ОписанияТиповЗагрузки() Экспорт
Набор = Новый Структура;
// 1. По строке: имена типов через запятую
Набор.Вставить("Количество", Новый ОписаниеТипов("Число"));
Набор.Вставить("КодИлиНомер", Новый ОписаниеТипов("Число, Строка"));
Набор.Вставить("Контрагент", Новый ОписаниеТипов("СправочникСсылка.Контрагенты"));
// 2. По массиву значений типа Тип
МассивТипов = Новый Массив;
МассивТипов.Добавить(Тип("СправочникСсылка.Контрагенты"));
МассивТипов.Добавить(Тип("СправочникСсылка.Организации"));
Набор.Вставить("Сторона", Новый ОписаниеТипов(МассивТипов));
// 3. С квалификаторами: 2-й параметр - число, 3-й - строка, 4-й - дата
Набор.Вставить("Сумма", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 2)));
Набор.Вставить("Артикул", Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(25)));
Набор.Вставить("День", Новый ОписаниеТипов("Дата", , , Новый КвалификаторыДаты(ЧастиДаты.Дата)));
// 4. На основе другого описания: добавить тип, вычесть тип
Набор.Вставить("СторонаИлиТекст", Новый ОписаниеТипов(Набор.Сторона, "Строка"));
Набор.Вставить("ТолькоОрганизация",
Новый ОписаниеТипов(Набор.Сторона, , "СправочникСсылка.Контрагенты"));
// 5. На основе другого описания: заменить квалификатор строки (5-я позиция)
Набор.Вставить("АртикулДлинный",
Новый ОписаниеТипов(Набор.Артикул, , , , Новый КвалификаторыСтроки(100)));
Возврат Набор;
КонецФункции
Процедура ПроверитьОписанияТипов() Экспорт
Набор = ОписанияТиповЗагрузки();
Сообщить(Набор.СторонаИлиТекст.Типы().Количество()); // 3
Сообщить(Набор.ТолькоОрганизация.Типы().Количество()); // 1
Сообщить(Набор.АртикулДлинный.КвалификаторыСтроки.Длина); // 100
КонецПроцедуры
Тип(): Число, Строка, Дата, Булево, СправочникСсылка.Имя, ДокументСсылка.Имя, ПеречислениеСсылка.Имя.Тип удобен, когда список собирается в цикле.Новый КвалификаторыЧисла(Разрядность, РазрядностьДробнойЧасти, ДопустимыйЗнак). Разрядность — все цифры вместе с дробной частью: Число(15, 2) вмещает 13 цифр до запятой. Знак — ДопустимыйЗнак.Любой (по умолчанию) или ДопустимыйЗнак.Неотрицательный.Новый КвалификаторыСтроки(Длина, ДопустимаяДлина). Длина 0 — неограниченная строка. ДопустимаяДлина.Переменная — по умолчанию, Фиксированная — для кодов постоянной длины вроде КПП.Новый КвалификаторыДаты(ЧастиДаты): ЧастиДаты.Дата, ЧастиДаты.Время или ЧастиДаты.ДатаВремя (по умолчанию).Читаются квалификаторы через одноимённые свойства описания. Функция ниже собирает их в текст для журнала загрузки или сообщения пользователю.
// Общий модуль РаботаСТипамиСервер (флажок «Сервер»)
// Возвращает ограничения описания типов текстом: "Число(10, 3), неотрицательное" и т.п.
Функция ПредставлениеОграничений(Описание) Экспорт
Части = Новый Массив;
Если Описание.СодержитТип(Тип("Число")) Тогда
КЧ = Описание.КвалификаторыЧисла;
Части.Добавить(СтрШаблон("Число(%1, %2)%3", КЧ.Разрядность, КЧ.РазрядностьДробнойЧасти,
?(КЧ.ДопустимыйЗнак = ДопустимыйЗнак.Неотрицательный, ", неотрицательное", "")));
КонецЕсли;
Если Описание.СодержитТип(Тип("Строка")) Тогда
КС = Описание.КвалификаторыСтроки;
Части.Добавить(СтрШаблон("Строка(%1)%2",
?(КС.Длина = 0, "неограниченная", XMLСтрока(КС.Длина)),
?(КС.ДопустимаяДлина = ДопустимаяДлина.Фиксированная, ", фиксированная", "")));
КонецЕсли;
Если Описание.СодержитТип(Тип("Дата")) Тогда
ЧД = Описание.КвалификаторыДаты.ЧастиДаты;
Если ЧД = ЧастиДаты.Дата Тогда
Части.Добавить("Дата без времени");
ИначеЕсли ЧД = ЧастиДаты.Время Тогда
Части.Добавить("Время");
Иначе
Части.Добавить("Дата и время");
КонецЕсли;
КонецЕсли;
Возврат СтрСоединить(Части, "; ");
КонецФункции
Процедура ПоказатьКвалификаторы() Экспорт
ТипВес = Новый ОписаниеТипов("Число",
Новый КвалификаторыЧисла(10, 3, ДопустимыйЗнак.Неотрицательный));
ТипКПП = Новый ОписаниеТипов("Строка", ,
Новый КвалификаторыСтроки(9, ДопустимаяДлина.Фиксированная));
ТипВремя = Новый ОписаниеТипов("Дата", , ,
Новый КвалификаторыДаты(ЧастиДаты.Время));
Сообщить(ПредставлениеОграничений(ТипВес)); // Число(10, 3), неотрицательное
Сообщить(ПредставлениеОграничений(ТипКПП)); // Строка(9), фиксированная
Сообщить(ПредставлениеОграничений(ТипВремя)); // Время
КонецПроцедуры
Квалификатор действует только на свой тип, поэтому функция сначала проверяет СодержитТип: длина строки ничего не значит, если строки в описании нет. XMLСтрока выводит длину без пробела между разрядами. В конфигурациях на БСП есть готовые обёртки: ОбщегоНазначения.ОписаниеТипаСтрока(100), ОбщегоНазначения.ОписаниеТипаЧисло(15, 2), ОбщегоНазначения.ОписаниеТипаДата(ЧастиДаты.Дата).
Если тип значения входит в описание, ПривестиЗначение применяет к нему квалификаторы. Если не входит — пробует преобразовать, а при неудаче возвращает пустое значение типа. Исключений метод не вызывает.
// Общий модуль РаботаСТипамиСервер (флажок «Сервер»)
Процедура ПроверитьПриведение() Экспорт
ТипЧисло = Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(5, 2));
ТипКод = Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(5));
ТипДень = Новый ОписаниеТипов("Дата", , , Новый КвалификаторыДаты(ЧастиДаты.Дата));
ТипТовар = Новый ОписаниеТипов("СправочникСсылка.Номенклатура");
Сообщить(ТипЧисло.ПривестиЗначение("12.5")); // 12,5
Сообщить(ТипЧисло.ПривестиЗначение("12 шт")); // 0, исключения нет
Сообщить(ТипЧисло.ПривестиЗначение(3.14159)); // 3,14
Сообщить(ТипКод.ПривестиЗначение("АБВГДЕЖ")); // АБВГД
Сообщить(ТипДень.ПривестиЗначение('20261001153000')); // 01.10.2026 0:00:00
// Пустое значение нужного типа
ПустойКод = ТипКод.ПривестиЗначение(Неопределено);
ПустойТовар = ТипТовар.ПривестиЗначение(Неопределено);
Сообщить(ПустойКод = ""); // Да
Сообщить(ПустойТовар = Справочники.Номенклатура.ПустаяСсылка()); // Да
// Ссылка другого справочника превращается в пустую ссылку нужного типа
Выборка = Справочники.Контрагенты.Выбрать();
Если Выборка.Следующий() Тогда
Сообщить(ТипТовар.ПривестиЗначение(Выборка.Ссылка) = ПустойТовар); // Да
КонецЕсли;
КонецПроцедуры
"12.5" становится числом, "12 шт" — нулём. Для загрузки это удобно, для контроля опасно: ноль и мусор неотличимы.ПривестиЗначение(Неопределено) — короткий способ получить пустое значение типа.| Описание типов | Значение | Результат |
|---|---|---|
| Число | "125" | 125 |
| Число | "12 шт" | 0 |
| Число | Неопределено | 0 |
| Число(5, 2) | 10.456 | 10.46 — округление до разрядности |
| Число(3, 0) | 12345 | 999 — максимум, который помещается |
| Число(10, 2), неотрицательное | -5 | 0 |
| Строка(5) | "АБВГДЕЖ" | "АБВГД" |
| Строка(5), фиксированная | "АБ" | "АБ" и три пробела — дополнена до длины 5 |
| Строка | 1234.5 | "1 234,5" — как у функции Строка() |
| Строка | Неопределено | пустая строка |
| Дата (ЧастиДаты.Дата) | 01.10.2026 15:30:00 | 01.10.2026 0:00:00 |
| Дата (ЧастиДаты.Время) | 01.10.2026 15:30:00 | 01.01.0001 15:30:00 |
| СправочникСсылка.Номенклатура | "Стол" | пустая ссылка |
| СправочникСсылка.Номенклатура | ссылка на контрагента | пустая ссылка номенклатуры |
| Число, Строка | "12" | "12" — строка допустима, преобразования нет |
Последняя строка таблицы — ловушка составного типа: строка уже допустима, поэтому в число она не превращается. Нужно число — приводите к описанию с одним типом.
Составной тип — описание, где типов больше одного; в коде это Типы().Количество() > 1. Типы() возвращает массив значений Тип, причём порядок задаёт платформа, а не строка конструктора. СодержитТип(Тип) отвечает, входит ли тип в описание.
// Общий модуль РаботаСТипамиСервер (флажок «Сервер»)
// Раскладывает описание типов на ссылочные и прочие типы.
Функция СоставОписанияТипов(Описание) Экспорт
Результат = Новый Структура;
Результат.Вставить("Составной", Описание.Типы().Количество() > 1);
Результат.Вставить("Ссылочные", Новый Массив);
Результат.Вставить("Прочие", Новый Массив);
Для Каждого ТекущийТип Из Описание.Типы() Цикл
ОбъектМетаданных = Метаданные.НайтиПоТипу(ТекущийТип);
Если ОбъектМетаданных = Неопределено Тогда
Результат.Прочие.Добавить(Строка(ТекущийТип));
Иначе
Результат.Ссылочные.Добавить(ОбъектМетаданных.ПолноеИмя());
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
// Вызывает исключение, если тип значения не входит в описание типов.
Процедура ПроверитьТипПараметра(Значение, ДопустимыеТипы, ИмяПараметра) Экспорт
Если Не ДопустимыеТипы.СодержитТип(ТипЗнч(Значение)) Тогда
ВызватьИсключение СтрШаблон("Параметр %1: тип %2 не входит в допустимые",
ИмяПараметра, ТипЗнч(Значение));
КонецЕсли;
КонецПроцедуры
Процедура ПримерСоставногоТипа() Экспорт
ТипСубконто = Новый ОписаниеТипов("Число, Строка, СправочникСсылка.Контрагенты");
Состав = СоставОписанияТипов(ТипСубконто);
Сообщить(Состав.Составной); // Да
Сообщить(СтрСоединить(Состав.Ссылочные, ", ")); // Справочник.Контрагенты
Сообщить(СтрСоединить(Состав.Прочие, ", ")); // Число, Строка (порядок задаёт платформа)
Попытка
ПроверитьТипПараметра(ТекущаяДатаСеанса(), ТипСубконто, "Субконто");
Исключение
Сообщить(ОписаниеОшибки()); // ...Параметр Субконто: тип Дата не входит в допустимые
КонецПопытки;
КонецПроцедуры
Метаданные.НайтиПоТипу возвращает объект метаданных для ссылочного типа и Неопределено для примитивного — по этому признаку типы делятся на группы.ПроверитьТипПараметра принимает описание целиком, поэтому одинаково проверяет одиночный и составной тип. Для определяемого типа передайте Метаданные.ОпределяемыеТипы.Имя.Тип.Свойство Тип у реквизита, реквизита табличной части, измерения и ресурса регистра — это ОписаниеТипов. Так же устроены Метаданные.ОпределяемыеТипы.Имя.Тип и Метаданные.ПланыВидовХарактеристик.Имя.Тип. Обращения к Метаданные держите в серверном коде.
// Общий модуль РаботаСТипамиСервер (флажок «Сервер»)
// Возвращает ОписаниеТипов реквизита или стандартного реквизита объекта метаданных.
// Если реквизита с таким именем нет - Неопределено.
Функция ТипРеквизита(МетаОбъект, ИмяРеквизита) Экспорт
МетаРеквизит = МетаОбъект.Реквизиты.Найти(ИмяРеквизита);
Если МетаРеквизит <> Неопределено Тогда
Возврат МетаРеквизит.Тип;
КонецЕсли;
Для Каждого СтандартныйРеквизит Из МетаОбъект.СтандартныеРеквизиты Цикл
Если СтандартныйРеквизит.Имя = ИмяРеквизита Тогда
Возврат СтандартныйРеквизит.Тип;
КонецЕсли;
КонецЦикла;
Возврат Неопределено;
КонецФункции
Процедура ПримерТиповИзМетаданных() Экспорт
МетаНоменклатура = Метаданные.Справочники.Номенклатура;
МетаТовары = Метаданные.Документы.РеализацияТоваровУслуг.ТабличныеЧасти.Товары;
// Прямой путь: имена известны при разработке
ТипАртикула = МетаНоменклатура.Реквизиты.Артикул.Тип;
ТипКоличества = МетаТовары.Реквизиты.Количество.Тип;
// Через функцию: находит и стандартные реквизиты
ТипНаименования = ТипРеквизита(МетаНоменклатура, "Наименование");
Сообщить(ТипАртикула.КвалификаторыСтроки.Длина); // длина из конфигуратора
Сообщить(ТипНаименования.КвалификаторыСтроки.Длина = МетаНоменклатура.ДлинаНаименования); // Да
Сообщить(ТипКоличества.КвалификаторыЧисла.РазрядностьДробнойЧасти); // точность количества
// Пустая таблица с колонками и типами как у табличной части
Таблица = Новый ТаблицаЗначений;
Для Каждого МетаРеквизит Из МетаТовары.Реквизиты Цикл
Таблица.Колонки.Добавить(МетаРеквизит.Имя, МетаРеквизит.Тип, МетаРеквизит.Синоним);
КонецЦикла;
Сообщить(Таблица.Колонки.Количество());
КонецПроцедуры
Код, Наименование, Владелец, Дата, Номер) лежат в коллекции СтандартныеРеквизиты, поэтому функция проверяет обе коллекции.Реквизиты.Найти возвращает Неопределено, если имени нет, — функцию безопасно вызывать для имён из файла.Значения из Excel, JSON или параметров HTTP-запроса нужно разложить по реквизитам. Присваивание реквизиту приведёт значение само, но молча; вызов ПривестиЗначение заранее позволяет показать потери.
// Общий модуль РаботаСТипамиСервер (флажок «Сервер»)
// Переносит значения из структуры "ИмяРеквизита - значение" в объект с приведением
// к типам реквизитов из метаданных. Возвращает массив предупреждений о потерях.
Функция ЗаполнитьРеквизитыСПриведением(Объект, Данные) Экспорт
Предупреждения = Новый Массив;
МетаОбъект = Объект.Метаданные();
Для Каждого Элемент Из Данные Цикл
ОписаниеРеквизита = ТипРеквизита(МетаОбъект, Элемент.Ключ);
Если ОписаниеРеквизита = Неопределено Тогда
Предупреждения.Добавить(Элемент.Ключ + ": нет такого реквизита, поле пропущено");
Продолжить;
КонецЕсли;
Исходное = Элемент.Значение;
// Число из Excel вида "1 234,50": убрать пробелы, запятую заменить точкой
Если ТипЗнч(Исходное) = Тип("Строка")
И ОписаниеРеквизита.Типы().Количество() = 1
И ОписаниеРеквизита.СодержитТип(Тип("Число")) Тогда
Исходное = СтрЗаменить(СтрЗаменить(Исходное, " ", ""), Символы.НПП, "");
Исходное = СтрЗаменить(Исходное, ",", ".");
КонецЕсли;
Приведенное = ОписаниеРеквизита.ПривестиЗначение(Исходное);
Если ТипЗнч(Исходное) = Тип("Строка") И ТипЗнч(Приведенное) = Тип("Строка")
И СтрДлина(Приведенное) < СтрДлина(Исходное) Тогда
Предупреждения.Добавить(СтрШаблон("%1: текст обрезан до %2 символов",
Элемент.Ключ, СтрДлина(Приведенное)));
ИначеЕсли ЗначениеЗаполнено(Исходное) И Не ЗначениеЗаполнено(Приведенное)
И Исходное <> "0" Тогда
Предупреждения.Добавить(СтрШаблон("%1: значение ""%2"" не приводится к типу реквизита",
Элемент.Ключ, Исходное));
КонецЕсли;
Объект[Элемент.Ключ] = Приведенное;
КонецЦикла;
Возврат Предупреждения;
КонецФункции
Процедура ПримерЗагрузки() Экспорт
Данные = Новый Структура("Артикул, Наименование",
"ART-2026-0001-ДЛИННЫЙ-АРТИКУЛ-ИЗ-ФАЙЛА", "Стол офисный");
Товар = Справочники.Номенклатура.СоздатьЭлемент();
Для Каждого Текст Из ЗаполнитьРеквизитыСПриведением(Товар, Данные) Цикл
Сообщить(Текст); // например: "Артикул: текст обрезан до 25 символов"
КонецЦикла;
КонецПроцедуры
ТипРеквизита из предыдущего раздела.Символы.НПП), а запятая меняется на точку: Excel часто отдаёт «1 234,50».ПривестиЗначение не найдёт — нужен поиск в справочнике по коду или наименованию.Создание реквизитов формы с описанием типов (Новый РеквизитФормы(Имя, ОписаниеТипов)) разобрано в статье о программном изменении формы. Здесь другой случай: тип поля хранится в данных. У элемента плана видов характеристик есть реквизит ТипЗначения — это тоже ОписаниеТипов.
// Модуль формы. Объект.Свойство - ссылка на план видов характеристик,
// Объект.Значение - реквизит составного типа «Характеристика» этого плана.
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
НастроитьПолеЗначения(Ложь);
КонецПроцедуры
&НаКлиенте
Процедура СвойствоПриИзменении(Элемент)
НастроитьПолеЗначения(Истина);
КонецПроцедуры
&НаСервере
Процедура НастроитьПолеЗначения(ПривестиТекущееЗначение)
Если ЗначениеЗаполнено(Объект.Свойство) Тогда
ТипЗначения = Объект.Свойство.ТипЗначения;
Иначе
ТипЗначения = Метаданные.НайтиПоТипу(ТипЗнч(Объект.Свойство)).Тип;
КонецЕсли;
Элементы.Значение.ОграничениеТипа = ТипЗначения;
Если ПривестиТекущееЗначение Тогда
Объект.Значение = ТипЗначения.ПривестиЗначение(Объект.Значение);
КонецЕсли;
КонецПроцедуры
ОграничениеТипа сужает выбор типа в поле, а ПривестиЗначение сбрасывает значение, которое не подходит новому виду характеристики. Пока вид не выбран, берётся общий тип значений из метаданных плана.
Новый ОписаниеТипов("Строка", Новый КвалификаторыСтроки(10)) квалификатор строки стоит на месте квалификатора числа, и длина 10 к строке не применится. Правильно: Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(10)).Тип("СправочникСсылка.Контрагент") сразу даёт «Тип не определен (СправочникСсылка.Контрагент)». В строковом конструкторе неизвестное имя может пропасть без ошибки, и описание окажется пустым — проверяйте Типы().Количество().Описание.КвалификаторыСтроки.Длина = 100 завершается ошибкой «Поле объекта недоступно для записи (Длина)». Создайте новое описание на основе старого.Метаданные.Справочники.Номенклатура.Реквизиты.Наименование даёт «Поле объекта не обнаружено (Наименование)».Реквизиты.Найти("Артикл").Тип при опечатке в имени даёт «Значение не является значением объектного типа (Тип)».Вызовите у описания ПривестиЗначение(Неопределено): получите 0, пустую строку, пустую дату или пустую ссылку. Для составного типа надёжнее явно взять Неопределено — именно его содержит незаполненный реквизит составного типа.
Число("12 шт") вызывает исключение «Преобразование значения к типу Число не может быть выполнено», а ПривестиЗначение вернёт 0. Кроме того, приведение учитывает квалификаторы: обрезает строку и округляет число до заданной разрядности.
Поле из левого соединения может быть пустым, и платформа добавляет Null в тип колонки результата. Убрать его можно конструктором на основе: Новый ОписаниеТипов(Колонка.ТипЗначения, , "Null"). В тексте запроса ту же задачу решает ЕСТЬNULL().
Через Метаданные.Справочники.Номенклатура.Реквизиты.Артикул.Тип.КвалификаторыСтроки.Длина; 0 означает неограниченную строку. Для кода и наименования справочника есть готовые свойства ДлинаКода и ДлинаНаименования.
Загрузка из Excel или обмен с проверкой типов, сопоставлением ссылок и отчётом о потерях — типовой заказ на разработку обработок 1С. Опишите формат файла и правила заполнения в задании — исполнители предложат решение и сроки.
Станьте частью сообщества!
Войдите или зарегистрируйтесь, и вы сможете участвовать в обсуждениях.