Разработка и Конфигурация · 9 мин
Как выразить регистратор как документ в 1С
Как выразить регистратор как документ в 1С с помощью ВЫРАЗИТЬ в запросе, зачем это нужно, типовые ошибки и примеры кода для регистров накопления и сведений.
Регистратор в 1С — это ссылка на документ, который создал движения по регистру. Проблема в том, что поле «Регистратор» имеет составной тип: в одном регистре движения могут формировать документы разных видов — «Поступление товаров», «Реализация товаров», «Списание» и другие. Из-за этого платформа не позволяет напрямую обратиться к реквизитам регистратора через точку в запросе или коде: система не знает заранее, какой именно документ окажется в поле.
Задача «выразить регистратор как документ» возникает, когда нужно получить из движений регистра реквизиты документа-регистратора: контрагента, склад, дату, номер, организацию. Решается она двумя способами — оператором ВЫРАЗИТЬ в языке запросов или методом ПолучитьОбъект() / проверкой типа в коде. Правильный выбор зависит от того, где выполняется обработка данных.
Ниже разобраны оба подхода с примерами, типичные ошибки, которые приводят к пустым значениям и ошибкам запроса, и способы проверить результат.
Что такое регистратор и почему его нельзя использовать напрямую
Каждая запись регистра (накопления, сведений, бухгалтерии, расчёта) содержит служебное поле «Регистратор». В нём хранится ссылка на документ, сформировавший запись. Если регистр заполняется только одним видом документов, тип поля простой, и обращение Движения.Регистратор.Контрагент сработает без дополнительных действий.
На практике большинство регистров имеет несколько регистраторов. Например, регистр накопления «Товары на складах» заполняют «Поступление товаров», «Реализация товаров», «Перемещение», «Оприходование». Тип поля становится составным, и платформа запрещает «разыменование» через точку: у разных документов разный набор реквизитов, поэтому запрос вида ВЫБРАТЬ Движения.Регистратор.Контрагент завершится ошибкой ещё на этапе проверки.
Как выразить регистратор в запросе через ВЫРАЗИТЬ
Оператор ВЫРАЗИТЬ приводит значение составного типа к конкретному типу. Синтаксис для регистратора выглядит так:
ВЫБРАТЬ
Движения.Номенклатура,
ВЫРАЗИТЬ(Движения.Регистратор КАК Документ.ПоступлениеТоваров) КАК ДокументПоступления,
ВЫРАЗИТЬ(Движения.Регистратор КАК Документ.ПоступлениеТоваров).Контрагент КАК Контрагент
ИЗ
РегистрНакопления.ТоварыНаСкладах КАК Движения
ГДЕ
Движения.Регистратор ССЫЛКА Документ.ПоступлениеТоваров
Ключевые моменты конструкции:
- условие
Регистратор ССЫЛКА Документ.ПоступлениеТоваровотсекает записи других документов — без него ВЫРАЗИТЬ вернёт для них NULL; - после приведения типа к реквизитам документа обращаются через точку:
.Контрагент,.Склад,.Номер; - если реквизит нужен в нескольких местах запроса, выгоднее один раз выразить регистратор в поле и дальше использовать псевдоним, а не повторять ВЫРАЗИТЬ.
Если нужны движения по двум видам документов, используют два выражения и функцию ЕСТЬNULL либо объединение через ОБЪЕДИНИТЬ ВСЕ с отдельным условием ССЫЛКА в каждой части.
- 1Определите, какие виды документов являются регистраторами нужного регистра (свойства регистра, закладка «Регистраторы» в конфигураторе)
- 2Добавьте в запрос условие Регистратор ССЫЛКА Документ.ИмяДокумента
- 3Оберните поле регистратора в ВЫРАЗИТЬ(... КАК Документ.ИмяДокумента)
- 4Обратитесь к нужным реквизитам через точку после приведения типа
- 5Выполните запрос в консоли и проверьте, что поля реквизитов заполнены, а не NULL
Как выразить регистратор в коде модуля
В программном коде оператора ВЫРАЗИТЬ нет — вместо него проверяют тип значения и работают со ссылкой. Типовой приём:
Если ТипЗнч(Запись.Регистратор) = Тип("ДокументСсылка.ПоступлениеТоваров") Тогда
Контрагент = Запись.Регистратор.Контрагент;
КонецЕсли;
Обращение Запись.Регистратор.Контрагент через ссылку безопасно: платформа выполнит неявный запрос к базе и вернёт значение реквизита. Однако внутри цикла по тысячам записей такое обращение порождает отдельный запрос на каждую итерацию — это классическая причина медленной обработки. Правильный подход — собрать ссылки в массив, одним запросом получить реквизиты в соответствие и дальше читать из него.
Метод ПолучитьОбъект() для простого чтения реквизитов не нужен: он вычитывает весь объект документа со всеми табличными частями, что в разы тяжелее. Его применяют только когда документ требуется изменить и записать.
Выбор между запросом и кодом
Оба подхода решают одну задачу, но область применения разная. Сопоставление помогает выбрать без лишних экспериментов.
| Критерий | ВЫРАЗИТЬ в запросе | Проверка типа в коде |
|---|---|---|
| Объём данных | Большие выборки, тысячи записей | Единичные записи, точечная логика |
| Производительность | Один запрос к СУБД | Риск запроса на каждую итерацию |
| Гибкость | Только чтение, декларативная логика | Любая логика, ветвления, изменение данных |
| Типовое применение | Отчёты, СКД, выгрузки | Обработчики, проведение, обмены |
Для отчётов и аналитики однозначно выбирайте ВЫРАЗИТЬ: вся фильтрация и соединения выполняются на стороне СУБД. Для обработчиков проведения или единичных операций достаточно проверки ТипЗнч() в коде.
Как выбрать действие
Типичные ошибки и как их избежать
Самая частая ошибка — забыть условие ССЫЛКА и получить NULL в реквизитах для «чужих» документов. Внешне запрос выполняется без ошибок, поэтому проблему замечают поздно, когда в отчёте пустые контрагенты. Второй симптом той же ошибки — соединение по выраженному регистратору, которое «теряет» строки.
Вторая группа ошибок связана с производительностью: ВЫРАЗИТЬ применяют к полю, по которому идёт соединение больших таблиц, без предварительного отбора. Оптимизатору тяжелее строить план по вычисляемому выражению, поэтому сначала отберите записи условием ССЫЛКА во временную таблицу, а приведение типа делайте уже к ней.
Как проверить результат
Проверка начинается в консоли запросов: выполните запрос и убедитесь, что колонка с выраженным регистратором заполнена ссылками нужного вида, а колонки реквизитов не содержат неожиданных NULL. Затем сравните количество строк с отбором по виду документа и без него — разница покажет, сколько записей формируют другие регистраторы.
Для кода контроль простой: поставьте точку останова после проверки ТипЗнч() и убедитесь, что ветка выполняется именно для ожидаемых документов. Если условие никогда не срабатывает, чаще всего перепутан вид документа или регистр заполняется другим регистратором, чем предполагалось, — фактический список смотрите в свойствах регистра в конфигураторе.
Как проверить результат
Заполнена ссылками нужного вида документа
NULL или ссылки других видов
Значения соответствуют данным документов
Пустые значения при заполненных документах
Один пакетный запрос на всю выборку
Запрос к базе на каждой итерации цикла
FAQ
Можно ли обратиться к реквизитам регистратора без ВЫРАЗИТЬ?
Да, но только к стандартным реквизитам, общим для всех документов: Дата, Номер, Проведён. Они доступны через точку даже при составном типе. Для прикладных реквизитов (Контрагент, Склад, Договор) приведение типа через ВЫРАЗИТЬ обязательно.
Что вернёт ВЫРАЗИТЬ, если регистратор — документ другого вида?
Оператор вернёт NULL, а обращение к реквизиту через точку даст NULL без ошибки выполнения. Поэтому условие ССЫЛКА в запросе обязательно — оно отсекает такие записи на уровне выборки, а не оставляет их с пустыми полями.
Работает ли ВЫРАЗИТЬ с регистратором в СКД?
Да, в наборе данных схемы компоновки работает тот же язык запросов, включая ВЫРАЗИТЬ и ССЫЛКА. Типовой приём — выразить регистратор в поле набора данных, а реквизиты документа вытащить через точку уже в выбранных полях отчёта.
Как в запросе получить движения сразу по двум видам регистраторов?
Используйте ОБЪЕДИНИТЬ ВСЕ двух выборок, в каждой — своё условие ССЫЛКА и своё ВЫРАЗИТЬ. Альтернатива — одна выборка с условием «ССЫЛКА первый ИЛИ ССЫЛКА второй» и извлечением реквизитов через ЕСТЬNULL(ВЫРАЗИТЬ(...КАК Первый).Реквизит, ВЫРАЗИТЬ(...КАК Второй).Реквизит).
Почему запрос с ВЫРАЗИТЬ работает медленно?
Чаще всего приведение типа применяется до отбора данных или участвует в соединении больших таблиц. Сначала поместите во временную таблицу записи, отфильтрованные условием ССЫЛКА и периодом, а ВЫРАЗИТЬ применяйте уже к этой сокращённой выборке — план запроса станет заметно легче.
Что важно запомнить
Регистратор с составным типом приводится к конкретному документу оператором ВЫРАЗИТЬ в запросе или проверкой ТипЗнч() в коде. Всегда сопровождайте приведение условием ССЫЛКА, не читайте реквизиты по ссылке внутри больших циклов и проверяйте результат на NULL в консоли запросов.