Passed
Push — master ( d35f3b...b6c9eb )
by Guangyu
07:20 queued 12s
created

excelexporters.shopfloorcarbon   F

Complexity

Total Complexity 77

Size/Duplication

Total Lines 794
Duplicated Lines 94.84 %

Importance

Changes 0
Metric Value
wmc 77
eloc 583
dl 753
loc 794
rs 2.24
c 0
b 0
f 0

4 Functions

Rating   Name   Duplication   Size   Complexity  
A get_parameters_timestamps_lists_max_len() 0 7 3
A timestamps_data_all_equal_0() 0 6 3
B export() 39 39 5
F generate_excel() 714 714 66

How to fix   Duplicated Code    Complexity   

Duplicated Code

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

Common duplication problems, and corresponding solutions are:

Complexity

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

Complex classes like excelexporters.shopfloorcarbon often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
import base64
2
import uuid
3
import os
4
import re
5
from decimal import Decimal
6
from openpyxl.chart import PieChart, LineChart, Reference
7
from openpyxl.styles import PatternFill, Border, Side, Alignment, Font
8
from openpyxl.drawing.image import Image
9
from openpyxl import Workbook
10
from openpyxl.chart.label import DataLabelList
11
import openpyxl.utils.cell as format_cell
12
13
14
########################################################################################################################
15
# PROCEDURES
16
# Step 1: Validate the report data
17
# Step 2: Generate excel file
18
# Step 3: Encode the excel file bytes to Base64
19
########################################################################################################################
20
21
22 View Code Duplication
def export(report,
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
23
           name,
24
           reporting_start_datetime_local,
25
           reporting_end_datetime_local,
26
           period_type):
27
    ####################################################################################################################
28
    # Step 1: Validate the report data
29
    ####################################################################################################################
30
    if report is None:
31
        return None
32
33
    ####################################################################################################################
34
    # Step 2: Generate excel file from the report data
35
    ####################################################################################################################
36
    filename = generate_excel(report,
37
                              name,
38
                              reporting_start_datetime_local,
39
                              reporting_end_datetime_local,
40
                              period_type)
41
    ####################################################################################################################
42
    # Step 3: Encode the excel file to Base64
43
    ####################################################################################################################
44
    binary_file_data = b''
45
    try:
46
        with open(filename, 'rb') as binary_file:
47
            binary_file_data = binary_file.read()
48
    except IOError as ex:
49
        pass
50
51
    # Base64 encode the bytes
52
    base64_encoded_data = base64.b64encode(binary_file_data)
53
    # get the Base64 encoded data using human-readable characters.
54
    base64_message = base64_encoded_data.decode('utf-8')
55
    # delete the file from server
56
    try:
57
        os.remove(filename)
58
    except NotImplementedError as ex:
59
        pass
60
    return base64_message
61
62
63 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...
64
                   name,
65
                   reporting_start_datetime_local,
66
                   reporting_end_datetime_local,
67
                   period_type):
68
    wb = Workbook()
69
    ws = wb.active
70
    ws.title = "ShopFloorCarbon"
71
72
    # Row height
73
    ws.row_dimensions[1].height = 102
74
    for i in range(2, 2000 + 1):
75
        ws.row_dimensions[i].height = 42
76
77
    # Col width
78
    ws.column_dimensions['A'].width = 1.5
79
80
    ws.column_dimensions['B'].width = 25.0
81
82
    for i in range(ord('C'), ord('L')):
83
        ws.column_dimensions[chr(i)].width = 15.0
84
85
    # Font
86
    name_font = Font(name='Arial', size=15, bold=True)
87
    title_font = Font(name='Arial', size=15, bold=True)
88
89
    table_fill = PatternFill(fill_type='solid', fgColor='1F497D')
90
    f_border = Border(left=Side(border_style='medium', color='00000000'),
91
                      right=Side(border_style='medium', color='00000000'),
92
                      bottom=Side(border_style='medium', color='00000000'),
93
                      top=Side(border_style='medium', color='00000000')
94
                      )
95
    b_border = Border(
96
        bottom=Side(border_style='medium', color='00000000'),
97
    )
98
99
    b_c_alignment = Alignment(vertical='bottom',
100
                              horizontal='center',
101
                              text_rotation=0,
102
                              wrap_text=True,
103
                              shrink_to_fit=False,
104
                              indent=0)
