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

· 9 мин

Содержание

Перезаписать данные регистра сведений прямо в Конфигураторе нельзя — там меняют структуру регистра, а не его содержимое. Сами записи в 1С 8.3 перезаписывают кодом (менеджер записи или набор записей) либо вручную в списке регистра. Какой способ выбрать для перезаписи — зависит от того, независимый это регистр сведений или подчинён регистратору.

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

Ниже — код с пояснениями, таблица для выбора метода и разбор ошибок, из-за которых данные пропадают после записи.

Независимый или подчинённый регистратору — от этого зависит способ

У каждого регистра сведений есть свойство Режим записи. Посмотреть его можно в Конфигураторе: откройте регистр и найдите это свойство в палитре. Два варианта меняют всё.

🔹 Независимый. Записи живут сами по себе. Их пишут кодом или руками через форму списка. Это настройки, курсы валют, цены, соответствия — то, что заводят напрямую.

🔹 Подчинение регистратору. Записи принадлежат документу-регистратору. Они появляются при проведении документа и исчезают при отмене проведения. Напрямую такие записи обычно не пишут.

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

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

Что проверить перед перезаписью

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

  1. Сделайте резервную копию базы (для файловой — выгрузку в .dt, для клиент-серверной — средствами СУБД). Массовая перезапись необратима штатными средствами.
  2. Определите режим записи регистра — независимый или подчинение регистратору. От этого зависит, писать напрямую или перепроводить документ.
  3. Проверьте, кто читает этот регистр. Если на нём завязаны другие механизмы (ценообразование, остатки, права доступа ), прикиньте, что изменится после перезаписи.
  4. Обкатайте код на копии базы. Запустите обработку на тестовой копии и сверьте результат, прежде чем трогать рабочую базу.
  5. Выберите время. Массовую перезапись запускают в нерабочие часы — она держит блокировки и мешает пользователям.

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

Способы перезаписи регистра сведений: сравнение

Четыре рабочих подхода. Выбор зависит от объёма правки и от того, кто владеет записями.

МетодКогда применятьРиск
Менеджер записиОдна запись по полному набору измерений (и периоду)Минимальный
Набор записей с отборомГруппа записей независимого регистра, очисткаЗамещение удаляет всё под отбором
Запрос в циклеМассовое заполнение из документов или другого регистраБлокировки, время выполнения
Перепроведение / правка вручнуюБез программированияДля подчинённого — только через документ

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

Менеджер записи: перезапись одной записи

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

Пример для периодического независимого регистра цен:

МенеджерЗаписи = РегистрыСведений.ЦеныНоменклатуры.СоздатьМенеджерЗаписи();
МенеджерЗаписи.Период      = ТекущаяДата();
МенеджерЗаписи.Номенклатура = ВыбраннаяНоменклатура;
МенеджерЗаписи.ТипЦен       = ВыбранныйТипЦен;
МенеджерЗаписи.Цена         = 1500;
МенеджерЗаписи.Записать();  // перезапишет запись с таким ключом или создаст новую

Чтобы изменить уже существующее значение, а не задавать его с нуля, запись сначала читают:

МенеджерЗаписи = РегистрыСведений.ЦеныНоменклатуры.СоздатьМенеджерЗаписи();
МенеджерЗаписи.Период       = ДатаЦены;
МенеджерЗаписи.Номенклатура  = ВыбраннаяНоменклатура;
МенеджерЗаписи.ТипЦен        = ВыбранныйТипЦен;
МенеджерЗаписи.Прочитать();           // загрузит текущее значение, если запись найдена
МенеджерЗаписи.Цена = МенеджерЗаписи.Цена * 1.1;
МенеджерЗаписи.Записать();

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

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

В управляемом приложении запись регистра выполняется на сервере. Код менеджера записи размещайте в серверной процедуре (&НаСервере или общий серверный модуль), иначе получите ошибку выполнения на клиенте.

Набор записей: групповая правка и очистка

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

НаборЗаписей = РегистрыСведений.ЦеныНоменклатуры.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Номенклатура.Установить(ВыбраннаяНоменклатура);
НаборЗаписей.Прочитать();
Для Каждого Запись Из НаборЗаписей Цикл
    Запись.Цена = Запись.Цена * 1.1;
