Passed
Push — master ( 7a1547...4f6858 )
by Guangyu
08:49 queued 12s
created

excelexporters.virtualmetersaving   A

Complexity

Total Complexity 26

Size/Duplication

Total Lines 327
Duplicated Lines 93.88 %

Importance

Changes 0
Metric Value
wmc 26
eloc 240
dl 307
loc 327
rs 10
c 0
b 0
f 0

2 Functions

Rating   Name   Duplication   Size   Complexity  
B export() 35 35 5
F generate_excel() 272 272 21

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