Как выгрузить кадровые данные сотрудников из табличной части в текстовый файл?

Программист 1С v8.3 (Управляемые формы) 1С:ERP Управление предприятием IT и автоматизация бизнеса
← На главную

В процессе разработки в 1С:ERP 2.4 или ЗУП 3.1 часто возникает задача выгрузки персональных данных сотрудников (ФИО, серия и номер паспорта) во внешние системы через текстовые файлы. Рассмотрим, как эффективно решить эту задачу, избежав типичных ошибок производительности и используя возможности программного интерфейса (API) типовых решений.

Анализ задачи и выбор метода получения данных

Для реализации выгрузки нам необходимо пройти по строкам табличной части (например, «Реестр»), получить ссылки на сотрудников или физических лиц, извлечь их персональные данные из регистров сведений и сформировать строку определенного формата для записи в файл. В современных конфигурациях 1С существует два основных подхода к решению этой задачи:

  1. Использование типовых функций (API): Это рекомендуемый способ для ERP и ЗУП, так как он учитывает права доступа, историю изменений данных на конкретную дату и особенности хранения документов.
  2. Прямой запрос к регистрам: Используется в самописных конфигурациях или когда требуется нестандартная логика выбора данных.

Метод №1: Использование типового программного интерфейса (API)

В конфигурациях на базе 1С:ЗУП 3.1 и 1С:ERP 2.4 предусмотрен мощный инструмент — программный модуль КадровыйУчет. Функция КадровыеДанныеСотрудников позволяет получить все необходимые сведения одним запросом сразу по всему массиву сотрудников. Это избавляет от необходимости вручную описывать связи между таблицами физических лиц и их документов.

Разберем алгоритм реализации на сервере:


// Сначала соберем всех сотрудников из табличной части в массив
МассивСотрудников = Объект.Реестр.ВыгрузитьКолонку("Сотрудник");

// Определим список полей, которые нам нужны
// ДокументСерия, ДокументНомер — это предопределенные поля в API
Поля = "Фамилия, Имя, Отчество, ДокументСерия, ДокументНомер";

// Получаем таблицу значений с данными на текущую дату (или дату документа)
ДатаСведений = ТекущаяДата(); 
ТаблицаДанных = КадровыйУчет.КадровыеДанныеСотрудников(Истина, МассивСотрудников, Поля, ДатаСведений);

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

Важное преимущество: Метод КадровыеДанныеСотрудников автоматически проверяет права пользователя на чтение персональных данных. Если у пользователя нет прав на просмотр паспортов, поля будут пустыми, что предотвращает утечку конфиденциальной информации.

Метод №2: Использование прямого запроса

Если по каким-то причинам использование API невозможно, мы можем составить запрос к регистру сведений ДокументыФизическихЛиц. Проанализируем ситуацию: данные о паспортах хранятся в срезе последних этого регистра.

Внимание: Никогда не выполняйте запрос внутри цикла Для каждого. Это создает избыточную нагрузку на сервер (проблема N+1). Правильно — передать весь список физлиц в запрос один раз.

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


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

В данном запросе мы используем ЛЕВОЕ СОЕДИНЕНИЕ, чтобы в выборку попали даже те сотрудники, у которых паспортные данные не заполнены. Параметр ВидДокумента критически важен, так как в регистре может храниться множество типов документов для одного человека.

Реализация выгрузки в текстовый файл

После получения данных необходимо собрать их в текстовый документ. Рассмотрим процесс создания файла. Традиционно используется объект ТекстовыйДокумент, но для повышения производительности и корректной работы с кодировками рекомендуется использовать ЗаписьТекста.

Проанализируем процедуру выгрузки на клиенте:


&НаКлиенте
Процедура ВыгрузитьДанные(Команда)
    // 1. Получаем данные с сервера (одним вызовом)
    ТаблицаСведений = ПолучитьДанныеДляВыгрузкиСервер(); 
    
    // 2. Определяем путь к файлу
    ПутьКФайлу = "C:\Export\StaffData.txt"; // Пример статичного пути
    
    // 3. Записываем данные
    ФайлЗаписи = Новый ЗаписьТекста(ПутьКФайлу, КодировкаТекста.ANSI);
    
    Для каждого Строка Из ТаблицаСведений Цикл
        // Собираем массив полей для удобного соединения через разделитель "*"
        МассивПолей = Новый Массив;
        МассивПолей.Добавить(Строка.Фамилия);
        МассивПолей.Добавить(Строка.Имя);
        МассивПолей.Добавить(Строка.Отчество);
        
        // Обработка пустых значений паспорта
        Серия = ?(ЗначениеЗаполнено(Строка.Серия), Строка.Серия, "");
        Номер = ?(ЗначениеЗаполнено(Строка.Номер), Строка.Номер, "");
        
        МассивПолей.Добавить(Серия + " " + Номер);
        
        // Формируем финальную строку
        СтрокаДляЗаписи = СтрСоединить(МассивПолей, "*");
        ФайлЗаписи.ЗаписатьСтроку(СтрокаДляЗаписи);
    КонецЦикла;
    
    ФайлЗаписи.Закрыть();
    ПоказатьПредупреждение(, "Выгрузка завершена успешно!");
КонецПроцедуры

Важные технические нюансы

При работе с персональными данными и текстовыми файлами следует учитывать несколько моментов, которые часто упускают начинающие разработчики:

  1. Обработка NULL: При использовании запросов с левым соединением, если данных в регистре нет, вы получите значение NULL. Перед записью в файл или конкатенацией строк обязательно преобразуйте его в пустую строку, иначе возникнет ошибка типов.
  2. Выбор кодировки: Большинство старых банковских систем и государственных шлюзов требуют кодировку ANSI (Windows-1251). Если же файл будет открываться в современных веб-сервисах, используйте UTF-8 (с BOM или без).
  3. Форматирование ФИО: Иногда требуется выгружать ФИО одной строкой, а иногда — раздельно. Используя СтрСоединить, вы гарантируете, что количество разделителей (звездочек) в строке будет всегда одинаковым, даже если у сотрудника нет отчества.
  4. Безопасность: Всегда регистрируйте факт выгрузки персональных данных в Журнале регистрации. Это требование законодательства (ФЗ-152 «О персональных данных»). Используйте метод ЗаписьЖурналаРегистрации, чтобы зафиксировать, какой пользователь и когда выгрузил список сотрудников в файл.

Выясним причину, почему использование ЗаписьТекста предпочтительнее ТекстовыйДокумент. Объект ТекстовыйДокумент хранит все строки в оперативной памяти до момента вызова метода Записать(). Если в вашем реестре тысячи сотрудников, это может привести к значительному потреблению памяти. Объект ЗаписьТекста работает в режиме потока, записывая данные на диск сразу после вызова ЗаписатьСтроку(), что гораздо эффективнее для больших объемов данных.

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

← На главную