К статье
Практический материал

Разработка и Конфигурация · 11 мин

1С: запись в регистр сведений, подчинённый регистратору

Как программно записать данные в регистр сведений, подчинённый регистратору, в 1С: набор записей, движения документа, типовые ошибки и проверка результата.

Регистр сведений, подчинённый регистратору, — это регистр, каждая запись которого жёстко привязана к документу-регистратору. В отличие от независимого регистра сведений, здесь нельзя просто создать менеджер записи и сохранить строку: платформа требует указать регистратор, а сам набор записей живёт и умирает вместе с документом. Такая модель используется, когда данные имеют смысл только в контексте конкретного документа — например, дополнительные параметры проведения, история согласования или расшифровки, сформированные при проведении.

Главное следствие подчинённости: запись выполняется через объект «Набор записей» с установленным отбором по регистратору, либо через коллекцию «Движения» самого документа. Второй способ предпочтителен при проведении, первый — когда нужно изменить данные вне обработки проведения, например из внешней обработки или при программной корректировке.

Ниже разобраны оба подхода с примерами кода на встроенном языке, типичные ошибки (запись без отбора, потеря данных при перепроведении, конфликт с обработкой проведения) и способы проверить, что данные действительно попали в базу.

Чем подчинённый регистратору регистр отличается от независимого

При создании регистра сведений в конфигураторе свойство «Режим записи» принимает два значения: «Независимый» и «Подчинение регистратору». В независимом режиме каждая запись существует сама по себе, уникальность обеспечивается комбинацией измерений и периода. В подчинённом режиме у каждой записи появляется служебное поле «Регистратор», которое входит в ключ уникальности и не может быть пустым.

Из этого вытекают практические ограничения. Менеджер записи (РегистрыСведений.Имя.СоздатьМенеджерЗаписи()) для подчинённого регистра работает с ограничениями: записать через него строку без регистратора нельзя, поэтому основной инструмент — набор записей. Удаление документа-регистратора автоматически удаляет его записи в регистре, а отмена проведения очищает движения — это удобно, но требует аккуратности при ручных правках.

Способ 1: запись через набор записей с отбором по регистратору

Универсальный вариант, который работает в любом контексте — во внешней обработке, в регламентном задании, в кнопке формы. Алгоритм: создать набор записей, установить отбор по регистратору, добавить строки, заполнить измерения и ресурсы, вызвать Записать(). Отбор по регистратору обязателен: без него метод Записать() либо завершится ошибкой, либо затронет чужие данные.

НаборЗаписей = РегистрыСведений.ПараметрыДокумента.СоздатьНаборЗаписей();

НаборЗаписей.Отбор.Регистратор.Установить(СсылкаНаДокумент);

НоваяЗапись = НаборЗаписей.Добавить();

НоваяЗапись.Регистратор = СсылкаНаДокумент;

НоваяЗапись.Период = СсылкаНаДокумент.Дата;

НоваяЗапись.Сотрудник = ТекущийСотрудник; // измерение

НоваяЗапись.Комментарий = "Сформировано обработкой"; // ресурс

НаборЗаписей.Записать();

Обратите внимание: метод Записать() по умолчанию полностью замещает существующий набор записей этого регистратора. Если нужно добавить строку к уже существующим, сначала вызовите НаборЗаписей.Прочитать(), затем добавьте строку и запишите. Если регистр периодический, поле «Период» заполняется явно; для непериодического его нет.

Порядок действий
  1. 1
    Получите ссылку на документ-регистратор (он должен существовать в базе)
  2. 2
    Создайте набор записей через РегистрыСведений.Имя.СоздатьНаборЗаписей()
  3. 3
    Установите отбор: НаборЗаписей.Отбор.Регистратор.Установить(Ссылка)
  4. 4
    При необходимости прочитайте существующие записи методом Прочитать()
  5. 5
    Добавьте строки и заполните измерения, ресурсы, период
  6. 6
    Вызовите НаборЗаписей.Записать() и проверьте результат запросом

