Issues (1588)

myems-api/excelexporters/spacestatistics.py (3 issues)

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