105
    c_c_alignment = Alignment(vertical='center',
106
                              horizontal='center',
107
                              text_rotation=0,
108
                              wrap_text=True,
109
                              shrink_to_fit=False,
110
                              indent=0)
111
    b_r_alignment = Alignment(vertical='bottom',
112
                              horizontal='right',
113
                              text_rotation=0,
114
                              wrap_text=True,
115
                              shrink_to_fit=False,
116
                              indent=0)
117
118
    # Img
119
    img = Image("excelexporters/myems.png")
120
    ws.add_image(img, 'A1')
121
122
    # Title
123
    ws['B3'].alignment = b_r_alignment
124
    ws['B3'] = 'Name:'
125
    ws['C3'].border = b_border
126
    ws['C3'].alignment = b_c_alignment
127
    ws['C3'] = name
128
129
    ws['D3'].alignment = b_r_alignment
130
    ws['D3'] = 'Period:'
131
    ws['E3'].border = b_border
132
    ws['E3'].alignment = b_c_alignment
133
    ws['E3'] = period_type
134
135
    ws['B4'].alignment = b_r_alignment
136
    ws['B4'] = 'Reporting Start Datetime:'
137
    ws['C4'].border = b_border
138
    ws['C4'].alignment = b_c_alignment
139
    ws['C4'] = reporting_start_datetime_local
140
141
    ws['D4'].alignment = b_r_alignment
142
    ws['D4'] = 'Reporting End Datetime:'
143
    ws['E4'].border = b_border
144
    ws['E4'].alignment = b_c_alignment
145
    ws['E4'] = reporting_end_datetime_local
146
147
    if "reporting_period" not in report.keys() or \
148
            "names" not in report['reporting_period'].keys() or len(report['reporting_period']['names']) == 0:
149
        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...
150
        wb.save(filename)
151
152
        return filename
153
154
    ####################################################################################################################
155
156
    reporting_period_data = report['reporting_period']
157
158
    has_energy_data_flag = True
159
    if "names" not in reporting_period_data.keys() or \
160
            reporting_period_data['names'] is None or \
161
            len(reporting_period_data['names']) == 0:
162
        has_energy_data_flag = False
163
164
    if has_energy_data_flag:
165
        ws['B6'].font = title_font
166
        ws['B6'] = name + ' ' + 'Reporting Period Carbon Dioxide Emissions'
167
168
        category = reporting_period_data['names']
169
        ca_len = len(category)
170
171
        ws.row_dimensions[7].height = 60
172
        ws['B7'].fill = table_fill
173
        ws['B7'].border = f_border
174
175
        ws['B8'].font = title_font
176
        ws['B8'].alignment = c_c_alignment
177
        ws['B8'] = 'Carbon Dioxide Emissions'
178
        ws['B8'].border = f_border
179
180
        ws['B9'].font = title_font
181
        ws['B9'].alignment = c_c_alignment
182
        ws['B9'] = 'Per Unit Area'
183
        ws['B9'].border = f_border
184
185
        ws['B10'].font = title_font
186
        ws['B10'].alignment = c_c_alignment
187
        ws['B10'] = 'Increment Rate'
188
        ws['B10'].border = f_border
189
190
        col = 'B'
191
192
        for i in range(0, ca_len):
193
            col = chr(ord('C') + i)
194
            ws[col + '7'].fill = table_fill
195
            ws[col + '7'].font = name_font
196
            ws[col + '7'].alignment = c_c_alignment
197
            ws[col + '7'] = reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")"
198
            ws[col + '7'].border = f_border
199
200
            ws[col + '8'].font = name_font
201
            ws[col + '8'].alignment = c_c_alignment
202
            ws[col + '8'] = round(reporting_period_data['subtotals'][i], 2)
203
            ws[col + '8'].border = f_border
204
205
            ws[col + '9'].font = name_font
206
            ws[col + '9'].alignment = c_c_alignment
207
            ws[col + '9'] = round(reporting_period_data['subtotals_per_unit_area'][i], 2)
208
            ws[col + '9'].border = f_border
209
210
            ws[col + '10'].font = name_font
211
            ws[col + '10'].alignment = c_c_alignment
212
            ws[col + '10'] = str(round(reporting_period_data['increment_rates'][i] * 100, 2)) + "%" \
213
                if reporting_period_data['increment_rates'][i] is not None else "-"
