Passed
Push — master ( 107ae9...7e7300 )
by Guangyu
12:14 queued 12s
created

excelexporters.storestatistics.export()   B

Complexity

Conditions 5

Size

Total Lines 45
Code Lines 31

Duplication

Lines 45
Ratio 100 %

Importance

Changes 0
Metric Value
eloc 31
dl 45
loc 45
rs 8.6693
c 0
b 0
f 0
cc 5
nop 8

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
import base64
2
import gettext
3
import os
4
import uuid
5
6
import openpyxl.utils.cell as format_cell
7
from openpyxl import Workbook
8
from openpyxl.chart import LineChart, Reference
9
from openpyxl.chart.label import DataLabelList
10
from openpyxl.drawing.image import Image
11
from openpyxl.styles import PatternFill, Border, Side, Alignment, Font
12
13
14
########################################################################################################################
15
# PROCEDURES
16
# Step 1: Validate the report data
17
# Step 2: Generate excel file
18
# Step 3: Encode the excel file to Base64
19
########################################################################################################################
20
21
22 View Code Duplication
def export(report,
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
23
           name,
24
           base_period_start_datetime_local,
25
           base_period_end_datetime_local,
26
           reporting_start_datetime_local,
27
           reporting_end_datetime_local,
28
           period_type,
29
           language):
30
    ####################################################################################################################
31
    # Step 1: Validate the report data
32
    ####################################################################################################################
33
    if report is None:
34
        return None
35
36
    ####################################################################################################################
37
    # Step 2: Generate excel file from the report data
38
    ####################################################################################################################
39
    filename = generate_excel(report,
40
                              name,
41
                              base_period_start_datetime_local,
42
                              base_period_end_datetime_local,
43
                              reporting_start_datetime_local,
44
                              reporting_end_datetime_local,
45
                              period_type,
46
                              language)
47
    ####################################################################################################################
48
    # Step 3: Encode the excel file to Base64
49
    ####################################################################################################################
50
    binary_file_data = b''
51
    try:
52
        with open(filename, 'rb') as binary_file:
53
            binary_file_data = binary_file.read()
54
    except IOError as ex:
55
        print(str(ex))
56
57
    # Base64 encode the bytes
58
    base64_encoded_data = base64.b64encode(binary_file_data)
59
    # get the Base64 encoded data using human-readable characters.
60
    base64_message = base64_encoded_data.decode('utf-8')
61
    # delete the file from server
62
    try:
63
        os.remove(filename)
64
    except NotImplementedError as ex:
65
        print(str(ex))
66
    return base64_message
67
68
69
def generate_excel(report,
70
                   name,
71
                   base_period_start_datetime_local,
72
                   base_period_end_datetime_local,
73
                   reporting_start_datetime_local,
74
                   reporting_end_datetime_local,
75
                   period_type,
76
                   language):
77
78
    locale_path = './i18n/'
79
    if language == 'zh_CN':
80
        trans = gettext.translation('myems', locale_path, languages=['zh_CN'])
81
    elif language == 'de':
82
        trans = gettext.translation('myems', locale_path, languages=['de'])
83
    elif language == 'en':
84
        trans = gettext.translation('myems', locale_path, languages=['en'])
85
    else:
86
        trans = gettext.translation('myems', locale_path, languages=['en'])
87
    trans.install()
88
    _ = trans.gettext
89
90
    wb = Workbook()
91
    ws = wb.active
92
    ws.title = "StoreStatistics"
93
94
    # Row height
95
    ws.row_dimensions[1].height = 102
96
97
    for i in range(2, 2000 + 1):
98
        ws.row_dimensions[i].height = 42
99
100
    # Col width
101
    ws.column_dimensions['A'].width = 1.5
102
    ws.column_dimensions['B'].width = 25.0
103
104
    for i in range(ord('C'), ord('Z')):
105
        ws.column_dimensions[chr(i)].width = 15.0
106
107
    # Font
108
    name_font = Font(name='Arial', size=15, bold=True)
109
    title_font = Font(name='Arial', size=15, bold=True)
110
111
    table_fill = PatternFill(fill_type='solid', fgColor='90ee90')
112
    f_border = Border(left=Side(border_style='medium'),
113
                      right=Side(border_style='medium'),
114
                      bottom=Side(border_style='medium'),
115
                      top=Side(border_style='medium')
116
                      )
117
    b_border = Border(
118
        bottom=Side(border_style='medium'),
119
    )
120
121
    b_c_alignment = Alignment(vertical='bottom',
122
                              horizontal='center',
123
                              text_rotation=0,
124
                              wrap_text=True,
125
                              shrink_to_fit=False,
126
                              indent=0)
127
    c_c_alignment = Alignment(vertical='center',
128
                              horizontal='center',
129
                              text_rotation=0,
130
                              wrap_text=True,
131
                              shrink_to_fit=False,
132
                              indent=0)
133
    b_r_alignment = Alignment(vertical='bottom',
134
                              horizontal='right',
135
                              text_rotation=0,
136
                              wrap_text=True,
137
                              shrink_to_fit=False,
138
                              indent=0)
139
140
    # Img
141
    img = Image("excelexporters/myems.png")
142
    ws.add_image(img, 'A1')
143
144
    # Title
145
    ws['B3'].alignment = b_r_alignment
146
    ws['B3'] = _('Name') + ':'
147
    ws['C3'].border = b_border
148
    ws['C3'].alignment = b_c_alignment
149
    ws['C3'] = name
150
151
    ws['D3'].alignment = b_r_alignment
152
    ws['D3'] = _('Period Type') + ':'
153
    ws['E3'].border = b_border
154
    ws['E3'].alignment = b_c_alignment
155
    ws['E3'] = period_type
