Загрузка исторических данных в регистр сведений: рабочие способы
Содержание
Чтобы занести историю в регистр сведений , сделайте его периодическим с независимым режимом записи — тогда записи с любой прошлой датой пишутся напрямую через менеджер записи или набор записей с замещением. Если регистр подчинён регистратору, историю вводят документами задним числом либо меняют режим записи на независимый.
«Обойти» регистр сведений — значит не взломать платформу, а занести данные вопреки тем ограничениям, которые заложены в его конструкцию: уникальность ключа, подчинение документу и дата запрета изменений. Все способы ниже — штатные механизмы 1С 8.3. Разберём, что именно мешает вводу истории, как записать прошлые периоды кодом и когда вместо регистра сведений правильнее взять регистр накопления.
Способов ввода истории три, и выбор зависит от режима записи регистра и от того, нужна ли согласованность с документами:
| Способ | Когда применять | Риски |
|---|---|---|
| Документы задним числом | Регистр подчинён регистратору, историю менять нельзя без источника | Долго при больших объёмах; нужны сами документы |
| Прямая запись (независимый режим) | Регистр хранит состояния, документы-источники не нужны | Теряется связь с регистраторами; потеря истории при неверном замещении |
| Документ ввода остатков | Нужны остатки и обороты (регистр накопления) | Не для регистра сведений; требует готового документа ввода остатков |
Дальше — каждый способ по шагам, с кодом и предостережениями.
Что именно мешает занести прошлые периоды
У регистра сведений три свойства, из-за которых прямой ввод истории не всегда проходит.
- 🔑 Уникальность ключа. На одну комбинацию «период + значения измерений» хранится ровно один набор ресурсов. Две записи с одинаковым ключом платформа не примет — при попытке получите ошибку записи.
- 📌 Режим записи. Он бывает «Независимый» и «Подчинение регистратору». Подчинённый регистр пишется только через документ-регистратор, и период записи берётся из даты этого документа. Напрямую кодом в него history не загрузишь, пока режим не сменён.
- 📅 Периодичность. Непериодический регистр хранит одно значение на ключ без привязки к дате — истории в нём нет в принципе. Для хранения значений по датам нужна периодичность: в пределах секунды, день, месяц, квартал, год или по позиции регистратора.
Отдельно стоит периодичность «По позиции регистратора» — она доступна только в режиме подчинения регистратору и жёстко привязывает запись к документу и его моменту времени. При такой настройке ввести историю кодом в обход документа не выйдет вообще: платформа ждёт регистратор. Если история нужна без документов, этот вариант периодичности не подходит — остаётся либо смена режима записи, либо ввод через документы.
Чем мельче периодичность, тем точнее история, но тем проще получить смысловые дубли. При периодичности «В пределах секунды» две записи на одну дату с разным временем — это два разных ключа, и срез последних покажет ту, что позже по времени. При периодичности «День» всё, что в пределах суток, схлопывается в одну запись на дату. Выбирайте шаг под реальную частоту изменений: для курсов валют хватает дня, для журнала статусов иногда нужна секунда.
К этому добавляется дата запрета изменения данных — механизм из состава библиотеки стандартных подсистем (БСП) в типовых конфигурациях. Если она выставлена, запись в закрытый период блокируется прикладной логикой, и загрузку истории до этой даты придётся отдельно разрешать.
Прежде чем менять структуру, определитесь: вам нужна история состояний (цена, курс, статус, ставка на дату) или история движений (приход и расход, из которых складываются остатки). От ответа зависит, останетесь вы в регистре сведений или уйдёте в регистр накопления.
Независимый периодический регистр — запись с нужной датой
Самый частый сценарий: регистр подчинён регистратору, а историю хочется залить напрямую, без создания сотен документов. Решение — перевести регистр в независимый режим.
В конфигураторе откройте свойства регистра сведений и задайте:
- Периодичность — выберите ту, что соответствует данным (чаще всего «В пределах секунды» или «День»).
- Режим записи —
Независимый.
После обновления конфигурации базы записи можно создавать с произвольным полем Период.
Смена режима записи — это изменение структуры таблицы. Платформа реструктуризирует регистр, и связь записей с прежними регистраторами теряется. Перед сменой режима снимите резервную копию и проверьте результат на копии базы.
Одиночную запись проще всего занести менеджером записи:
МЗ = РегистрыСведений.ЦеныНоменклатуры.СоздатьМенеджерЗаписи();
МЗ.Период = Дата(2022, 01, 10);
МЗ.Номенклатура = Товар;
МЗ.Цена = 1500;
МЗ.Записать(Истина); // Истина — заместить запись с тем же ключом
Параметр Истина в методе Записать означает замещение: если запись с таким ключом уже есть, она перезапишется, а не вызовет ошибку уникальности. Для независимого периодического регистра ключ — это Период плюс значения измерений, поэтому один и тот же товар на разные даты спокойно сосуществует.
Менеджер записи удобен для одиночных операций и точечной правки: он работает с одной записью по полному набору ключевых полей. Как только записей становится много, он проигрывает по скорости — каждая запись идёт отдельной транзакцией. Для истории из десятков и сотен строк переходите на набор записей, о котором ниже.
Массовая загрузка через набор записей и таблицу значений
Когда историю нужно залить пакетом (например, цены за три года из внешнего файла), менеджер записи по одной строке — медленно. Используйте набор записей.
Схема простая: собираете историю в таблицу значений (из .xls, .csv, другой базы или обмена), затем переносите в набор и записываете одним вызовом.
НаборЗаписей = РегистрыСведений.ЦеныНоменклатуры.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Номенклатура.Установить(Товар);
Для Каждого Строка Из ТаблицаИстории Цикл
Запись = НаборЗаписей.Добавить();
Запись.Период = Строка.Дата;
Запись.Номенклатура = Товар;
Запись.Цена = Строка.Цена;
КонецЦикла;
НаборЗаписей.Записать(Истина); // заместить все записи по установленному отбору
Здесь важный нюанс. Запись набора с замещением (Истина) удаляет все существующие записи, попадающие под отбор, и пишет на их место содержимое набора. В примере отбор стоит по одной номенклатуре — значит, вся история цен именно этого товара сначала стирается, затем создаётся заново из таблицы.
Если вы грузите историю частями, а в наборе окажется не весь период по товару, замещение сотрёт то, что в набор не попало. Либо держите в наборе полную историю по ключу отбора, либо грузите без замещения (Записать(Ложь)), но тогда следите за уникальностью периодов.
Источником таблицы истории чаще всего служит внешний файл или другая база. Порядок один и тот же: сначала данные попадают в таблицу значений с колонками под период, измерения и ресурсы, и только потом — в набор записей. Промежуточная таблица позволяет вычистить данные до записи: отбросить пустые строки, привести типы, свести дубли по ключу. Писать в регистр сразу из файла, строка за строкой, не стоит — это и медленно, и не оставляет шанса проверить данные перед заливкой.
Если история берётся из другой информационной базы 1С, удобнее перенести её через обмен или внешнее соединение в ту же таблицу значений, а дальше действовать по описанной схеме. Логика не меняется: внешний источник отвечает за данные, набор записей — за корректную запись в регистр.
Для производительности разбивайте большую загрузку на транзакции по несколько тысяч строк и не держите в памяти всю таблицу истории сразу, если она измеряется сотнями тысяч записей.
Служебные флаги и дата запрета при загрузке
При записи в регистр нередко срабатывает прикладная логика — обработчики ПередЗаписью в модуле набора записей, проверки заполнения, контроль даты запрета. На живой истории эти проверки часто мешают: данные уже выверены, их нужно просто положить как есть.
Признак режима загрузки — свойство ОбменДанными.Загрузка:
НаборЗаписей.ОбменДанными.Загрузка = Истина;
НаборЗаписей.Записать(Истина);
Важно понимать механику: сам по себе этот флаг ничего не отключает автоматически. Он лишь сигнал, который читает ваш код. Обработчики в типовых решениях обычно начинаются со строки вроде Если ОбменДанными.Загрузка Тогда Возврат; КонецЕсли; — и именно поэтому при установленном флаге проверки пропускаются. Если в обработчике такой проверки нет, флаг на него не повлияет.
С датой запрета изменения — похожая история. Платформа сама по себе не запрещает запись в регистр по дате; блокировку выполняет подсистема БСП в прикладном коде. Чтобы загрузить историю до даты запрета:
- временно сдвиньте дату запрета в настройках (раздел
Администрирование, подраздел с датами запрета изменений — в разных конфигурациях название подраздела отличается) и верните её после загрузки; - либо выполняйте запись в режиме загрузки, если подсистема учитывает
ОбменДанными.Загрузка.
Служебные флаги — это не «тихий обход», а штатный механизм переноса данных. Но ответственность за корректность переходит к вам: пропущенные проверки больше не защищают от неверных значений.
Когда историю правильнее хранить в регистре накопления
Регистр сведений хранит значение на момент времени — цену, курс, ставку, статус, ответственного. Срез последних отдаёт актуальное значение на дату. Если ваша «история» — это именно такие состояния, остаётесь в регистре сведений.
Но если под историей понимаются движения — поступления и списания, из которых складываются остатки и обороты, — регистр сведений для этого не предназначен. Здесь работает регистр накопления, а начальные значения вводят не прямой записью в регистр, а документом ввода остатков.
Подмена одного регистра другим «ради удобной загрузки» — частая ошибка проектирования. Если смысл данных — обороты, независимый регистр сведений даст вам записи без контроля остатков, и отрицательные величины вылезут там, где их быть не должно.
Проверка целостности после загрузки истории
Залить данные — половина дела. После загрузки историю нужно проверить, иначе срез последних начнёт отдавать не то, что ожидается.
На что смотреть в первую очередь:
- Срез последних на контрольные даты. Запросом
РегистрыСведений.ЦеныНоменклатуры.СрезПоследних(&Дата, Номенклатура = &Товар)сверьте значение на несколько дат с источником. - Заполненность измерений. Пустое ведущее измерение (например, незаполненная номенклатура) ломает отбор и срезы. Отфильтруйте записи с пустыми ключами.
- Корректность периодов. Проверьте, что
Периодпопал в нужную дату, а не обнулился до начала суток там, где важно время. - Дубли по смыслу. Технических дублей ключа платформа не допустит, но смысловые задвоения (две цены на один день с разницей в секунду при периодичности «В пределах секунды») отследите отдельным запросом с группировкой.
Если на историю завязаны движения документов или зависимые регистры, после загрузки может потребоваться перепроведение документов за период — тогда производные данные пересчитаются от загруженной истории.
Частые вопросы
Можно ли записать историю, не меняя подчинение регистратору?
Почему при записи набора пропадает часть ранее загруженных данных?
Записать(Истина) стирает все записи по установленному отбору и пишет на их место содержимое набора. Если в наборе не вся история по ключу отбора, недостающее удаляется. Держите в наборе полную историю либо пишите без замещения.