214
            ws[col + '10'].border = f_border
215
216
        end_col = chr(ord(col) + 1)
217
        ws[end_col + '7'].fill = table_fill
218
        ws[end_col + '7'].font = name_font
219
        ws[end_col + '7'].alignment = c_c_alignment
220
        ws[end_col + '7'] = "Total (" + reporting_period_data['total_unit'] + ")"
221
        ws[end_col + '7'].border = f_border
222
223
        ws[end_col + '8'].font = name_font
224
        ws[end_col + '8'].alignment = c_c_alignment
225
        ws[end_col + '8'] = round(reporting_period_data['total'], 2)
226
        ws[end_col + '8'].border = f_border
227
228
        ws[end_col + '9'].font = name_font
229
        ws[end_col + '9'].alignment = c_c_alignment
230
        ws[end_col + '9'] = round(reporting_period_data['total_per_unit_area'], 2)
231
        ws[end_col + '9'].border = f_border
232
233
        ws[end_col + '10'].font = name_font
234
        ws[end_col + '10'].alignment = c_c_alignment
235
        ws[end_col + '10'] = str(round(reporting_period_data['total_increment_rate'] * 100, 2)) + "%" \
236
            if reporting_period_data['total_increment_rate'] is not None else "-"
237
        ws[end_col + '10'].border = f_border
238
239
    else:
240
        for i in range(6, 10 + 1):
241
            ws.row_dimensions[i].height = 0.1
242
243
    ####################################################################################################################
244
245
    has_ele_peak_flag = True
246
    if "toppeaks" not in reporting_period_data.keys() or \
247
            reporting_period_data['toppeaks'] is None or \
248
            len(reporting_period_data['toppeaks']) == 0:
249
        has_ele_peak_flag = False
250
251
    if has_ele_peak_flag:
252
        ws['B12'].font = title_font
253
        ws['B12'] = name + 'Electricity Carbon Dioxide Emissions by Time-Of-Use'
254
255
        ws['B13'].fill = table_fill
256
        ws['B13'].font = name_font
257
        ws['B13'].alignment = c_c_alignment
258
        ws['B13'].border = f_border
259
260
        ws['C13'].fill = table_fill
261
        ws['C13'].font = name_font
262
        ws['C13'].alignment = c_c_alignment
263
        ws['C13'].border = f_border
264
        ws['C13'] = 'Electricity Carbon Dioxide Emissions by Time-Of-Use'
265
266
        ws['D13'].fill = table_fill
267
        ws['D13'].font = name_font
268
        ws['D13'].alignment = c_c_alignment
269
        ws['D13'].border = f_border
270
        ws['D13'] = 'Electricity Carbon Dioxide Emissions Proportion by Time-Of-Use'
271
272
        wssum = round(reporting_period_data['toppeaks'][0], 2) + round(reporting_period_data['onpeaks'][0], 2) + round(
273
            reporting_period_data['midpeaks'][0], 2) + round(reporting_period_data['offpeaks'][0], 2)
274
275
        ws['B14'].font = title_font
276
        ws['B14'].alignment = c_c_alignment
277
        ws['B14'] = 'TopPeak'
278
        ws['B14'].border = f_border
279
280
        ws['C14'].font = title_font
281
        ws['C14'].alignment = c_c_alignment
282
        ws['C14'].border = f_border
283
        ws['C14'] = round(reporting_period_data['toppeaks'][0], 2)
284
285
        ws['D14'].font = title_font
286
        ws['D14'].alignment = c_c_alignment
287
        ws['D14'].border = f_border
288
        ws['D14'] = '{:.2%}'.format(round(reporting_period_data['toppeaks'][0], 2) / wssum) \
289
            if wssum is not None and wssum != 0 else "0.00%"
290
291
        ws['B15'].font = title_font
292
        ws['B15'].alignment = c_c_alignment
293
        ws['B15'] = 'OnPeak'
294
        ws['B15'].border = f_border
295
296
        ws['C15'].font = title_font
297
        ws['C15'].alignment = c_c_alignment
298
        ws['C15'].border = f_border
299
        ws['C15'] = round(reporting_period_data['onpeaks'][0], 2)
300
301
        ws['D15'].font = title_font
302
        ws['D15'].alignment = c_c_alignment
303
        ws['D15'].border = f_border
