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

excelexporters.storeload.generate_excel()   F

Complexity

Conditions 98

Size

Total Lines 886
Code Lines 679

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 679
dl 0
loc 886
rs 0
c 0
b 0
f 0
cc 98
nop 8

How to fix   Long Method    Complexity    Many Parameters   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like excelexporters.storeload.generate_excel() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

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 bytes 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 = "StoreLoad"
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'].font = title_font
219
    ws['C8'].alignment = c_c_alignment
220
    ws['C8'] = _('Average Load')
221
    ws['C8'].border = f_border
222
223
    ws['D8'].font = title_font
224
    ws['D8'].alignment = c_c_alignment
225
    ws['D8'] = _('Maximum Load')
226
    ws['D8'].border = f_border
227
228
    ws['E8'].font = title_font
229
    ws['E8'].alignment = c_c_alignment
230
    ws['E8'] = _('Load Factor')
231
    ws['E8'].border = f_border
232
233
    # table_data
234
235
    for i, value in enumerate(category):
236
        row = i * 2 + 9
237
        ws['B' + str(row)].font = name_font
238
        ws['B' + str(row)].alignment = c_c_alignment
239
        ws['B' + str(row)] = reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + "/H )"
240
        ws['B' + str(row)].border = f_border
241
242
        ws['B' + str(row + 1)].font = name_font
243
        ws['B' + str(row + 1)].alignment = c_c_alignment
244
        ws['B' + str(row + 1)] = _('Increment Rate')
245
        ws['B' + str(row + 1)].border = f_border
246
247
        ws['C' + str(row)].font = name_font
248
        ws['C' + str(row)].alignment = c_c_alignment
249
        ws['C' + str(row)] = round(reporting_period_data['averages'][i], 2) \
250
            if reporting_period_data['averages'][i] is not None else ''
251
        ws['C' + str(row)].border = f_border
252
        ws['C' + str(row)].number_format = '0.00'
253
254
        ws['C' + str(row + 1)].font = name_font
255
        ws['C' + str(row + 1)].alignment = c_c_alignment
256
        ws['C' + str(row + 1)] = str(round(reporting_period_data['averages_increment_rate'][i] * 100, 2)) + "%" \
257
            if reporting_period_data['averages_increment_rate'][i] is not None else '0.00%'
258
        ws['C' + str(row + 1)].border = f_border
259
260
        ws['D' + str(row)].font = name_font
261
        ws['D' + str(row)].alignment = c_c_alignment
262
        ws['D' + str(row)] = round(reporting_period_data['maximums'][i], 2) \
263
            if reporting_period_data['maximums'][i] is not None else ''
264
        ws['D' + str(row)].border = f_border
265
        ws['D' + str(row)].number_format = '0.00'
266
267
        ws['D' + str(row + 1)].font = name_font
268
        ws['D' + str(row + 1)].alignment = c_c_alignment
269
        ws['D' + str(row + 1)] = str(round(reporting_period_data['maximums_increment_rate'][i] * 100, 2)) + "%" \
270
            if reporting_period_data['maximums_increment_rate'][i] is not None else '0.00%'
271
        ws['D' + str(row + 1)].border = f_border
272
273
        ws['E' + str(row)].font = name_font
274
        ws['E' + str(row)].alignment = c_c_alignment
275
        ws['E' + str(row)] = round(reporting_period_data['factors'][i], 2) \
276
            if reporting_period_data['factors'][i] is not None else ''
277
        ws['E' + str(row)].border = f_border
278
        ws['E' + str(row)].number_format = '0.00'
279
280
        ws['E' + str(row + 1)].font = name_font
281
        ws['E' + str(row + 1)].alignment = c_c_alignment
282
        ws['E' + str(row + 1)] = str(round(reporting_period_data['factors_increment_rate'][i] * 100, 2)) + "%" \
283
            if reporting_period_data['factors_increment_rate'][i] is not None else '0.00%'
284
        ws['E' + str(row + 1)].border = f_border
285
286
    ####################################################################################################################
287
    # Second: Per Unit Area
288
    # 10 + ca_len * 2: title
289
    # 11 + ca_len * 2: table title
290
    # per_unit_area_start_row_number + 2 ~ per_unit_area_start_row_number + 2 + ca_len :  table_data
291
    ####################################################################################################################
292
293
    names = reporting_period_data['names']
294
    ca_len = len(names)
295
    per_unit_area_start_row_number = 10 + ca_len * 2
296
297
    ws['B' + str(per_unit_area_start_row_number)].font = title_font
298
    ws['B' + str(per_unit_area_start_row_number)] = name + ' ' \
299
        + _('Per Unit Area') + str(report['store']['area']) + 'M²'