156
157
    ws['B4'].alignment = b_r_alignment
158
    ws['B4'] = _('Reporting Start Datetime') + ':'
159
    ws['C4'].border = b_border
160
    ws['C4'].alignment = b_c_alignment
161
    ws['C4'] = reporting_start_datetime_local
162
163
    ws['D4'].alignment = b_r_alignment
164
    ws['D4'] = _('Reporting End Datetime') + ':'
165
    ws['E4'].border = b_border
166
    ws['E4'].alignment = b_c_alignment
167
    ws['E4'] = reporting_end_datetime_local
168
169
    is_base_period_timestamp_exists_flag = is_base_period_timestamp_exists(report['base_period'])
170
171
    if is_base_period_timestamp_exists_flag:
172
        ws['B5'].alignment = b_r_alignment
173
        ws['B5'] = _('Base Period Start Datetime') + ':'
174
        ws['C5'].border = b_border
175
        ws['C5'].alignment = b_c_alignment
176
        ws['C5'] = base_period_start_datetime_local
177
178
        ws['D5'].alignment = b_r_alignment
179
        ws['D5'] = _('Base Period End Datetime') + ':'
180
        ws['E5'].border = b_border
181
        ws['E5'].alignment = b_c_alignment
182
        ws['E5'] = base_period_end_datetime_local
183
184
    if "reporting_period" not in report.keys() or \
185
            "names" not in report['reporting_period'].keys() or len(report['reporting_period']['names']) == 0:
186
        filename = str(uuid.uuid4()) + '.xlsx'
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable str does not seem to be defined.
Loading history...
187
        wb.save(filename)
188
189
        return filename
190
    ####################################################################################################################
191
    # First: Statistics
192
    # 7: title
193
    # 8: table title
194
    # 9~ca_len table_data
195
    ####################################################################################################################
196
    reporting_period_data = report['reporting_period']
197
198
    if "names" not in reporting_period_data.keys() or \
199
            reporting_period_data['names'] is None or \
200
            len(reporting_period_data['names']) == 0:
201
        filename = str(uuid.uuid4()) + '.xlsx'
202
        wb.save(filename)
203
        return filename
204
205
    ws['B7'].font = title_font
206
    ws['B7'] = name + ' ' + _('Statistics')
207
208
    category = reporting_period_data['names']
209
210
    # table_title
211
    ws['B8'].fill = table_fill
212
    ws['B8'].font = title_font
213
    ws['B8'].alignment = c_c_alignment
214
    ws['B8'] = _('Reporting Period')
215
    ws['B8'].border = f_border
216
217
    ws['C8'].font = title_font
218
    ws['C8'].alignment = c_c_alignment
219
    ws['C8'] = _('Arithmetic Mean')
220
    ws['C8'].border = f_border
221
222
    ws['D8'].font = title_font
223
    ws['D8'].alignment = c_c_alignment
224
    ws['D8'] = _('Median (Middle Value)')
225
    ws['D8'].border = f_border
226
227
    ws['E8'].font = title_font
228
    ws['E8'].alignment = c_c_alignment
229
    ws['E8'] = _('Minimum Value')
230
    ws['E8'].border = f_border
231
232
    ws['F8'].font = title_font
233
    ws['F8'].alignment = c_c_alignment
234
    ws['F8'] = _('Maximum Value')
235
    ws['F8'].border = f_border
236
237
    ws['G8'].font = title_font
238
    ws['G8'].alignment = c_c_alignment
239
    ws['G8'] = _('Sample Standard Deviation')
240
    ws['G8'].border = f_border
241
242
    ws['H8'].font = title_font
243
    ws['H8'].alignment = c_c_alignment
244
    ws['H8'] = _('Sample Variance')
245
    ws['H8'].border = f_border
246
247
    # table_data
248
249
    for i, value in enumerate(category):
250
        row = i * 2 + 9
251
        ws['B' + str(row)].font = name_font
252
        ws['B' + str(row)].alignment = c_c_alignment
253
        ws['B' + str(row)] = reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + " )"
254
        ws['B' + str(row)].border = f_border
255
256
        ws['B' + str(row + 1)].font = name_font
257
        ws['B' + str(row + 1)].alignment = c_c_alignment
258
        ws['B' + str(row + 1)] = _('Increment Rate')
259
        ws['B' + str(row + 1)].border = f_border
260
261
        ws['C' + str(row)].font = name_font
262
        ws['C' + str(row)].alignment = c_c_alignment
263
        ws['C' + str(row)] = round(reporting_period_data['means'][i], 2) \
264
            if reporting_period_data['means'][i] is not None else ''
265
        ws['C' + str(row)].border = f_border
266
        ws['C' + str(row)].number_format = '0.00'
267
268
        ws['C' + str(row + 1)].font = name_font
269
        ws['C' + str(row + 1)].alignment = c_c_alignment
270
        ws['C' + str(row + 1)] = str(round(reporting_period_data['means_increment_rate'][i] * 100, 2)) + "%" \
271
            if reporting_period_data['means_increment_rate'][i] is not None else '0.00%'
272
        ws['C' + str(row + 1)].border = f_border
273
274
        ws['D' + str(row)].font = name_font
275
        ws['D' + str(row)].alignment = c_c_alignment
276
        ws['D' + str(row)] = round(reporting_period_data['medians'][i], 2) \
277
            if reporting_period_data['medians'][i] is not None else ''
278
        ws['D' + str(row)].border = f_border
279
        ws['D' + str(row)].number_format = '0.00'
280
281
        ws['D' + str(row + 1)].font = name_font
282
        ws['D' + str(row + 1)].alignment = c_c_alignment
