При интеграции 1С с внешними системами контроля доступа (СКУД), терминалами сбора данных или рабочими местами кассиров часто возникает ситуация, когда данные загружаются в виде простого текстового журнала событий формата «КОД;ВРЕМЯ». После загрузки разработчик получает плоскую таблицу значений, содержащую тысячи неструктурированных строк. Для анализа такой информации человеку требуется кросс-таблица или сводный отчет, где по строкам указаны сотрудники, по колонкам — даты, а в ячейках — время первого входа и последнего выхода.
Разберем основные и наиболее эффективные способы трансформации таких данных в платформе 1С:Предприятие.
Использование СКД — самый гибкий и рекомендуемый разработчиками платформы вариант. Он позволяет без ручного кода развернуть плоские данные в кросс-таблицу любой сложности.
Рассмотрим порядок реализации через внешний набор данных:
ТаблицаОтметок.Сотрудник (или Код), Дата (тип Дата), ВремяПрихода (тип Дата), ВремяУхода (тип Дата).Сотрудник, в колонках — Дата, а в ресурсах — агрегированные показатели времени.Посмотрим на пример программного вызова СКД на сервере:
СхемаКомпоновки = ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
Настройки = СхемаКомпоновки.НастройкиПоУмолчанию;
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновки, Настройки);
ВнешниеНаборыДанных = Новый Структура;
ВнешниеНаборыДанных.Вставить("ТаблицаОтметок", ТаблицаЗначений);
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, ВнешниеНаборыДанных);
ТабличныйДокумент.Очистить();
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ТабличныйДокумент);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);
Если требуется получить сгруппированную таблицу значений программно для дальнейшей обработки алгоритмами, наиболее производительным решением будет загрузка таблицы в Запрос с группировкой по сотруднику и календарному дню.
Проанализируем этот подход. Чтобы агрегировать первое и последнее событие дня, выделим дату без времени функцией НАЧАЛОПЕРИОДА, а время отметки свернем функциями МИНИМУМ и МАКСИМУМ.
Посмотрим на пример формирования запроса:
// Обязательно убедимся, что колонки исходной таблицы типизированы
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
Запрос.Текст =
"ВЫБРАТЬ
| Исходная.Код КАК Код,
| НАЧАЛОПЕРИОДА(Исходная.Время, ДЕНЬ) КАК ДатаОтметки,
| МИНИМУМ(Исходная.Время) КАК ВремяПрихода,
| МАКСИМУМ(Исходная.Время) КАК ВремяУхода
|ПОМЕСТИТЬ ВТ_Отметки
|ИЗ
| &ТаблицаЛога КАК Исходная
|СГРУППИРОВАТЬ ПО
| Исходная.Код,
| НАЧАЛОПЕРИОДА(Исходная.Время, ДЕНЬ)
|;
|
|ВЫБРАТЬ
| ВТ.Код КАК Код,
| ВТ.ДатаОтметки КАК Дата,
| ВТ.ВремяПрихода КАК Приход,
| ВТ.ВремяУхода КАК Уход
|ИЗ
| ВТ_Отметки КАК ВТ
|УПОРЯДОЧИТЬ ПО
| Код,
| Дата";
Запрос.УстановитьПараметр("ТаблицаЛога", ИсходнаяТаблицаЗначений);
СвернутаяТаблица = Запрос.Выполнить().Выгрузить();
В случаях, когда необходимо быстро построить сводную кросс-таблицу программным кодом без создания отдельной схемы СКД, отлично подходит ПостроительОтчета.
Разберем пример настройки измерений строк и колонок через объект ОписаниеИсточникаДанных:
Построитель = Новый ПостроительОтчета;
Построитель.ИсточникДанных = Новый ОписаниеИсточникаДанных(СвернутаяТаблица);
// Настраиваем группировки
Построитель.ИзмеренияСтроки.Добавить("Код");
Построитель.ИзмеренияКолонки.Добавить("Дата");
Построитель.ВыбранныеПоля.Добавить("Приход");
Построитель.ВыбранныеПоля.Добавить("Уход");
Построитель.Выполнить();
Построитель.Вывести(ТабличныйДокумент);
Если требуется нестандартное визуальное оформление ячеек (например, цветовая индикация опозданий или переработок), сформируем отчет вручную с помощью методов ТабличныйДокумент.Вывести() и ТабличныйДокумент.Присоединить().
Рассмотрим алгоритм вывода:
ТабличныйДокумент.Присоединить(ОбластьКолонкаДата).Вывести(), а затем в цикле по датам присоединяем ячейки со значениями прихода и ухода методом Присоединить().При реализации алгоритмов разбора логов посещаемости важно учитывать следующие платформенные и прикладные ограничения:
ТаблицаЗначений не поддерживается на клиенте в режиме тонкого клиента. Все манипуляции по чтению текстовых файлов, группировке и вычислениям должны выполняться на сервере в процедурах с директивой &НаСервере.КвалификаторыДаты, КвалификаторыСтроки и ОписаниеТипов. Если типы колонок не заданы, запрос завершится ошибкой.МИНИМУМ и МАКСИМУМ вернут одинаковое время. В коде формирования отчета следует предусмотреть условие: если ВремяПрихода = ВремяУхода, то время ухода считается незафиксированным и ячейка очищается либо подсвечивается.