304
        ws['D15'] = '{:.2%}'.format(round(reporting_period_data['onpeaks'][0], 2) / wssum) \
305
            if wssum is not None and wssum != 0 else "0.00%"
306
307
        ws['B16'].font = title_font
308
        ws['B16'].alignment = c_c_alignment
309
        ws['B16'] = 'MidPeak'
310
        ws['B16'].border = f_border
311
312
        ws['C16'].font = title_font
313
        ws['C16'].alignment = c_c_alignment
314
        ws['C16'].border = f_border
315
        ws['C16'] = round(reporting_period_data['midpeaks'][0], 2)
316
317
        ws['D16'].font = title_font
318
        ws['D16'].alignment = c_c_alignment
319
        ws['D16'].border = f_border
320
        ws['D16'] = '{:.2%}'.format(round(reporting_period_data['midpeaks'][0], 2) / wssum) \
321
            if wssum is not None and wssum != 0 else "0.00%"
322
323
        ws['B17'].font = title_font
324
        ws['B17'].alignment = c_c_alignment
325
        ws['B17'] = 'OffPeak'
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['offpeaks'][0], 2)
332
333
        ws['D17'].font = title_font
334
        ws['D17'].alignment = c_c_alignment
335
        ws['D17'].border = f_border
336
        ws['D17'] = '{:.2%}'.format(round(reporting_period_data['offpeaks'][0], 2) / wssum) \
337
            if wssum is not None and wssum != 0 else "0.00%"
338
339
        pie = PieChart()
340
        pie.title = name + 'Electricity Carbon Dioxide Emissions by Time-Of-Use'
341
        labels = Reference(ws, min_col=2, min_row=14, max_row=17)
342
        pie_data = Reference(ws, min_col=3, min_row=13, max_row=17)
343
        pie.add_data(pie_data, titles_from_data=True)
344
        pie.set_categories(labels)
345
        pie.height = 6.6
346
        pie.width = 9
347
        s1 = pie.series[0]
348
        s1.dLbls = DataLabelList()
349
        s1.dLbls.showCatName = False
350
        s1.dLbls.showVal = True
351
        s1.dLbls.showPercent = True
352
        ws.add_chart(pie, "E13")
353
354
    else:
355
        for i in range(12, 18 + 1):
356
            ws.row_dimensions[i].height = 0.1
357
358
    ####################################################################################################################
359
360
    current_row_number = 19
361
362
    has_subtotals_data_flag = True
363
    if "subtotals" not in reporting_period_data.keys() or \
364
            reporting_period_data['subtotals'] is None or \
365
            len(reporting_period_data['subtotals']) == 0:
366
        has_subtotals_data_flag = False
367
368
    if has_subtotals_data_flag:
369
        ws['B' + str(current_row_number)].font = title_font
370
        ws['B' + str(current_row_number)] = name + ' ' + 'Carbon Dioxide Emissions Proportion'
371
372
        current_row_number += 1
373
374
        table_start_row_number = current_row_number
375
376
        ws['B' + str(current_row_number)].fill = table_fill
377
        ws['B' + str(current_row_number)].font = name_font
378
        ws['B' + str(current_row_number)].alignment = c_c_alignment
379
        ws['B' + str(current_row_number)].border = f_border
380
381
        ws['C' + str(current_row_number)].fill = table_fill
382
        ws['C' + str(current_row_number)].font = name_font
383
        ws['C' + str(current_row_number)].alignment = c_c_alignment
384
        ws['C' + str(current_row_number)].border = f_border
385
        ws['C' + str(current_row_number)] = 'Carbon Dioxide Emissions'
386
387
        ws['D' + str(current_row_number)].fill = table_fill
388
        ws['D' + str(current_row_number)].font = name_font
389
        ws['D' + str(current_row_number)].alignment = c_c_alignment
390
        ws['D' + str(current_row_number)].border = f_border
391
        ws['D' + str(current_row_number)] = 'Carbon Dioxide Emissions Proportion'
392
393
        current_row_number += 1
394
395
        ca_len = len(reporting_period_data['names'])
396
        wssum = 0
397
        for i in range(0, ca_len):
398
            wssum = round(reporting_period_data['subtotals'][i], 2) + wssum
399
        for i in range(0, ca_len):
400
            ws['B' + str(current_row_number)].font = title_font
401
            ws['B' + str(current_row_number)].alignment = c_c_alignment