КонецЦикла;
НаборЗаписей.Записать();  // замещение по умолчанию Истина

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

Отсюда же приём очистки: установить отбор, прочитать не нужно — просто записать пустой набор.

НаборЗаписей = РегистрыСведений.ЦеныНоменклатуры.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Номенклатура.Установить(СнимаемаяНоменклатура);
НаборЗаписей.Записать();  // набор пуст — записи под отбором будут удалены

Если нужно добавить записи, не трогая существующие, замещение отключают:

НаборЗаписей.Записать(Ложь);  // добавит записи набора, старые не удалит

Все записи в наборе должны соответствовать установленному отбору. Если отбор стоит по одной номенклатуре, а в записи измерение заполнено другой, платформа вернёт ошибку «Запись не соответствует отбору набора записей».

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

Массовая перезапись регистра запросом

Типичная задача — перезаписать регистр по данным из документов или другого регистра. Источник берут запросом, а каждую строку результата пишут менеджером записи.

Запрос = Новый Запрос;
Запрос.Текст =
    "ВЫБРАТЬ
    |    Ном.Ссылка КАК Номенклатура,
    |    Ном.БазоваяЦена КАК Цена
    |ИЗ
    |    Справочник.Номенклатура КАК Ном
    |ГДЕ
    |    НЕ Ном.ПометкаУдаления";

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

НачатьТранзакцию();
Попытка
    Пока Выборка.Следующий() Цикл
        МЗ = РегистрыСведений.ЦеныНоменклатуры.СоздатьМенеджерЗаписи();
        МЗ.Период       = ТекущаяДата();
        МЗ.Номенклатура = Выборка.Номенклатура;
        МЗ.ТипЦен       = ВыбранныйТипЦен;
        МЗ.Цена         = Выборка.Цена;
        МЗ.Записать();
    КонецЦикла;
    ЗафиксироватьТранзакцию();
Исключение
    ОтменитьТранзакцию();
    ВызватьИсключение;
КонецПопытки;

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

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

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

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

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

Запрос = Новый Запрос;
Запрос.Текст =
    "ВЫБРАТЬ
    |    Срез.Номенклатура КАК Номенклатура,
    |    Срез.Цена         КАК Цена
    |ИЗ
    |    РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Дата, ) КАК Срез";
Запрос.УстановитьПараметр("Дата", ТекущаяДата());

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

Перезапись без программирования

Код нужен не всегда. Разовую правку делают прямо в режиме 1С:Предприятие.

Независимый регистр — правка в списке. Сначала включите команду доступа к служебным объектам: Главное меню → Сервис → Параметры (или Настройки → Параметры) → отметьте Отображать команду «Все функции». После этого откройте Главное меню → Все функции → Регистры сведений и выберите нужный регистр. В форме списка записи можно добавлять, изменять и удалять — если для регистра разрешено редактирование. Это и есть ручная перезапись.

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

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

Если записи регистра не меняются после правок в документе, проверьте, не отключено ли проведение по этому регистру в самом документе, и проводится ли документ вообще.

Ошибки при перезаписи и как их устранить

Большинство проблем при перезаписи регистра сведений сводится к нескольким симптомам.

Диагностика: выберите симптом

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

Чем менеджер записи отличается от набора записей?
Менеджер записи работает с одной записью по полному ключу (измерения плюс период). Набор записей — с группой записей по отбору и умеет заменять или очищать сразу несколько строк.
Можно ли перезаписать регистр, подчинённый регистратору, напрямую?
Технически можно установить отбор по регистратору и записать набор, но на практике это не делают: при следующем проведении документа записи перезапишутся. Правьте документ и перепроводите.
Что означает параметр метода Записать()?
Это флаг замещения. При Истина (по умолчанию) записи под отбором заменяются набором. При Ложь набор добавляется к существующим записям, а для менеджера записи повторный ключ вызовет ошибку.
Как полностью очистить независимый регистр сведений?
Создайте набор записей без отбора (или с нужным отбором), не читайте его и вызовите Записать() с пустым набором — все записи под отбором удалятся.
Где запускать код перезаписи?
Удобнее всего во внешней обработке: открыл в режиме 1С:Предприятие, выполнил, закрыл. Сам код записи должен исполняться на сервере.