300
301
    category = reporting_period_data['names']
302
303
    # table_title
304
    ws['B' + str(per_unit_area_start_row_number + 1)].fill = table_fill
305
    ws['B' + str(per_unit_area_start_row_number + 1)].font = title_font
306
    ws['B' + str(per_unit_area_start_row_number + 1)].alignment = c_c_alignment
307
    ws['B' + str(per_unit_area_start_row_number + 1)] = _('Reporting Period')
308
    ws['B' + str(per_unit_area_start_row_number + 1)].border = f_border
309
310
    ws['C' + str(per_unit_area_start_row_number + 1)].font = title_font
311
    ws['C' + str(per_unit_area_start_row_number + 1)].alignment = c_c_alignment
312
    ws['C' + str(per_unit_area_start_row_number + 1)] = _('Average Load')
313
    ws['C' + str(per_unit_area_start_row_number + 1)].border = f_border
314
315
    ws['D' + str(per_unit_area_start_row_number + 1)].font = title_font
316
    ws['D' + str(per_unit_area_start_row_number + 1)].alignment = c_c_alignment
317
    ws['D' + str(per_unit_area_start_row_number + 1)] = _('Maximum Load')
318
    ws['D' + str(per_unit_area_start_row_number + 1)].border = f_border
319
320
    # table_data
321
322
    for i, value in enumerate(category):
323
        row_data = per_unit_area_start_row_number + 2 + i
324
        ws['B' + str(row_data)].font = name_font
325
        ws['B' + str(row_data)].alignment = c_c_alignment
326
        ws['B' + str(row_data)] = reporting_period_data['names'][i] + " (" + reporting_period_data['units'][
327
            i] + "/H/M²)"
328
        ws['B' + str(row_data)].border = f_border
329
330
        ws['C' + str(row_data)].font = name_font
331
        ws['C' + str(row_data)].alignment = c_c_alignment
332
        if reporting_period_data['averages_per_unit_area'][i] \
333
                or reporting_period_data['averages_per_unit_area'][i] == 0:
334
            ws['C' + str(row_data)] = round(reporting_period_data['averages_per_unit_area'][i], 2)
335
        ws['C' + str(row_data)].border = f_border
336
        ws['C' + str(row_data)].number_format = '0.00'
337
338
        ws['D' + str(row_data)].font = name_font
339
        ws['D' + str(row_data)].alignment = c_c_alignment
340
        if reporting_period_data['maximums_per_unit_area'][i] \
341
                or reporting_period_data['maximums_per_unit_area'][i] == 0:
342
            ws['D' + str(row_data)] = round(reporting_period_data['maximums_per_unit_area'][i], 2)
343
        ws['D' + str(row_data)].border = f_border
344
        ws['D' + str(row_data)].number_format = '0.00'
345
346
    ####################################################################################################################
347
    # Third: Detailed Data
348
    # current_row_number~ current_row_number + 1 + real_timestamps_len * 6 + 1 + 2 + ca_len * 6 + ca_len * 6: line
349
    # current_row_number: table title
350
    # current_row_number + 1~: table_data
351
    ####################################################################################################################
352
    current_row_number = per_unit_area_start_row_number + 2 + len(category) + 1
353
354
    has_sub_averages_data_flag = True
355
    has_sub_maximums_data_flag = True
356
357
    if "sub_averages" not in report['reporting_period'].keys() or len(report['reporting_period']['sub_averages']) == 0:
358
        has_sub_averages_data_flag = False
359
360
    if "sub_maximums" not in report['reporting_period'].keys() or len(report['reporting_period']['sub_maximums']) == 0:
361
        has_sub_maximums_data_flag = False
362
363
    current_chart_row_number = current_row_number
364
365
    if has_sub_averages_data_flag or has_sub_maximums_data_flag:
366
        if not is_base_period_timestamp_exists_flag:
367
            reporting_period_data = report['reporting_period']
368
            category = reporting_period_data['names']
369
            ca_len = len(category)
370
            times = reporting_period_data['timestamps']
371
            time = times[0]
372
            real_timestamps_len = timestamps_data_not_equal_0(report['parameters']['timestamps'])
373
            ws['B' + str(current_row_number)].font = title_font
374
            ws['B' + str(current_row_number)] = name + _('Detailed Data')
375
376
            current_row_number += 1
377
            chart_start_number = current_row_number
378
            # 1: Stand for blank line  2: Stand for title
379
            current_row_number += real_timestamps_len * 6 + 1 + 2
380
            if has_sub_averages_data_flag:
381
                current_row_number = (current_row_number + ca_len * 6)
382
383
            if has_sub_maximums_data_flag:
384
                current_row_number = (current_row_number + ca_len * 6)
