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