Passed
Push — master ( 17dcd8...c09fbc )
by Guangyu
01:53 queued 10s
created

excelexporters.metertrend.export()   B

Complexity

Conditions 8

Size

Total Lines 42
Code Lines 27

Duplication

Lines 42
Ratio 100 %

Importance

Changes 0
Metric Value
cc 8
eloc 27
nop 5
dl 42
loc 42
rs 7.3333
c 0
b 0
f 0
1
import base64
2
import uuid
3
import os
4
from openpyxl.chart import (
5
    PieChart,
6
    BarChart,
7
    Reference,
8
)
9
from openpyxl.styles import PatternFill, Border, Side, Alignment, Font
10
from openpyxl.drawing.image import Image
11
from openpyxl import Workbook
12
from openpyxl.chart.label import DataLabelList
13
14
15
####################################################################################################################
16
# PROCEDURES
17
# Step 1: Validate the report data
18
# Step 2: Generate excel file
19
# Step 3: Encode the excel file bytes to Base64
20
####################################################################################################################
21
22
23 View Code Duplication
def export(result,
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
24
           name,
25
           reporting_start_datetime_local,
26
           reporting_end_datetime_local,
27
           period_type):
28
    ####################################################################################################################
29
    # Step 1: Validate the report data
30
    ####################################################################################################################
31
    if result is None:
32
        return None
33
34
    if "reporting_period" not in result.keys() or \
35
            "names" not in result['reporting_period'].keys() or len(result['reporting_period']['names']) == 0:
36
        return None
37
    ####################################################################################################################
38
    # Step 2: Generate excel file from the report data
39
    ####################################################################################################################
40
    filename = generate_excel(result,
41
                              name,
42
                              reporting_start_datetime_local,
43
                              reporting_end_datetime_local,
44
                              period_type)
45
46
    ####################################################################################################################
47
    # Step 3: Encode the excel file to Base64
48
    ####################################################################################################################
49
    try:
50
        with open(filename, 'rb') as binary_file:
51
            binary_file_data = binary_file.read()
52
    except IOError as ex:
53
        pass
54
55
    # Base64 encode the bytes
56
    base64_encoded_data = base64.b64encode(binary_file_data)
0 ignored issues
show
introduced by
The variable binary_file_data does not seem to be defined for all execution paths.
Loading history...
57
    # get the Base64 encoded data using human-readable characters.
58
    base64_message = base64_encoded_data.decode('utf-8')
59
    # delete the file from server
60
    try:
61
        os.remove(filename)
62
    except NotImplementedError as ex:
63
        pass
64
    return base64_message
65
66
67
def generate_excel(result,
68
                   name,
69
                   reporting_start_datetime_local,
70
                   reporting_end_datetime_local,
71
                   period_type):
72
    wb = Workbook()
73
    ws = wb.active
74
75
    # Row height
76
    ws.row_dimensions[1].height = 118
77
78
    for i in range(2, 6 + 1):
79
        ws.row_dimensions[i].height = 30
80
81
    ws.row_dimensions[7].height = 60
82
    ws.row_dimensions[3].height = 50
83
84
    # Col width
85
    ws.column_dimensions['A'].width = 1.5
86
87
    ws.column_dimensions['B'].width = 20.0
88
    for i in range(ord('C'), ord('C')+16):
89
        ws.column_dimensions[chr(i)].width = 15.0
90
91
    # Font
92
    name_font = Font(name='Constantia', size=15, bold=True)
93
    title_font = Font(name='宋体', size=15, bold=True)
94
    data_font = Font(name='Franklin Gothic Book', size=11)
95
96
    table_fill = PatternFill(fill_type='solid', fgColor='1F497D')
97
    f_border = Border(left=Side(border_style='medium', color='00000000'),
98
                      right=Side(border_style='medium', color='00000000'),
99
                      bottom=Side(border_style='medium', color='00000000'),
100
                      top=Side(border_style='medium', color='00000000')
101
                      )
102
    b_border = Border(
103
        bottom=Side(border_style='medium', color='00000000'),
104
    )
105
106
    b_c_alignment = Alignment(vertical='bottom',
107
                              horizontal='center',
108
                              text_rotation=0,
109
                              wrap_text=True,
110
                              shrink_to_fit=False,
111
                              indent=0)
112
    c_c_alignment = Alignment(vertical='center',
113
                              horizontal='center',
114
                              text_rotation=0,
115
                              wrap_text=True,
116
                              shrink_to_fit=False,
117
                              indent=0)
118
    b_r_alignment = Alignment(vertical='bottom',
119
                              horizontal='right',
120
                              text_rotation=0,
121
                              wrap_text=True,
122
                              shrink_to_fit=False,
123
                              indent=0)
124
    c_r_alignment = Alignment(vertical='bottom',
125
                              horizontal='center',
126
                              text_rotation=0,
127
                              wrap_text=True,
128
                              shrink_to_fit=False,
129
                              indent=0)
