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