283
        ws['D' + str(row + 1)] = str(round(reporting_period_data['medians_increment_rate'][i] * 100, 2)) + "%" \
284
            if reporting_period_data['medians_increment_rate'][i] is not None else '0.00%'
285
        ws['D' + str(row + 1)].border = f_border
286
287
        ws['E' + str(row)].font = name_font
288
        ws['E' + str(row)].alignment = c_c_alignment
289
        ws['E' + str(row)] = round(reporting_period_data['minimums'][i], 2) \
290
            if reporting_period_data['minimums'][i] is not None else ''
291
        ws['E' + str(row)].border = f_border
292
        ws['E' + str(row)].number_format = '0.00'
293
294
        ws['E' + str(row + 1)].font = name_font
295
        ws['E' + str(row + 1)].alignment = c_c_alignment
296
        ws['E' + str(row + 1)] = str(round(reporting_period_data['minimums_increment_rate'][i] * 100, 2)) + "%" \
297
            if reporting_period_data['minimums_increment_rate'][i] is not None else '0.00%'
298
        ws['E' + str(row + 1)].border = f_border
299
300
        ws['F' + str(row)].font = name_font
301
        ws['F' + str(row)].alignment = c_c_alignment
302
        ws['F' + str(row)] = round(reporting_period_data['maximums'][i], 2) \
303
            if reporting_period_data['maximums'][i] is not None else ''
304
        ws['F' + str(row)].border = f_border
305
        ws['F' + str(row)].number_format = '0.00'
306
307
        ws['F' + str(row + 1)].font = name_font
308
        ws['F' + str(row + 1)].alignment = c_c_alignment
309
        ws['F' + str(row + 1)] = str(round(reporting_period_data['maximums_increment_rate'][i] * 100, 2)) + "%" \
310
            if reporting_period_data['maximums_increment_rate'][i] is not None else '0.00%'
311
        ws['F' + str(row + 1)].border = f_border
312
313
        ws['G' + str(row)].font = name_font
314
        ws['G' + str(row)].alignment = c_c_alignment
315
        ws['G' + str(row)] = round(reporting_period_data['stdevs'][i], 2) \
316
            if reporting_period_data['stdevs'][i] is not None else ''
317
        ws['G' + str(row)].border = f_border
318
        ws['G' + str(row)].number_format = '0.00'
319
320
        ws['G' + str(row + 1)].font = name_font
321
        ws['G' + str(row + 1)].alignment = c_c_alignment
322
        ws['G' + str(row + 1)] = str(round(reporting_period_data['stdevs_increment_rate'][i] * 100, 2)) + "%" \
323
            if reporting_period_data['stdevs_increment_rate'][i] is not None else '0.00%'
324
        ws['G' + str(row + 1)].border = f_border
325
326
        ws['H' + str(row)].font = name_font
327
        ws['H' + str(row)].alignment = c_c_alignment
328
        ws['H' + str(row)] = round(reporting_period_data['variances'][i], 2) \
329
            if reporting_period_data['variances'][i] is not None else ''
330
        ws['H' + str(row)].border = f_border
331
        ws['H' + str(row)].number_format = '0.00'
332
333
        ws['H' + str(row + 1)].font = name_font
334
        ws['H' + str(row + 1)].alignment = c_c_alignment
335
        ws['H' + str(row + 1)] = str(round(reporting_period_data['variances_increment_rate'][i] * 100, 2)) + "%" \
336
            if reporting_period_data['variances_increment_rate'][i] is not None else '0.00%'
337
        ws['H' + str(row + 1)].border = f_border
338
    ####################################################################################################################
339
    # Second: Reporting Period Consumption
340
    # 10 + ca_len * 2: title
341
    # 11 + ca_len * 2: table title
342
    # per_unit_area_start_row_number + 2 ~ per_unit_area_start_row_number + 2 + ca_len :  table_data
343
    ####################################################################################################################
344
345
    names = reporting_period_data['names']
346
    ca_len = len(names)
347
348
    per_unit_area_start_row_number = 10 + ca_len * 2
349
350
    ws['B' + str(per_unit_area_start_row_number)].font = title_font
351
    ws['B' + str(per_unit_area_start_row_number)] = name + ' ' \
352
        + _('Per Unit Area') + str(report['store']['area']) + 'M²'
353
354
    category = reporting_period_data['names']
355
356
    # table_title
357
    ws['B' + str(per_unit_area_start_row_number + 1)].fill = table_fill
358
    ws['B' + str(per_unit_area_start_row_number + 1)].font = title_font
359
    ws['B' + str(per_unit_area_start_row_number + 1)].alignment = c_c_alignment
360
    ws['B' + str(per_unit_area_start_row_number + 1)] = _('Reporting Period')
361
    ws['B' + str(per_unit_area_start_row_number + 1)].border = f_border
362
363
    ws['C' + str(per_unit_area_start_row_number + 1)].font = title_font
364
    ws['C' + str(per_unit_area_start_row_number + 1)].alignment = c_c_alignment
365
    ws['C' + str(per_unit_area_start_row_number + 1)] = _('Arithmetic Mean')
366
    ws['C' + str(per_unit_area_start_row_number + 1)].border = f_border
367
368
    ws['D' + str(per_unit_area_start_row_number + 1)].font = title_font
369
    ws['D' + str(per_unit_area_start_row_number + 1)].alignment = c_c_alignment
370
    ws['D' + str(per_unit_area_start_row_number + 1)] = _('Median (Middle Value)')
371
    ws['D' + str(per_unit_area_start_row_number + 1)].border = f_border
372
373
    ws['E' + str(per_unit_area_start_row_number + 1)].font = title_font
374
    ws['E' + str(per_unit_area_start_row_number + 1)].alignment = c_c_alignment
