В практике разработки на платформе 1С нередко возникают задачи, когда данные, вводимые в справочнике, должны дублироваться или фиксироваться в регистре сведений. Несмотря на то что термин «движения» традиционно относится к документам, программная запись в регистры из справочников — это стандартная задача для хранения настроек, цен, дополнительных характеристик или истории изменений объекта. Рассмотрим подробнее, как реализовать этот механизм корректно, избегая типичных ошибок новичков.
Проанализируем ситуацию, которая чаще всего ставит разработчиков в тупик. При попытке записать данные в регистр система выдает ошибку: «Не установлен отбор по регистратору».
В системе 1С существует два режима записи в регистр сведений:
Регистратор.Если вы пытаетесь писать в регистр из справочника и получаете вышеуказанную ошибку, это означает, что ваш регистр имеет режим записи «Подчинение регистратору». Помните: справочник не может быть регистратором. Единственный способ записывать данные в такой регистр из справочника — это создавать вспомогательный документ, что архитектурно не всегда оправдано. Поэтому для работы со справочником в свойствах регистра на вкладке «Основные» должен быть установлен режим записи «Независимый».
Посмотрим на два основных инструмента для работы с записями регистра. Программисту доступны РегистрСведенийМенеджерЗаписи и РегистрСведенийНаборЗаписей. Выбор зависит от конкретной задачи.
Менеджер записи удобен, если нам нужно работать с одной-единственной строкой регистра. Он ведет себя подобно объекту (как справочник или документ): мы можем его прочитать, изменить ресурсы и записать. Однако при работе из справочника, особенно если у одного элемента справочника может быть несколько строк в регистре, использование менеджера записи становится неэффективным.
Набор записей — это более мощный инструмент. Проанализируем ситуацию: когда мы нажимаем кнопку «Записать» в справочнике, нам нужно актуализировать данные в регистре. Набор записей позволяет одним вызовом метода Записать() удалить старые данные по конкретному объекту и записать новые.
Рассмотрим пример кода, который часто приводит к катастрофическим последствиям — полной очистке регистра. Для быстрой подготовки таких фрагментов кода можно использовать генерацию кода по ссылке, включая движения. Проанализируем вредный пример:
НаборЗаписей = РегистрыСведений.ЦеныНоменклатуры.СоздатьНаборЗаписей();
НоваяЗапись = НаборЗаписей.Добавить();
НоваяЗапись.Номенклатура = СсылкаНаСправочник;
НоваяЗапись.Цена = 100;
НаборЗаписей.Записать(); // ВНИМАНИЕ: Это удалит ВСЕ записи в регистре перед записью одной новой!
Чтобы не «похерить» все данные, мы обязательно должны использовать Отбор. Метод Записать() без установленного отбора очищает весь регистр.
Разберем правильный алгоритм по шагам:
НаборЗаписей.Номенклатура или Владелец).Записать().Посмотрим на корректный пример реализации:
// Код в модуле объекта справочника
Набор = РегистрыСведений.ДополнительныеСведения.СоздатьНаборЗаписей();
// Устанавливаем жесткий отбор по текущему объекту
Набор.Отбор.Объект.Установить(ЭтотОбъект.Ссылка);
// Если нужно добавить новые записи из табличной части справочника
Для Каждого СтрокаТЧ Из ЭтотОбъект.Состав Цикл
НоваяЗапись = Набор.Добавить();
НоваяЗапись.Объект = ЭтотОбъект.Ссылка;
НоваяЗапись.Свойство = СтрокаТЧ.Свойство;
НоваяЗапись.Значение = СтрокаТЧ.Значение;
КонецЦикла;
// Система удалит старые записи только по ЭТОМУ объекту и запишет новые
Набор.Записать();
Часто новички пишут логику в Модуле формы (например, в событии ПослеЗаписиНаСервере). Это допустимо, но не является хорошей практикой.
Почему лучше использовать Модуль объекта? Если данные в справочник будут загружаться программно, код в форме просто не сработает. Чтобы данные в регистре всегда были актуальными, используйте обработчик ПриЗаписи. Однако, если вам требуется сложная логика, выполняемая строго после завершения транзакции, можно внедрить самодельный обработчик ПослеЗаписи объекта.
Также не забывайте про ПередУдалением — это обязательное место для очистки регистра. В отличие от подчиненных регистров, данные в независимом регистре не удаляются автоматически при удалении элемента справочника.
Если ваш регистр сведений является периодическим, важно помнить о поле Период. При записи из справочника вы должны явно указать дату (например, ТекущаяДата() или реквизит объекта). Если не заполнить период, 1С запишет данные на 01.01.0001, что приведет к ошибкам в отчетах.
В независимом регистре уникальность записи определяется набором его Измерений. Если вы используете НаборЗаписей с установленным отбором по ключевому измерению, задвоение вам не грозит, так как набор полностью перезаписывает данные по этому фильтру. Всегда проверяйте, чтобы набор измерений в регистре был достаточным для обеспечения уникальности ваших данных в контексте одного элемента справочника.