Статья предназначена в первую очередь для консультантов и архитекторов, работающих с продуктами SAP, перед которыми стоит задача проектирования и реализации решения по подготовке отчетности в формате Excel.
В настоящее время все большую популярность набирают облачные решения для визуализации данных, демонстрируя двузначный рост год-к-году по большинству показателей. Однако не все компании - клиенты поставщиков облачных решений могут позволить себе использовать “облака” по самым разным причинам: от требований безопасности данных до недостаточной функциональности или даже более высокой стоимости владения по сравнению с on-premise.
Поэтому время от времени возникают задачи подготовки отчетности для визуализации в on-premise-инструментах. Автор долгое время работал и продолжает работать с решениями SAP, поэтому именно решения SAP (SAP BW/4, SAP S/4), как поставщики данных для отчетности, наиболее близки. Однако предлагаемый подход может быть скопирован и на другие системы-источники. Никаких препятствий к этому нет.
Задача формулируется так: реализовать on-premise решение по автоматической и регулярной подготовке отчетов по бизнес-данным SAP-систем (BW/4 или S/4).
Технические требования к отчетам:
минимальное время отклика при открытии отчета пользователем (2-4 сек)
возможность смотреть отчеты как на настольном, так и на мобильном устройстве (планшет, телефон)
комбинация табличных и графических представления данных на одной странице
несколько страниц (вкладок) с отчетами
корректное разбиение на страницы при печати на принтере/PDF.
отдельные табличные представления могут содержать большое число строк и/или столбцов (более 1 млн ячеек совокупно).
табличные представления
реализуют кросс-табличный формат
содержат итоги, подитоги по строкам и столбцам.
содержат иерархические группировки
содержат данные нарастающим итогом по календарным аналитикам
поддерживают функции “автофильтр”, “фиксация прокрутки” и некоторые другие функции Excel (например, комментарии к ячейкам, merge cells)
добавление статических картинок
условное форматирование ячеек
построены по csv-выгрузкам данных из исходных систем. Это означает, что отчеты содержат данные, сформированные на момент выгрузки данных из исходных систем. Чем чаще выполняется выгрузка, тем более актуальные данные в отчетах.
Наиболее близкими стандартными инструментами SAP, подходящими для этой задачи, является a)SAP BW on HANA + Broadcaster или b)SAP BW/4 HANA + SAP BI Platform + SAP Crystal Report Enterprise + Publishing.
Вариант a) подходит для клиентов, остающихся пока на решении SAP BW on HANA.
Вариант b) - для клиентов, перешедших на новое перспективное решение SAP BW/4 HANA и имеющих лицензии SAP BI Platform
Однако, оба этих варианта имеют те или иные ограничения, которые может быть крайне непросто или даже невозможно преодолеть, в т.ч. даже с добавлением “точечной” разработки (макросы VBA, ABAP-программы или кода на встроенном script-языке в Crystal Reports). Даже если в первоначальной постановке задачи нерешаемых требований нет, это не означает, что в будущем такие требования не появятся. Это означает, что лучше с самого начала выбрать подход, достаточно гибкий для решения как известных сейчас, так и неизвестных, но ожидаемых будущих требований.
Очевидно, что реализация третьего варианта, варианта с) будет с высокой долей собственной разработки отдельных компонентов целевого решения. Какие же опции могут существовать для технологических решений SAP в этом случае?
Существуют классы из библиотеки ABAP2XLSX (Apache2 licence model). Написанные на ABAP, они содержат методы по генерации XLSX-файла без использования Excel: XLSX-файлы создаются напрямую из кода на ABAP. Создав программную “обертку” для этих классов внутри S/4 или BW, вы можете генерировать XLSX-файлы с требуемым форматированием. Запускать эту генерацию возможно как диалоговом, так и в пакетном (batch) режиме, что позволяет настроить автоматическую публикацию, рассылку и пр. по расписанию или событиям.
Таким образом, все стадии процесса: извлечение данных, преобразования в формат отчета и генерация XLSX реализуются на одном языке (ABAP), и являются неотъемлемой частью хорошо знакомой в SAP-мире инфраструктуры жизненного цикла и среды выполнения ABAP-кода.
Но представляет интерес и альтернативный подход, который при определенном масштабе более эффективен и функционален. Речь идет о генерации XLSX-файла в коде на Python. Существует минимум две очень популярные python-библиотеки генерации Excel-кода: openpyxl и xlsxwriter. Это дает больше гибкости при выборе и развитии вашего решения, чем использование единственно возможной библиотеки на ABAP.
Процессы целевого решения могут выглядеть, например, так:
Данные системы-источника выгружаются на регулярной основе в текстовые csv-файлы. Файлы выгружаются в каталоги сервера приложений SAP или на выделенный файловый сервер или даже в облачный каталог, если это позволяют политики безопасности.
csv-файлы считываются Python-программой, которая затем выполняет обработку данных (расчет подитогов, итогов, расчет нарастающих итогов, объединение нескольких наборов данных, подтягивание наименований к кодам аналитик и т.п и т.д.), генерацию и публикацию XLSX-файла
Архитектура целевого решения состоит из:
SAP-системы-источника данных, которая генерирует csv-файлы. Генератором файлов может быть:
разработанные ABAP-программы,
SAP BW OpenHub.
В последнем случае легко настроить считывание данных из т.н. BW-запросов, в которых нередко реализуют сложную логику расчета бизнес-показателей пользовательских отчетов. Инструмент создания BW-моделей и -запросов (SAP HANA Studio BWMT) нельзя назвать инструментом “конечного пользователя”, но тем не менее он обладает мощным функционалом, позволяющим в создании даже сложных объектов во многих случаях обходиться без программирования. Однако, верно и то, что с помощью этого инструмента добиться желаемой производительности (см. требования выше) практически не представляется возможным. Поэтому результат работы BW-запроса - [кросс-]табличное представление данных - приходится визуализировать в Excel не стандартным инструментом SAP Analysis for Excel, а просто Excel. Но XLSX-файл нужно ещё подготовить и где-то разместить. А для этого применяются....
Python-программы, использующие библиотеки:
работы с данными - pandas;
генерации XLSX-файлов - openpyxl или/и xlsxwriter;
любые другие библиотеки Python для дополнительных преобразований считанных из файлов данных;
Сервер для запуска Python-программ. При наличии лицензий, можно рассмотреть SAP Data Intelligence, но подойдут и другие решения. На самых начальных этапах, при небольшом количестве Python-программ - генераторов XLSX-файлов можно обойтись средствами планирования задач операционной системы
Полученный XLSX-файл конечный пользователь может просмотреть как в Excel, так и его opensource-аналогах (LibreOffice, OpenOffice). Последнее особенно важно для компаний, в которых не используются продукты Microsoft Office или планируется от них отказаться. Использование же стандартного on-premise SAP-инструмента для визуализации данных BW-отчетов - SAP Analysis for Excel невозможно без Excel, т.к. технически он является его addOn.
Несколько слов про центральную часть архитектуры - Python-программы. Принимая во внимание, что генерировать XLSX-файл можно и с помощью ABAP-библиотеки, в Python это делать во многих аспектах удобнее:
существенно больше программистов на Python, чем на ABAP. Python изучают чуть ли не в школах, не говоря уже о ВУЗах. Нетрудно предположить, что и уровень зарплатных ожиданий для Python также ниже при прочих равных
Существенно больше готовых и бесплатных Python-библиотек, которые выполнят необходимые преобразования и расчеты.
возможно разрабатывать Python-код для генерации XLSX-файлов без доступа к SAP-системам, практически в offline-режиме. Так удобнее отдавать работу на outsource.
проще пользоваться всеми возможностями git-репозиториев. Да, в ABAP это тоже возможно, но это гораздо менее распространено.
Более лаконичный код, чем на ABAP.
Например, при таких исходных данных для визуализации
src = ['1;1;2020;1;10;30',
'1;1;2020;2;11;31',
'1;1;2021;1;12;32',
'1;1;2021;2;13;33',
'1;2;2020;1;14;34',
'1;2;2020;2;15;35',
'1;2;2021;1;16;36',
'1;2;2021;2;17;37',
'2;1;2020;1;18;38',
'2;1;2020;2;19;39',
'2;1;2021;1;20;40',
'2;1;2021;2;21;41',
'2;2;2020;1;22;42',
'2;2;2020;2;23;43',
'2;2;2021;1;24;44',
'2;2;2021;2;25;45',
]
следующий компактный код
char_count = 4 # первые 4 колонки (поля) в каждой строке данных соответствуют аналитикам. Остальные (2 в этом примере) - показатели.
column_count = src[0].count(";")+1 # общее число полей в строке с данными
src = list(map(lambda s: s.split(';'), src))
src = list(map(lambda row: list(map(lambda e, i: float(e) if i >= char_count else e, row, range(len(row)))), src))
df = pd.DataFrame.from_records(src, columns = list(map(lambda i: chr(65+i), range(column_count))))
table = pd.pivot_table(df, values='E', index=['A', 'B'], columns=['C', 'D'], aggfunc=np.sum, margins = False)
выполняет преобразование строк в исходном массиве: разбивает строку на поля, разделенные ;. Последние 2 поля, которые по смыслу есть “показатели”, сохраняются как числа float. Первые 4 поля - это аналитики и хранятся как строки.
На выходе кода - кросс-таблица, в которой по строкам - развертка по полям A и B, а по столбцам - развертка по полям C и D. Поле E - один (из двух в исходных данных) показателей, используемый в кросс-таблице.
C 2020 2021
D 1 2 1 2
A B
1 1 10.0 11.0 12.0 13.0
2 14.0 15.0 16.0 17.0
2 1 18.0 19.0 20.0 21.0
2 22.0 23.0 24.0 25.0
Если добавить код для расчета подитогов и итогов по строкам и столбцам (еще 5 - 6 строк кода), получится
C 2020 2021 all total
D 1 2 total-2020 1 2 total-2021 all total
A B
1 1 10.0 11.0 21.0 12.0 13.0 25.0 46.0
2 14.0 15.0 29.0 16.0 17.0 33.0 62.0
1 total 24.0 26.0 50.0 28.0 30.0 58.0 108.0
2 1 18.0 19.0 37.0 20.0 21.0 41.0 78.0
2 22.0 23.0 45.0 24.0 25.0 49.0 94.0
2 total 40.0 42.0 82.0 44.0 46.0 90.0 172.0
all total all total 64.0 68.0 132.0 72.0 76.0 148.0 280.0
Очевидно, что это уже почти готовая “матрица” для публикации в XLSX, после чего останется только применить форматирование [опять же, методами Python-библиотеки генерации XLSX] и файл готов. Файл можно публиковать средствами Python или операционной системы, и затем открывать в Excel, LibreOffice и т п.
Что касается производительности и потребления системных ресурсов при выполнении всех шагов процесса, начиная от выгрузки данных в csv из SAP и заканчивая генерацией XSLX-файла в Python-программе, то предложенная архитектура позволяет управлять распределением нагрузки, перенося ее с одних компонент на другие.
Например, если Python-код потребляет слишком много памяти при выполнении подготовки данных (слишком сложные расчеты или/и миллионы строк в выгрузке), то можно, не меняя степени параллелизации выполнения Python, и не выполняя аппаратного масштабирования, рассмотреть перенос вычислений или/и большее уплотнение данных на стороне SAP-сервера. Возможно и обратное, когда уменьшать нагрузку следует уже на SAP-сервер.