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

generate_excel()   F

Complexity

Conditions 83

Size

Total Lines 777
Code Lines 593

Duplication

Lines 353
Ratio 45.43 %

Importance

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