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

excelexporters.combinedequipmentsaving   F

Complexity

Total Complexity 106

Size/Duplication

Total Lines 1019
Duplicated Lines 38.57 %

Importance

Changes 0
Metric Value
wmc 106
eloc 764
dl 393
loc 1019
rs 1.836
c 0
b 0
f 0

7 Functions

Rating   Name   Duplication   Size   Complexity  
F generate_excel() 336 900 86
A is_base_period_timestamp_exists() 11 11 4
A get_parameters_timestamps_lists_max_len() 0 7 3
A timestamps_data_all_equal_0() 0 6 3
A sum_list() 0 7 2
B export() 46 46 5
A timestamps_data_not_equal_0() 0 6 3

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complexity

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like excelexporters.combinedequipmentsaving 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.

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