Способ 2: запись через Движения в обработке проведения

Если регистр заполняется при проведении документа, правильное место для кода — процедура ОбработкаПроведения в модуле объекта. Документ должен быть отмечен как регистратор в свойствах регистра (галочка в списке «Регистраторы» на закладке «Регистраторы» регистра или в свойствах документа). Тогда в модуле доступна коллекция Движения.

Процедура ОбработкаПроведения(Отказ, РежимПроведения)

Движения.ПараметрыДокумента.Записывать = Истина;

Для Каждого СтрокаТЧ Из Товары Цикл

Движение = Движения.ПараметрыДокумента.Добавить();

Движение.Период = Дата;

Движение.Номенклатура = СтрокаТЧ.Номенклатура;

Движение.Количество = СтрокаТЧ.Количество;

КонецЦикла;

КонецПроцедуры

Регистратор и период при таком подходе платформа подставляет автоматически: регистратором становится сам документ. Строка Движения.ИмяРегистра.Записывать = Истина нужна, чтобы набор был записан даже если он пуст — например, чтобы при перепроведении очистить старые движения, если в этот раз строк не добавлено. Сама запись в базу выполняется платформой при завершении проведения, явный вызов Записать() обычно не требуется.

Как добавить записи к существующим, не стирая их

Частая задача: документ уже проведён, нужно дописать строку в его подчинённый регистр, не теряя текущие данные. Здесь два нюанса. Во-первых, набор записей нужно прочитать перед добавлением. Во-вторых, если документ проведён, ручная правка его движений будет потеряна при следующем перепроведении — обработка проведения сформирует движения заново.

НаборЗаписей = РегистрыСведений.ПараметрыДокумента.СоздатьНаборЗаписей();

НаборЗаписей.Отбор.Регистратор.Установить(СсылкаНаДокумент);

НаборЗаписей.Прочитать(); // загружаем существующие строки

НоваяЗапись = НаборЗаписей.Добавить();

НоваяЗапись.Регистратор = СсылкаНаДокумент;

НоваяЗапись.Период = ТекущаяДатаСеанса();

НоваяЗапись.Сотрудник = Сотрудник;

НаборЗаписей.Записать();

Если дополнительные данные должны переживать перепроведение, лучше либо доработать обработку проведения, чтобы она сама формировала эти строки, либо вынести данные в независимый регистр сведений с измерением «Документ». Ручная правка движений проведённого документа — временное решение.

Сравнение вариантов

Набор записей с отбором по регистратору

Подходит для внешних обработок, исправлений и сервисных операций. Ограничение: при перепроведении документа ручные правки движений будут потеряны.

Коллекция Движения в ОбработкеПроведения

Правильный способ для данных, формируемых при проведении. Записи автоматически очищаются и пересоздаются при перепроведении.

Независимый регистр с измерением «Документ»

Альтернатива, когда данные не должны зависеть от проведения. Минус: нет автоматической очистки при удалении документа, нужна своя логика контроля.

Типичные ошибки и как их избежать

Самая распространённая ошибка — попытка записать набор без отбора по регистратору. Платформа либо выдаст исключение, либо (что хуже) при определённых настройках запись пройдёт некорректно. Вторая по частоте — использование СоздатьМенеджерЗаписи() для подчинённого регистра без указания регистратора: менеджер записи просто не предназначен для такого сценария.

Третья группа проблем связана с транзакциями и правами. Запись набора выполняется в транзакции текущего вызова; если она происходит внутри длительной операции, возможны блокировки при параллельной работе пользователей. Также у пользователя должны быть права на изменение регистра — при недостатке прав Записать() вызовет исключение «Нарушение прав доступа».

Типичные ошибки
01
Записать() без отбора по регистратору — ошибка выполнения или повреждение чужих данных
02
Добавление строк без Прочитать() — старые записи регистратора полностью замещаются и теряются
03
Ручная правка движений проведённого документа — изменения исчезают при первом же перепроведении
04
Запись набора внутри ОбработкиПроведения вместо коллекции Движения — двойная запись и конфликт с механизмом проведения
05
Не установлен флаг Записывать = Истина у пустого набора — старые движения не очищаются при перепроведении

