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

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

Как перезаписать запись в регистре сведений 1С программно

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

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

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

Ниже разобраны оба подхода с готовым кодом, указаны ограничения, типичные ошибки и способы проверить результат. Примеры приведены на встроенном языке 1С:Предприятие 8.3 и подходят для управляемых и обычных форм.

Как устроена перезапись: ключ записи и режимы регистра

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

Прежде чем писать код, откройте свойства регистра в конфигураторе и проверьте три параметра: режим записи (независимый или подчинён регистратору), периодичность (непериодический, в пределах секунды/дня/месяца и т.д.) и состав измерений. От этого напрямую зависит, какой метод доступен и какие поля нужно заполнять для отбора.

Перезапись одиночной записи через менеджер записи

Менеджер записи подходит для независимых регистров, когда нужно изменить одну конкретную запись. Сначала заполняются поля ключа, затем вызывается Прочитать() — объект заполняется текущими данными из базы. После этого меняются нужные ресурсы и вызывается Записать().

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

МенеджерЗаписи.Номенклатура = НоменклатураСсылка;

МенеджерЗаписи.ВидЦены = ВидЦеныСсылка;

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

МенеджерЗаписи.Прочитать();

Если МенеджерЗаписи.Выбран() Тогда

МенеджерЗаписи.Цена = НоваяЦена;

МенеджерЗаписи.Записать();

Иначе

// Записи с таким ключом нет — Записать() создаст новую

МенеджерЗаписи.Цена = НоваяЦена;

МенеджерЗаписи.Записать();

КонецЕсли;

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

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

Перезапись через набор записей с отбором

Набор записей — универсальный инструмент. Он обязателен для регистров, подчинённых регистратору, и удобен, когда нужно перезаписать несколько записей за одну операцию. Логика такая: устанавливается отбор, набор читается, строки изменяются, набор записывается с замещением.

НаборЗаписей = РегистрыСведений.КурсыВалют.СоздатьНаборЗаписей();

НаборЗаписей.Отбор.Валюта.Установить(ВалютаСсылка);

НаборЗаписей.Отбор.Период.Установить(НужнаяДата);

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

Если НаборЗаписей.Количество() > 0 Тогда

Запись = НаборЗаписей[0];

Запись.Курс = НовыйКурс;

НаборЗаписей.Записать(); // по умолчанию с замещением

КонецЕсли;

По умолчанию Записать() вызывается с параметром Замещение = Истина: набор полностью заменяет все записи, попадающие под отбор. Если в базе по этому отбору было три записи, а в наборе вы оставили одну — две остальные будут удалены. Чтобы добавить записи без удаления существующих, используйте НаборЗаписей.Записать(Ложь).

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

Массовая перезапись и транзакции

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

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

НачатьТранзакцию();

Попытка

Выборка = Запрос.Выполнить().Выбрать();

Пока Выборка.Следующий() Цикл

МенеджерЗаписи = РегистрыСведений.ПараметрыУчета.СоздатьМенеджерЗаписи();

МенеджерЗаписи.Организация = Выборка.Организация;

МенеджерЗаписи.Прочитать();

Если МенеджерЗаписи.Выбран() Тогда

МенеджерЗаписи.Значение = НовоеЗначение;

МенеджерЗаписи.Записать();

КонецЕсли;

КонецЦикла;

ЗафиксироватьТранзакцию();

Исключение

ОтменитьТранзакцию();

ЗаписьЖурналаРегистрации("Перезапись регистра",

УровеньЖурналаРегистрации.Ошибка, , ,

ОписаниеОшибки());

ВызватьИсключение;

КонецПопытки;

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

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

Типичные ошибки при перезаписи

Самая частая ошибка — неполный ключ. Если в периодическом регистре забыть заполнить Период, отбор не совпадёт с существующей записью, и вместо перезаписи будет создана новая запись с пустой или текущей датой. Внешне это выглядит как «запись не обновилась», а в регистре появляются дубли.

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

Отдельно стоит упомянуть обмен данными. При записи в рамках обмена или фоновой синхронизации следует устанавливать ОбменДанными.Загрузка = Истина у объекта, чтобы не срабатывали подписки на события и бизнес-логика записи. Но делать это нужно осознанно: вместе с проверками отключается и контроль корректности данных.

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

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

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

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

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

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

Повторное чтение по ключу
Норма

Выбран() = Истина, ресурсы равны новым значениям

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

Запись не найдена или содержит старые значения

Количество записей по измерениям
Норма

Ровно одна запись на комбинацию измерений и периода

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

Две и более записи — признак дубля из-за неверного ключа

Журнал регистрации
Норма

Нет ошибок записи и отказов в транзакции

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

Ошибки блокировок, отказ в проведении транзакции

Выбор способа под задачу

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

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

Менеджер записи

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

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

Подчинённые регистры и групповые операции. Требует аккуратности с замещением — можно удалить лишние записи под отбором.

Запрос + обход выборки

Массовая перезапись по сложному условию. Медленнее на больших объёмах, требует транзакции и контроля блокировок.

Практическое правило: если вы точно знаете ключ одной записи — берите менеджер записи; если работаете с движениями документа или группой записей — набор записей; если сначала нужно найти записи по условию — запрос с последующей записью в транзакции.

Итог

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

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

Частые вопросы

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

Технически — да, через набор записей с отбором по регистратору: прочитать набор, изменить строки и записать. Но это создаёт рассогласование с данными документа и ломает логику учёта. Корректный путь — изменить данные документа и перепровести его, либо использовать документ «Корректировка регистров», если он предусмотрен конфигурацией.

Почему после Записать() появляется новая запись вместо обновления старой?

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

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

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

Нужно ли устанавливать ОбменДанными.Загрузка при перезаписи?

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

Как перезаписать большое количество записей без блокировок?

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

Чем отличается Записать(Истина) от Записать(Ложь) у набора записей?

Записать(Истина) — замещение: набор полностью заменяет все записи под отбором, отсутствующие в наборе записи удаляются. Записать(Ложь) — добавление: строки набора записываются поверх существующих, совпадающие по ключу перезаписываются, остальные записи под отбором сохраняются.