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