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