402
            ws['B' + str(current_row_number)] = reporting_period_data['names'][i]
403
            ws['B' + str(current_row_number)].border = f_border
404
405
            ws['C' + str(current_row_number)].font = title_font
406
            ws['C' + str(current_row_number)].alignment = c_c_alignment
407
            ws['C' + str(current_row_number)].border = f_border
408
            ws['C' + str(current_row_number)] = round(reporting_period_data['subtotals'][i], 2)
409
410
            ws['D' + str(current_row_number)].font = title_font
411
            ws['D' + str(current_row_number)].alignment = c_c_alignment
412
            ws['D' + str(current_row_number)].border = f_border
413
            ws['D' + str(current_row_number)] = '{:.2%}'.format(round(reporting_period_data['subtotals'][i], 2) /
414
                                                                wssum) if wssum is not None and wssum != 0 else "0.00%"
415
416
            current_row_number += 1
417
418
        table_end_row_number = current_row_number - 1
419
420
        pie = PieChart()
421
        pie.title = name + ' ' + 'Carbon Dioxide Emissions Proportion'
422
        labels = Reference(ws, min_col=2, min_row=table_start_row_number + 1, max_row=table_end_row_number)
423
        pie_data = Reference(ws, min_col=3, min_row=table_start_row_number, max_row=table_end_row_number)
424
        pie.add_data(pie_data, titles_from_data=True)
425
        pie.set_categories(labels)
426
        pie.height = 6.6
427
        pie.width = 9
428
        s1 = pie.series[0]
429
        s1.dLbls = DataLabelList()
430
        s1.dLbls.showCatName = False
431
        s1.dLbls.showVal = True
432
        s1.dLbls.showPercent = True
433
        table_cell = 'E' + str(table_start_row_number)
434
        ws.add_chart(pie, table_cell)
435
436
        if ca_len < 4:
437
            current_row_number = current_row_number - ca_len + 4
438
439
    else:
440
        for i in range(21, 29 + 1):
441
            current_row_number = 30
442
            ws.row_dimensions[i].height = 0.1
443
444
    ####################################################################################################################
445
446
    current_row_number += 1
447
448
    has_detail_data_flag = True
449
450
    table_start_draw_flag = current_row_number + 1
451
452
    if "timestamps" not in reporting_period_data.keys() or \
453
            reporting_period_data['timestamps'] is None or \
454
            len(reporting_period_data['timestamps']) == 0:
455
        has_detail_data_flag = False
456
457
    if has_detail_data_flag:
458
        reporting_period_data = report['reporting_period']
459
        times = reporting_period_data['timestamps']
460
        ca_len = len(report['reporting_period']['names'])
461
        parameters_names_len = len(report['parameters']['names'])
462
        parameters_parameters_datas_len = 0
463
        for i in range(0, parameters_names_len):
464
            if len(report['parameters']['timestamps'][i]) == 0:
465
                continue
466
            parameters_parameters_datas_len += 1
467
468
        ws['B' + str(current_row_number)].font = title_font
469
        ws['B' + str(current_row_number)] = name + ' ' + 'Detailed Data'
470
471
        detail_data_table_start_row_number = current_row_number + (ca_len + parameters_parameters_datas_len) * 6 + 3
472
        current_row_number = detail_data_table_start_row_number
473
474
        time = times[0]
475
        has_data = False
476
477
        if len(time) > 0:
478
            has_data = True
479
480
        if has_data:
481
482
            ws.row_dimensions[current_row_number].height = 60
483
            ws['B' + str(current_row_number)].fill = table_fill
484
            ws['B' + str(current_row_number)].border = f_border
485
            ws['B' + str(current_row_number)].font = title_font
486
            ws['B' + str(current_row_number)].alignment = c_c_alignment
487
            ws['B' + str(current_row_number)] = 'Datetime'
488
489
            col = 'B'
490
491
            for i in range(0, ca_len):
492
                col = chr(ord('C') + i)
493
494
                ws[col + str(current_row_number)].fill = table_fill
495
                ws[col + str(current_row_number)].font = title_font
496
                ws[col + str(current_row_number)].alignment = c_c_alignment
497
                ws[col + str(current_row_number)] = \
498
                    reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")"
499
                ws[col + str(current_row_number)].border = f_border
500
501
            end_col = chr(ord(col) + 1)