130
    # Img
131
    img = Image("excelexporters/myems.png")
132
    ws.add_image(img, 'B1')
133
134
    # Title
135
    ws['B3'].font = name_font
136
    ws['B3'].alignment = b_r_alignment
137
    ws['B3'] = 'Name:'
138
    ws['C3'].border = b_border
139
    ws['C3'].alignment = b_c_alignment
140
    ws['C3'].font = name_font
141
    ws['C3'] = name
142
143
    ws['D3'].font = name_font
144
    ws['D3'].alignment = b_r_alignment
145
    ws['D3'] = 'Period:'
146
    ws['E3'].border = b_border
147
    ws['E3'].alignment = b_c_alignment
148
    ws['E3'].font = name_font
149
    ws['E3'] = period_type
150
151
    ws['F3'].font = name_font
152
    ws['F3'].alignment = b_r_alignment
153
    ws['F3'] = 'Date:'
154
    ws['G3'].border = b_border
155
    ws['G3'].alignment = b_c_alignment
156
    ws['G3'].font = name_font
157
    ws['G3'] = reporting_start_datetime_local + "__" + reporting_end_datetime_local
158
    ws.merge_cells("G3:H3")
159
160
    ################################################
161
    # First: 趋势
162
    # 6: title
163
    # 7: table title
164
    # 8~ table_data
165
    ################################################
166
    has_data_flag = True
167
    report = result['reporting_period']
168
    if "names" not in report.keys() or report['names'] is None or len(report['names']) == 0:
169
        has_data_flag = False
170
171
    if "timestamps" not in report.keys() or report['timestamps'] is None or len(report['timestamps']) == 0:
172
        has_data_flag = False
173
174
    if "values" not in report.keys() or report['values'] is None or len(report['values']) == 0:
175
        has_data_flag = False
176
    ca = report['names']
177
    ca_len = len(ca)
178
    temp_max_row = 0
179
    times = report['timestamps']
180
    if has_data_flag:
181
        ws['B6'].font = title_font
182
        ws['B6'] = name + ' 趋势'
183
184
        ws['B7'].fill = table_fill
185
        ws['B7'].border = f_border
186
        ws['B7'].alignment = c_c_alignment
187
        ws['B7'] = '时间'
188
        time = times[0]
189
        has_data = False
190
        max_row = 0
191
        if len(time) > 0:
192
            has_data = True
193
            max_row = 8 + len(time)
194
            print("max_row", max_row)
195
            temp_max_row = max_row
196
        if has_data:
197
            for i in range(0, len(time)):
198
                col = 'B'
199
                row = str(8 + i)
200
                # col = chr(ord('B') + i)
201
                ws[col + row].font = title_font
202
                ws[col + row].alignment = c_c_alignment
203
                ws[col + row] = time[i]
204
                ws[col + row].border = f_border
205
206
            for i in range(0, ca_len):
207
                # 38 title
208
                col = chr(ord('C') + i)
209
210
                ws[col + '7'].fill = table_fill
211
                ws[col + '7'].font = title_font
212
                ws[col + '7'].alignment = c_c_alignment
213
                ws[col + '7'] = report['names'][i]
214
                ws[col + '7'].border = f_border
215
216
                # 39 data
217
                time = times[i]
218
                time_len = len(time)
219
220
                for j in range(0, time_len):
221
                    row = str(8 + j)
222
                    # col = chr(ord('B') + i)
223
                    ws[col + row].font = title_font
224
                    ws[col + row].alignment = c_c_alignment
225
                    ws[col + row] = round(report['values'][i][j], 0)
226
                    ws[col + row].border = f_border
227
                # bar
228
                # 39~: bar
229
                bar = BarChart()
230
                labels = Reference(ws, min_col=2, min_row=8, max_row=max_row + 1)
231
                bar_data = Reference(ws, min_col=3 + i, min_row=7, max_row=max_row + 1)  # openpyxl bug
232
                bar.add_data(bar_data, titles_from_data=True)
233
                bar.set_categories(labels)
234
                bar.height = 5.25  # cm 1.05*5 1.05cm = 30 pt
235
                bar.width = 36
236
                # pie.title = "Pies sold by category"
237
                bar.dLbls = DataLabelList()
238
                # bar.dLbls.showCatName = True  # label show
239
                # bar.dLbls.showVal = True  # val show
240
                bar.dLbls.showPercent = True  # percent show
241
                # s1 = CharacterProperties(sz=1800)     # font size *100
242
                chart_col = chr(ord('B'))
243
                chart_cell = chart_col + str(max_row + 2 + 10*i)
244
                print("chart_cell", chart_cell)
245
                ws.add_chart(bar, chart_cell)
246
    else:
247
        pass
248
249
    for i in range(8, temp_max_row + 1 + 1):
250
        ws.row_dimensions[i].height = 20
251
252
    filename = str(uuid.uuid4()) + '.xlsx'
253
    wb.save(filename)
254
255
    return filename
256