Как проверить, что запись прошла успешно

После записи убедитесь, что данные реально в базе. Самый быстрый способ в режиме предприятия — открыть регистр через команду «Перейти» из формы документа (если настроена) или через универсальный отчёт / консоль запросов. Программно проверка делается запросом с отбором по регистратору:

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ *

|ИЗ РегистрСведений.ПараметрыДокумента КАК Параметры

|ГДЕ Параметры.Регистратор = &Регистратор";

Запрос.УстановитьПараметр("Регистратор", СсылкаНаДокумент);

Результат = Запрос.Выполнить().Выгрузить();

Дополнительно проверьте количество строк и значения ключевых измерений. Если запрос возвращает пустую таблицу, типичные причины: запись выполнялась в транзакции, которая откатилась; отбор в запросе не совпадает по типу ссылки; документ после записи был перепроведён и движения перезаписаны.

Контрольные точки

Как проверить результат

Запрос по регистратору возвращает строки
Норма

Количество и содержимое строк совпадает с добавленными

Тревожный признак

Пустой результат — запись не выполнилась или транзакция откачена

Регистратор в записях
Норма

Поле Регистратор заполнено ссылкой на нужный документ

Тревожный признак

Пустой регистратор — запись не сохранится или будет отвергнута

Поведение при перепроведении
Норма

Движения формируются обработкой проведения и восстанавливаются корректно

Тревожный признак

После перепроведения ручные строки исчезают — нужна доработка логики

Ограничения и когда выбрать другой механизм

Подчинённый регистратору регистр сведений не подходит, если данные должны существовать без документа, изменяться независимо от проведения или редактироваться пользователями вручную через список. В таких случаях используйте независимый регистр сведений, а связь с документом храните в обычном измерении.

Также учитывайте, что записи подчинённого регистра удаляются вместе с регистратором без возможности восстановления (кроме как из резервной копии). Если данные представляют самостоятельную ценность — например, история изменений, которую нельзя терять, — подчинение регистратору создаёт риск их потери при удалении документов в ходе свёртки или чистки базы.

FAQ: частые вопросы о записи в подчинённый регистр

Можно ли записать в подчинённый регистр через СоздатьМенеджерЗаписи()?

Формально объект создаётся, но для подчинённого регистратора регистра этот способ практически не применяется: менеджер записи не работает с набором, а запись без регистратора невозможна. Используйте набор записей с отбором по регистратору — это штатный и надёжный путь.

Почему после Записать() пропали старые записи документа?

Метод Записать() по умолчанию замещает весь набор записей регистратора. Чтобы дополнить существующие строки, сначала вызовите Прочитать(), затем добавляйте новые записи и только потом записывайте.

Нужно ли проводить документ, чтобы записать в его подчинённый регистр?

Нет. Записать набор с отбором по регистратору можно для любого существующего в базе документа, даже непроведённого. Но при следующем проведении движения будут сформированы заново обработкой проведения, и ручные записи исчезнут.

Как очистить все записи регистра для конкретного документа?

Создайте набор записей, установите отбор по регистратору и вызовите Записать() без добавления строк — пустой набор заместит существующие записи. Альтернатива внутри проведения: Движения.ИмяРегистра.Записывать = Истина без добавления движений.

Что делать, если при записи возникает ошибка блокировки?

Ошибка «Конфликт блокировок» означает, что другой сеанс изменяет этот документ или его движения. Повторите попытку позже, сократите длительность своей транзакции и не держите набор записей открытым между чтением и записью дольше необходимого.

Итог

Что важно запомнить

В подчинённый регистратору регистр сведений пишут через набор записей с обязательным отбором по регистратору либо через коллекцию Движения в обработке проведения. Записать() замещает весь набор — читайте перед добавлением. Ручные правки движений не переживают перепроведение, а перед массовыми операциями делайте копию базы.