375
    ws['E' + str(per_unit_area_start_row_number + 1)] = _('Minimum Value')
376
    ws['E' + str(per_unit_area_start_row_number + 1)].border = f_border
377
378
    ws['F' + str(per_unit_area_start_row_number + 1)].font = title_font
379
    ws['F' + str(per_unit_area_start_row_number + 1)].alignment = c_c_alignment
380
    ws['F' + str(per_unit_area_start_row_number + 1)] = _('Maximum Value')
381
    ws['F' + str(per_unit_area_start_row_number + 1)].border = f_border
382
383
    ws['G' + str(per_unit_area_start_row_number + 1)].font = title_font
384
    ws['G' + str(per_unit_area_start_row_number + 1)].alignment = c_c_alignment
385
    ws['G' + str(per_unit_area_start_row_number + 1)] = _('Sample Standard Deviation')
386
    ws['G' + str(per_unit_area_start_row_number + 1)].border = f_border
387
388
    ws['H' + str(per_unit_area_start_row_number + 1)].font = title_font
389
    ws['H' + str(per_unit_area_start_row_number + 1)].alignment = c_c_alignment
390
    ws['H' + str(per_unit_area_start_row_number + 1)] = _('Sample Variance')
391
    ws['H' + str(per_unit_area_start_row_number + 1)].border = f_border
392
393
    # table_data
394
395
    for i, value in enumerate(category):
396
        row_data = per_unit_area_start_row_number + 2 + i
397
        ws['B' + str(row_data)].font = name_font
398
        ws['B' + str(row_data)].alignment = c_c_alignment
399
        ws['B' + str(row_data)] = reporting_period_data['names'][i] + " (" + reporting_period_data['units'][
400
            i] + "/M²)"
401
        ws['B' + str(row_data)].border = f_border
402
403
        ws['C' + str(row_data)].font = name_font
404
        ws['C' + str(row_data)].alignment = c_c_alignment
405
        if reporting_period_data['means_per_unit_area'][i] \
406
                or reporting_period_data['means_per_unit_area'][i] == 0:
407
            ws['C' + str(row_data)] = round(reporting_period_data['means_per_unit_area'][i], 2)
408
        ws['C' + str(row_data)].border = f_border
409
        ws['C' + str(row_data)].number_format = '0.00'
410
411
        ws['D' + str(row_data)].font = name_font
412
        ws['D' + str(row_data)].alignment = c_c_alignment
413
        if reporting_period_data['medians_per_unit_area'][i] \
414
                or reporting_period_data['medians_per_unit_area'][i] == 0:
415
            ws['D' + str(row_data)] = round(reporting_period_data['medians_per_unit_area'][i], 2)
416
        ws['D' + str(row_data)].border = f_border
417
        ws['D' + str(row_data)].number_format = '0.00'
418
419
        ws['E' + str(row_data)].font = name_font
420
        ws['E' + str(row_data)].alignment = c_c_alignment
421
        if reporting_period_data['minimums_per_unit_area'][i] \
422
                or reporting_period_data['minimums_per_unit_area'][i] == 0:
423
            ws['E' + str(row_data)] = round(reporting_period_data['minimums_per_unit_area'][i], 2)
424
        ws['E' + str(row_data)].border = f_border
425
        ws['E' + str(row_data)].number_format = '0.00'
426
427
        ws['F' + str(row_data)].font = name_font
428
        ws['F' + str(row_data)].alignment = c_c_alignment
429
        if reporting_period_data['maximums_per_unit_area'][i] \
430
                or reporting_period_data['maximums_per_unit_area'][i] == 0:
431
            ws['F' + str(row_data)] = round(reporting_period_data['maximums_per_unit_area'][i], 2)
432
        ws['F' + str(row_data)].border = f_border
433
        ws['F' + str(row_data)].number_format = '0.00'
434
435
        ws['G' + str(row_data)].font = name_font
436
        ws['G' + str(row_data)].alignment = c_c_alignment
437
        if (reporting_period_data['stdevs_per_unit_area'][i]) \
438
                or reporting_period_data['stdevs_per_unit_area'][i] == 0:
439
            ws['G' + str(row_data)] = round(reporting_period_data['stdevs_per_unit_area'][i], 2)
440
        ws['G' + str(row_data)].border = f_border
441
        ws['G' + str(row_data)].number_format = '0.00'
442
443
        ws['H' + str(row_data)].font = name_font
444
        ws['H' + str(row_data)].alignment = c_c_alignment
445
        if reporting_period_data['variances_per_unit_area'][i] \
446
                or reporting_period_data['variances_per_unit_area'][i] == 0:
447
            ws['H' + str(row_data)] = round(reporting_period_data['variances_per_unit_area'][i], 2)
448
        ws['H' + str(row_data)].border = f_border
449
        ws['H' + str(row_data)].number_format = '0.00'
450
451
    ####################################################################################################################
452
    # Third: Detailed Data
453
    # current_row_number~ current_row_number + 1 + real_timestamps_len * 6 + 1 + 2 + ca_len * 6 + ca_len * 6: line
454
    # current_row_number: table title
455
    # current_row_number + 1~: table_data
456
    ####################################################################################################################
457
    current_row_number = per_unit_area_start_row_number + 2 + len(category) + 1
458
459
    table_start_draw_flag = current_row_number + 1
460 View Code Duplication
    if "timestamps" not in reporting_period_data.keys() or \
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
461
            reporting_period_data['timestamps'] is None or \
462
            len(reporting_period_data['timestamps']) == 0:
463
        pass
464
    else:
465
        if not is_base_period_timestamp_exists_flag:
466
            reporting_period_data = report['reporting_period']
467
            times = reporting_period_data['timestamps']
