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