Тип в запросе 1С проверяют парой функций: ТИПЗНАЧЕНИЯ() возвращает тип значения поля, ТИП() — тип по имени, а условие записывают сравнением: ТИПЗНАЧЕНИЯ(Движения.Регистратор) = ТИП(Документ.РеализацияТоваровУслуг). Для ссылок есть короткая форма — оператор ССЫЛКА. Нужно это для полей составного типа, где в одной колонке лежат документы разных видов, контрагенты вперемешку с физлицами или числа со строками.
Примеры — для платформы 8.3, запросы выполняются на сервере. Имена объектов взяты из УТ 11.4 и БП 3.0, в другом релизе сверьте их в конфигураторе.
Значение — число, строка, дата, булево или ссылка, смотря какое свойство.ДокументОснование, Объект в регистрах сведений, Владелец: в БП 3.0 владелец банковского счёта — организация, контрагент или физлицо.ТИПЗНАЧЕНИЯ в запросе 1С принимает поле или выражение и возвращает значение типа Тип. ТИП принимает имя без кавычек: ссылочной таблицы, как в секции ИЗ (Справочник.Контрагенты, Перечисление.СтатусыЗаказовКлиентов), или примитивного типа — ЧИСЛО, СТРОКА, ДАТА, БУЛЕВО. Параметр внутрь ТИП() не подставить — его ставят вместо всего выражения. ССЫЛКА — логический оператор: Поле ССЫЛКА Документ.РеализацияТоваровУслуг.
ТИП(Имя) | ТИПЗНАЧЕНИЯ(Поле) | Поле ССЫЛКА Таблица | |
|---|---|---|---|
| Результат | Тип | Тип | Булево |
| Аргумент | имя таблицы или примитивного типа | поле или выражение | справа — имя ссылочной таблицы |
| Примитивные типы | да | да | нет |
| Тип из параметра | нет | = &Тип, В (&Типы) | нет |
| Колонка результата, группировка | — | да | через ВЫБОР |
Чаще всего путают имена: в коде и в запросе один и тот же тип пишется по-разному.
| Тип | Встроенный язык | Текст запроса |
|---|---|---|
| Документ | Тип("ДокументСсылка.РеализацияТоваровУслуг") | ТИП(Документ.РеализацияТоваровУслуг) |
| Справочник | Тип("СправочникСсылка.Контрагенты") | ТИП(Справочник.Контрагенты) |
| Перечисление | Тип("ПеречислениеСсылка.СтатусыЗаказовКлиентов") | ТИП(Перечисление.СтатусыЗаказовКлиентов) |
| Примитивы | Тип("Число"), Тип("Строка"), Тип("Дата"), Тип("Булево") | ТИП(ЧИСЛО), ТИП(СТРОКА), ТИП(ДАТА), ТИП(БУЛЕВО) |
У поля составного типа вид ссылки хранится в служебной колонке, и обе записи сводятся к сравнению этой колонки с кодом типа — без соединения с таблицей документа, так что по скорости они равны. Разница в читаемости и возможностях: ССЫЛКА короче, его ставьте в обычные отборы; ТИПЗНАЧЕНИЯ — когда тип приходит параметром, типов список, тип примитивный или он нужен колонкой результата. Об операторе и полях через точку — в статье «Ссылка в запросе 1С».
Тип значения в запросе 1С 8.3 часто известен только при выполнении: виды документов выбирает пользователь или они лежат в настройках. Правая часть оператора ССЫЛКА фиксируется в тексте запроса, поэтому тип передают параметром и сравнивают с ТИПЗНАЧЕНИЯ, несколько видов — массивом через В.
// Движения регистра «Товары на складах» за период только от документов
// указанных видов. Виды передаются строкой имен метаданных через запятую,
// например "РеализацияТоваровУслуг, ВозвратТоваровОтКлиента".
// Серверный общий модуль. Регистр и поля - из УТ 11.4, в другой конфигурации подставьте свои.
Функция ДвиженияПоВидамДокументов(Знач ИменаДокументов, Знач НачалоПериода, Знач КонецПериода) Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗРЕШЕННЫЕ
| Движения.Период КАК Период,
| Движения.Регистратор КАК Регистратор,
| ТИПЗНАЧЕНИЯ(Движения.Регистратор) КАК ТипРегистратора,
| Движения.ВидДвижения КАК ВидДвижения,
| Движения.Номенклатура КАК Номенклатура,
| Движения.Склад КАК Склад,
| Движения.ВНаличии КАК Количество
|ИЗ
| РегистрНакопления.ТоварыНаСкладах КАК Движения
|ГДЕ
| Движения.Период МЕЖДУ &НачалоПериода И &КонецПериода
| И Движения.Активность
| И ТИПЗНАЧЕНИЯ(Движения.Регистратор) В (&ТипыДокументов)
|
|УПОРЯДОЧИТЬ ПО
| Период";
Запрос.УстановитьПараметр("НачалоПериода", НачалоДня(НачалоПериода));
Запрос.УстановитьПараметр("КонецПериода", КонецДня(КонецПериода));
Запрос.УстановитьПараметр("ТипыДокументов", ТипыДокументовПоИменам(ИменаДокументов));
Возврат Запрос.Выполнить().Выгрузить();
КонецФункции
// Превращает строку имен документов в массив значений Тип для параметра запроса.
// Опечатка в имени дает понятное исключение до вызова Тип().
Функция ТипыДокументовПоИменам(Знач ИменаДокументов) Экспорт
ТипыДокументов = Новый Массив;
Для Каждого Элемент Из СтрРазделить(ИменаДокументов, ",", Ложь) Цикл
ИмяДокумента = СокрЛП(Элемент);
Если ПустаяСтрока(ИмяДокумента) Тогда
Продолжить;
КонецЕсли;
Если Метаданные.Документы.Найти(ИмяДокумента) = Неопределено Тогда
ВызватьИсключение СтрШаблон("В конфигурации нет документа ""%1""", ИмяДокумента);
КонецЕсли;
ТипыДокументов.Добавить(Тип("ДокументСсылка." + ИмяДокумента));
КонецЦикла;
Если ТипыДокументов.Количество() = 0 Тогда
ВызватьИсключение "Не указан ни один вид документа";
КонецЕсли;
Возврат ТипыДокументов;
КонецФункции
ТИПЗНАЧЕНИЯ(Движения.Регистратор) В (&ТипыДокументов) — список видов приходит из кода. Для одного вида условие — ТИПЗНАЧЕНИЯ(Движения.Регистратор) = &ТипДокумента, а в параметр кладут Тип("ДокументСсылка.РеализацияТоваровУслуг").Тип("ДокументСсылка." + ИмяДокумента). В запросе тот же тип — ТИП(Документ.Имя).Метаданные.Документы.Найти() ловит опечатку до вызова Тип(), который на неизвестном имени выбрасывает «Тип не определен».ТипРегистратора — колонка значений Тип, в коде её сравнивают с Тип("ДокументСсылка.…") как обычно.РАЗРЕШЕННЫЕ нужно на случай ограничения доступа на уровне записей: без него запрос у пользователя с урезанными правами упадёт с ошибкой. СтрРазделить() и СтрШаблон() — с 8.3.6, в модуле формы функциям нужна директива &НаСервереБезКонтекста.Если типы уже лежат в описании типов — определяемый тип БСП, тип реквизита, Документы.ТипВсеСсылки(), — передайте массив из метода Типы(). Так делает и типовой код УТ 11: Метаданные.ОпределяемыеТипы.Имя.Тип.Типы() прямо в УстановитьПараметр.
Функция показывает, документы каких видов двигали регистр за период, сколько их и сколько строк дал каждый вид. Пригодится перед написанием отчёта и при разборе неожиданных движений после обновления или установки расширения.
// Какие виды документов делали движения по регистру за период:
// сколько документов каждого вида и сколько строк движений они дали.
// Серверный общий модуль. Регистр - из УТ 11.4, подойдет любой регистр с регистратором.
Функция ВидыРегистраторовЗаПериод(Знач НачалоПериода, Знач КонецПериода) Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗРЕШЕННЫЕ
| Движения.Регистратор КАК Регистратор,
| КОЛИЧЕСТВО(*) КАК СтрокДвижений
|ПОМЕСТИТЬ ВТ_Регистраторы
|ИЗ
| РегистрНакопления.ТоварыНаСкладах КАК Движения
|ГДЕ
| Движения.Период МЕЖДУ &НачалоПериода И &КонецПериода
|
|СГРУППИРОВАТЬ ПО
| Движения.Регистратор
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ТИПЗНАЧЕНИЯ(Регистраторы.Регистратор) КАК ТипРегистратора,
| КОЛИЧЕСТВО(*) КАК Документов,
| СУММА(Регистраторы.СтрокДвижений) КАК СтрокДвижений
|ИЗ
| ВТ_Регистраторы КАК Регистраторы
|
|СГРУППИРОВАТЬ ПО
| ТИПЗНАЧЕНИЯ(Регистраторы.Регистратор)
|
|УПОРЯДОЧИТЬ ПО
| СтрокДвижений УБЫВ";
Запрос.УстановитьПараметр("НачалоПериода", НачалоДня(НачалоПериода));
Запрос.УстановитьПараметр("КонецПериода", КонецДня(КонецПериода));
Таблица = Запрос.Выполнить().Выгрузить();
Таблица.Колонки.Добавить("ВидДокумента", Новый ОписаниеТипов("Строка"));
Таблица.Колонки.Добавить("ПолноеИмя", Новый ОписаниеТипов("Строка"));
// В колонке ТипРегистратора - значения типа Тип: по ним находим метаданные.
Для Каждого СтрокаТаблицы Из Таблица Цикл
ОбъектМетаданных = Метаданные.НайтиПоТипу(СтрокаТаблицы.ТипРегистратора);
Если ОбъектМетаданных <> Неопределено Тогда
СтрокаТаблицы.ВидДокумента = ОбъектМетаданных.Представление();
СтрокаТаблицы.ПолноеИмя = ОбъектМетаданных.ПолноеИмя();
КонецЕсли;
КонецЦикла;
Возврат Таблица;
КонецФункции
ТИПЗНАЧЕНИЯ стоит и в ВЫБРАТЬ, и в СГРУППИРОВАТЬ ПО: в группировке выражение повторяют, псевдоним там не принимается.Метаданные.НайтиПоТипу() превращает значение Тип в объект метаданных с синонимом и полным именем.Тип субконто зависит от счёта. В остатках сразу по 60, 62 и 71 колонка Субконто1 содержит и контрагентов, и физлиц, а ИНН у них — реквизиты разных справочников. ВЫБОР по типу выбирает ветку, ВЫРАЗИТЬ в ветке даёт реквизит через одно соединение.
// Остатки по счетам 60, 62 и 71 с ИНН из первого субконто.
// На 60 и 62 первое субконто - контрагент, на 71 - физическое лицо
// (вид субконто «Работники организаций»), ИНН у них - реквизиты разных справочников.
// Имена - из БП 3.0. Серверный общий модуль.
Функция ОстаткиРасчетовСИНН(Знач Организация, Знач НаДату) Экспорт
Счета = Новый Массив;
Счета.Добавить(ПланыСчетов.Хозрасчетный.РасчетыСПоставщикамиИПодрядчиками);
Счета.Добавить(ПланыСчетов.Хозрасчетный.РасчетыСПокупателямиИЗаказчиками);
Счета.Добавить(ПланыСчетов.Хозрасчетный.РасчетыСПодотчетнымиЛицами_);
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗРЕШЕННЫЕ
| Остатки.Счет КАК Счет,
| Остатки.Субконто1 КАК Субконто,
| ВЫБОР
| КОГДА ТИПЗНАЧЕНИЯ(Остатки.Субконто1) = ТИП(Справочник.Контрагенты)
| ТОГДА ""Контрагент""
| КОГДА ТИПЗНАЧЕНИЯ(Остатки.Субконто1) = ТИП(Справочник.ФизическиеЛица)
| ТОГДА ""Физическое лицо""
| ИНАЧЕ ""Другое""
| КОНЕЦ КАК ВидСубконто,
| ВЫБОР
| КОГДА ТИПЗНАЧЕНИЯ(Остатки.Субконто1) = ТИП(Справочник.Контрагенты)
| ТОГДА ВЫРАЗИТЬ(Остатки.Субконто1 КАК Справочник.Контрагенты).ИНН
| КОГДА ТИПЗНАЧЕНИЯ(Остатки.Субконто1) = ТИП(Справочник.ФизическиеЛица)
| ТОГДА ВЫРАЗИТЬ(Остатки.Субконто1 КАК Справочник.ФизическиеЛица).ИНН
| ИНАЧЕ """"
| КОНЕЦ КАК ИНН,
| Остатки.СуммаОстатокДт КАК ОстатокДт,
| Остатки.СуммаОстатокКт КАК ОстатокКт
|ИЗ
| РегистрБухгалтерии.Хозрасчетный.Остатки(
| &НаДату,
| Счет В ИЕРАРХИИ (&Счета),
| ,
| Организация = &Организация) КАК Остатки
|
|УПОРЯДОЧИТЬ ПО
| ВидСубконто,
| ИНН";
Запрос.УстановитьПараметр("НаДату", Новый Граница(КонецДня(НаДату), ВидГраницы.Включая));
Запрос.УстановитьПараметр("Счета", Счета);
Запрос.УстановитьПараметр("Организация", Организация);
Возврат Запрос.Выполнить().Выгрузить();
КонецФункции
Субконто1 — первое субконто каждого счёта: на 60 и 62 — «Контрагенты», на 71 — «Работники организаций», то есть справочник ФизическиеЛица.Остатки.Субконто1.ИНН заставила бы платформу строить соединения по всему составу типа субконто, а в БП 3.0 это больше сотни типов. Подробнее — в статье «ВЫРАЗИТЬ в запросе 1С».ИНАЧЕ "" оставляет колонку ИНН строковой, без NULL.ТИП(Справочник.Контрагенты) можно заменить на Остатки.Субконто1 ССЫЛКА Справочник.Контрагенты — результат тот же.РасчетыСПодотчетнымиЛицами_, с подчёркиванием: без него это субсчёт 71.01.Тип поля Значение в табличной части ДополнительныеРеквизиты (подсистема «Свойства» БСП) определяет свойство. В УТ 11.4 в его составе — ссылки и примитивы Число(17, 5), Строка(1024), Дата и Булево. Функция раскладывает значение свойства по колонкам — для выгрузки в Excel или отчёта с отбором по числу и дате.
// Значение одного дополнительного реквизита у всей номенклатуры, разложенное
// по колонкам в зависимости от типа. Табличная часть ДополнительныеРеквизиты -
// подсистема «Свойства» БСП (есть в УТ 11, БП 3.0, ERP). Свойство - ссылка
// на ПВХ ДополнительныеРеквизитыИСведения. Серверный общий модуль.
Функция ЗначенияДопРеквизита(Знач Свойство) Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗРЕШЕННЫЕ
| Товары.Ссылка КАК Номенклатура,
| ВЫБОР
| КОГДА ДопРеквизиты.Значение ЕСТЬ NULL
| ТОГДА ""Нет значения""
| КОГДА ДопРеквизиты.Значение = НЕОПРЕДЕЛЕНО
| ТОГДА ""Неопределено""
| КОГДА ТИПЗНАЧЕНИЯ(ДопРеквизиты.Значение) = ТИП(ЧИСЛО)
| ТОГДА ""Число""
| КОГДА ТИПЗНАЧЕНИЯ(ДопРеквизиты.Значение) = ТИП(СТРОКА)
| ТОГДА ""Строка""
| КОГДА ТИПЗНАЧЕНИЯ(ДопРеквизиты.Значение) = ТИП(ДАТА)
| ТОГДА ""Дата""
| КОГДА ТИПЗНАЧЕНИЯ(ДопРеквизиты.Значение) = ТИП(БУЛЕВО)
| ТОГДА ""Булево""
| ИНАЧЕ ""Ссылка""
| КОНЕЦ КАК ВидЗначения,
| ВЫБОР
| КОГДА ТИПЗНАЧЕНИЯ(ДопРеквизиты.Значение) = ТИП(ЧИСЛО)
| ТОГДА ВЫРАЗИТЬ(ДопРеквизиты.Значение КАК ЧИСЛО(17, 5))
| КОНЕЦ КАК ЗначениеЧисло,
| ВЫБОР
| КОГДА ТИПЗНАЧЕНИЯ(ДопРеквизиты.Значение) = ТИП(СТРОКА)
| ТОГДА ВЫРАЗИТЬ(ДопРеквизиты.Значение КАК СТРОКА(1024))
| КОНЕЦ КАК ЗначениеСтрока,
| ВЫБОР
| КОГДА ТИПЗНАЧЕНИЯ(ДопРеквизиты.Значение) = ТИП(ДАТА)
| ТОГДА ВЫРАЗИТЬ(ДопРеквизиты.Значение КАК ДАТА)
| КОНЕЦ КАК ЗначениеДата,
| ВЫБОР
| КОГДА ТИПЗНАЧЕНИЯ(ДопРеквизиты.Значение) = ТИП(БУЛЕВО)
| ТОГДА ВЫРАЗИТЬ(ДопРеквизиты.Значение КАК БУЛЕВО)
| КОНЕЦ КАК ЗначениеБулево,
| ВЫБОР
| КОГДА ДопРеквизиты.Значение ССЫЛКА Справочник.ЗначенияСвойствОбъектов
| ТОГДА ВЫРАЗИТЬ(ДопРеквизиты.Значение КАК Справочник.ЗначенияСвойствОбъектов)
| КОНЕЦ КАК ЗначениеИзСписка
|ИЗ
| Справочник.Номенклатура КАК Товары
| ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура.ДополнительныеРеквизиты КАК ДопРеквизиты
| ПО ДопРеквизиты.Ссылка = Товары.Ссылка
| И ДопРеквизиты.Свойство = &Свойство
|ГДЕ
| НЕ Товары.ЭтоГруппа
| И НЕ Товары.ПометкаУдаления
|
|УПОРЯДОЧИТЬ ПО
| ВидЗначения";
Запрос.УстановитьПараметр("Свойство", Свойство);
Возврат Запрос.Выполнить().Выгрузить();
КонецФункции
ТИП() пишут без кавычек, регистр не важен: в типовом коде есть и ТИП(СТРОКА), и ТИП(Строка).ВЫРАЗИТЬ даёт колонке один тип: числа можно суммировать, по датам — отбирать период. Разрядность взята из УТ 11.4.ВЫБОР без ИНАЧЕ возвращает NULL — в колонках «чужих» типов пусто.ПО, а не в ГДЕ: иначе товары без значения выпадут, у них Свойство — NULL.ЕСТЬ NULL и = НЕОПРЕДЕЛЕНО идут первыми, иначе такие строки уйдут в ИНАЧЕ с видом «Ссылка». Для иерархических списков добавьте такую же ветку для Справочник.ЗначенияСвойствОбъектовИерархия.У поля составного типа три «пустых» состояния, и проверка типа ведёт себя в них по-разному:
| В поле | Откуда | ТИПЗНАЧЕНИЯ(Поле) = ТИП(Документ.X) | НЕ Поле ССЫЛКА Документ.X | Как проверить |
|---|---|---|---|---|
| NULL | левое соединение без пары, точка от пустой ссылки | не истина | тоже не истина | Поле ЕСТЬ NULL |
| Неопределено | у составного реквизита не выбран тип | ЛОЖЬ | ИСТИНА | Поле = НЕОПРЕДЕЛЕНО |
| Пустая ссылка на X | тип выбран, значение нет | ИСТИНА | ЛОЖЬ | Поле = ЗНАЧЕНИЕ(Документ.X.ПустаяСсылка) |
Ловушка — в отрицаниях: для NULL из левого соединения ни НЕ ... ССЫЛКА, ни ТИПЗНАЧЕНИЯ(...) <> ТИП(...) не дают истину, и строки без пары теряются. Запрос ищет товары, у которых свойство не заполнено или заполнено не из списка (например, осталось строкой после смены типа свойства). Без ЕСТЬ NULL незаполненные в выборку не попали бы.
ВЫБРАТЬ
Товары.Ссылка КАК Номенклатура,
ДопРеквизиты.Значение КАК Значение
ИЗ
Справочник.Номенклатура КАК Товары
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура.ДополнительныеРеквизиты КАК ДопРеквизиты
ПО ДопРеквизиты.Ссылка = Товары.Ссылка
И ДопРеквизиты.Свойство = &Свойство
ГДЕ
НЕ Товары.ЭтоГруппа
И (ДопРеквизиты.Значение ЕСТЬ NULL
ИЛИ (НЕ ДопРеквизиты.Значение ССЫЛКА Справочник.ЗначенияСвойствОбъектов
И НЕ ДопРеквизиты.Значение ССЫЛКА Справочник.ЗначенияСвойствОбъектовИерархия))
Поиск незаполненных составных реквизитов разобран в статье «Пустая ссылка в запросе», синтаксис ЗНАЧЕНИЕ() — в материале о функции ЗНАЧЕНИЕ.
Тип("ДокументСсылка.РеализацияТоваровУслуг"). Обратная ошибка — ТИП(ДокументСсылка.РеализацияТоваровУслуг) в запросе: он не пройдёт проверку синтаксиса, платформа покажет строку и позицию в фигурных скобках.Регистратор ССЫЛКА &ТипДокумента — ошибка синтаксиса, справа ожидается имя таблицы. Пишите ТИПЗНАЧЕНИЯ(Регистратор) = &ТипДокумента."ДокументСсылка.РеализацияТоваровУслуг" — строка, а не тип. Оберните имя в Тип(), из описания типов возьмите Типы().ТИПЗНАЧЕНИЯ(Основание) = ТИП(Документ.ЗаказКлиента) истинно и для пустой ссылки на заказ. Нужен заполненный — добавьте И Основание <> ЗНАЧЕНИЕ(Документ.ЗаказКлиента.ПустаяСсылка).ИЛИ Поле ЕСТЬ NULL; сравнение = NULL тоже не работает.&НаКлиенте, а объекта Запрос на клиенте нет. Перенесите его в серверную функцию вместе со сборкой массива типов.ССЫЛКА принимает одну таблицу. Передайте массив Документы.ТипВсеСсылки().Типы() и напишите ТИПЗНАЧЕНИЯ(Поле) В (&ТипыДокументов); для справочников — Справочники.ТипВсеСсылки(). Список длинный, но сравнивается всё равно только код типа.
Передают не сам объект, а его типы: ТИПЗНАЧЕНИЯ сравнивают со значением Тип или списком таких значений, поэтому в параметр кладут массив из Типы(). Обратно описание типов приходит само: Таблица.Колонки.Найти("Регистратор").ТипЗначения у выгруженного результата. Подробно — в статье «Описание типов 1С».
Смысл один, синтаксис разный: ТипЗнч(Значение) = Тип("ДокументСсылка.РеализацияТоваровУслуг") против ТИПЗНАЧЕНИЯ(Поле) = ТИП(Документ.РеализацияТоваровУслуг). Отбирать записи по типу лучше в запросе — лишние строки не придут из базы. Проверки в коде — в статье «Тип значения 1С».
Для двух-трёх видов — ВЫБОР КОГДА Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг ТОГДА "Реализация" прямо в запросе. Для любого числа видов выводите ТИПЗНАЧЕНИЯ и берите синоним через Метаданные.НайтиПоТипу(), как во втором примере. ПРЕДСТАВЛЕНИЕ(Регистратор) не подойдёт: это представление самого документа, с номером и датой.
Если нужен отчёт по регистру с разбивкой по видам документов или запрос с составными полями тормозит и его пора переписать, передайте задачу программисту: разработка отчётов и обработок 1С. Разместите задачу бесплатно — оценка тоже бесплатная, ответ в течение рабочего дня.
Станьте частью сообщества!
Войдите или зарегистрируйтесь, и вы сможете участвовать в обсуждениях.