468
            ca_len = len(report['reporting_period']['names'])
469
            real_timestamps_len = timestamps_data_not_equal_0(report['parameters']['timestamps'])
470
            ws['B' + str(current_row_number)].font = title_font
471
            ws['B' + str(current_row_number)] = name + ' ' + _('Detailed Data')
472
473
            current_row_number += 1
474
            # 1: Stand for blank line  2: Stand for title
475
            current_row_number += ca_len * 6 + real_timestamps_len * 6 + 1 + 2
476
            table_start_row_number = current_row_number
477
478
            time = times[0]
479
            has_data = False
480
481
            if len(time) > 0:
482
                has_data = True
483
484
            if has_data:
485
486
                ws.row_dimensions[current_row_number].height = 60
487
                current_col_number = 2
488
                col = format_cell.get_column_letter(current_col_number)
489
                ws[col + str(current_row_number)].fill = table_fill
490
                ws[col + str(current_row_number)].font = title_font
491
                ws[col + str(current_row_number)].border = f_border
492
                ws[col + str(current_row_number)].alignment = c_c_alignment
493
                ws[col + str(current_row_number)] = _('Datetime')
494
495
                for i in range(0, ca_len):
496
                    current_col_number += 1
497
                    col = format_cell.get_column_letter(current_col_number)
498
499
                    ws[col + str(current_row_number)].fill = table_fill
500
                    ws[col + str(current_row_number)].font = title_font
501
                    ws[col + str(current_row_number)].alignment = c_c_alignment
502
                    ws[col + str(current_row_number)] = reporting_period_data['names'][i] + \
503
                        " (" + reporting_period_data['units'][i] + ")"
504
                    ws[col + str(current_row_number)].border = f_border
505
506
                current_row_number += 1
507
508
                for i in range(0, len(time)):
509
                    current_col_number = 2
510
                    col = format_cell.get_column_letter(current_col_number)
511
                    ws[col + str(current_row_number)].font = title_font
512
                    ws[col + str(current_row_number)].alignment = c_c_alignment
513
                    ws[col + str(current_row_number)] = time[i]
514
                    ws[col + str(current_row_number)].border = f_border
515
516
                    for j in range(0, ca_len):
517
                        current_col_number += 1
518
                        col = format_cell.get_column_letter(current_col_number)
519
520
                        ws[col + str(current_row_number)].font = title_font
521
                        ws[col + str(current_row_number)].alignment = c_c_alignment
522
                        ws[col + str(current_row_number)] = round(reporting_period_data['values'][j][i], 2)
523
                        ws[col + str(current_row_number)].border = f_border
524
525
                    current_row_number += 1
526
527
                table_end_row_number = current_row_number - 1
528
529
                current_col_number = 2
530
                col = format_cell.get_column_letter(current_col_number)
531
                ws[col + str(current_row_number)].font = title_font
532
                ws[col + str(current_row_number)].alignment = c_c_alignment
533
                ws[col + str(current_row_number)] = _('Subtotal')
534
                ws[col + str(current_row_number)].border = f_border
535
536
                for i in range(0, ca_len):
537
                    current_col_number += 1
538
                    col = format_cell.get_column_letter(current_col_number)
539
540
                    ws[col + str(current_row_number)].font = title_font
541
                    ws[col + str(current_row_number)].alignment = c_c_alignment
542
                    ws[col + str(current_row_number)] = round(reporting_period_data['subtotals'][i], 2)
543
                    ws[col + str(current_row_number)].border = f_border
544
545
                    # line
546
                    line = LineChart()
547
                    line.title = _('Reporting Period Consumption') + ' - ' \
548
                        + reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")"
549
                    labels = Reference(ws, min_col=2, min_row=table_start_row_number + 1, max_row=table_end_row_number)
550
                    line_data = Reference(ws, min_col=3 + i, min_row=table_start_row_number,
551
                                          max_row=table_end_row_number)
552
                    line.add_data(line_data, titles_from_data=True)
553
                    line.set_categories(labels)
554
                    line_data = line.series[0]
555
                    line_data.marker.symbol = "circle"
556
                    line_data.smooth = True
557
                    line.x_axis.crosses = 'min'
558
                    line.height = 8.25
559
                    line.width = 24
560
                    line.dLbls = DataLabelList()
561
                    line.dLbls.dLblPos = 't'
562
                    line.dLbls.showVal = True
563
                    line.dLbls.showPercent = False
564
                    chart_col = 'B'
565
                    chart_cell = chart_col + str(table_start_draw_flag + 6 * i)
566
                    ws.add_chart(line, chart_cell)
567
568
                current_row_number += 2
569
        else:
570
            base_period_data = report['base_period']
571
            reporting_period_data = report['reporting_period']
572
            base_period_timestamps = base_period_data['timestamps']
573
            reporting_period_timestamps = reporting_period_data['timestamps']
574
            # Tip:
575
            #     base_period_data['names'] == reporting_period_data['names']
576
            #     base_period_data['units'] == reporting_period_data['units']
577
            base_period_data_ca_len = len(base_period_data['names'])
578
            reporting_period_data_ca_len = len(reporting_period_data['names'])
579
            real_timestamps_len = timestamps_data_not_equal_0(report['parameters']['timestamps'])
580
            ws['B' + str(current_row_number)].font = title_font
581
            ws['B' + str(current_row_number)] = name + ' ' + _('Detailed Data')
582
583
            current_row_number += 1
584
            # 1: Stand for blank line  2: Stand for title
585
            current_row_number += reporting_period_data_ca_len * 6 + real_timestamps_len * 6 + 1 + 2
586
            table_start_row_number = current_row_number
587
588
            has_data = False