502
503
            ws[end_col + str(current_row_number)].fill = table_fill
504
            ws[end_col + str(current_row_number)].font = title_font
505
            ws[end_col + str(current_row_number)].alignment = c_c_alignment
506
            ws[end_col + str(current_row_number)] = "Total (" + reporting_period_data['total_unit'] + ")"
507
            ws[end_col + str(current_row_number)].border = f_border
508
509
            current_row_number += 1
510
511
            for i in range(0, len(time)):
512
                ws['B' + str(current_row_number)].font = title_font
513
                ws['B' + str(current_row_number)].alignment = c_c_alignment
514
                ws['B' + str(current_row_number)] = time[i]
515
                ws['B' + str(current_row_number)].border = f_border
516
517
                col = 'B'
518
519
                periodic_sum = Decimal(0.0)
520
521
                for j in range(0, ca_len):
522
                    col = chr(ord('C') + j)
523
524
                    ws[col + str(current_row_number)].font = title_font
525
                    ws[col + str(current_row_number)].alignment = c_c_alignment
526
                    value = round(reporting_period_data['values'][j][i], 2)
527
                    periodic_sum += value
528
                    ws[col + str(current_row_number)] = value
529
                    ws[col + str(current_row_number)].border = f_border
530
531
                end_col = chr(ord(col) + 1)
532
                ws[end_col + str(current_row_number)].font = title_font
533
                ws[end_col + str(current_row_number)].alignment = c_c_alignment
534
                ws[end_col + str(current_row_number)] = round(periodic_sum, 2)
535
                ws[end_col + str(current_row_number)].border = f_border
536
537
                current_row_number += 1
538
539
            table_end_row_number = current_row_number - 1
540
541
            ws['B' + str(current_row_number)].font = title_font
542
            ws['B' + str(current_row_number)].alignment = c_c_alignment
543
            ws['B' + str(current_row_number)] = 'Subtotal'
544
            ws['B' + str(current_row_number)].border = f_border
545
546
            col = 'B'
547
548
            for i in range(0, ca_len):
549
                col = chr(ord('C') + i)
550
                ws[col + str(current_row_number)].font = title_font
551
                ws[col + str(current_row_number)].alignment = c_c_alignment
552
                ws[col + str(current_row_number)] = round(reporting_period_data['subtotals'][i], 2)
553
                ws[col + str(current_row_number)].border = f_border
554
555
                # line
556
                line = LineChart()
557
                line.title = 'Reporting Period Carbon Dioxide Emissions - ' + \
558
                             reporting_period_data['names'][i] + " (" + reporting_period_data['units'][i] + ")"
559
                labels = Reference(ws, min_col=2, min_row=detail_data_table_start_row_number + 1,
560
                                   max_row=table_end_row_number)
561
                line_data = Reference(ws, min_col=3 + i, min_row=detail_data_table_start_row_number,
562
                                      max_row=table_end_row_number)
563
                line.add_data(line_data, titles_from_data=True)
564
                line.set_categories(labels)
565
                line_data = line.series[0]
566
                line_data.marker.symbol = "circle"
567
                line_data.smooth = True
568
                line.x_axis.crosses = 'min'
569
                line.height = 8.25
570
                line.width = 24
571
                line.dLbls = DataLabelList()
572
                line.dLbls.dLblPos = 't'
573
                line.dLbls.showVal = True
574
                line.dLbls.showPercent = False
575
                chart_col = 'B'
576
                chart_cell = chart_col + str(table_start_draw_flag + 6 * i)
577
                ws.add_chart(line, chart_cell)
578
579
            end_col = chr(ord(col) + 1)
580
            ws[end_col + str(current_row_number)].font = title_font
581
            ws[end_col + str(current_row_number)].alignment = c_c_alignment
582
            ws[end_col + str(current_row_number)] = round(reporting_period_data['total'], 2)
583
            ws[end_col + str(current_row_number)].border = f_border
584
585
            current_row_number += 1
586
587
    else:
588
        for i in range(30, 69 + 1):
589
            current_row_number = 70
590
            ws.row_dimensions[i].height = 0.1
591
    ####################################################################################################################
592
    has_parameters_names_and_timestamps_and_values_data = True
593
594
    ca_len = len(report['reporting_period']['names'])
595
    current_sheet_parameters_row_number = table_start_draw_flag + ca_len * 6