385
386
            table_start_number = current_row_number
387
388
            ws.row_dimensions[current_row_number].height = 60
389
            current_col_number = 2
390
            col = format_cell.get_column_letter(current_col_number)
391
            ws[col + str(current_row_number)].fill = table_fill
392
            ws[col + str(current_row_number)].font = title_font
393
            ws[col + str(current_row_number)].alignment = c_c_alignment
394
            ws[col + str(current_row_number)].border = f_border
395
            ws[col + str(current_row_number)] = _('Datetime')
396
397
            current_col_number = 3
398
            col = format_cell.get_column_letter(current_col_number)
399
400
            for i in range(0, ca_len):
401
                if has_sub_averages_data_flag:
402
                    ws[col + str(current_row_number)].fill = table_fill
403
                    ws[col + str(current_row_number)].font = title_font
404
                    ws[col + str(current_row_number)].alignment = c_c_alignment
405
                    ws[col + str(current_row_number)].border = f_border
406
                    ws[col + str(current_row_number)] = reporting_period_data['names'][i] + \
407
                        " " + _('Average Load') + "(" + reporting_period_data['units'][i] + "/H)"
408
409
                    current_col_number += 1
410
                    col = format_cell.get_column_letter(current_col_number)
411
412
                if has_sub_maximums_data_flag:
413
                    ws[col + str(current_row_number)].fill = table_fill
414
                    ws[col + str(current_row_number)].font = title_font
415
                    ws[col + str(current_row_number)].alignment = c_c_alignment
416
                    ws[col + str(current_row_number)].border = f_border
417
                    ws[col + str(current_row_number)] = reporting_period_data['names'][i] + \
418
                        " " + _('Maximum Load') + "(" + reporting_period_data['units'][i] + "/H)"
419
420
                    current_col_number += 1
421
                    col = format_cell.get_column_letter(current_col_number)
422
423
            current_row_number += 1
424
425
            for i in range(0, len(time)):
426
                current_col_number = 2
427
                col = format_cell.get_column_letter(current_col_number)
428
                ws[col + str(current_row_number)].font = title_font
429
                ws[col + str(current_row_number)].alignment = c_c_alignment
430
                ws[col + str(current_row_number)].border = f_border
431
                ws[col + str(current_row_number)] = time[i]
432
433
                current_col_number = 3
434
                col = format_cell.get_column_letter(current_col_number)
435
                for j in range(0, ca_len):
436
437
                    if has_sub_averages_data_flag:
438
                        ws[col + str(current_row_number)].font = title_font
439
                        ws[col + str(current_row_number)].alignment = c_c_alignment
440
                        ws[col + str(current_row_number)].border = f_border
441
                        ws[col + str(current_row_number)] = round(reporting_period_data['sub_averages'][j][i], 2) \
442
                            if reporting_period_data['sub_averages'][j][i] is not None else None
443
                        current_col_number += 1
444
                        col = format_cell.get_column_letter(current_col_number)
445
446
                    if has_sub_maximums_data_flag:
447
                        ws[col + str(current_row_number)].font = title_font
448
                        ws[col + str(current_row_number)].alignment = c_c_alignment
449
                        ws[col + str(current_row_number)].border = f_border
450
                        ws[col + str(current_row_number)] = round(reporting_period_data['sub_maximums'][j][i], 2) \
451
                            if reporting_period_data['sub_maximums'][j][i] is not None else None
452
                        current_col_number += 1
453
                        col = format_cell.get_column_letter(current_col_number)
454
455
                current_row_number += 1
456
457
            table_end_number = current_row_number - 1
458
459
            current_chart_col_number = 3
460
            current_chart_row_number = chart_start_number
461
462
            for i in range(0, ca_len):
463
                labels = Reference(ws, min_col=2, min_row=table_start_number + 1, max_row=table_end_number)
464
465
                if has_sub_averages_data_flag:
466
                    line = LineChart()
467
                    line.title = _('Reporting Period Average Load') + ' - ' \
468
                        + reporting_period_data['names'][i] + \
469
                        " " + _('Average Load') + "(" + reporting_period_data['units'][i] + "/H)"
470
                    datas = Reference(ws, min_col=current_chart_col_number, min_row=table_start_number,
471
                                      max_row=table_end_number)
472
                    line.add_data(datas, titles_from_data=True)
473
                    line.set_categories(labels)
474
                    line_data = line.series[0]
475
                    line_data.marker.symbol = "circle"
476
                    line_data.smooth = True
477
                    line.x_axis.crosses = 'min'
478
                    line.height = 8.25
479
                    line.width = 24
480
                    line.dLbls = DataLabelList()
481
                    line.dLbls.dLblPos = 't'