589
590
            if len(base_period_timestamps[0]) or len(reporting_period_timestamps[0]) > 0:
591
                has_data = True
592
593
            if has_data:
594
                ws.row_dimensions[current_row_number].height = 60
595
                current_col_number = 2
596
                col = format_cell.get_column_letter(current_col_number)
597
                ws[col + str(current_row_number)].fill = table_fill
598
                ws[col + str(current_row_number)].font = title_font
599
                ws[col + str(current_row_number)].border = f_border
600
                ws[col + str(current_row_number)].alignment = c_c_alignment
601
                ws[col + str(current_row_number)] = _('Base Period') + " - " + _('Datetime')
602
603
                for i in range(0, base_period_data_ca_len):
604
                    current_col_number += 1
605
                    col = format_cell.get_column_letter(current_col_number)
606
607
                    ws[col + str(current_row_number)].fill = table_fill
608
                    ws[col + str(current_row_number)].font = title_font
609
                    ws[col + str(current_row_number)].alignment = c_c_alignment
610
                    ws[col + str(current_row_number)] = _('Base Period') + " - " + base_period_data['names'][i] + \
611
                        " (" + base_period_data['units'][i] + ")"
612
                    ws[col + str(current_row_number)].border = f_border
613
                current_col_number += 1
614
                col = format_cell.get_column_letter(current_col_number)
615
616
                ws[col + str(current_row_number)].fill = table_fill
617
                ws[col + str(current_row_number)].font = title_font
618
                ws[col + str(current_row_number)].border = f_border
619
                ws[col + str(current_row_number)].alignment = c_c_alignment
620
                ws[col + str(current_row_number)] = _('Reporting Period') + " - " + _('Datetime')
621
622
                for i in range(0, reporting_period_data_ca_len):
623
                    current_col_number += 1
624
                    col = format_cell.get_column_letter(current_col_number)
625
                    ws[col + str(current_row_number)].fill = table_fill
626
                    ws[col + str(current_row_number)].font = title_font
627
                    ws[col + str(current_row_number)].alignment = c_c_alignment
628
                    ws[col + str(current_row_number)] = _('Reporting Period') + " - " \
629
                        + reporting_period_data['names'][i] + " (" + \
630
                        reporting_period_data['units'][i] + ")"
631
                    ws[col + str(current_row_number)].border = f_border
632
633
                current_row_number += 1
634
635
                max_timestamps_len = len(base_period_timestamps[0]) \
636
                    if len(base_period_timestamps[0]) >= len(reporting_period_timestamps[0]) \
637
                    else len(reporting_period_timestamps[0])
638
639
                for i in range(0, max_timestamps_len):
640
                    current_col_number = 2
641
                    col = format_cell.get_column_letter(current_col_number)
642
                    ws[col + str(current_row_number)].font = title_font
643
                    ws[col + str(current_row_number)].alignment = c_c_alignment
644
                    ws[col + str(current_row_number)] = base_period_timestamps[0][i] \
645
                        if i < len(base_period_timestamps[0]) else None
646
                    ws[col + str(current_row_number)].border = f_border
647
648
                    for j in range(0, base_period_data_ca_len):
649
                        current_col_number += 1
650
                        col = format_cell.get_column_letter(current_col_number)
651
652
                        ws[col + str(current_row_number)].font = title_font
653
                        ws[col + str(current_row_number)].alignment = c_c_alignment
654
                        ws[col + str(current_row_number)] = round(base_period_data['values'][j][i], 2) \
655
                            if i < len(base_period_data['values'][j]) else None
656
                        ws[col + str(current_row_number)].border = f_border
657
                    current_col_number += 1
658
                    col = format_cell.get_column_letter(current_col_number)
659
660
                    ws[col + str(current_row_number)].font = title_font
661
                    ws[col + str(current_row_number)].alignment = c_c_alignment
662
                    ws[col + str(current_row_number)] = reporting_period_timestamps[0][i] \
663
                        if i < len(reporting_period_timestamps[0]) else None
664
                    ws[col + str(current_row_number)].border = f_border
665
666
                    for j in range(0, reporting_period_data_ca_len):
667
                        current_col_number += 1
668
                        col = format_cell.get_column_letter(current_col_number)
669
670
                        ws[col + str(current_row_number)].font = title_font
671
                        ws[col + str(current_row_number)].alignment = c_c_alignment
672
                        ws[col + str(current_row_number)] = round(reporting_period_data['values'][j][i], 2) \
673
                            if i < len(reporting_period_data['values'][j]) else None
674
                        ws[col + str(current_row_number)].border = f_border
675
676
                    current_row_number += 1
677
678
                current_col_number = 2
679
                col = format_cell.get_column_letter(current_col_number)
680
                ws[col + str(current_row_number)].font = title_font
681
                ws[col + str(current_row_number)].alignment = c_c_alignment
682
                ws[col + str(current_row_number)] = _('Subtotal')
683
                ws[col + str(current_row_number)].border = f_border
684
685
                for i in range(0, base_period_data_ca_len):
686
                    current_col_number += 1
687
                    col = format_cell.get_column_letter(current_col_number)
688
                    ws[col + str(current_row_number)].font = title_font
689
                    ws[col + str(current_row_number)].alignment = c_c_alignment
690
                    ws[col + str(current_row_number)] = round(base_period_data['subtotals'][i], 2)
691
                    ws[col + str(current_row_number)].border = f_border
692
693
                current_col_number += 1
694
                col = format_cell.get_column_letter(current_col_number)
695
696
                ws[col + str(current_row_number)].font = title_font
697
                ws[col + str(current_row_number)].alignment = c_c_alignment
698
                ws[col + str(current_row_number)] = _('Subtotal')
699
                ws[col + str(current_row_number)].border = f_border
