Passed
Push — master ( b39490...8d87b3 )
by Guangyu
07:54 queued 12s
created

excelexporters.virtualmetercarbon   A

Complexity

Total Complexity 31

Size/Duplication

Total Lines 340
Duplicated Lines 94.12 %

Importance

Changes 0
Metric Value
wmc 31
eloc 248
dl 320
loc 340
rs 9.92
c 0
b 0
f 0

2 Functions

Rating   Name   Duplication   Size   Complexity  
B export() 38 38 8
F generate_excel() 282 282 23

How to fix   Duplicated Code   

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:

1
import base64
2
import uuid
3
import os
4
from openpyxl.chart import LineChart, Reference, Series
5
from openpyxl.styles import PatternFill, Border, Side, Alignment, Font
6
from openpyxl.drawing.image import Image
7
from openpyxl import Workbook
8
from openpyxl.chart.label import DataLabelList
9
10
11
########################################################################################################################
12
# PROCEDURES
13
# Step 1: Validate the report data
14
# Step 2: Generate excelexporters file
15
# Step 3: Encode the excelexporters file to Base64
16
########################################################################################################################
17
18 View Code Duplication
def export(report, name, reporting_start_datetime_local, reporting_end_datetime_local, period_type):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
19
    ####################################################################################################################
20
    # Step 1: Validate the report data
21
    ####################################################################################################################
22
    if report is None:
23
        return None
24
25
    if "reporting_period" not in report.keys() or \
26
            "values" not in report['reporting_period'].keys() or len(report['reporting_period']['values']) == 0:
27
        return None
28
    ####################################################################################################################
29
    # Step 2: Generate excel file from the report data
30
    ####################################################################################################################
31
    filename = generate_excel(report,
32
                              name,
33
                              reporting_start_datetime_local,
34
                              reporting_end_datetime_local,
35
                              period_type)
36
    ####################################################################################################################
37
    # Step 3: Encode the excel file to Base64
38
    ####################################################################################################################
39
    binary_file_data = b''
40
    try:
41
        with open(filename, 'rb') as binary_file:
42
            binary_file_data = binary_file.read()
43
    except IOError as ex:
44
        pass
45
46
    # Base64 encode the bytes
47
    base64_encoded_data = base64.b64encode(binary_file_data)
48
    # get the Base64 encoded data using human-readable characters.
49
    base64_message = base64_encoded_data.decode('utf-8')
50
    # delete the file from server
51
    try:
52
        os.remove(filename)
53
    except NotImplementedError as ex:
54
        pass
55
    return base64_message
56
57
58 View Code Duplication
def generate_excel(report, name, reporting_start_datetime_local, reporting_end_datetime_local, period_type):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
59
    wb = Workbook()
60
61
    ws = wb.active
62
    ws.title = "VirtualMeterCarbonDioxideEmissions"
63
    # Row height
64
    ws.row_dimensions[1].height = 102
65
    for i in range(2, 2000 + 1):
66
        ws.row_dimensions[i].height = 42
67
68
    # Col width
69
    ws.column_dimensions['A'].width = 1.5
70
71
    ws.column_dimensions['B'].width = 25.0
72
73
    for i in range(ord('C'), ord('L')):
74
        ws.column_dimensions[chr(i)].width = 15.0
75
76
    # Font
77
    name_font = Font(name='Arial', size=15, bold=True)
78
    title_font = Font(name='Arial', size=15, bold=True)
79
80
    table_fill = PatternFill(fill_type='solid', fgColor='1F497D')
81
    f_border = Border(left=Side(border_style='medium', color='00000000'),
82
                      right=Side(border_style='medium', color='00000000'),
83
                      bottom=Side(border_style='medium', color='00000000'),
84
                      top=Side(border_style='medium', color='00000000')
85
                      )
86
    b_border = Border(
87
        bottom=Side(border_style='medium', color='00000000'),
88
    )
89
90
    b_c_alignment = Alignment(vertical='bottom',
91
                              horizontal='center',
92
                              text_rotation=0,
93
                              wrap_text=True,
94
                              shrink_to_fit=False,
95
                              indent=0)
96
    c_c_alignment = Alignment(vertical='center',
97
                              horizontal='center',
98
                              text_rotation=0,
99
                              wrap_text=True,
100
                              shrink_to_fit=False,
101
                              indent=0)
102
    b_r_alignment = Alignment(vertical='bottom',
103
                              horizontal='right',
104
                              text_rotation=0,
105
                              wrap_text=True,
106
                              shrink_to_fit=False,
107
                              indent=0)
108
109
    # Img
110
    img = Image("excelexporters/myems.png")
111
    ws.add_image(img, 'A1')
112
113
    # Title
114
    ws['B3'].alignment = b_r_alignment
115
    ws['B3'] = 'Name:'
116
    ws['C3'].border = b_border
