Passed
Push — master ( 82dd0d...8c8679 )
by Guangyu
10:18 queued 13s
created

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