700
701
                for i in range(0, reporting_period_data_ca_len):
702
                    current_col_number += 1
703
                    col = format_cell.get_column_letter(current_col_number)
704
                    ws[col + str(current_row_number)].font = title_font
705
                    ws[col + str(current_row_number)].alignment = c_c_alignment
706
                    ws[col + str(current_row_number)] = round(reporting_period_data['subtotals'][i], 2)
707
                    ws[col + str(current_row_number)].border = f_border
708
709
                for i in range(0, reporting_period_data_ca_len):
710
                    # line
711
                    line = LineChart()
712
                    line.title = _('Base Period Consumption') + ' / ' \
713
                        + _('Reporting Period Consumption') + ' - ' \
714
                        + reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")"
715
                    labels = Reference(ws, min_col=2 + base_period_data_ca_len + 1,
716
                                       min_row=table_start_row_number + 1,
717
                                       max_row=table_start_row_number + len(reporting_period_timestamps[0]))
718
                    base_line_data = Reference(ws, min_col=3 + i, min_row=table_start_row_number,
719
                                               max_row=table_start_row_number + len(reporting_period_timestamps[0]))
720
                    reporting_line_data = Reference(ws, min_col=3 + base_period_data_ca_len + 1 + i,
721
                                                    min_row=table_start_row_number,
722
                                                    max_row=table_start_row_number
723
                                                    + len(reporting_period_timestamps[0]))
724
                    line.add_data(base_line_data, titles_from_data=True)
725
                    line.add_data(reporting_line_data, titles_from_data=True)
726
                    line.set_categories(labels)
727
                    for j in range(len(line.series)):
728
                        line.series[j].marker.symbol = "circle"
729
                        line.series[j].smooth = True
730
                    line.x_axis.crosses = 'min'
731
                    line.height = 8.25
732
                    line.width = 24
733
                    line.dLbls = DataLabelList()
734
                    line.dLbls.dLblPos = 't'
735
                    line.dLbls.showVal = True
736
                    line.dLbls.showPercent = False
737
                    chart_col = 'B'
738
                    chart_cell = chart_col + str(table_start_draw_flag + 6 * i)
739
                    ws.add_chart(line, chart_cell)
740
741
                current_row_number += 2
742
743
    ####################################################################################################################
744
    current_sheet_parameters_row_number = table_start_draw_flag + len(reporting_period_data['names']) * 6 + 1
745
    if 'parameters' not in report.keys() or \
746
            report['parameters'] is None or \
747
            'names' not in report['parameters'].keys() or \
748
            report['parameters']['names'] is None or \
749
            len(report['parameters']['names']) == 0 or \
750
            'timestamps' not in report['parameters'].keys() or \
751
            report['parameters']['timestamps'] is None or \
752
            len(report['parameters']['timestamps']) == 0 or \
753
            'values' not in report['parameters'].keys() or \
754
            report['parameters']['values'] is None or \
755
            len(report['parameters']['values']) == 0 or \
756
            timestamps_data_all_equal_0(report['parameters']['timestamps']):
757
        pass
758
    else:
759
760
        ################################################################################################################
761
        # new worksheet
762
        ################################################################################################################
763
764
        parameters_data = report['parameters']
765
766
        parameters_names_len = len(parameters_data['names'])
767
768
        file_name = ws.title
769
        parameters_ws = wb.create_sheet(file_name + _('Parameters'))
770
771
        parameters_timestamps_data_max_len = \
772
            get_parameters_timestamps_lists_max_len(list(parameters_data['timestamps']))
773
774
        # Row height
775
        parameters_ws.row_dimensions[1].height = 102
776
        for i in range(2, 7 + 1):
777
            parameters_ws.row_dimensions[i].height = 42
778
779
        for i in range(8, parameters_timestamps_data_max_len + 10):
780
            parameters_ws.row_dimensions[i].height = 60
781
782
        # Col width
783
        parameters_ws.column_dimensions['A'].width = 1.5
784
785
        parameters_ws.column_dimensions['B'].width = 25.0
786
787
        for i in range(3, 12 + parameters_names_len * 3):
788
            parameters_ws.column_dimensions[format_cell.get_column_letter(i)].width = 15.0
789
790
        # Img
791
        img = Image("excelexporters/myems.png")
792
        parameters_ws.add_image(img, 'A1')
793
794
        # Title
795
        parameters_ws['B3'].alignment = b_r_alignment
796
        parameters_ws['B3'] = _('Name') + ':'
797
        parameters_ws['C3'].border = b_border
798
        parameters_ws['C3'].alignment = b_c_alignment
799
        parameters_ws['C3'] = name
800
801
        parameters_ws['D3'].alignment = b_r_alignment
802
        parameters_ws['D3'] = _('Period Type') + ':'
803
        parameters_ws['E3'].border = b_border
804
        parameters_ws['E3'].alignment = b_c_alignment
805
        parameters_ws['E3'] = period_type
806
807
        parameters_ws['B4'].alignment = b_r_alignment
808
        parameters_ws['B4'] = _('Reporting Start Datetime') + ':'
809
        parameters_ws['C4'].border = b_border
810
        parameters_ws['C4'].alignment = b_c_alignment
811
        parameters_ws['C4'] = reporting_start_datetime_local
812
813
        parameters_ws['D4'].alignment = b_r_alignment
814
        parameters_ws['D4'] = _('Reporting End Datetime') + ':'
815
        parameters_ws['E4'].border = b_border
816
        parameters_ws['E4'].alignment = b_c_alignment
817
        parameters_ws['E4'] = reporting_end_datetime_local
818
819
        parameters_ws_current_row_number = 6
820
821
        parameters_ws['B' + str(parameters_ws_current_row_number)].font = title_font
