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