482
                    line.dLbls.showVal = True
483
                    ws.add_chart(line, "B" + str(current_chart_row_number))
484
                    current_chart_row_number += 6
485
                    current_chart_col_number += 1
486
487
                if has_sub_maximums_data_flag:
488
                    line = LineChart()
489
                    line.title = _('Reporting Period Maximum Load') + ' - ' \
490
                        + reporting_period_data['names'][i] + \
491
                        " " + _('Maximum Load') + "(" + reporting_period_data['units'][i] + "/H)"
492
                    datas = Reference(ws, min_col=current_chart_col_number, min_row=table_start_number,
493
                                      max_row=table_end_number)
494
                    line.add_data(datas, titles_from_data=True)
495
                    line.set_categories(labels)
496
                    line_data = line.series[0]
497
                    line_data.marker.symbol = "circle"
498
                    line_data.smooth = True
499
                    line.x_axis.crosses = 'min'
500
                    line.height = 8.25
501
                    line.width = 24
502
                    line.dLbls = DataLabelList()
503
                    line.dLbls.dLblPos = 't'
504
                    line.dLbls.showVal = True
505
                    ws.add_chart(line, "B" + str(current_chart_row_number))
506
                    current_chart_row_number += 6
507
                    current_chart_col_number += 1
508
        else:
509
            base_period_data = report['base_period']
510
            reporting_period_data = report['reporting_period']
511
            base_period_timestamps = base_period_data['timestamps']
512
            reporting_period_timestamps = reporting_period_data['timestamps']
513
            # Tip:
514
            #     base_period_data['names'] == reporting_period_data['names']
515
            #     base_period_data['units'] == reporting_period_data['units']
516
            base_period_data_ca_len = len(base_period_data['names'])
517
            reporting_period_data_ca_len = len(reporting_period_data['names'])
518
            real_timestamps_len = timestamps_data_not_equal_0(report['parameters']['timestamps'])
519
            ws['B' + str(current_row_number)].font = title_font
520
            ws['B' + str(current_row_number)] = name + ' ' + _('Detailed Data')
521
522
            current_row_number += 1
523
            chart_start_number = current_row_number
524
525
            # 1: Stand for blank line  2: Stand for title
526
            current_row_number += real_timestamps_len * 6 + 1 + 2
527
528
            if has_sub_averages_data_flag:
529
                current_row_number = (current_row_number + reporting_period_data_ca_len * 6)
530
531
            if has_sub_maximums_data_flag:
532
                current_row_number = (current_row_number + reporting_period_data_ca_len * 6)
533
534
            table_start_row_number = current_row_number
535
536
            has_data = False
537
538
            if len(base_period_timestamps[0]) or len(reporting_period_timestamps[0]) > 0:
539
                has_data = True
540
541
            if has_data:
542
                ws.row_dimensions[current_row_number].height = 60
543
                current_col_number = 2
544
                col = format_cell.get_column_letter(current_col_number)
545
                ws[col + str(current_row_number)].fill = table_fill
546
                ws[col + str(current_row_number)].font = title_font
547
                ws[col + str(current_row_number)].border = f_border
548
                ws[col + str(current_row_number)].alignment = c_c_alignment
549
                ws[col + str(current_row_number)] = _('Base Period') + " - " + _('Datetime')
550
551
                for i in range(0, base_period_data_ca_len):
552
                    if has_sub_averages_data_flag:
553
                        current_col_number += 1
554
                        col = format_cell.get_column_letter(current_col_number)
555
556
                        ws[col + str(current_row_number)].fill = table_fill
557
                        ws[col + str(current_row_number)].font = title_font
558
                        ws[col + str(current_row_number)].alignment = c_c_alignment
559
                        ws[col + str(current_row_number)] = _('Base Period') + " - " \
560
                            + base_period_data['names'][i] + \
561
                            " " + _('Average Load') + "(" + base_period_data['units'][i] + "/H)"
562
                        ws[col + str(current_row_number)].border = f_border
563
564
                    if has_sub_maximums_data_flag:
565
                        current_col_number += 1
566
                        col = format_cell.get_column_letter(current_col_number)
567
568
                        ws[col + str(current_row_number)].fill = table_fill
569
                        ws[col + str(current_row_number)].font = title_font
570
                        ws[col + str(current_row_number)].alignment = c_c_alignment
571
                        ws[col + str(current_row_number)] = _('Base Period') + " - " \
572
                            + base_period_data['names'][i] + \
573
                            " " + _('Maximum Load') + "(" + base_period_data['units'][i] + "/H)"
574
                        ws[col + str(current_row_number)].border = f_border
575
576
                current_col_number += 1
577
                col = format_cell.get_column_letter(current_col_number)