117
    ws['C3'].alignment = b_c_alignment
118
    ws['C3'] = name
119
120
    ws['D3'].alignment = b_r_alignment
121
    ws['D3'] = 'Period:'
122
    ws['E3'].border = b_border
123
    ws['E3'].alignment = b_c_alignment
124
    ws['E3'] = period_type
125
126
    ws['B4'].alignment = b_r_alignment
127
    ws['B4'] = 'Reporting Start Datetime:'
128
    ws['C4'].border = b_border
129
    ws['C4'].alignment = b_c_alignment
130
    ws['C4'] = reporting_start_datetime_local
131
132
    ws['D4'].alignment = b_r_alignment
133
    ws['D4'] = 'Reporting End Datetime:'
134
    ws['E4'].border = b_border
135
    ws['E4'].alignment = b_c_alignment
136
    ws['E4'] = reporting_end_datetime_local
137
138
    if "reporting_period" not in report.keys() or \
139
            "values" not in report['reporting_period'].keys() or len(report['reporting_period']['values']) == 0:
140
        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...
141
        wb.save(filename)
142
143
        return filename
144
145
    ####################################################################################################################
146
147
    has_values_flag = True
148
149
    if "values" not in report['reporting_period'].keys() or len(report['reporting_period']['values']) == 0:
150
        has_values_flag = False
151
152
    if has_values_flag:
153
        ws['B6'].font = title_font
154
        ws['B6'] = name + 'Reporting Period Carbon Dioxide Emissions'
155
156
        reporting_period_data = report['reporting_period']
157
        category = report['virtual_meter']['energy_category_name']
158
        ca_len = len(category)
159
160
        ws.row_dimensions[7].height = 60
161
        ws['B7'].fill = table_fill
162
        ws['B7'].border = f_border
163
164
        ws['B8'].font = title_font
165
        ws['B8'].alignment = c_c_alignment
166
        ws['B8'] = 'Carbon Dioxide Emissions'
167
        ws['B8'].border = f_border
168
169
        ws['B9'].font = title_font
170
        ws['B9'].alignment = c_c_alignment
171
        ws['B9'] = 'Increment Rate'
172
        ws['B9'].border = f_border
173
174
        col = 'B'
175
176
        for i in range(0, ca_len):
177
            col = chr(ord('C') + i)
178
179
            ws[col + '7'].fill = table_fill
180
            ws[col + '7'].font = name_font
181
            ws[col + '7'].alignment = c_c_alignment
182
            ws[col + '7'] = report['virtual_meter']['energy_category_name'] + \
183
                " (" + report['virtual_meter']['unit_of_measure'] + ")"
184
            ws[col + '7'].border = f_border
185
186
            ws[col + '8'].font = name_font
187
            ws[col + '8'].alignment = c_c_alignment
188
            ws[col + '8'] = round(reporting_period_data['total_in_category'], 2)
189
            ws[col + '8'].border = f_border
190
191
            ws[col + '9'].font = name_font
192
            ws[col + '9'].alignment = c_c_alignment
193
            ws[col + '9'] = str(round(reporting_period_data['increment_rate'] * 100, 2)) + "%" \
194
                if reporting_period_data['increment_rate'] is not None else "-"
195
            ws[col + '9'].border = f_border
196
197
        # TCE TCO2E
198
        end_col = col
199
        # TCE
200
        tce_col = chr(ord(end_col) + 1)
201
        ws[tce_col + '7'].fill = table_fill
202
        ws[tce_col + '7'].font = name_font
203
        ws[tce_col + '7'].alignment = c_c_alignment
204
        ws[tce_col + '7'] = 'Ton of Standard Coal (TCE)'
205
        ws[tce_col + '7'].border = f_border
206
207
        ws[tce_col + '8'].font = name_font
208
        ws[tce_col + '8'].alignment = c_c_alignment
209
        ws[tce_col + '8'] = round(reporting_period_data['total_in_kgce'] / 1000, 2)
210
        ws[tce_col + '8'].border = f_border
211
212
        ws[tce_col + '9'].font = name_font
213
        ws[tce_col + '9'].alignment = c_c_alignment
214
        ws[tce_col + '9'] = str(round(reporting_period_data['increment_rate'] * 100, 2)) + "%" \
215
            if reporting_period_data['increment_rate'] is not None else "-"
216
        ws[tce_col + '9'].border = f_border
217
218
        # TCO2E
219
        tco2e_col = chr(ord(end_col) + 2)
220
        ws[tco2e_col + '7'].fill = table_fill
221
        ws[tco2e_col + '7'].font = name_font
222
        ws[tco2e_col + '7'].alignment = c_c_alignment
223
        ws[tco2e_col + '7'] = 'Ton of Carbon Dioxide Emissions (TCO2E)'
224
        ws[tco2e_col + '7'].border = f_border
225
226
        ws[tco2e_col + '8'].font = name_font