596
    if 'parameters' not in report.keys() or \
597
            report['parameters'] is None or \
598
            'names' not in report['parameters'].keys() or \
599
            report['parameters']['names'] is None or \
600
            len(report['parameters']['names']) == 0 or \
601
            'timestamps' not in report['parameters'].keys() or \
602
            report['parameters']['timestamps'] is None or \
603
            len(report['parameters']['timestamps']) == 0 or \
604
            'values' not in report['parameters'].keys() or \
605
            report['parameters']['values'] is None or \
606
            len(report['parameters']['values']) == 0 or \
607
            timestamps_data_all_equal_0(report['parameters']['timestamps']):
608
        has_parameters_names_and_timestamps_and_values_data = False
609
    if has_parameters_names_and_timestamps_and_values_data:
610
611
        ################################################################################################################
612
        # new worksheet
613
        ################################################################################################################
614
615
        parameters_data = report['parameters']
616
617
        parameters_names_len = len(parameters_data['names'])
618
619
        file_name = (re.sub(r'[^A-Z]', '', ws.title))+'_'
620
        parameters_ws = wb.create_sheet(file_name + 'Parameters')
621
622
        parameters_timestamps_data_max_len = \
623
            get_parameters_timestamps_lists_max_len(list(parameters_data['timestamps']))
624
625
        # Row height
626
        parameters_ws.row_dimensions[1].height = 102
627
        for i in range(2, 7 + 1):
628
            parameters_ws.row_dimensions[i].height = 42
629
630
        for i in range(8, parameters_timestamps_data_max_len + 10):
631
            parameters_ws.row_dimensions[i].height = 60
632
633
        # Col width
634
        parameters_ws.column_dimensions['A'].width = 1.5
635
636
        parameters_ws.column_dimensions['B'].width = 25.0
637
638
        for i in range(3, 12 + parameters_names_len * 3):
639
            parameters_ws.column_dimensions[format_cell.get_column_letter(i)].width = 15.0
640
641
        # Img
642
        img = Image("excelexporters/myems.png")
643
        parameters_ws.add_image(img, 'A1')
644
645
        # Title
646
        parameters_ws['B3'].alignment = b_r_alignment
647
        parameters_ws['B3'] = 'Name:'
648
        parameters_ws['C3'].border = b_border
649
        parameters_ws['C3'].alignment = b_c_alignment
650
        parameters_ws['C3'] = name
651
652
        parameters_ws['D3'].alignment = b_r_alignment
653
        parameters_ws['D3'] = 'Period:'
654
        parameters_ws['E3'].border = b_border
655
        parameters_ws['E3'].alignment = b_c_alignment
656
        parameters_ws['E3'] = period_type
657
658
        parameters_ws['B4'].alignment = b_r_alignment
659
        parameters_ws['B4'] = 'Reporting Start Datetime:'
660
        parameters_ws['C4'].border = b_border
661
        parameters_ws['C4'].alignment = b_c_alignment
662
        parameters_ws['C4'] = reporting_start_datetime_local
663
664
        parameters_ws['D4'].alignment = b_r_alignment
665
        parameters_ws['D4'] = 'Reporting End Datetime:'
666
        parameters_ws['E4'].border = b_border
667
        parameters_ws['E4'].alignment = b_c_alignment
668
        parameters_ws['E4'] = reporting_end_datetime_local
669
670
        parameters_ws_current_row_number = 6
671
672
        parameters_ws['B' + str(parameters_ws_current_row_number)].font = title_font
673
        parameters_ws['B' + str(parameters_ws_current_row_number)] = name + ' ' + 'Parameters'
674
675
        parameters_ws_current_row_number += 1
676
677
        parameters_table_start_row_number = parameters_ws_current_row_number
678
679
        parameters_ws.row_dimensions[parameters_ws_current_row_number].height = 80
680
681
        parameters_ws_current_row_number += 1
682
683
        table_current_col_number = 2
684
685
        for i in range(0, parameters_names_len):
686
687
            if len(parameters_data['timestamps'][i]) == 0:
688
                continue
689
690
            col = format_cell.get_column_letter(table_current_col_number)
691
692
            parameters_ws[col + str(parameters_ws_current_row_number - 1)].fill = table_fill
693
            parameters_ws[col + str(parameters_ws_current_row_number - 1)].border = f_border
