import json import pandas as pd import io import xlsxwriter as xlx class Exporter : def __init__(self,_data): """ The data is passed by syncfusion """ self._data = _data self._sheets = _data['sheets'] if 'JSONData' not in _data else _data['JSONData']['sheets'] self._stream = io.BytesIO() self._workbook = xlx.Workbook(self._stream) def _getColRowIndex(self,_label): """ This function will return column/row given an excel specification for instance C1 -> 2,0 """ _ndxCol = [] _ndxRow = [] for xchar in _label.strip() : if xchar.isnumeric() : _ndxRow.append( xchar ) else: _ndxCol.append( ord(xchar) -65) return sum(_ndxCol), int("".join(_ndxRow)) -1 def _initData (self): self._charts = [] for _info in self._sheets : _rows = _info['rows'] _name = _info['name'] #-- sheet name _icol,_irow = self._getColRowIndex( _info.get('topLeftCell','A1')) _worksheet = self._workbook.add_worksheet(_name) for _item in _rows : cells = _item['cells'] for _ndxcol in range(0, len(cells)) : if not cells[_ndxcol] : continue if 'value' in cells[_ndxcol] : _value = cells[_ndxcol]['value'] if 'formattedText' in cells[_ndxcol] : _value = cells[_ndxcol]['formattedText'] _worksheet.write(_irow, _icol + _ndxcol, _value) if 'chart' in cells[_ndxcol] : for _chart in cells[_ndxcol]['chart'] : offset = 0 if 'value' not in cells[_ndxcol] else 1 _xchar = chr( _ndxcol + _icol + 65 + offset)+str(_irow+1) _meta = {'cell':_xchar, 'sheet_name':_name,'chart':_chart} self._charts.append(_meta) _irow += 1 # incrementing rows def _initCharts(self): for _meta in self._charts : _sheet = self._workbook.get_worksheet_by_name(_meta['sheet_name']) _chart = self._workbook.add_chart({'type':_meta['chart']['type'].lower()}) if 'range' in _meta['chart'] : # # Analysis of the range expression in case we have more than one series _range = _meta['chart']['range'].split('!')[-1] # # # # _series = _range.split(':') _lowerColIndex,_lowerRowIndex = self._getColRowIndex(_series[-1]) _upperColIndex,_upperRowIndex = self._getColRowIndex(_series[0]) if _upperColIndex == _lowerColIndex : _xchar = chr(_upperColIndex + 65) _chart.add_series({'values':_meta['chart']['range'],'name':f"{_meta['sheet_name']}!{_xchar}{_upperRowIndex+1}"}) else: for _i in range(_upperColIndex,_lowerColIndex + 1) : _xchar = chr( _i + 65) _range = f"{_meta['sheet_name']}!{_xchar}{_upperRowIndex+1}:{_xchar}{_lowerRowIndex+1}" _chart.add_series({'values':_range,'name':f'{_meta["sheet_name"]}!{_xchar}{_upperRowIndex+1}'}) _sheet.insert_chart(_meta['cell'],_chart) def get(self): self._initData () self._initCharts() self._workbook.close() self._stream.seek(0) return self._stream # # here is the interface to the calling code (in case it can) def instance (_data) : return (Exporter(_data)).get()