Passed
Push — master ( 414b30...be43ee )
by Guangyu
14:19 queued 13s
created

generate_excel()   F

Complexity

Conditions 106

Size

Total Lines 911
Code Lines 700

Duplication

Lines 0
Ratio 0 %

Importance

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