Как правильно программно записать данные в регистр сведений в 1С: Набор записей и Менеджер записи

Программист 1С v8.3 (Обычные формы)
← На главную

При разработке обработок по загрузке данных из внешних файлов (Excel, CSV, TXT) программисты часто сталкиваются с ситуацией, когда данные в регистр сведений либо не записываются вовсе, либо только обновляют старые записи, игнорируя создание новых. В этой статье мы подробно разберем, почему возникают такие сложности при работе с регистром Контактная информация в конфигурациях на базе 1С:Предприятие 8 (например, УПП или КА 1.1), и как правильно реализовать алгоритм записи.

Метод 1: Использование Набора записей (РегистрСведенийНаборЗаписей)

Рассмотрим ситуацию, когда мы используем объект НаборЗаписей. Это наиболее универсальный и производительный метод, особенно если нужно перезаписать группу данных по определенному фильтру. Однако у него есть важная особенность: если мы пытаемся прочитать данные по отбору, а их в базе еще нет, набор остается пустым.

Проанализируем ошибку в исходном коде: когда программист выполняет метод Прочитать(), система загружает в память существующие записи. Если записей нет, цикл Для каждого Запись из НаборЗаписей просто не выполняется, и новые данные не создаются. Чтобы исправить это, необходимо явно добавлять новую строку в набор.

Разберем правильный алгоритм работы с набором записей:


НаборЗаписей = РегистрыСведений.КонтактнаяИнформация.СоздатьНаборЗаписей();

// Устанавливаем жесткие отборы по измерениям
НаборЗаписей.Отбор.Объект.Установить(СсылкаНаФизЛицо);
НаборЗаписей.Отбор.Тип.Установить(Перечисления.ТипыКонтактнойИнформации.Другое);
НаборЗаписей.Отбор.Вид.Установить(Справочники.ВидыКонтактнойИнформации.НайтиПоНаименованию("Номер пропуска"));

НаборЗаписей.Прочитать();

Если НаборЗаписей.Количество() = 0 Тогда
    // Если записи нет, создаем ее
    НоваяЗапись = НаборЗаписей.Добавить();
    НоваяЗапись.Объект = СсылкаНаФизЛицо;
    НоваяЗапись.Тип = Перечисления.ТипыКонтактнойИнформации.Другое;
    НоваяЗапись.Вид = Справочники.ВидыКонтактнойИнформации.НайтиПоНаименованию("Номер пропуска");
    НоваяЗапись.Представление = НомерКарты;
Иначе
    // Если запись существует, редактируем найденную
    Для каждого Запись Из НаборЗаписей Цикл
        Запись.Представление = НомерКарты;
    КонецЦикла;
КонецЕсли;

НаборЗаписей.Записать();

Важный момент: Метод Записать() без параметров по умолчанию заменяет все записи, подходящие под текущий отбор. Это значит, что если в базе было три записи по данному физлицу и виду информации, а вы добавили в набор только одну, после выполнения Записать() останется только одна (ваша) запись.

Метод 2: Использование Менеджера записи (РегистрСведенийМенеджерЗаписи)

Многим разработчикам этот метод кажется более простым, так как он напоминает работу с объектом справочника или документа. МенеджерЗаписи предназначен для работы с одной конкретной строкой регистра, определенной уникальным ключом (комбинацией измерений).

Выясним причину ошибки "Не удалось записать", которая часто возникает при использовании этого метода. Как правило, она связана с тем, что не все измерения (ключевые поля) были заполнены перед вызовом метода Записать(), либо в системе уже существует запись с такими измерениями, и возникает конфликт уникальности.

Посмотрим на пример правильного использования менеджера записи:


МенеджерЗаписи = РегистрыСведений.КонтактнаяИнформация.СоздатьМенеджерЗаписи();

// Заполняем КЛЮЧЕВЫЕ поля (измерения)
МенеджерЗаписи.Объект = Справочники.ФизическиеЛица.НайтиПоНаименованию(СтрокаФИО);
МенеджерЗаписи.Тип    = Перечисления.ТипыКонтактнойИнформации.Другое;
МенеджерЗаписи.Вид    = Справочники.ВидыКонтактнойИнформации.НайтиПоНаименованию("Номер пропуска");

// Пытаемся прочитать существующую запись
МенеджерЗаписи.Прочитать();

// Заполняем ресурсы и реквизиты
МенеджерЗаписи.Представление = СокрЛП(НомерКарты);

// Записываем данные. Параметр Истина означает замещение существующей записи
Попытка
    МенеджерЗаписи.Записать(Истина);
Исключение
    Сообщить("Ошибка записи для: " + СтрокаФИО + ". Текст ошибки: " + ОписаниеОшибки());
КонецПопытки;

Особенности регистра «Контактная информация» в УПП

Проанализируем структуру регистра в типовой конфигурации «Управление производственным предприятием». Этот регистр имеет специфическую логику, и прямая запись в него может привести к тому, что данные не будут отображаться в интерфейсе карточки сотрудника. Рассмотрим несколько критических моментов:

  1. Поиск объектов в цикле: Использование НайтиПоНаименованию внутри цикла загрузки — это плохая практика. Если в файле 1000 строк, система сделает 1000 запросов к БД для поиска физлица и 1000 запросов для поиска вида информации. Рекомендуется заранее выгрузить необходимые справочники в Соответствие или ТаблицуЗначений.
  2. Проверка на пустые ссылки: Если НайтиПоНаименованию не найдет физлицо, метод вернет Справочники.ФизическиеЛица.ПустаяСсылка(). Запись в регистр с пустым объектом часто запрещена настройками метаданных или логикой системы.
  3. Обмен данными: При массовой загрузке данных полезно устанавливать свойство ОбменДанными.Загрузка = Истина. Это позволит обойти прикладные проверки в модуле регистра (например, проверку формата телефона или адреса), что ускорит процесс и поможет избежать ошибок блокировки.

Диагностика ошибок при записи

Если метод Записать() по-прежнему выдает ошибку, выполним следующие шаги для диагностики:

1. Включите режим "Остановка по ошибке" в конфигураторе (Меню Отладка -> Настройка отладки). Это позволит прервать выполнение кода именно в тот момент, когда запись сбоит, и посмотреть значения всех полей объекта.

2. Проверьте права доступа. Часто у пользователя, под которым запускается обработка, нет прав на изменение регистра сведений или справочника «Виды контактной информации».

3. Оцените уникальность записей. В регистре КонтактнаяИнформация измерениями являются Объект, Тип и Вид. Если вы пытаетесь записать две разные строки с одинаковым набором этих трех полей, система выдаст ошибку.

В заключение отметим, что для конфигураций, использующих БСП (Библиотеку стандартных подсистем), более правильным способом будет использование программного интерфейса (API) общих модулей, таких как УправлениеКонтактнойИнформацией, однако для простых задач загрузки в УПП предложенные методы с использованием НабораЗаписей остаются наиболее эффективными.

← На главную