Sky's blog

flask的excel导入与导出

字数统计: 1,523阅读时长: 8 min
2017/07/18 Share

前言

最近几天天天都在给CTFd开源网站做二次开发……被派去写excel导入和导出的功能,感觉flask怎么说呢,可能因为python的原因,写起来还是比较方便的,再加上有xlrd和xlwt两个库,使excel的功能实现变得简单

导入excel —— xlrd

xlrd的安装

一条指令即可:pip install xlrd

使用介绍

1、导入模块:
import xlrd
2、打开Excel文件读取数据:
data = xlrd.open_workbook('excelFile.xls')
3、使用技巧:
3.1 获取一个工作表:
table = data.sheets()[0] 通过索引顺序获取

table = data.sheet_by_index(0) 通过索引顺序获取

table = data.sheet_by_name(u'Sheet1') 通过名称获取

3.2 获取整行和整列的值(数组):
table.row_values(i)

table.col_values(i)

3.3 获取行数和列数:
nrows = table.nrows

ncols = table.ncols

3.4 单元格:
cell_A1 = table.cell(0,0).value

cell_C4 = table.cell(2,3).value

3.5 使用行列索引:
cell_A1 = table.row(0)[0].value

cell_A2 = table.col(1)[0].value

使用经验

首先在我开发的过程中,个人认为最常用的还是下面几条指令:

1
2
3
data = open_excel(file=filepath + filename).sheets()[0]
nrows = data.nrows
data.row_values(i)[j] #第i行第j个数据

这3个命令组合起来,基本可以访问到所有excel内的数据了(23333)可能是我经验不足~

使用案例

下面是一个选择题excel导入的功能
大体思路如下:
先让用户上传excel,然后保存到相应的路径,然后用xlrd库的操作,读取该excel,取出里面的数据,存入数据库,然后删除用户上传的该excel文件
缺点:必须规范excel的内容格式,否则很可能失败上传!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# -*- coding: utf-8 -*-
from flask import render_template, request, redirect, Blueprint ,flash
from CTFd.utils import admins_only
from CTFd.models import db, Radio

import os # 为了进行系统操作,路径,保存,删除等
import xlrd # 用来读excel
import hashlib # 为了使用md5加密
import time # 为了使用时间戳防止文件名可控加入
import json # 因为选择题选项部分我们采用了json编码,所以引入

import sys # 为了解决编码问题加入(flask内部机制,unicode太麻烦)
reload(sys)
sys.setdefaultencoding('utf8')

admin_Add_Radios = Blueprint('admin_Add_Radios', __name__)
def open_excel(file='file.xls'):
try:
data = xlrd.open_workbook(file,encoding_override="utf-8")
return data
except Exception as e:
print (str(e))

# 根据索引获取Excel表格中的数据
# 参数:file:Excel文件路径
# colnameindex:表头列名所在行的索引
# by_index:表的索引
def allowed_format(file='file.xls', colnameindex=0, by_index=0):
data = open_excel(file)
table = data.sheets()[by_index]
colnames = table.row_values(colnameindex) # 表头列名所在行的索引
if len(colnames)!=6:
return 0
if colnames[0].encode("utf-8") == "题目描述" and \
colnames[1].encode("utf-8") == "A" and \
colnames[2].encode("utf-8") == "B" and \
colnames[3].encode("utf-8") == "C" and \
colnames[4].encode("utf-8") == "D" and \
colnames[5].encode("utf-8") == "答案":
return 1
else:
return 0



ALLOWED_EXTENSIONS = ['xls', 'xlsx']

def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS

@admins_only
@admin_Add_Radios.route('/admin/add_radios', methods=['GET','POST'])
def add_radios():
if request.method == 'POST':
file = request.files['file']
filename = file.filename

