Как преобразовать плоскую таблицу значений с отметками времени в сводный читаемый отчет?

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

При интеграции 1С с внешними системами контроля доступа (СКУД), терминалами сбора данных или рабочими местами кассиров часто возникает ситуация, когда данные загружаются в виде простого текстового журнала событий формата «КОД;ВРЕМЯ». После загрузки разработчик получает плоскую таблицу значений, содержащую тысячи неструктурированных строк. Для анализа такой информации человеку требуется кросс-таблица или сводный отчет, где по строкам указаны сотрудники, по колонкам — даты, а в ячейках — время первого входа и последнего выхода.

Разберем основные и наиболее эффективные способы трансформации таких данных в платформе 1С:Предприятие.

Способ 1. Использование Системы компоновки данных (СКД) с внешним набором данных

Использование СКД — самый гибкий и рекомендуемый разработчиками платформы вариант. Он позволяет без ручного кода развернуть плоские данные в кросс-таблицу любой сложности.

Рассмотрим порядок реализации через внешний набор данных:

  1. Создадим схему компоновки данных и добавим Набор данных - объект с именем ТаблицаОтметок.
  2. Опишем поля набора данных: Сотрудник (или Код), Дата (тип Дата), ВремяПрихода (тип Дата), ВремяУхода (тип Дата).
  3. На вкладке Настройки добавим структуру типа Таблица, где в строках укажем поле Сотрудник, в колонках — Дата, а в ресурсах — агрегированные показатели времени.
  4. Программно передадим готовую таблицу значений в компоновщик макета и выполним компоновку.

Посмотрим на пример программного вызова СКД на сервере:


СхемаКомпоновки = ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
Настройки = СхемаКомпоновки.НастройкиПоУмолчанию;

КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновки, Настройки);

ВнешниеНаборыДанных = Новый Структура;
ВнешниеНаборыДанных.Вставить("ТаблицаОтметок", ТаблицаЗначений);

ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, ВнешниеНаборыДанных);

ТабличныйДокумент.Очистить();
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ТабличныйДокумент);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);

Способ 2. Обработка через язык запросов и временную таблицу

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

Проанализируем этот подход. Чтобы агрегировать первое и последнее событие дня, выделим дату без времени функцией НАЧАЛОПЕРИОДА, а время отметки свернем функциями МИНИМУМ и МАКСИМУМ.

Посмотрим на пример формирования запроса:


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

Запрос.УстановитьПараметр("ТаблицаЛога", ИсходнаяТаблицаЗначений);
СвернутаяТаблица = Запрос.Выполнить().Выгрузить();

Способ 3. Использование Построителя отчета

В случаях, когда необходимо быстро построить сводную кросс-таблицу программным кодом без создания отдельной схемы СКД, отлично подходит ПостроительОтчета.

Разберем пример настройки измерений строк и колонок через объект ОписаниеИсточникаДанных:


Построитель = Новый ПостроительОтчета;
Построитель.ИсточникДанных = Новый ОписаниеИсточникаДанных(СвернутаяТаблица);

// Настраиваем группировки
Построитель.ИзмеренияСтроки.Добавить("Код");
Построитель.ИзмеренияКолонки.Добавить("Дата");
Построитель.ВыбранныеПоля.Добавить("Приход");
Построитель.ВыбранныеПоля.Добавить("Уход");

Построитель.Выполнить();
Построитель.Вывести(ТабличныйДокумент);

Способ 4. Программное заполнение Табличного документа по макету

Если требуется нестандартное визуальное оформление ячеек (например, цветовая индикация опозданий или переработок), сформируем отчет вручную с помощью методов ТабличныйДокумент.Вывести() и ТабличныйДокумент.Присоединить().

Рассмотрим алгоритм вывода:

  1. Выводим шапку таблицы с фиксированными левыми колонками (Сотрудник / Код).
  2. Горизонтальным циклом присоединяем секции дат вправо: ТабличныйДокумент.Присоединить(ОбластьКолонкаДата).
  3. В основном цикле по сотрудникам сначала выводим строку с данными сотрудника методом Вывести(), а затем в цикле по датам присоединяем ячейки со значениями прихода и ухода методом Присоединить().

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

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

  1. Контекст исполнения: Объект ТаблицаЗначений не поддерживается на клиенте в режиме тонкого клиента. Все манипуляции по чтению текстовых файлов, группировке и вычислениям должны выполняться на сервере в процедурах с директивой &НаСервере.
  2. Типизация колонок: При передаче таблицы значений в качестве параметра запроса все колонки должны иметь строго определенные типы через КвалификаторыДаты, КвалификаторыСтроки и ОписаниеТипов. Если типы колонок не заданы, запрос завершится ошибкой.
  3. Одиночные отметки: Если сотрудник отметился только один раз за смену (например, забыл отметиться на выходе), функции МИНИМУМ и МАКСИМУМ вернут одинаковое время. В коде формирования отчета следует предусмотреть условие: если ВремяПрихода = ВремяУхода, то время ухода считается незафиксированным и ячейка очищается либо подсвечивается.
← На главную