578
579
                ws[col + str(current_row_number)].fill = table_fill
580
                ws[col + str(current_row_number)].font = title_font
581
                ws[col + str(current_row_number)].border = f_border
582
                ws[col + str(current_row_number)].alignment = c_c_alignment
583
                ws[col + str(current_row_number)] = _('Reporting Period') + " - " + _('Datetime')
584
585
                for i in range(0, reporting_period_data_ca_len):
586
                    if has_sub_averages_data_flag:
587
                        current_col_number += 1
588
                        col = format_cell.get_column_letter(current_col_number)
589
                        ws[col + str(current_row_number)].fill = table_fill
590
                        ws[col + str(current_row_number)].font = title_font
591
                        ws[col + str(current_row_number)].alignment = c_c_alignment
592
                        ws[col + str(current_row_number)] = _('Reporting Period') + " - " \
593
                            + reporting_period_data['names'][i] + \
594
                            " " + _('Average Load') + "(" + reporting_period_data['units'][i] + "/H)"
595
                        ws[col + str(current_row_number)].border = f_border
596
597
                    if has_sub_maximums_data_flag:
598
                        current_col_number += 1
599
                        col = format_cell.get_column_letter(current_col_number)
600
                        ws[col + str(current_row_number)].fill = table_fill
601
                        ws[col + str(current_row_number)].font = title_font
602
                        ws[col + str(current_row_number)].alignment = c_c_alignment
603
                        ws[col + str(current_row_number)] = _('Reporting Period') + " - " \
604
                            + reporting_period_data['names'][i] + \
605
                            " " + _('Maximum Load') + "(" + \
606
                            reporting_period_data['units'][i] + "/H)"
607
                        ws[col + str(current_row_number)].border = f_border
608
609
                current_row_number += 1
610
611
                max_timestamps_len = len(base_period_timestamps[0]) \
612
                    if len(base_period_timestamps[0]) >= len(reporting_period_timestamps[0]) \
613
                    else len(reporting_period_timestamps[0])
614
615
                for i in range(0, max_timestamps_len):
616
                    current_col_number = 2
617
                    col = format_cell.get_column_letter(current_col_number)
618
                    ws[col + str(current_row_number)].font = title_font
619
                    ws[col + str(current_row_number)].alignment = c_c_alignment
620
                    ws[col + str(current_row_number)] = base_period_timestamps[0][i] \
621
                        if i < len(base_period_timestamps[0]) else None
622
                    ws[col + str(current_row_number)].border = f_border
623
624
                    for j in range(0, base_period_data_ca_len):
625
                        if has_sub_averages_data_flag:
626
                            current_col_number += 1
627
                            col = format_cell.get_column_letter(current_col_number)
628
629
                            ws[col + str(current_row_number)].font = title_font
630
                            ws[col + str(current_row_number)].alignment = c_c_alignment
631
                            ws[col + str(current_row_number)] = round(base_period_data['sub_averages'][j][i], 2) \
632
                                if i < len(base_period_data['sub_averages'][j]) \
633
                                and base_period_data['sub_averages'][j][i] is not None else None
634
                            ws[col + str(current_row_number)].border = f_border
635
636
                        if has_sub_maximums_data_flag:
637
                            current_col_number += 1
638
                            col = format_cell.get_column_letter(current_col_number)
639
640
                            ws[col + str(current_row_number)].font = title_font
641
                            ws[col + str(current_row_number)].alignment = c_c_alignment
642
                            ws[col + str(current_row_number)] = round(base_period_data['sub_maximums'][j][i], 2) \
643
                                if i < len(base_period_data['sub_maximums'][j]) \
644
                                and base_period_data['sub_averages'][j][i] is not None else None
645
                            ws[col + str(current_row_number)].border = f_border
646
647
                    current_col_number += 1
648
                    col = format_cell.get_column_letter(current_col_number)
649
650
                    ws[col + str(current_row_number)].font = title_font
651
                    ws[col + str(current_row_number)].alignment = c_c_alignment
652
                    ws[col + str(current_row_number)] = reporting_period_timestamps[0][i] \
653
                        if i < len(reporting_period_timestamps[0]) else None
654
                    ws[col + str(current_row_number)].border = f_border
655
656
                    for j in range(0, reporting_period_data_ca_len):
657
                        if has_sub_averages_data_flag:
658
                            current_col_number += 1
659
                            col = format_cell.get_column_letter(current_col_number)
660
661
                            ws[col + str(current_row_number)].font = title_font
662
                            ws[col + str(current_row_number)].alignment = c_c_alignment
663
                            ws[col + str(current_row_number)] = round(reporting_period_data['sub_averages'][j][i], 2) \
