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