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

is_base_period_timestamp_exists()   A

Complexity

Conditions 4

Size

Total Lines 11
Code Lines 8

Duplication

Lines 11
Ratio 100 %

Importance

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