694
695
            col = format_cell.get_column_letter(table_current_col_number + 1)
696
697
            parameters_ws[col + str(parameters_ws_current_row_number - 1)].fill = table_fill
698
            parameters_ws[col + str(parameters_ws_current_row_number - 1)].border = f_border
699
            parameters_ws[col + str(parameters_ws_current_row_number - 1)].font = name_font
700
            parameters_ws[col + str(parameters_ws_current_row_number - 1)].alignment = c_c_alignment
701
            parameters_ws[col + str(parameters_ws_current_row_number - 1)] = parameters_data['names'][i]
702
703
            table_current_row_number = parameters_ws_current_row_number
704
705
            for j, value in enumerate(list(parameters_data['timestamps'][i])):
706
                col = format_cell.get_column_letter(table_current_col_number)
707
708
                parameters_ws[col + str(table_current_row_number)].border = f_border
709
                parameters_ws[col + str(table_current_row_number)].font = title_font
710
                parameters_ws[col + str(table_current_row_number)].alignment = c_c_alignment
711
                parameters_ws[col + str(table_current_row_number)] = value
712
713
                col = format_cell.get_column_letter(table_current_col_number + 1)
714
715
                parameters_ws[col + str(table_current_row_number)].border = f_border
716
                parameters_ws[col + str(table_current_row_number)].font = title_font
717
                parameters_ws[col + str(table_current_row_number)].alignment = c_c_alignment
718
                parameters_ws[col + str(table_current_row_number)] = round(parameters_data['values'][i][j], 2)
719
720
                table_current_row_number += 1
721
722
            table_current_col_number = table_current_col_number + 3
723
724
        ################################################################################################################
725
        # parameters chart and parameters table
726
        ################################################################################################################
727
728
        ws['B' + str(current_sheet_parameters_row_number)].font = title_font
729
        ws['B' + str(current_sheet_parameters_row_number)] = name + ' ' + 'Parameters'
730
731
        current_sheet_parameters_row_number += 1
732
733
        chart_start_row_number = current_sheet_parameters_row_number
734
735
        col_index = 0
736
737
        for i in range(0, parameters_names_len):
738
739
            if len(parameters_data['timestamps'][i]) == 0:
740
                continue
741
742
            line = LineChart()
743
            data_col = 3 + col_index * 3
744
            labels_col = 2 + col_index * 3
745
            col_index += 1
746
            line.title = 'Parameters - ' + \
747
                         parameters_ws.cell(row=parameters_table_start_row_number, column=data_col).value
748
            labels = Reference(parameters_ws, min_col=labels_col, min_row=parameters_table_start_row_number + 1,
749
                               max_row=(len(parameters_data['timestamps'][i]) + parameters_table_start_row_number))
750
            line_data = Reference(parameters_ws, min_col=data_col, min_row=parameters_table_start_row_number,
751
                                  max_row=(len(parameters_data['timestamps'][i]) + parameters_table_start_row_number))
752
            line.add_data(line_data, titles_from_data=True)
753
            line.set_categories(labels)
754
            line_data = line.series[0]
755
            line_data.marker.symbol = "circle"
756
            line_data.smooth = True
757
            line.x_axis.crosses = 'min'
758
            line.height = 8.25
759
            line.width = 24
760
            line.dLbls = DataLabelList()
761
            line.dLbls.dLblPos = 't'
762
            line.dLbls.showVal = False
763
            line.dLbls.showPercent = False
764
            chart_col = 'B'
765
            chart_cell = chart_col + str(chart_start_row_number)
766
            chart_start_row_number += 6
767
            ws.add_chart(line, chart_cell)
768
769
        current_sheet_parameters_row_number = chart_start_row_number
770
771
        current_sheet_parameters_row_number += 1
772
773
    filename = str(uuid.uuid4()) + '.xlsx'
774
    wb.save(filename)
775
776
    return filename
777
778
779
def get_parameters_timestamps_lists_max_len(parameters_timestamps_lists):
780
    max_len = 0
781
    for i, value in enumerate(list(parameters_timestamps_lists)):
782
        if len(value) > max_len:
783
            max_len = len(value)
784
785
    return max_len
786
787
788
def timestamps_data_all_equal_0(lists):
789
    for i, value in enumerate(list(lists)):
790
        if len(value) > 0:
791
            return False
792
793
    return True
794