664
                                if i < len(reporting_period_data['sub_averages'][j]) \
665
                                and reporting_period_data['sub_averages'][j][i] is not None else None
666
                            ws[col + str(current_row_number)].border = f_border
667
668
                        if has_sub_maximums_data_flag:
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)] = round(reporting_period_data['sub_maximums'][j][i], 2) \
675
                                if i < len(reporting_period_data['sub_maximums'][j]) \
676
                                and reporting_period_data['sub_maximums'][j][i] is not None else None
677
                            ws[col + str(current_row_number)].border = f_border
678
679
                    current_row_number += 1
680
681
                current_chart_col_number = 3
682
                current_chart_row_number = chart_start_number
683
684
                for i in range(0, reporting_period_data_ca_len):
685
                    labels = Reference(ws, min_col=2 + base_period_data_ca_len * 2 + 1,
686
                                       min_row=table_start_row_number + 1,
687
                                       max_row=table_start_row_number + len(reporting_period_timestamps[0]))
688
689
                    if has_sub_averages_data_flag:
690
                        # line
691
                        line = LineChart()
692
                        line.title = _('Base Period Average Load') + ' / ' \
693
                            + _('Reporting Period Average Load') + ' - ' \
694
                            + reporting_period_data['names'][i] + \
695
                            " " + _('Average Load') + "(" + reporting_period_data['units'][i] + "/H)"
696
                        base_line_data = Reference(ws,
697
                                                   min_col=current_chart_col_number,
698
                                                   min_row=table_start_row_number,
699
                                                   max_row=table_start_row_number
700
                                                   + len(reporting_period_timestamps[0]))
701
702
                        data_distance = base_period_data_ca_len
703
                        if has_sub_maximums_data_flag:
704
                            data_distance *= 2
705
706
                        reporting_line_data = Reference(ws,
707
                                                        min_col=current_chart_col_number + data_distance + 1,
708
                                                        min_row=table_start_row_number,
709
                                                        max_row=table_start_row_number
710
                                                        + len(reporting_period_timestamps[0]))
711
                        line.add_data(base_line_data, titles_from_data=True)
712
                        line.add_data(reporting_line_data, titles_from_data=True)
713
                        line.set_categories(labels)
714
                        for j in range(len(line.series)):
715
                            line.series[j].marker.symbol = "circle"
716
                            line.series[j].smooth = True
717
                        line.x_axis.crosses = 'min'
718
                        line.height = 8.25
719
                        line.width = 24
720
                        line.dLbls = DataLabelList()
721
                        line.dLbls.dLblPos = 't'
722
                        line.dLbls.showVal = True
723
                        line.dLbls.showPercent = False
724
                        chart_col = 'B'
725
                        chart_cell = chart_col + str(current_chart_row_number)
726
                        ws.add_chart(line, chart_cell)
727
                        current_chart_row_number += 6
728
                        current_chart_col_number += 1
729
730
                    if has_sub_maximums_data_flag:
731
                        # line
732
                        line = LineChart()
733
                        line.title = _('Base Period Maximum Load') + ' / ' \
734
                            + _('Reporting Period Maximum Load') + ' - ' \
735
                            + reporting_period_data['names'][i] + \
736
                            " " + _('Maximum Load') + "(" + reporting_period_data['units'][i] + "/H)"
737
                        base_line_data = Reference(ws,
738
                                                   min_col=current_chart_col_number,
739
                                                   min_row=table_start_row_number,
740
                                                   max_row=table_start_row_number
741
                                                   + len(reporting_period_timestamps[0]))
742
743
                        data_distance = base_period_data_ca_len
744
                        if has_sub_averages_data_flag:
745
                            data_distance *= 2
746
747
                        reporting_line_data = Reference(ws,
748
                                                        min_col=current_chart_col_number + data_distance + 1,
749
                                                        min_row=table_start_row_number,
750
                                                        max_row=table_start_row_number
751
                                                        + len(reporting_period_timestamps[0]))
752
                        line.add_data(base_line_data, titles_from_data=True)
753
                        line.add_data(reporting_line_data, titles_from_data=True)
754
                        line.set_categories(labels)
755
                        for j in range(len(line.series)):
756
                            line.series[j].marker.symbol = "circle"
757
                            line.series[j].smooth = True
758
                        line.x_axis.crosses = 'min'
759
                        line.height = 8.25
760
                        line.width = 24
761
                        line.dLbls = DataLabelList()
762
                        line.dLbls.dLblPos = 't'
763
                        line.dLbls.showVal = True
764
                        line.dLbls.showPercent = False
765
                        chart_col = 'B'
766
                        chart_cell = chart_col + str(current_chart_row_number)
767
                        ws.add_chart(line, chart_cell)
