Работа с регистрами накопления и бухгалтерии в 1С:Предприятие 8 часто требует анализа поля Регистратор․ Поскольку это поле имеет составной тип (может ссылаться на различные документы), программисту необходимо уметь определять конкретный тип документа-регистратора прямо в тексте запроса․ В этой статье подробно разбираются все актуальные способы решения этой задачи․
Теоретические основы
Поле Регистратор в регистрах накопления представляет собой ссылку на объект метаданных типа Документ․ В отличие от измерений, которые могут ссылаться на справочники, регистратор всегда документ․ Однако в одном регистре регистраторами могут выступать несколько разных видов документов (например, РеализацияТоваровУслуг, ПоступлениеТоваровУслуг, СписаниеТоваров и т․д․)․
Язык запросов 1С предоставляет специальные операторы для работы с составными типами данных:
- ТИПЗНАЧЕНИЯ(Поле) — возвращает строковое представление типа значения (например,
ДокументСсылка․РеализацияТоваровУслуг)․ - ТИП(Метаданные) — получает описание типа по объекту метаданных (например,
ТИП(Документ․РеализацияТоваровУслуг))․ - ВЫБОР КОГДА ․․․ ТОГДА ․․․ ИНАЧЕ ․․․ КОНЕЦ — конструкция для условной логики (аналог CASE/IF)․
- ВЫРАЗИТЬ(Поле КАК Тип) — приведение поля составного типа к конкретному типу для доступа к реквизитам конкретного документа․
- ССЫЛКА, оператор проверки типа в условии
ГДЕ(доступен в новых версиях платформы)․
Основные способы определения типа регистратора
Использование функции ТИПЗНАЧЕНИЯ в секции ВЫБРАТЬ
Самый прямой способ — вывести тип регистратора в результат запроса для анализа или группировки․
ВЫБРАТЬ
Взаиморасчеты․Регистратор КАК Регистратор,
ТИПЗНАЧЕНИЯ(Взаиморасчеты․Регистратор) КАК ТипРегистратора,
Взаиморасчеты․СуммаОборот
ИЗ
РегистрНакопления․ВзаиморасчетыСКонтрагентами КАК Взаиморасчеты Результат: В поле ТипРегистратора вернется строка вида ДокументСсылка․РеализацияТоваровУслуг․
Фильтрация по типу в секции ГДЕ (Оператор В)
Для отбора записей только определенных типов документов удобно использовать оператор В со списком типов, полученных через функцию ТИП․
ВЫБРАТЬ
ТоварныеЗапасы․Регистратор,
ТоварныеЗапасы․Номенклатура,
ТоварныеЗапасы․КоличествоОборот
ИЗ
РегистрНакопления․ТоварныеЗапасы КАК ТоварныеЗапасы
ГДЕ
ТИПЗНАЧЕНИЯ(ТоварныеЗапасы․Регистратор) В
(ТИП(Документ․ПоступлениеТоваровУслуг),
ТИП(Документ․ПеремещениеТоваров)) Важно: В параметрах запроса можно передать массив типов (Массив), заполненный через Метаданные․Документы․ИмяДокумента․
Оператор ССЫЛКА (Современный синтаксис)
Начиная с платформы 8․3․18+ (проверяйте актуальность для своей версии), в секции ГДЕ можно использовать более читаемую конструкцию ССЫЛКА․
ГДЕ
ТоварныеЗапасы․Регистратор ССЫЛКА Документ․РасходТовара
// Или для списка:
// ТоварныеЗапасы․Регистратор ССЫЛКА Документ․РасходТовара, Документ․СписаниеТоваров Конструкция ВЫБОР для получения читаемого имени типа
Чтобы получить не техническое имя типа (ДокументСсылка․․․․), а понятное название (например, «Реализация», «Поступление»), используют ВЫБОР․
ВЫБРАТЬ
Продажи․Регистратор КАК Регистратор,
ВЫБОР
КОГДА ТИПЗНАЧЕНИЯ(Продажи․Регистратор) = ТИП(Документ․ОтгрузкаТоваров)
ТОГДА "Накладная (Отгрузка)"
КОГДА ТИПЗНАЧЕНИЯ(Продажи․Регистратор) = ТИП(Документ․РеализацияТоваровУслуг)
ТОГДА "Реализация (Услуги)"
ИНАЧЕ "Прочий документ"
КОНЕЦ КАК ВидДокумента
ИЗ
РегистрНакопления․Продажи КАК Продажи Работа с реквизитами конкретного документа-регистратора
Часто требуется не просто узнать тип, а получить доступ к реквизитам или табличным частям конкретного документа (например, Номер, Дата, Контрагент или строки ТЧ)․
Разыменование через точку (неявное приведение)
Если в запросе обратиться к реквизиту, который есть не во всех документах-регистраторах, платформа вернет NULL для несоответствующих типов․
ВЫБРАТЬ
Взаиморасчеты․Регистратор․Номер КАК НомерДок,
Взаиморасчеты․Регистратор․Контрагент КАК Контрагент
// Если у документа нет поля Контрагент, вернется NULL
ИЗ
РегистрНакопления․ВзаиморасчетыСКонтрагентами КАК Взаиморасчеты Явное приведение типа: ВЫРАЗИТЬ(․․․ КАК ․․․)
Это профессиональный подход, гарантирующий доступ к реквизитам конкретного вида документа и корректную работу оптимизатора запросов․
ВЫБРАТЬ
ВЫРАЗИТЬ(Продажи․Регистратор КАК Документ․РеализацияТоваровУслуг)․Номер КАК НомерРеал,
ВЫРАЗИТЬ(Продажи․Регистратор КАК Документ․РеализацияТоваровУслуг)․Контрагент КАК КонтрагентРеал
ИЗ
РегистрНакопления․Продажи КАК Продажи
ГДЕ
ТИПЗНАЧЕНИЯ(Продажи․Регистратор) = ТИП(Документ․РеализацияТоваровУслуг) Получение реквизитов табличной части регистратора
Для доступа к табличной части нужно использовать соединение (СОЕДИНЕНИЕ) с табличной частью документа, предварительно приведя регистратор к нужному типу․
ВЫБРАТЬ
Реал․Номенклатура,
Реал․Количество,
Продажи․Регистратор․Номер КАК НомерДок
ИЗ
РегистрНакопления․Продажи КАК Продажи
ЛЕВОЕ СОЕДИНЕНИЕ Документ․РеализацияТоваровУслуг․Товары КАК Реал
ПО ВЫРАЗИТЬ(Продажи․Регистратор КАК Документ․РеализацияТоваровУслуг) = Реал․Ссылка
ГДЕ
ТИПЗНАЧЕНИЯ(Продажи․Регистратор) = ТИП(Документ․РеализацияТоваровУслуг) Передача типов через параметры запроса
Жесткое кодирование типов в тексте запроса (ТИП(Документ․Имя)) удобно, но негибко․ Лучше передавать список типов параметром․
Пример кода на встроенном языке:
Запрос = Новый Запрос;
Запрос․Текст =
"ВЫБРАТЬ
| Остатки․Регистратор,
| Остатки․Номенклатура,
| Остатки․КоличествоОстаток
|ИЗ
| РегистрНакопления․ТоварыНаСкладах․Остатки КАК Остатки
|ГДЕ
| ТИПЗНАЧЕНИЯ(Остатки․Регистратор) В (&МассивТиповРегистраторов)";
// Формируем массив типов
МассивТипов = Новый Массив;
МассивТипов․Добавить(Метаданные․Документы․ПоступлениеТоваровУслуг);
МассивТипов․Добавить(Метаданные․Документы․ПеремещениеТоваров);
// Можно добавить любой другой документ
Запрос․УстановитьПараметр("МассивТиповРегистраторов", МассивТипов);
Результат = Запрос․Выполнить; Особенности производительности и оптимизации
- Индексы: Поле
Регистраториндексируется автоматически․ УсловияТИПЗНАЧЕНИЯ(․․․) В (․․․)иССЫЛКАэффективно используют индексы․ - Избегайте ВЫБОР в ГДЕ: Конструкция
ГДЕ ВЫБОР КОГДА ТИПЗНАЧЕНИЯ(․․․) = ТИП(․․․) ТОГДА ИСТИНА ИНАЧЕ ЛОЖЬ КОНЕЦработает медленнее, чем нативныйВилиССЫЛКА․ - Временные таблицы: Если запрос сложный и многократно фильтруется по типу регистратора, выгодно сначала отобрать нужные типы во временную таблицу (
ПОМЕСТИТЬ ВТ_Отбор), а затем соединять с ней․ - Полнотекстовый поиск по типам: Не используйте
СТРОКА(ТИПЗНАЧЕНИЯ(․․․)) ПОДОБНО "%Реализация%"— это полное сканирование таблицы․
Типичные ошибки и подводные камни
- Сравнение со строкой: Нельзя писать
ТИПЗНАЧЕНИЯ(Регистратор) = "ДокументСсылка․РеализацияТоваровУслуг"․ Сравнивать нужно только с результатом функцииТИП․ - NULL в регистраторе: В регистрах накопления регистратор не может быть NULL (это обязательное системное поле)․ Проверка
Регистратор ЕСТЬ NULLвсегда вернет Ложь․ - Доступ к реквизитам без приведения: Обращение
Регистратор․СпецифичныйРеквизитдля документа, у которого его нет, вернет NULL, но может сбить с толку при анализе данных․ Всегда используйтеВЫРАЗИТЬвнутриВЫБОРили после проверки типа․ - Регистратор vs Записатель: Поле
Записатель(в регистрах бухгалтерии) может иметь типДокументСсылкаилиБизнесПроцессСсылкаи т․д․ Логика определения типа идентична․
Сводная таблица конструкций
| Задача | Рекомендуемая конструкция | Примечание |
|---|---|---|
| Вывести тип в результат | ТИПЗНАЧЕНИЯ(Регистратор) | Возвращает строку метаданных |
| Отбор по одному типу в ГДЕ | ТИПЗНАЧЕНИЯ(Рег) = ТИП(Док․Имя) или Рег ССЫЛКА Док․Имя | ССЫЛКА более читаем (платформа 8․3․18+) |
| Отбор по списку типов | ТИПЗНАЧЕНИЯ(Рег) В (&МассивТипов) | Параметр — Массив из Метаданные․Документы․Имя |
| Получить имя вида документа (строка) | ВЫБОР КОГДА ТИПЗНАЧЕНИЯ(Рег)=ТИП(Док․Имя) ТОГДА "Имя" КОНЕЦ | Для отчетов пользователю |
| Доступ к реквизиту конкретного док․ | ВЫРАЗИТЬ(Рег КАК Док․Имя)․Реквизит | Обязательно после проверки типа в ГДЕ |
| Соединение с ТЧ документа | ЛЕВОЕ СОЕДИНЕНИЕ Док․Имя․ТЧ КАК ТЧ ПО ВЫРАЗИТЬ(Рег КАК Док․Имя) = ТЧ․Ссылка | Только для документов нужного типа |
Умение корректно определять и использовать тип регистратора — базовый навык 1С-разработчика․ Главные правила:
- Используйте ТИПЗНАЧЕНИЯ для анализа и ТИП для эталона сравнения․
- Для фильтрации применяйте оператор В с массивом типов, переданным параметром․
- Для доступа к уникальным реквизитам документа обязательно используйте ВЫРАЗИТЬ(․․․ КАК ․․․)․
- Следите за версиями платформы: оператор ССЫЛКА делает код чище и понятнее․
Правильное применение этих техник позволяет писать быстрые, надежные и читаемые запросы для любых отчетов и обработок данных․