一、openpyxl 介绍
openpyxl
是一个用于读取和写入 Excel 2010 xlsx/xlsm/xltx/xltm 文件的 Python 库。使用场景包括:
- 数据分析:从 Excel 文件中读取数据,进行处理和分析。
- 自动化办公:自动生成报告、填写表格等。
- 数据导入导出:将数据从 Python 程序导入到 Excel,或将 Excel 数据导入到 Python 程序中。
安装openpyxl
sh
pip install openpyxl
二、Excel文件下载
创建并保存 Excel 文件
示例:创建一个新的 Excel 工作簿,并写入一些数据,最后保存为文件
python
from openpyxl import Workbook
# 创建一个新的工作簿
workbook = Workbook()
# 获取默认的工作表
sheet = workbook.active
sheet.title = "MySheet" # 设置工作表标题
# 写入数据到单元格
sheet['A1'] = "Hello, Openpyxl!"
sheet['B2'] = 42
# 保存工作簿
workbook.save('new_example.xlsx')
Excel工具函数
为提高代码复用率,整理处理Excel工具函数
- create_excel_workbook():将数据
data
按照指定字段和标签写入一个新的 Excel 工作簿,并设置表头和列宽。 - generate_excel_response():将
workbook
(Excel 工作簿)生成 Excel 文件,并通过 HTTP 响应返回给客户端下载 - process_item():将一个数据项
item
按照指定字段顺序fields
转换为一行数据(列表) - convert_datetime():将带有时区信息的 ISO 格式时间字符串(如
"2023-01-01T12:34:56.789+08:00"
)转换为去除时区、毫秒并替换T
为空格的字符串,输出格式为"YYYY-MM-DD HH:MM:SS"
。
python
from urllib.parse import quote
from django.http import HttpResponse
from openpyxl import Workbook
from openpyxl.utils import get_column_letter
def convert_datetime(datetime_str):
# 移除时区部分(+08:00)
datetime_without_tz = datetime_str.replace("+08:00", "")
# 移除 "T" 并截取到秒部分(去掉毫秒)
return datetime_without_tz.replace("T", " ").split(".")[0]
def process_item(item, fields, data_map={}):
"""将单个数据项转换为行数据"""
row = []
for field in fields:
value = item.get(field)
# 友好显示转换
if field in data_map:
value = data_map[field].get(value, None)
# 特殊字段类型转换
elif field == "id" or field == "job_id":
value = str(value)
elif field == "create_time" or field == "date_created" or field == "date_done":
value = convert_datetime(value)
row.append(value)
return row
def create_excel_workbook(data, fields_labels, data_map={}, sheet_name="Sheet1"):
"""
将数据写入Excel文件
"""
fields = list(fields_labels.keys())
labels = list(fields_labels.values())
# 创建一个 Excel 工作簿
workbook = Workbook()
sheet = workbook.active
sheet.title = sheet_name
# 设置表头
sheet.append(labels)
# 添加数据
for item in data:
row = process_item(item, fields, data_map)
sheet.append(row)
# 设置列宽
for col_num in range(1, len(labels) + 1):
col_letter = get_column_letter(col_num)
sheet.column_dimensions[col_letter].width = 15
return workbook
def generate_excel_response(workbook, file_name="export.xlsx"):
"""
生成 Excel 文件并返回 HTTP 响应。
"""
response = HttpResponse(
content_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
)
response["Content-Disposition"] = f"attachment; filename={quote(file_name)}"
workbook.save(response)
return response
项目实战:Excel文件下载
实战场景:在Django+Vue3后台管理系统中,实现用户的导入导出功能是常见需求。用户导入功能,一般需要先下载模板,填写后再导入。
实战代码:定义视图,将示例数据导出为 Excel 文件并返回给用户下载,实现下载模板功能
python
@extend_schema(summary="获得用户导入模板")
@action(
methods=["get"],
detail=False,
url_path="get-import-template",
)
def get_import_template(self, request, *args, **kwargs):
"""获得用户导入模板"""
# 定义示例数据
data = [
{
"username": "xiaozhang",
"nickname": "小张",
"deptId": "103",
"email": "xz@qq.com",
"mobile": "13312345670",
"sex": "男",
"status": "开启",
},
{
"username": "xiaoli",
"nickname": "小李",
"deptId": "",
"email": "",
"mobile": "",
"sex": "",
"status": "关闭",
},
]
fields_labels = {
"username": "用户账号",
"nickname": "用户昵称",
"deptId": "部门编号",
"email": "用户邮箱",
"mobile": "手机号码",
"sex": "用户性别",
"status": "账号状态",
}
# 返回工作簿
workbook = create_excel_workbook(data, fields_labels)
return generate_excel_response(workbook, "用户导入模板.xlsx")
实现效果
三、Excel 文件上传
获取上传的文件
当 Django 处理文件上传时,文件数据会被放置在 request.FILES 中。获取上传文件示例
python
file = request.FILES.get("file")
读取Excel中的数据
示例:读取example.xlsx
文件中的标题、单元格等信息
python
from openpyxl import load_workbook
# 加载一个已存在的Excel文件
workbook = load_workbook('example.xlsx')
# 获取工作簿中的工作表
sheet = workbook.active # 获取当前活动的工作表
print(sheet.title) # 输出工作表的标题
# 读取单元格的值
cell_value = sheet['A1'].value
print(cell_value)
项目实战:Excel文件上传
实战场景:在Django+Vue3后台管理系统中,实现用户导入功能
- 第一步:获取用户上传的文件
- 第二步:调用
get_user_import_data()
函数,读取Excel文件中的用户数据,并将其转换为系统所需格式的字典列表。 - 第三步:使用序列化器,将用户信息保存到数据库
python
def get_user_import_data(file) -> list:
"""
读取Excel文件中的用户信息,并将其转换为字典列表
"""
# 加载Excel文件
workbook = load_workbook(file)
sheet = workbook.active
# 固定表头,以确保数据字段的一致性
headers = ["username", "nickname", "deptId", "email", "mobile", "sex", "status"]
# 初始化数据列表
data = []
# 遍历每一行数据
for row in sheet.iter_rows(min_row=2, values_only=True):
# 将当前行数据与表头 zip 后转换为字典
user_data = dict(zip(headers, row))
# 转换 sex 和 status 字段
user_data["sex"] = (
1 if user_data["sex"] == "男" else 2 if user_data["sex"] == "女" else 0
)
user_data["status"] = (
0
if user_data["status"] == "开启"
else 1 if user_data["status"] == "关闭" else None
)
data.append(user_data)
return data
实现效果:点击查看完整代码
您正在阅读的是《Django从入门到实战》专栏!关注不迷路~