822
        parameters_ws['B' + str(parameters_ws_current_row_number)] = name + ' ' + _('Parameters')
823
824
        parameters_ws_current_row_number += 1
825
826
        parameters_table_start_row_number = parameters_ws_current_row_number
827
828
        parameters_ws.row_dimensions[parameters_ws_current_row_number].height = 80
829
830
        parameters_ws_current_row_number += 1
831
832
        table_current_col_number = 2
833
834
        for i in range(0, parameters_names_len):
835
836
            if len(parameters_data['timestamps'][i]) == 0:
837
                continue
838
839
            col = format_cell.get_column_letter(table_current_col_number)
840
841
            parameters_ws[col + str(parameters_ws_current_row_number - 1)].fill = table_fill
842
            parameters_ws[col + str(parameters_ws_current_row_number - 1)].border = f_border
843
844
            col = format_cell.get_column_letter(table_current_col_number + 1)
845
846
            parameters_ws[col + str(parameters_ws_current_row_number - 1)].fill = table_fill
847
            parameters_ws[col + str(parameters_ws_current_row_number - 1)].border = f_border
848
            parameters_ws[col + str(parameters_ws_current_row_number - 1)].font = name_font
849
            parameters_ws[col + str(parameters_ws_current_row_number - 1)].alignment = c_c_alignment
850
            parameters_ws[col + str(parameters_ws_current_row_number - 1)] = parameters_data['names'][i]
851
852
            table_current_row_number = parameters_ws_current_row_number
853
854
            for j, value in enumerate(list(parameters_data['timestamps'][i])):
855
                col = format_cell.get_column_letter(table_current_col_number)
856
857
                parameters_ws[col + str(table_current_row_number)].border = f_border
858
                parameters_ws[col + str(table_current_row_number)].font = title_font
859
                parameters_ws[col + str(table_current_row_number)].alignment = c_c_alignment
860
                parameters_ws[col + str(table_current_row_number)] = value
861
862
                col = format_cell.get_column_letter(table_current_col_number + 1)
863
864
                parameters_ws[col + str(table_current_row_number)].border = f_border
865
                parameters_ws[col + str(table_current_row_number)].font = title_font
866
                parameters_ws[col + str(table_current_row_number)].alignment = c_c_alignment
867
                parameters_ws[col + str(table_current_row_number)] = round(parameters_data['values'][i][j], 2)
868
869
                table_current_row_number += 1
870
871
            table_current_col_number = table_current_col_number + 3
872
873
        ################################################################################################################
874
        # parameters chart and parameters table
875
        ################################################################################################################
876
877
        ws['B' + str(current_sheet_parameters_row_number)].font = title_font
878
        ws['B' + str(current_sheet_parameters_row_number)] = name + ' ' + _('Parameters')
879
880
        current_sheet_parameters_row_number += 1
881
882
        chart_start_row_number = current_sheet_parameters_row_number
883
884
        col_index = 0
885
886
        for i in range(0, parameters_names_len):
887
888
            if len(parameters_data['timestamps'][i]) == 0:
889
                continue
890
891
            line = LineChart()
892
            data_col = 3 + col_index * 3
893
            labels_col = 2 + col_index * 3
894
            col_index += 1
895
            line.title = _('Parameters') + ' - ' + \
896
                parameters_ws.cell(row=parameters_table_start_row_number, column=data_col).value
897
            labels = Reference(parameters_ws, min_col=labels_col, min_row=parameters_table_start_row_number + 1,
898
                               max_row=(len(parameters_data['timestamps'][i]) + parameters_table_start_row_number))
899
            line_data = Reference(parameters_ws, min_col=data_col, min_row=parameters_table_start_row_number,
900
                                  max_row=(len(parameters_data['timestamps'][i]) + parameters_table_start_row_number))
901
            line.add_data(line_data, titles_from_data=True)
902
            line.set_categories(labels)
903
            line_data = line.series[0]
904
            line_data.marker.symbol = "circle"
905
            line_data.smooth = True
906
            line.x_axis.crosses = 'min'
907
            line.height = 8.25
908
            line.width = 24
909
            line.dLbls = DataLabelList()
910
            line.dLbls.dLblPos = 't'
911
            line.dLbls.showVal = False
912
            line.dLbls.showPercent = False
913
            chart_col = 'B'
914
            chart_cell = chart_col + str(chart_start_row_number)
915
            chart_start_row_number += 6
916
            ws.add_chart(line, chart_cell)
917
918
        current_sheet_parameters_row_number = chart_start_row_number
919
920
        current_sheet_parameters_row_number += 1
921
922
    filename = str(uuid.uuid4()) + '.xlsx'
923
    wb.save(filename)
924
925
    return filename
926
927
928
def get_parameters_timestamps_lists_max_len(parameters_timestamps_lists):
929
    max_len = 0
930
    for i, value in enumerate(list(parameters_timestamps_lists)):
931
        if len(value) > max_len:
932
            max_len = len(value)
933
934
    return max_len
935
936
937
def timestamps_data_all_equal_0(lists):
938
    for i, value in enumerate(list(lists)):
939
        if len(value) > 0:
940
            return False
941
942
    return True
943
944
945
def timestamps_data_not_equal_0(lists):
946
    number = 0
947
    for i, value in enumerate(list(lists)):
948
        if len(value) > 0:
949
            number += 1
950
    return number
951
952
953 View Code Duplication
def is_base_period_timestamp_exists(base_period_data):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
954
    timestamps = base_period_data['timestamps']
955
956
    if len(timestamps) == 0:
957
        return False
958
959
    for timestamp in timestamps:
960
        if len(timestamp) > 0:
961
            return True
962
963
    return False
964