768
                        current_chart_row_number += 6
769
                        current_chart_col_number += 1
770
771
                current_row_number += 2
772
773
    ####################################################################################################################
774
    current_sheet_parameters_row_number = current_chart_row_number + 1
775
    if 'parameters' not in report.keys() or \
776
            report['parameters'] is None or \
777
            'names' not in report['parameters'].keys() or \
778
            report['parameters']['names'] is None or \
779
            len(report['parameters']['names']) == 0 or \
780
            'timestamps' not in report['parameters'].keys() or \
781
            report['parameters']['timestamps'] is None or \
782
            len(report['parameters']['timestamps']) == 0 or \
783
            'values' not in report['parameters'].keys() or \
784
            report['parameters']['values'] is None or \
785
            len(report['parameters']['values']) == 0 or \
786
            timestamps_data_all_equal_0(report['parameters']['timestamps']):
787
        pass
788
    else:
789
        ################################################################################################################
790
        # new worksheet
791
        ################################################################################################################
792
        parameters_data = report['parameters']
793
794
        parameters_names_len = len(parameters_data['names'])
795
796
        file_name = "Store"+re.sub(r'[^A-Z]', '', ws.title.strip('S')) + "_"
797
        parameters_ws = wb.create_sheet(file_name + _('Parameters'))
798
799
        parameters_timestamps_data_max_len = \
800
            get_parameters_timestamps_lists_max_len(list(parameters_data['timestamps']))
801
802
        # Row height
803
        parameters_ws.row_dimensions[1].height = 102
804
        for i in range(2, 7 + 1):
805
            parameters_ws.row_dimensions[i].height = 42
806
807
        for i in range(8, parameters_timestamps_data_max_len + 10):
808
            parameters_ws.row_dimensions[i].height = 60
809
810
        # Col width
811
        parameters_ws.column_dimensions['A'].width = 1.5
812
813
        parameters_ws.column_dimensions['B'].width = 25.0
814
815
        for i in range(3, 12 + parameters_names_len * 3):
816
            parameters_ws.column_dimensions[format_cell.get_column_letter(i)].width = 15.0
817
818
        # Img
819
        img = Image("excelexporters/myems.png")
820
        img.width = img.width * 0.85
821
        img.height = img.height * 0.85
822
        parameters_ws.add_image(img, 'B1')
823
824
        # Title
825
        parameters_ws['B3'].alignment = b_r_alignment
826
        parameters_ws['B3'] = _('Name') + ':'
827
        parameters_ws['C3'].border = b_border
828
        parameters_ws['C3'].alignment = b_c_alignment
829
        parameters_ws['C3'] = name
830
831
        parameters_ws['D3'].alignment = b_r_alignment
832
        parameters_ws['D3'] = _('Period Type') + ':'
833
        parameters_ws['E3'].border = b_border
834
        parameters_ws['E3'].alignment = b_c_alignment
835
        parameters_ws['E3'] = period_type
836
837
        parameters_ws['B4'].alignment = b_r_alignment
838
        parameters_ws['B4'] = _('Reporting Start Datetime') + ':'
839
        parameters_ws['C4'].border = b_border
840
        parameters_ws['C4'].alignment = b_c_alignment
841
        parameters_ws['C4'] = reporting_start_datetime_local
842
843
        parameters_ws['D4'].alignment = b_r_alignment
844
        parameters_ws['D4'] = _('Reporting End Datetime') + ':'
845
        parameters_ws['E4'].border = b_border
846
        parameters_ws['E4'].alignment = b_c_alignment
847
        parameters_ws['E4'] = reporting_end_datetime_local
848
849
        parameters_ws_current_row_number = 6
850
851
        parameters_ws['B' + str(parameters_ws_current_row_number)].font = title_font
852
        parameters_ws['B' + str(parameters_ws_current_row_number)] = name + ' ' + _('Parameters')
853
854
        parameters_ws_current_row_number += 1
855
856
        parameters_table_start_row_number = parameters_ws_current_row_number
857
858
        parameters_ws.row_dimensions[parameters_ws_current_row_number].height = 80
859
860
        parameters_ws_current_row_number += 1
861
862
        table_current_col_number = 2
863
864
        for i in range(0, parameters_names_len):
865
866
            if len(parameters_data['timestamps'][i]) == 0:
867
                continue
868
869
            col = format_cell.get_column_letter(table_current_col_number)
870
871
            parameters_ws[col + str(parameters_ws_current_row_number - 1)].fill = table_fill
872
            parameters_ws[col + str(parameters_ws_current_row_number - 1)].border = f_border
873
874
            col = format_cell.get_column_letter(table_current_col_number + 1)