if file and allowed_file(filename): #判断文件名是否正确
now = time.ctime()
filename = hashlib.md5("这个不能告诉你" + str(now)).hexdigest()+".xls" # 增加时间戳,防止文件名可控
file.save('路径' + filename)
# 添加到数据库
flag = allowed_format(file='路径' + filename)
if flag :
data = open_excel(file='路径' + filename).sheets()[0]
nrows = data.nrows
pass_num = 0
success_num = 0
for i in range(1,nrows):
u = Radio.query.filter_by(content=data.row_values(i)[0]).first()
if (u):
pass_num += 1
pass
else:
jsons = {'a':data.row_values(i)[1],
'b':data.row_values(i)[2],
'c':data.row_values(i)[3],
'd':data.row_values(i)[4]
}
problems = Radio(content=data.row_values(i)[0],
option=json.dumps(jsons,ensure_ascii=False),
answer=data.row_values(i)[5].lower()
)
db.session.add(problems)
db.session.commit()
success_num += 1
member_num = len(Radio.query.all())
flash("成功导入题目"+str(success_num)+"个,去掉重复项"+str(pass_num)+"个,当前选择题共计"+str(member_num)+"个")
os.remove('路径' + filename)
return render_template('admin/add_radios.html')
else:
flash("选择题导入失败!")
os.remove('路径' + filename)
return render_template('admin/add_radios.html')
else:
flash("您导入的不是excel文件!")
return render_template('admin/add_radios.html')
return render_template('admin/add_radios.html')

即可完成选择题导入功能

导出excel —— xlwt

xlwt的安装

一条指令即可:pip install xlwt

使用经验

filename = xlwt.Workbook() 创建一个excel文件
sheet = filename.add_sheet("my_sheet") 在excel文件里给表单命名
sheet.write(rows, cols ,content) 在你加入的表单内写入内容,注意参数为行,列,内容

使用案例

下面是一个题解提交情况的excel导出的程序
大体思路如下:
先用xlwt生成一个excel文件,将数据库查询结果写入该excel,然后实现下载功能,即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# -*- coding: utf-8 -*-
from flask import Blueprint
from CTFd.utils import admins_only
from CTFd.models import db, Teams,Challenges,Writeup
from flask import request,send_from_directory

import os
import xlwt

import sys
reload(sys)
sys.setdefaultencoding('utf8')

admin_Import_Writeup = Blueprint('admin_Import_Writeup', __name__)

@admins_only
@admin_Import_Writeup.route('/admin/import_writeup', methods=['GET','POST'])
def loading():
if request.method == 'GET':
directory = os.getcwd() + '路径'
if os.path.exists(directory + '/' + "文件名.xls"):
os.remove(directory + '/' + "文件名.xls")
wp = Writeup.query.all()
problem = Challenges.query.all()
user = Teams.query.all()
repeat_allowed = []
filename = xlwt.Workbook()
sheet = filename.add_sheet("my_sheet")
challenge_col_name = []
user_name = []
for w in range(len(problem)):
if problem[w].id not in repeat_allowed:
repeat_allowed.append(problem[w].id)
challenge_col = Challenges.query.filter_by(id=problem[w].id).first()
challenge_col_name.append(challenge_col.name)
else:
pass
sheet.write(0,0,u'姓名')
for s in range(len(challenge_col_name)):
sheet.write(0,s+1,challenge_col_name[s])
for k in range(len(user)):
user_name.append(user[k].name)
sheet.write(k+1,0, user[k].name)
now_rows = 1
for now_name in user_name:
now_cols = 1
for now_challenge in challenge_col_name:
team = Teams.query.filter_by(name=now_name).first()
challenge = Challenges.query.filter_by(name=now_challenge).first()
writeup_up = Writeup.query.filter_by(user_id=team.id,Challenge_id=challenge.id).first()
if writeup_up:
sheet.write(now_rows, now_cols, 1)
else:
sheet.write(now_rows, now_cols, 0)
now_cols +=1
now_rows += 1
token = time.ctime()
filename_now = "文件名.xls"
filename.save("路径"+filename_now)
return send_from_directory(directory, filename_now, as_attachment=True)

即可完成题解提交情况导出功能

点击赞赏二维码,您的支持将鼓励我继续创作!
CATALOG
  1. 1. 前言
  2. 2. 导入excel —— xlrd
    1. 2.1. xlrd的安装
    2. 2.2. 使用介绍
    3. 2.3. 使用经验
    4. 2.4. 使用案例
  3. 3. 导出excel —— xlwt
    1. 3.1. xlwt的安装
    2. 3.2. 使用经验
    3. 3.3. 使用案例