Тип значения 1С показывает, что сейчас лежит в переменной: число, строка, дата, ссылка на справочник или Неопределено. Определить его помогают две функции встроенного языка: ТипЗнч(Значение) возвращает тип конкретного значения, а Тип("ИмяТипа") — тип по его имени. Сравнив одно с другим, вы проверите значение на нужный тип. Ниже — как проверить тип значения программно, таблица имён для Тип(), проверка ссылок и реквизитов составного типа и ошибки, которые чаще всего попадаются в чужом коде.
Всё описанное работает на платформе 8.3 в любой конфигурации. ТипЗнч и Тип доступны и на клиенте, и на сервере; проверки, которым нужны менеджеры объектов или метаданные, выполняются на сервере — это отмечено в коде. Пример с формой написан для управляемой формы. Тип поля в запросе (ТИПЗНАЧЕНИЯ, ТИП()) — отдельная тема языка запросов, здесь речь только о встроенном языке.
Источник.Неопределено.Null.ТипЗнч принимает любое значение и возвращает значение типа Тип. Функция Тип принимает строку с именем и возвращает такое же значение типа Тип. Два типа сравнивают только операторами = и <>: «больше» и «меньше» для типов смысла не имеют.
Значение = 12.5;
Если ТипЗнч(Значение) = Тип("Число") Тогда
// здесь Значение гарантированно число
КонецЕсли;
// Если проверок несколько, тип вычисляем один раз
ТипЗначения = ТипЗнч(Значение);
Если ТипЗначения = Тип("Строка") Тогда
// строка
ИначеЕсли ТипЗначения = Тип("Дата") Тогда
// дата (и время)
ИначеЕсли ТипЗначения = Тип("СправочникСсылка.Контрагенты") Тогда
// ссылка на конкретный справочник
ИначеЕсли ТипЗначения = Тип("Неопределено") Тогда
// значение не задано
КонецЕсли;
Что здесь важно:
Тип() пишется так, как в синтакс-помощнике: Число, Строка, Дата. Для прикладных объектов — вид типа и имя из метаданных через точку: СправочникСсылка.Контрагенты.ИначеЕсли, результат ТипЗнч сохраняют в переменную. Код короче, и читается он как переключатель по типу.Тип() не проверяет. Опечатка в имени всплывёт только тогда, когда строка выполнится, — об этом ниже в ошибках.Когда допустимых типов несколько, вместо длинного условия через Или удобнее ОписаниеТипов и его метод СодержитТип:
// Проверка параметра на любой из нескольких типов
Процедура ПроверитьТипПараметра(Значение)
ДопустимыеТипы = Новый ОписаниеТипов("Число, Строка, Дата");
Если Не ДопустимыеТипы.СодержитТип(ТипЗнч(Значение)) Тогда
ВызватьИсключение "Недопустимый тип параметра: " + Строка(ТипЗнч(Значение));
КонецЕсли;
КонецПроцедуры
// То же описание типов задаёт тип колонки с квалификатором
Функция НоваяТаблицаСумм()
Таблица = Новый ТаблицаЗначений;
Таблица.Колонки.Добавить("Сумма", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 2)));
Возврат Таблица;
КонецФункции
Конструктор ОписаниеТипов принимает имена типов строкой через запятую или массив значений Тип. Этот же объект задаёт тип колонок таблицы значений, реквизитов формы и параметров — с квалификаторами длины и точности.
Самые частые имена в одном месте. Прикладные имена в примерах взяты из типовых конфигураций — подставьте свои из дерева метаданных.
| Что проверяем | Как записать | Замечание |
|---|---|---|
| Число | Тип("Число") | Целые и дробные — один тип |
| Строка | Тип("Строка") | Длина задаётся квалификатором, а не типом |
| Дата и время | Тип("Дата") | Отдельного типа «Время» нет |
| Булево | Тип("Булево") | — |
| Неопределено | Тип("Неопределено") | Пустой составной реквизит, результат Соответствие.Получить() по отсутствующему ключу |
| Null | Тип("Null") | Поля запроса после левого соединения |
| Ссылка на справочник | Тип("СправочникСсылка.Контрагенты") | Имя — как в дереве метаданных |
| Ссылка на документ | Тип("ДокументСсылка.РеализацияТоваровУслуг") | — |
| Значение перечисления | Тип("ПеречислениеСсылка.СтавкиНДС") | — |
| Ссылка на ПВХ | Тип("ПланВидовХарактеристикСсылка.ВидыСубконтоХозрасчетные") | Имена объектов в примерах — из типовых, у вас могут отличаться |
| Счёт плана счетов | Тип("ПланСчетовСсылка.Хозрасчетный") | — |
| Объект справочника | Тип("СправочникОбъект.Контрагенты") | ПередЗаписью, ПриЗаписи, подписки на события |
| Объект документа | Тип("ДокументОбъект.РеализацияТоваровУслуг") | — |
| Коллекции | Тип("Массив"), Тип("Структура"), Тип("Соответствие"), Тип("СписокЗначений") | — |
| Таблицы | Тип("ТаблицаЗначений"), Тип("ДеревоЗначений") | — |
| Фиксированные коллекции | Тип("ФиксированныйМассив"), Тип("ФиксированнаяСтруктура") | Это другие типы, не Массив и не Структура |
| Данные формы | Тип("ДанныеФормыСтруктура"), Тип("ДанныеФормыКоллекция") | Объект и табличные части в модуле формы |
| Идентификатор | Тип("УникальныйИдентификатор") | — |
| Двоичные данные | Тип("ДвоичныеДанные"), Тип("ХранилищеЗначения") | — |
Обратите внимание на пары «ссылка — объект» и «коллекция — фиксированная коллекция». СправочникСсылка.Контрагенты и СправочникОбъект.Контрагенты — разные типы, и проверка одного не пропустит другой. То же с Массив и ФиксированныйМассив: если функция может вернуть оба, проверяйте через ОписаниеТипов("Массив, ФиксированныйМассив").
Под запросом «тип значения число» обычно скрываются две разные задачи. Первая — убедиться, что в переменной уже лежит число: хватает ТипЗнч(Значение) = Тип("Число"). Вторая — понять, можно ли превратить строку в число. Это уже не проверка типа, а попытка преобразования: у строки «15» тип Строка, и ТипЗнч её не распознает.
// Число из строки вида "1 500,25" или ЗначениеПоУмолчанию, если это не число
Функция ЧислоИзСтроки(Знач Текст, ЗначениеПоУмолчанию = Неопределено) Экспорт
Если ТипЗнч(Текст) = Тип("Число") Тогда
Возврат Текст;
КонецЕсли;
Если ТипЗнч(Текст) <> Тип("Строка") Тогда
Возврат ЗначениеПоУмолчанию;
КонецЕсли;
Текст = СтрЗаменить(Текст, Символы.НПП, ""); // неразрывный пробел из Excel
Текст = СтрЗаменить(Текст, " ", "");
Текст = СтрЗаменить(Текст, ",", ".");
Если ПустаяСтрока(Текст) Тогда
Возврат ЗначениеПоУмолчанию;
КонецЕсли;
Попытка
Возврат Число(Текст);
Исключение
Возврат ЗначениеПоУмолчанию;
КонецПопытки;
КонецФункции
// Использование: Истина, если в ячейке удалось распознать число
Функция КоличествоРаспознано(ЗначениеЯчейки)
Количество = ЧислоИзСтроки(ЗначениеЯчейки);
Возврат ТипЗнч(Количество) = Тип("Число");
КонецФункции
Разбор ключевых строк:
Неопределено из пустой ячейки.Символы.НПП — частый гость в числах, скопированных из Excel и с сайтов. Обычный СтрЗаменить(Текст, " ", "") его не удаляет.Число() разбирает строку и по региональным установкам базы, и без их учёта: точка как разделитель дробной части распознаётся всегда, запятая — только если так задано в региональных установках. Приводим к точке, чтобы результат не зависел от настроек базы.Число() вызывает исключение, если строка не число. Поэтому преобразование обёрнуто в Попытка, а вызывающий код получает Неопределено и проверяет тип результата.С датой и булевым проще. У даты и времени один тип Дата; состав (только дата, только время или всё вместе) задаётся квалификатором в метаданных, а не типом. Пустая дата — Дата(1, 1, 1). Форматирование для вывода — в статье о формате даты.
Функция ДатаЗаполнена(Значение)
Возврат ТипЗнч(Значение) = Тип("Дата") И Значение <> Дата(1, 1, 1);
КонецФункции
// Именно Истина, а не непустая строка или единица
Функция ЭтоИстина(Значение)
Возврат ТипЗнч(Значение) = Тип("Булево") И Значение;
КонецФункции
Обе функции опираются на то, что И вычисляется по сокращённой схеме: если тип не подошёл, вторая часть условия не выполняется. Без проверки типа выражение И Значение со строкой в переменной упало бы на преобразовании к Булево.
Ссылку конкретного вида проверяют как примитивный тип — ТипЗнч(Значение) = Тип("ДокументСсылка.РеализацияТоваровУслуг"), это работает и на клиенте. Чтобы проверить принадлежность к целому классу объектов, у менеджеров Справочники, Документы и других есть метод ТипВсеСсылки(). Он возвращает ОписаниеТипов со всеми ссылочными типами этого класса. Метод доступен на сервере, в толстом клиенте и во внешнем соединении, поэтому в модуле формы такие функции помечают &НаСервереБезКонтекста, а в серверном общем модуле директива не нужна.
// Вид ссылки строкой: "Справочник", "Документ" или пустая строка.
// ТипВсеСсылки() доступен на сервере, в толстом клиенте и во внешнем соединении.
&НаСервереБезКонтекста
Функция ВидСсылки(Значение)
ТипЗначения = ТипЗнч(Значение);
Если Справочники.ТипВсеСсылки().СодержитТип(ТипЗначения) Тогда
Возврат "Справочник";
ИначеЕсли Документы.ТипВсеСсылки().СодержитТип(ТипЗначения) Тогда
Возврат "Документ";
КонецЕсли;
Возврат "";
КонецФункции
Если нужна проверка «это вообще ссылка на объект базы», соберите менеджеры в массив и пройдите по ним:
// Ссылка на любой объект базы. Выполняется на сервере.
&НаСервереБезКонтекста
Функция ЭтоСсылка(Значение)
ТипЗначения = ТипЗнч(Значение);
Менеджеры = Новый Массив;
Менеджеры.Добавить(Справочники);
Менеджеры.Добавить(Документы);
Менеджеры.Добавить(Перечисления);
Менеджеры.Добавить(ПланыВидовХарактеристик);
Менеджеры.Добавить(ПланыСчетов);
Менеджеры.Добавить(ПланыВидовРасчета);
Менеджеры.Добавить(БизнесПроцессы);
Менеджеры.Добавить(Задачи);
Менеджеры.Добавить(ПланыОбмена);
Для Каждого Менеджер Из Менеджеры Цикл
Если Менеджер.ТипВсеСсылки().СодержитТип(ТипЗначения) Тогда
Возврат Истина;
КонецЕсли;
КонецЦикла;
// Точки маршрута бизнес-процессов — отдельный ссылочный тип
Если БизнесПроцессы.ТипВсеСсылкиТочекМаршрутаБизнесПроцессов().СодержитТип(ТипЗначения) Тогда
Возврат Истина;
КонецЕсли;
Возврат Ложь;
КонецФункции
Точки маршрута бизнес-процессов не входят в БизнесПроцессы.ТипВсеСсылки(), поэтому для них отдельная проверка через ТипВсеСсылкиТочекМаршрутаБизнесПроцессов().
В конфигурациях на БСП свою функцию писать не нужно. В серверном общем модуле ОбщегоНазначения есть ЭтоСсылка(Тип) — она принимает тип, а не значение: ОбщегоНазначения.ЭтоСсылка(ТипЗнч(Значение)). Для проверки самого значения там же есть ОбщегоНазначения.ЗначениеСсылочногоТипа(Значение). Обе функции есть в БСП 3.1; в более старых редакциях сверьтесь с кодом модуля.
Реквизит составного типа хранит значение одного из нескольких типов. Пока он не заполнен, в нём лежит Неопределено, а не пустая ссылка. Поэтому любую логику с таким реквизитом начинают с ТипЗнч. Пример для формы документа, где «Получатель» — контрагент или физическое лицо, а поле договора нужно только для контрагента:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Документ вводят на основании контрагента: физлицо в получателе не нужно
Если ТипЗнч(Параметры.Основание) = Тип("СправочникСсылка.Контрагенты") Тогда
Элементы.Получатель.ОграничениеТипа = Новый ОписаниеТипов("СправочникСсылка.Контрагенты");
КонецЕсли;
УстановитьВидимостьДоговора(ЭтотОбъект);
КонецПроцедуры
&НаКлиенте
Процедура ПолучательПриИзменении(Элемент)
Если ТипЗнч(Объект.Получатель) <> Тип("СправочникСсылка.Контрагенты") Тогда
Объект.ДоговорКонтрагента = ПредопределенноеЗначение("Справочник.ДоговорыКонтрагентов.ПустаяСсылка");
КонецЕсли;
УстановитьВидимостьДоговора(ЭтотОбъект);
КонецПроцедуры
&НаКлиентеНаСервереБезКонтекста
Процедура УстановитьВидимостьДоговора(Форма)
Форма.Элементы.ДоговорКонтрагента.Видимость =
(ТипЗнч(Форма.Объект.Получатель) = Тип("СправочникСсылка.Контрагенты"));
КонецПроцедуры
Разбор:
&НаКлиентеНаСервереБезКонтекста, форма передаётся ей параметром. Её вызывают при создании формы на сервере и при изменении поля на клиенте.ПриИзменении срабатывает только при изменении поля пользователем. Без вызова из ПриСозданииНаСервере у записанного документа с физлицом в получателе поле договора было бы видно до первой правки.ОграничениеТипа поля формы сужает выбор: пользователь сможет выбрать только значения указанных типов. Здесь оно включается, когда документ вводят на основании контрагента.Если нужно узнать, какие типы вообще допустимы в реквизите, прочитайте их из метаданных на сервере:
// Список типов реквизита: "Число", "Справочник.Контрагенты" и т. п.
&НаСервереБезКонтекста
Функция ТипыРеквизита(ПолноеИмяОбъекта, ИмяРеквизита)
Результат = Новый Массив;
МетаданныеОбъекта = Метаданные.НайтиПоПолномуИмени(ПолноеИмяОбъекта);
Если МетаданныеОбъекта = Неопределено Тогда
Возврат Результат;
КонецЕсли;
МетаданныеРеквизита = МетаданныеОбъекта.Реквизиты.Найти(ИмяРеквизита);
Если МетаданныеРеквизита = Неопределено Тогда
Возврат Результат;
КонецЕсли;
Для Каждого ТипРеквизита Из МетаданныеРеквизита.Тип.Типы() Цикл
ОбъектМетаданных = Метаданные.НайтиПоТипу(ТипРеквизита);
Если ОбъектМетаданных = Неопределено Тогда
Результат.Добавить(Строка(ТипРеквизита)); // примитивный тип
Иначе
Результат.Добавить(ОбъектМетаданных.ПолноеИмя()); // Справочник.Контрагенты
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
// Вызов: ТипыРеквизита("Документ.РеализацияТоваровУслуг", "Контрагент")
Метаданные.НайтиПоТипу возвращает объект метаданных для ссылочных и объектных типов, а для примитивных — Неопределено. На этом и построено разделение. Стандартные реквизиты (Дата, Номер, Владелец) в коллекцию Реквизиты не входят — их ищут в СтандартныеРеквизиты.
ТипЗнч(Значение) = "Число" не вызывает ошибку, но всегда даёт Ложь: тип сравнивается со строкой. Похожая ловушка — Строка(ТипЗнч(Значение)) = "Контрагенты". Строковое представление ссылочного типа зависит от синонима объекта и языка интерфейса, и после переименования проверка молча перестаёт работать.ПередЗаписью и ПриЗаписи в параметр Источник приходит объект — ДокументОбъект.<Имя>. Проверка на ДокументСсылка.<Имя> вернёт Ложь. Проверяйте тип объекта или ТипЗнч(Источник.Ссылка).Объект имеет тип ДанныеФормыСтруктура, табличная часть — ДанныеФормыКоллекция. Сравнение с ДокументОбъект или ТаблицаЗначений там не сработает.Неопределено, и Объект.Получатель.Пустая() падает с ошибкой «Метод объекта не обнаружен (Пустая)». Сначала проверьте тип или используйте ЗначениеЗаполнено().ТипЗнч(Х) = Новый ОписаниеТипов("Число") — всегда Ложь: это значения разных типов. Для описания типов есть СодержитТип().Справочники, Документы и остальные в тонком и веб-клиенте недоступны, и модуль с такой процедурой &НаКлиенте не пройдёт проверку: «Переменная не определена (Справочники)». Проверку «любая ссылка» выносите на сервер.В табло и в окне «Вычислить выражение» рядом со значением есть колонка «Тип». Можно также вычислить там выражение ТипЗнч(Переменная) — это удобно, когда переменная составного типа и нужно понять, что в ней сейчас.
Строка(ТипЗнч(Значение)) даёт представление для пользователя, и в логике на него лучше не опираться. Для ссылочных типов на сервере подходит Метаданные.НайтиПоТипу(Тип).ПолноеИмя() — вернёт, например, «Справочник.Контрагенты». Ещё вариант — XMLТип(Тип).ИмяТипа: для типов с XML-представлением он даёт имя вида «CatalogRef.Контрагенты».
Передайте строку в Тип(ИмяТипа), но оберните вызов в Попытка. Если объект переименовали или удалили, платформа вызовет исключение, и лучше обработать его явно, чем уронить весь обмен.
Да, ТипЗнч и Тип доступны на клиенте, в том числе для ссылочных типов. На сервер нужно уходить, когда проверка требует метаданных или менеджеров объектов: Метаданные.НайтиПоТипу, ТипВсеСсылки().
ТипЗнч — функция встроенного языка, она работает со значением в памяти. ТИПЗНАЧЕНИЯ — функция языка запросов, она выполняется на стороне СУБД при отборе и соединении. Задачи похожие, но синтаксис и ограничения разные.
Если проверка типа — часть задачи побольше (загрузка из файлов с «грязными» данными, универсальная обработка для нескольких конфигураций, отчёт по полям составного типа), её можно отдать программисту. Опишите задачу на странице разместить задачу — оценка на площадке бесплатная, ответ в течение рабочего дня. Подробнее о направлении — в разделе отчёты и обработки 1С.
Станьте частью сообщества!
Войдите или зарегистрируйтесь, и вы сможете участвовать в обсуждениях.