Как записать таблицу значений в регистр сведений с поиском физлиц по СНИЛС и ФИО

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

В практике разработчика 1С часто возникает задача импорта данных из внешних источников (Excel, CSV или просто программно сформированных таблиц) в существующие регистры сведений. Типичный сценарий: у нас есть набор антропометрических данных (рост, размер одежды и т.д.) для сотрудников, и нам нужно обновить или создать записи в независимом непериодическом регистре сведений, сопоставляя данные по таким реквизитам, как СНИЛС или ФИО.

В данной статье мы подробно разберем, как правильно организовать этот процесс, избежав типичных ошибок типизации и обеспечив высокую производительность записи.

Шаг 1. Подготовка и типизация таблицы значений

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

Чтобы использовать таблицу значений в запросе, мы должны явно типизировать её колонки. Проанализируем, как это сделать правильно:


// Создаем таблицу с жестко заданными типами
ТзДляЗагрузки = Новый ТаблицаЗначений;
ТзДляЗагрузки.Колонки.Добавить("ФИО", Новый ОписаниеТипов("Строка", Новый КвалификаторыСтроки(150)));
ТзДляЗагрузки.Колонки.Добавить("СНИЛС", Новый ОписаниеТипов("Строка", Новый КвалификаторыСтроки(14)));
ТзДляЗагрузки.Колонки.Добавить("Рост", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(3, 0)));
// ... добавление остальных колонок (РазмерОдежды, РазмерОбуви и т.д.)

// Заполняем таблицу данными из источника (например, из Excel)
// После заполнения передаем её в процедуру обработки

Важно помнить: если вы используете МенеджерЗаписи, убедитесь, что типы данных в вашей таблице совпадают с типами ресурсов и измерений в регистре сведений.

Шаг 2. Сопоставление данных через запрос

Вместо того чтобы искать каждое физическое лицо в цикле (что крайне неэффективно), мы воспользуемся механизмом запросов. Рассмотрим алгоритм сопоставления. Мы передадим нашу ТаблицаЗначений в запрос в качестве параметра, поместим её во временную таблицу и соединим со справочником ФизическиеЛица.

Нюанс сопоставления: Поиск следует выполнять сначала по уникальному идентификатору (в данном случае СНИЛС), а если он не найден — по ФИО. Однако в запросе мы можем реализовать условие ПО (СНИЛС = ...) ИЛИ (ФИО = ...). Но будьте осторожны: поиск по ФИО может выдать дубли (однофамильцев), поэтому рекомендуется проверять результаты сопоставления.

Проанализируем пример запроса:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Таблица.ФИО КАК ФИО_ИзФайла,
    |	Таблица.СНИЛС КАК СНИЛС_ИзФайла,
    |	Таблица.Рост,
    |	Таблица.РазмерОдежды
    |ПОМЕСТИТЬ ВТ_ДанныеФайла
    |ИЗ
    |	&Таблица КАК Таблица
    |;
    |
    |////////////////////////////////////////////////////////////////////////////////
    |ВЫБРАТЬ
    |	ФизическиеЛица.Ссылка КАК ФизическоеЛицо,
    |	ВТ_ДанныеФайла.Рост,
    |	ВТ_ДанныеФайла.РазмерОдежды
    |ИЗ
    |	ВТ_ДанныеФайла КАК ВТ_ДанныеФайла
    |		ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.ФизическиеЛица КАК ФизическиеЛица
    |		ПО (ФизическиеЛица.СтраховойНомерПФР = ВТ_ДанныеФайла.СНИЛС
    |			ИЛИ ФизическиеЛица.Наименование = ВТ_ДанныеФайла.ФИО)";

Запрос.УстановитьПараметр("Таблица", ТзДляЗагрузки);
РезультатЗапроса = Запрос.Выполнить();

В данном примере мы используем ВНУТРЕННЕЕ СОЕДИНЕНИЕ, чтобы получить только те записи, для которых удалось найти соответствие в базе. Если вам нужно видеть список "ненайденных" людей, используйте ЛЕВОЕ СОЕДИНЕНИЕ и проверяйте поле ФизическоеЛицо на NULL.

Шаг 3. Запись данных в регистр сведений

После получения выборки из запроса нам необходимо записать данные в регистр. Для независимого регистра сведений удобнее всего использовать МенеджерЗаписи. Это объект, который позволяет работать с одной конкретной записью регистра, определяемой набором измерений.

Разберем процесс записи по шагам:

  1. Обходим выборку запроса в цикле.
  2. Для каждой строки создаем СоздатьМенеджерЗаписи().
  3. Устанавливаем ключевое измерение (в нашем случае это ФизическоеЛицо).
  4. Заполняем ресурсы (Рост, Размер и т.д.).
  5. Вызываем метод Записать().

Рассмотрим пример кода:


Выборка = РезультатЗапроса.Выбрать();

Пока Выборка.Следующий() Цикл
    
    // Создаем менеджер записи для конкретного регистра
    МенеджерЗаписи = РегистрыСведений.АнтропометрияФизЛиц.СоздатьМенеджерЗаписи();
    
    // Устанавливаем измерение (ключ записи)
    МенеджерЗаписи.ФизическоеЛицо = Выборка.ФизическоеЛицо;
    
    // Если нужно обновить существующую запись, не затирая другие поля (которых нет в файле),
    // сначала можно вызвать МенеджерЗаписи.Прочитать();
    
    // Заполняем ресурсы данными из выборки
    МенеджерЗаписи.Рост           = Выборка.Рост;
    МенеджерЗаписи.РазмерОдежды   = Выборка.РазмерОдежды;
    
    Попытка
        // Метод Записать(Истина) заменяет существующую запись с таким измерением
        МенеджерЗаписи.Записать();
    Исключение
        ОбщегоНазначенияКлиентСервер.СообщитьПользователю(
            СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
                "Ошибка при записи данных для: %1", Выборка.ФизическоеЛицо));
    КонецПопытки;
    
КонецЦикла;

Важные рекомендации по оптимизации

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

Использование Набора Записей. Если данных много, эффективнее использовать РегистрСведенийНаборЗаписей. Мы можем сгруппировать данные по физическим лицам и записывать их пачками. Однако для независимого регистра, где на одно физлицо приходится одна запись, МенеджерЗаписи остается наиболее простым и понятным инструментом.

Транзакции. Чтобы ускорить запись в разы, оберните цикл в транзакцию. Это позволит базе данных зафиксировать все изменения одним блоком:


НачатьТранзакцию();
Попытка
    // Ваш цикл с записью в регистр
    ЗафиксироватьТранзакцию();
Исключение
    ОтменитьТранзакцию();
    ВызватьИсключение; // Передаем ошибку дальше
КонецПопытки;

Формат СНИЛС. Обратите внимание на формат хранения СНИЛС в базе (обычно 123-456-789 01). Если в вашем файле СНИЛС представлен в виде сплошных цифр, сопоставление в запросе не сработает. В таком случае в Шаге 1, перед загрузкой в таблицу значений, выполните форматирование строки программно, чтобы она соответствовала стандарту 1С.

Проверка на дубли. Если поиск идет по ФИО, существует риск найти двух полных тезок. Чтобы избежать записи данных "не тому" человеку, в запросе можно добавить дополнительные поля для проверки (например, дату рождения) или использовать метод РАЗЛИЧНЫЕ, если вы уверены, что данные в справочнике уникальны.

Таким образом, мы рассмотрели полный цикл загрузки: от типизации входной таблицы до финальной записи в регистр сведений. Следуя этой структуре, вы сможете создавать надежные и быстрые механизмы импорта данных в систему 1С.

← На главную