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