Работа с регистрами сведений является фундаментальной частью разработки конфигураций на платформе 1С:Предприятие 8. Эти объекты позволяют хранить справочную информацию, настройки системы, курсы валют или остатки, которые не требуют двойной записи, но нуждаются в удобной выборке по измерениям и ресурсам. Понимание того, как корректно записать данные в такие структуры, критически важно для обеспечения целостности базы данных.
Начинающие разработчики часто сталкиваются с трудностями при попытке внести изменения, особенно когда речь идет о регистре с включенной периодичностью. Ошибки в последовательности действий могут привести к тому, что запись просто не сохранится, либо система выдаст предупреждение о дублировании ключа. В этом материале мы детально разберем программные и пользовательские способы добавления записей, а также нюансы обработки различных типов измерений.
Особенности структуры регистра сведений
Прежде чем приступать к записи данных, необходимо четко представлять архитектуру объекта. Регистр сведений состоит из измерений, ресурсов и реквизитов. Измерения формируют уникальный ключ записи, по которому система идентифицирует строку. Если вы попытаетесь создать две записи с одинаковым набором измерений в один и тот же момент времени (для периодических регистров), возникнет конфликт.
Ресурсы — это числовые поля, которые обычно суммируются при выборках, но при прямой записи в регистр сведений они просто хранят свое значение. Важно различать непериодические и периодические регистры. В непериодических регистрах запись ведется по состоянию «на сейчас», и измерение «Период» отсутствует. В периодических жеregistрах каждое изменение фиксируется с привязкой к конкретной дате и времени, что позволяет строить срезы данных на любой момент в прошлом или будущем.
Для разработчика ключевым моментом является выбор типа периодичности: «Непериодический», «В пределах секунды», «В пределах дня», «В пределах месяца» или «В пределах года». От этого зависит точность, с которой система будет сравнивать временные метки при проверке уникальности записей. Например, при периодичности «В пределах дня» две записи с одним набором измерений, созданные в 10:00 и 14:00 одного дня, будут считаться дублями, и вторая запись перезапишет первую или вызовет ошибку в зависимости от режима записи.
⚠️ Внимание: При изменении структуры регистра сведений (добавлении новых измерений) все существующие данные могут стать некорректными. Перед внесением изменений в конфигурацию всегда делайте резервную копию базы данных или используйте режим предприятия для обновления структуры.
Также стоит отметить роль реквизитов. В отличие от ресурсов, они не участвуют в агрегации и служат для хранения текстовой информации, ссылок на документы или булевы флаги. Правильное проектирование структуры на этапе создания метаданных сэкономит вам массу времени при написании программного кода для записи.
Программное добавление записей в коде
Самый распространенный способ наполнения регистра сведений — использование встроенного языка 1С. Для этого создается объект РегистрСведений.ИмяРегистра. Работа с ним напоминает работу с табличным документом или набором строк, где каждая строка соответствует одной записи в базе данных.
Процесс записи начинается с создания менеджера записи. Вы должны явно указать режим записи: Запись.РежимЗаписи = РежимЗаписиРегистраСведений.Запись. Это сообщает системе, что мы намерены добавить новую строку или обновить существующую. Если забыть установить этот режим, объект останется в состоянии чтения, и вызов метода Записать() не приведет к сохранению изменений.
Далее необходимо заполнить ключевые поля. Для периодического регистра обязательно устанавливается свойство Период. Если вы работаете с регистром, подчиненным регистратору, период устанавливается автоматически из связанного документа, но в ручном режиме это ваша ответственность. Затем заполняются все измерения, входящие в состав уникального ключа.
Регистр = РегистрыСведений.КурсыВалют.СоздатьЗапись();
Регистр.РежимЗаписи = РежимЗаписиРегистраСведений.Запись;
Регистр.Период = ТекущаяДата();
Регистр.Валюта = Справочники.Валюты.НайтиПоНаименованию("Доллар США");
Регистр.Курс = 92.50;
Регистр.Записать();
В приведенном примере мы видим классическую схему: создание объекта, настройка режима, присвоение значений измерениям и ресурсам, и финальная фиксация. Обратите внимание, что поле Курс является ресурсом, а Валюта — измерением. Ошибка в присваивании типов данных (например, попытка записать строку в числовое поле) вызовет исключение во время выполнения кода.
Используйте транзакции при массовой записи большого количества строк в регистр сведений. Это ускорит процесс и гарантирует атомарность операции: либо запишутся все данные, либо ни одной.
Если требуется добавить сразу много записей, эффективнее использовать объект НаборЗаписей. Он позволяет загрузить данные из временной таблицы или отбора и сохранить их одним обращением к базе данных, что значительно производительнее цикла с одиночными записями.
Работа с периодичностью и срезами
Периодичность регистра сведений диктует правила игры при добавлении записей. Когда вы создаете новую запись с датой, которая уже существует в базе для данного набора измерений, поведение системы зависит от настроек. Обычно новая запись вытесняет старую, если режим записи установлен корректно.
Однако, существуют нюансы при работе с «Срезами последних» или «Срезами первых». При выборке данных система ищет запись с максимальным (или минимальным) периодом, не превышающим дату среза. Поэтому при добавлении исторических данных важно следить за хронологией. Если вы вставите запись задним числом, она может не попасть в текущий срез, но будет видна при запросе на дату в прошлом.
| Тип периодичности | Точность времени | Особенность записи |
|---|---|---|
| Непериодический | Нет периода | Только одна запись на комбинацию измерений |
| В пределах секунды | До секунды | Максимальная точность, частые обновления |
| В пределах дня | До дня (время обнуляется) | Одна запись на день, время игнорируется |
| В пределах месяца | До месяца | Одна запись на месяц, удобно для итогов |
При использовании периода «В пределах дня» платформа автоматически округляет время записываемой даты до начала суток. Это полезно для хранения ежедневных остатков или курсов, где время суток не имеет значения. Попытка записать две разные версии данных на один день приведет к тому, что вторая версия перезапишет первую без возможности восстановления старой версии через стандартные срезы.
⚠️ Внимание: При работе с периодическими регистрами помните, что удаление записей может нарушить историю изменений. Если требуется отменить запись, лучше создать корректирующую запись с новым периодом, чем физически удалять строку из таблицы.
Для анализа текущей ситуации разработчики часто используют метод ПолучитьПервые или ПолучитьПоследние. Эти методы позволяют быстро извлечь актуальное значение без написания сложных запросов. Однако при массовой записи они не применяются, так как их задача — чтение, а не модификация.
Что происходит при записи в прошлое?
Если вы запишете данные с датой в прошлом, они станут видны в срезах на даты после этой записи. Это может изменить историческую отчетность, поэтому такие операции требуют особой осторожности и согласования с бухгалтерией или аналитиками.
Массовая загрузка данных из внешних источников
Часто возникает задача импорта данных из CSV-файлов, Excel или других информационных систем. В таких случаях построчная запись через цикл будет работать крайне медленно. Оптимальным решением является использование объекта НаборЗаписейРегистраСведений.
Алгоритм действий выглядит следующим образом: сначала создается набор записей, затем в него загружаются данные, например, из результата запроса или временной таблицы. После заполнения всех полей вызывается метод Записать() у самого набора. Платформа сформирует оптимальный SQL-запрос для вставки всех строк пакетом.
- 📂 Создайте объект набора записей:
Набор = РегистрыСведений.НоменклатураНаСкладах.СоздатьНаборЗаписей(). - 📥 Загрузите данные: используйте метод
Загрузить()или цикл по таблице значений, добавляя строки черезНабор.Добавить(). - ✅ Проверьте отбор: убедитесь, что в наборе нет дублирующихся ключей внутри самой выгрузки, чтобы избежать внутренних конфликтов.
- 💾 Выполните запись: вызовите
Набор.Записать()для фиксации всех изменений в базе данных.
Важно контролировать размер пакета данных. Если вы пытаетесь загрузить миллион строк за один раз, может возникнуть переполнение буфера или превышение времени выполнения запроса. В таких случаях рекомендуется разбивать данные на пакеты по 10-50 тысяч записей и обрабатывать их последовательно.
При импорте из внешних источников часто встречаются проблемы с соответствием типов данных. Строка «100,50» из текстового файла не может быть напрямую записана в числовое поле ресурса. Необходимо предварительно преобразовать данные, используя функции Число() или Дата(), чтобы избежать ошибок выполнения.
Обработка ошибок и контроль уникальности
При добавлении записей в регистр сведений одной из самых частых проблем является нарушение уникальности ключа. Платформа 1С строго следит за тем, чтобы комбинация измерений (и периода, если он есть) была уникальной. Если вы пытаетесь записать дубль, система по умолчанию заменяет старую запись новой.
Однако в некоторых сценариях требуется предотвратить перезапись. Для этого можно предварительно выполнить проверку существования записи. Это делается с помощью запроса к регистру или использования метода Получить. Если запись найдена, вы можете принять решение: обновить её, пропустить или выдать сообщение пользователю.
СуществующаяЗапись = РегистрыСведений.НастройкиПользователей.Получить(КлючИзмерений);
Если СуществующаяЗапись = Неопределено Тогда
// Записываем новую
НоваяЗапись.Записать();
Иначе
// Обрабатываем конфликт, например, логируем или обновляем
СуществующаяЗапись.Значение = НовоеЗначение;
СуществующаяЗапись.Записать();
КонецЕсли;
Использование блока Попытка...Исключение также является хорошим тоном программирования. Оно позволяет перехватить системные ошибки, например, блокировку записи другим пользователем, и корректно завершить работу или повторить попытку.
Всегда проверяйте типы данных перед записью. Попытка записать Неопределено в поле, где это не разрешено настройками метаданных, приведет к ошибке валидации.
Не стоит забывать о правах доступа. Даже если код написан верно, у пользователя или роли, от имени которой выполняется код, могут отсутствовать права на запись в конкретный регистр сведений. В таком случае метод Записать() завершится ошибкой прав доступа.
Особенности регистров, подчиненных регистратору
Отдельный класс регистров сведений — это регистры, подчиненные регистратору. Они привязаны к конкретному документу и не могут существовать без него. Запись в такие регистры обычно производится автоматически при проведении документа, но иногда требуется ручное вмешательство.
Главная особенность таких регистров заключается в том, что измерение «Регистратор» заполняется автоматически ссылкой на документ. Период также часто берется из даты документа. При программном создании записи вне контекста проведения документа вам придется вручную указать ссылку на существующий документ-регистратор.
Удаление документа-регистратора автоматически влечет за собой удаление всех записей в подчиненном регистре сведений. Это обеспечивает целостность данных: не может существовать настройка или движение, относящееся к удаленному документу. При разработке следует учитывать эту связь, чтобы не потерять важные данные при ошибочном удалении документов.
⚠️ Внимание: Интерфейс и возможности платформы 1С могут обновляться. Детали реализации методов записи в новых версиях (например, 8.3.24 и выше) могут отличаться от описанных здесь. Всегда сверяйтесь с синтаксис-помощником вашей конкретной версии платформы.
Работа с такими регистрами требует особой аккуратности при отладке. Если вы создаете запись в тестовых целях, убедитесь, что документ-регистратор реально существует в базе, иначе ссылка будет битой, и запись может не пройти валидацию при сохранении.
☑️ Проверка перед записью в регистр
Часто задаваемые вопросы (FAQ)
Можно ли добавить запись в регистр сведений без использования кода, только через интерфейс?
Да, если в конфигурации предусмотрен соответствующий интерфейс. Обычно для непериодических регистров существует форма списка, где можно добавить новую строку кнопкой «Добавить». Для периодических регистров интерфейс может быть ограничен, и запись возможна только через документы или специальные обработки.
Что произойдет, если записать две записи с одинаковым периодом и измерениями?
Вторая запись перезапишет первую. В базе данных останется только одна строка с данными из последней операции записи. Предыдущие значения будут утеряны, если не велось историческое логирование на уровне СУБД.
Как очистить все данные из регистра сведений программно?
Для этого используется метод Удалить() у объекта набора записей с установленным отбором, либо специальный запрос на удаление. Например: РегистрыСведений.ИмяРегистра.Удалить() удалит все записи, но требует прав администратора.
Почему запись в регистр не видна сразу после выполнения кода?
Возможно, вы забыли вызвать метод Записать(). Также проверьте, не находится ли код внутри транзакции, которая еще не зафиксирована. Еще одна причина — кэширование данных в форме, которое требует обновления списка (нажатие F5).
Можно ли использовать регистр сведений для хранения больших объемов текста?
Технически можно, если тип данных поля позволяет (например, Строка неограниченной длины или ХранениеНастройки). Однако для больших текстовых массивов лучше использовать отдельные справочники или таблицы документов, так как регистры оптимизированы для быстрой выборки по ключам, а не для хранения контента.