Как в 1С прочитать текстовый файл логов СКУД и извлечь данные о проходах сотрудников?

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

Работа с внешними системами контроля и управления доступом (СКУД) — частая задача для программиста 1С. Обычно такие системы выгружают данные в текстовые файлы (*.txt), которые содержат информацию о дате, времени, типе события и идентификаторе сотрудника. В этой статье мы подробно разберем, как автоматизировать чтение таких файлов, правильно распарсить строки и избежать типичных ошибок при работе с файловой системой.

Организация чтения текстового файла

Для начала проанализируем структуру типичного лога СКУД. В нашем примере каждая запись находится на новой строке. Для последовательного чтения файла в 1С используется объект ЧтениеТекста. Этот метод является наиболее производительным для работы с большими объемами текстовых данных.

Рассмотрим базовый алгоритм чтения строк файла:


ПутьКФайлу = "C:\Logs\skud_export.txt";
Файл = Новый ЧтениеТекста(ПутьКФайлу, КодировкаТекста.ANSI);

ТекСтрока = Файл.ПрочитатьСтроку();
Пока ТекСтрока <> Неопределено Цикл
    // Здесь будет выполняться парсинг строки
    ОбработатьСтрокуЛога(ТекСтрока);
    
    ТекСтрока = Файл.ПрочитатьСтроку();
КонецЦикла;

Файл.Закрыть();

Важно помнить, что если в файле используются специфические символы (например, кириллица), необходимо правильно указывать кодировку (обычно КодировкаТекста.ANSI или КодировкаТекста.UTF8).

Извлечение табельного номера из строки

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

Способ 1: Использование функции Прав()

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

ТабНомер = Прав(СокрЛП(ТекСтрока), 10);

Способ 2: Поиск по разделителю с конца строки

Если длина табельного номера может варьироваться, но он всегда отделен пробелом, проанализируем ситуацию и применим поиск последнего пробела. Это более надежный метод, так как он не зависит от длины строки или количества нулей:


// Очищаем строку от лишних пробелов по краям
ЧистаяСтрока = СокрЛП(ТекСтрока);
// Находим позицию последнего пробела
ПозицияПробела = СтрНайти(ЧистаяСтрока, " ", НаправлениеПоиска.СКонца);
// Извлекаем все, что идет после этого пробела
ТабНомер = Сред(ЧистаяСтрока, ПозицияПробела + 1);

Определение направления прохода (Вход или Выход)

Выясним причину, по которой простая логика "первая запись — вход, последняя — выход" может давать сбои. Сотрудники могут выходить в течение дня (на обед или по делам), и в логах зафиксируется множество событий. Кроме того, возможны ошибки оборудования или ситуации, когда сотрудник зашел в один день, а вышел в другой.

Проанализируем пример строки: ...Этаж:Выход 0 10 Pertov A. 0000000024. В самой строке уже содержится маркер направления — "Вход" или "Выход". Вместо того чтобы вычислять статус по времени, гораздо надежнее искать эти ключевые слова в тексте:


Если СтрНайти(ТекСтрока, "Выход") > 0 Тогда
    ТипСобытия = Перечисления.ТипыСобытийСКУД.Выход;
ИначеЕсли СтрНайти(ТекСтрока, "Вход") > 0 Тогда
    ТипСобытия = Перечисления.ТипыСобытийСКУД.Вход;
КонецЕсли;

Важный нюанс: Обратите внимание на различие между событиями "Доступ предоставлен" и "Проход". Первое означает только факт прикладывания карты, а второе — физический поворот турникета. Для учета рабочего времени рекомендуется использовать именно события "Проход".

Решение проблемы блокировки файла

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

Чтобы избежать этой ошибки, придерживайтесь следующих правил:

  1. Всегда вызывайте метод Файл.Закрыть() перед тем, как открывать этот же файл для записи или перемещения.
  2. Вместо редактирования исходного текстового файла (что считается плохим тоном в разработке), используйте механизм архивации.

Рассмотрим правильный алгоритм обработки файла по шагам:


// 1. Читаем данные и сохраняем в массив или таблицу значений
ДанныеЛога = Новый ТаблицаЗначений;
// ... (код чтения файла) ...
Файл.Закрыть(); // Обязательно освобождаем файл!

// 2. Обрабатываем данные в 1С (записываем в регистры)
ЗаписатьСобытияВБазу(ДанныеЛога);

// 3. Перемещаем файл в папку архива, чтобы не прочитать его повторно
ИмяФайла = "skud_" + Формат(ТекущаяДата(), "ДФ=yyyyMMdd_HHmmss") + ".txt";
ПереместитьФайл(ПутьКФайлу, "C:\Logs\Archive\" + ИмяФайла);

Рекомендации по автоматизации

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

Также стоит рассмотреть возможность прямого подключения к базе данных СКУД через Внешние источники данных (если СКУД использует SQL или Access). Это позволит получать данные в реальном времени без промежуточных текстовых файлов, что значительно повысит надежность системы.

← На главную