227
        ws[tco2e_col + '8'].alignment = c_c_alignment
228
        ws[tco2e_col + '8'] = round(reporting_period_data['total_in_kgco2e'] / 1000, 2)
229
        ws[tco2e_col + '8'].border = f_border
230
231
        ws[tco2e_col + '9'].font = name_font
232
        ws[tco2e_col + '9'].alignment = c_c_alignment
233
        ws[tco2e_col + '9'] = str(round(reporting_period_data['increment_rate'] * 100, 2)) + "%" \
234
            if reporting_period_data['increment_rate'] is not None else "-"
235
        ws[tco2e_col + '9'].border = f_border
236
237
    else:
238
        for i in range(6, 9 + 1):
239
            ws.rows_dimensions[i].height = 0.1
240
241
    ####################################################################################################################
242
    has_detailed_data_flag = True
243
    reporting_period_data = report['reporting_period']
244
    category = report['virtual_meter']['energy_category_name']
245
    ca_len = len(category)
246
    times = reporting_period_data['timestamps']
247
248
    if "values" not in reporting_period_data.keys() or len(reporting_period_data['values']) == 0:
249
        has_detailed_data_flag = False
250
251
    if has_detailed_data_flag:
252
        ws['B11'].font = title_font
253
        ws['B11'] = name + 'Detailed Data'
254
255
        ws.row_dimensions[18].height = 60
256
        ws['B18'].fill = table_fill
257
        ws['B18'].font = title_font
258
        ws['B18'].border = f_border
259
        ws['B18'].alignment = c_c_alignment
260
        ws['B18'] = 'Datetime'
261
        time = times
262
        has_data = False
263
        max_row = 0
264
        if len(time) > 0:
265
            has_data = True
266
            max_row = 18 + len(time)
267
268
        if has_data:
269
270
            end_data_row_number = 19
271
272
            for i in range(0, len(time)):
273
                col = 'B'
274
                end_data_row_number = 19 + i
275
                row = str(end_data_row_number)
276
277
                ws[col + row].font = title_font
278
                ws[col + row].alignment = c_c_alignment
279
                ws[col + row] = time[i]
280
                ws[col + row].border = f_border
281
282
            ws['B' + str(end_data_row_number + 1)].font = title_font
283
            ws['B' + str(end_data_row_number + 1)].alignment = c_c_alignment
284
            ws['B' + str(end_data_row_number + 1)] = 'Total'
285
            ws['B' + str(end_data_row_number + 1)].border = f_border
286
287
            for i in range(0, ca_len):
288
289
                col = chr(ord('C') + i)
290
291
                ws[col + '18'].fill = table_fill
292
                ws[col + '18'].font = title_font
293
                ws[col + '18'].alignment = c_c_alignment
294
                ws[col + '18'] = report['virtual_meter']['energy_category_name'] + \
295
                    " (" + report['virtual_meter']['unit_of_measure'] + ")"
296
                ws[col + '18'].border = f_border
297
298
                time = times
299
                time_len = len(time)
300
301
                for j in range(0, time_len):
302
                    row = str(19 + j)
303
304
                    ws[col + row].font = title_font
305
                    ws[col + row].alignment = c_c_alignment
306
                    ws[col + row] = round(reporting_period_data['values'][j], 2)
307
                    ws[col + row].border = f_border
308
309
                ws[col + str(end_data_row_number + 1)].font = title_font
310
                ws[col + str(end_data_row_number + 1)].alignment = c_c_alignment
311
                ws[col + str(end_data_row_number + 1)] = round(reporting_period_data['total_in_category'], 2)
312
                ws[col + str(end_data_row_number + 1)].border = f_border
313
314
            line = LineChart()
315
            labels = Reference(ws, min_col=2, min_row=19, max_row=max_row)
316
            line_data = Reference(ws, min_col=3, min_row=18, max_row=max_row)
317
            line.series.append(Series(line_data, title_from_data=True))
318
            line.set_categories(labels)
319
            line_data = line.series[0]
320
            line_data.marker.symbol = "circle"
321
            line_data.smooth = True
322
            line.x_axis.crosses = 'min'
323
            line.title = 'Reporting Period Carbon Dioxide Emissions - ' + \
324
                         report['virtual_meter']['energy_category_name'] + \
325
                         " (" + report['virtual_meter']['unit_of_measure'] + ")"
326
            line.dLbls = DataLabelList()
327
            line.dLbls.dLblPos = 't'
328
            line.dLbls.showVal = True
329
            line.height = 8.25
330
            line.width = 24
331
            ws.add_chart(line, "B12")
332
    else:
333
        for i in range(11, 43 + 1):
334
            ws.row_dimensions[i].height = 0.0
335
336
    filename = str(uuid.uuid4()) + '.xlsx'
337
    wb.save(filename)
338
339
    return filename
340