875
876
            parameters_ws[col + str(parameters_ws_current_row_number - 1)].fill = table_fill
877
            parameters_ws[col + str(parameters_ws_current_row_number - 1)].border = f_border
878
            parameters_ws[col + str(parameters_ws_current_row_number - 1)].font = name_font
879
            parameters_ws[col + str(parameters_ws_current_row_number - 1)].alignment = c_c_alignment
880
            parameters_ws[col + str(parameters_ws_current_row_number - 1)] = parameters_data['names'][i]
881
882
            table_current_row_number = parameters_ws_current_row_number
883
884
            for j, value in enumerate(list(parameters_data['timestamps'][i])):
885
                col = format_cell.get_column_letter(table_current_col_number)
886
887
                parameters_ws[col + str(table_current_row_number)].border = f_border
888
                parameters_ws[col + str(table_current_row_number)].font = title_font
889
                parameters_ws[col + str(table_current_row_number)].alignment = c_c_alignment
890
                parameters_ws[col + str(table_current_row_number)] = value
891
892
                col = format_cell.get_column_letter(table_current_col_number + 1)
893
894
                parameters_ws[col + str(table_current_row_number)].border = f_border
895
                parameters_ws[col + str(table_current_row_number)].font = title_font
896
                parameters_ws[col + str(table_current_row_number)].alignment = c_c_alignment
897
                parameters_ws[col + str(table_current_row_number)] = round(parameters_data['values'][i][j], 2)
898
899
                table_current_row_number += 1
900
901
            table_current_col_number = table_current_col_number + 3
902
903
        ################################################################################################################
904
        # parameters chart and parameters table
905
        ################################################################################################################
906
907
        ws['B' + str(current_sheet_parameters_row_number)].font = title_font
908
        ws['B' + str(current_sheet_parameters_row_number)] = name + ' ' + _('Parameters')
909
910
        current_sheet_parameters_row_number += 1
911
912
        chart_start_row_number = current_sheet_parameters_row_number
913
914
        col_index = 0
915
916
        for i in range(0, parameters_names_len):
917
918
            if len(parameters_data['timestamps'][i]) == 0:
919
                continue
920
921
            line = LineChart()
922
            data_col = 3 + col_index * 3
923
            labels_col = 2 + col_index * 3
924
            col_index += 1
925
            line.title = _('Parameters') + ' - ' + \
926
                parameters_ws.cell(row=parameters_table_start_row_number, column=data_col).value
927
            labels = Reference(parameters_ws, min_col=labels_col, min_row=parameters_table_start_row_number + 1,
928
                               max_row=(len(parameters_data['timestamps'][i]) + parameters_table_start_row_number))
929
            line_data = Reference(parameters_ws, min_col=data_col, min_row=parameters_table_start_row_number,
930
                                  max_row=(len(parameters_data['timestamps'][i]) + parameters_table_start_row_number))
931
            line.add_data(line_data, titles_from_data=True)
932
            line.set_categories(labels)
933
            line_data = line.series[0]
934
            line_data.marker.symbol = "circle"
935
            line_data.smooth = True
936
            line.x_axis.crosses = 'min'
937
            line.height = 8.25
938
            line.width = 24
939
            line.dLbls = DataLabelList()
940
            line.dLbls.dLblPos = 't'
941
            line.dLbls.showVal = False
942
            line.dLbls.showPercent = False
943
            chart_col = 'B'
944
            chart_cell = chart_col + str(chart_start_row_number)
945
            chart_start_row_number += 6
946
            ws.add_chart(line, chart_cell)
947
948
        current_sheet_parameters_row_number = chart_start_row_number
949
950
        current_sheet_parameters_row_number += 1
951
952
    filename = str(uuid.uuid4()) + '.xlsx'
953
    wb.save(filename)
954
955
    return filename
956
957
958
def get_parameters_timestamps_lists_max_len(parameters_timestamps_lists):
959
    max_len = 0
960
    for i, value in enumerate(list(parameters_timestamps_lists)):
961
        if len(value) > max_len:
962
            max_len = len(value)
963
964
    return max_len
965
966
967
def timestamps_data_all_equal_0(lists):
968
    for i, value in enumerate(list(lists)):
969
        if len(value) > 0:
970
            return False
971
972
    return True
973
974
975
def timestamps_data_not_equal_0(lists):
976
    number = 0
977
    for i, value in enumerate(list(lists)):
978
        if len(value) > 0:
979
            number += 1
980
    return number
981
982
983 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...
984
    timestamps = base_period_data['timestamps']
985
986
    if len(timestamps) == 0:
987
        return False
988
989
    for timestamp in timestamps:
990
        if len(timestamp) > 0:
991
            return True
992
993
    return False
994