使用 zipfile、openpyxl、flask 批量导出excel zip

本文介绍了如何使用Python的zipfile、openpyxl库来批量生成并压缩Excel文件,同时展示了如何通过Flask接口导出这些压缩文件。示例包括了对本地文件、流文件的压缩,以及openpyxl创建多Sheet Excel文件并压缩到ZIP中。此外,还提供了一个实际的Flask接口示例,用于根据条件动态生成和导出Excel ZIP文件。
摘要由CSDN通过智能技术生成

使用 zipfile、openpyxl、flask 批量导出excel zip


前言

 一、python 使用 openpyxl 操作 excel https://blog.csdn.net/mtl1994/article/details/123349397 


一、环境

  1. python3.10 (https://docs.python.org/3/library/zipfile.html)

二、使用

1.压缩本地文件

with ZipFile('spam.zip', 'w') as myzip:
    myzip.write('1.xls')
    myzip.write('app.py')

2.压缩流文件到zip

xls_byte = io.BytesIO()
xls_tmp = load_workbook('1.xlsx')
xls_tmp.save(xls_byte)
with ZipFile('spam.zip', 'w') as myzip:
    myzip.writestr('1.xlsx', xls_byte.getvalue())
xls_byte.seek(0)

3.压缩目录下 pyc

project = PyZipFile("project.zip", mode='w')
project.writepy("d:/datasets-work")

4.openpyxl 生成多个excel, excel zipfile 压缩 flask接口 导出

@admin.route("/export_all_tmplate", methods=["GET"])
def export_all_tmplate():
    all_zip = BytesIO()
    zf = ZipFile(all_zip, 'w')
    for i in range(10):
        output = BytesIO()
        wb_tmp = load_workbook(f'tmp-{i}.xlsx')
        wb_tmp.save(output)
        """
        操作excel...
        """
        zf.writestr(f"tmp-{i}.xlsx", output.getvalue())
        output.seek(0)
    zf.close()
    all_zip.seek(0)
    resp = make_response(all_zip.getvalue())
    basename = 'all.zip'
    # 转码,支持中文名称
    resp.headers["Content-Disposition"] = "attachment; filename*=UTF-8''{utf_filename}".format(
        utf_filename=basename)
    resp.headers['Content-Type'] = 'application/zip'
    return resp

5.实例

@admin.route("/equipment_standing_book/basic/export_all_tmplate", methods=["GET"])
# @need_login
# @cache.cached(timeout=600, key_prefix=make_cache_key)
def equipment_standing_book_export_all_tmplate():
    """
    #group  导出接口
    #name   导出接口
    #desc   导出excel
    #param  tmp_name #模板名称
    #priv   need_login
    #return data    <dict>   各个字段的注释
    #example
    {
        "code": 0,
        "msg": "成功",
        "data":{}
    }
    """
    tmp_name = str(g.request_data.get("tmp_name", "")).strip()
    time = str(g.request_data.get("time", "")).strip()
    filename = time
    tmplate = equip_standing_config.query({'tmp_name': tmp_name})[0]
    format = "%Y"
    if tmplate['type'] == '3':
        format = "%Y-%m"
    all_zip = BytesIO()
    zf = ZipFile(all_zip, 'w')
    record_list = equip_standing_record.query(where=f" and config_id='{tmplate['id']}' and date_format(create_time, '{format}') = '{time}'")
    last_record_time = ""
    for ri, record in enumerate(record_list):
        output = BytesIO()
        #如果相同日期合并到一个excel,多sheet
        if last_record_time != "" and last_record_time == record["create_time"].strftime('%Y-%m-%d'):
            ws = wb_tmp["next"]
            ws.title = record['code'].replace(":", "")
            target = wb_tmp.copy_worksheet(wb_tmp.active)
            target.title = "next"
        else:
            wb_tmp = load_workbook(f'./src/statics/{tmp_name}.xlsx')
            ws = wb_tmp[wb_tmp.sheetnames[0]]
            ws.title = record['code'].replace(":", "")
            target = wb_tmp.copy_worksheet(wb_tmp.active)
            target.title = "next"
        detail_list = eval(tmp_name).query({'record_id': record['id']})
        obj: {} = eval(tmp_name).get_dict()
        start, start_row, points = 0, [], {}
        #找到从哪一行赋值 excel中 配置和实体类对应的字段
        for i, row in enumerate(ws.values):
            print(type(row))
            start_row = row
            for j, value in enumerate(row):
                print(i,j,value)
                if value in obj.keys():
                    points[j] = value
                    start = i
                if value == 'serial_number':
                    points[j] = 'serial_number'
                    start = i
            if start > 0:
                break
        ws.delete_rows(start + 1)
        ws.insert_rows(start + 1, len(detail_list))
		#赋值
        for i, obj in enumerate(detail_list):
            for point in points.keys():
                cell = ws.cell(row=start + 1, column=point + 1)
                cell.value = i if points[point] == 'serial_number' else obj[points[point]]
                cell.border = Border(top=Side(border_style='thin', color='000000'),
                        bottom=Side(border_style='thin', color='000000'),
                        left=Side(border_style='thin', color='000000'),
                        right=Side(border_style='thin', color='000000'))
            start += 1
        #如果当前行和上一行相同,合并
        for i in range(start + 1, ws.max_row + 1):
            ws.merge_cells(start_row=i, start_column=1, end_row=i, end_column=ws.max_column)

        if (ri + 1 < len(record_list) and record_list[ri + 1]["create_time"].strftime('%Y-%m-%d') != record_list[ri]["create_time"].strftime('%Y-%m-%d'))\
                or (last_record_time != "" and last_record_time != record["create_time"].strftime('%Y-%m-%d')):
            wb_tmp.remove(wb_tmp["next"])
            wb_tmp.save(output)
            zf.writestr(record['create_time'].strftime('%Y-%m-%d') + ".xlsx", output.getvalue())
            output.seek(0)

        last_record_time = record["create_time"].strftime('%Y-%m-%d')
    zf.close()
    all_zip.seek(0)
    resp = make_response(all_zip.getvalue())
    basename = f'{filename}.zip'

    # 转码,支持中文名称
    resp.headers["Content-Disposition"] = "attachment; filename*=UTF-8''{utf_filename}".format(
        utf_filename=basename)
    resp.headers['Content-Type'] = 'application/zip'
    return resp

总结

~~~

文件的思路是将多个Excel文件打包为一个zip文件,可以按照以下步骤实现: 1. 创建一个空的zip文件,用于存储多个Excel文件。 2. 遍历需要导出Excel文件列表,将每个文件逐一写入到zip文件中。 3. 设置响应头,告知浏览器下载zip文件。 4. 将zip文件输出到响应流中,完成下载。 以下是示例代码: ```java @RequestMapping("/export/excel") public void exportExcel(HttpServletResponse response) throws IOException { // 获取需要导出Excel文件列表 List<File> excelList = getExcelList(); if (excelList == null || excelList.isEmpty()) { return; } // 创建一个空的zip文件 File zipFile = new File("export.zip"); ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFile)); // 遍历Excel文件列表,将每个文件逐一写入zip文件中 for (File excel : excelList) { FileInputStream excelIn = new FileInputStream(excel); ZipEntry entry = new ZipEntry(excel.getName()); zipOut.putNextEntry(entry); byte[] buffer = new byte[1024]; int len; while ((len = excelIn.read(buffer)) > 0) { zipOut.write(buffer, 0, len); } excelIn.close(); zipOut.closeEntry(); } zipOut.close(); // 设置响应头,告知浏览器下载zip文件 response.setContentType("application/zip"); response.setHeader("Content-Disposition", "attachment; filename=\"export.zip\""); // 将zip文件输出到响应流中 FileInputStream zipIn = new FileInputStream(zipFile); ServletOutputStream zipOut = response.getOutputStream(); byte[] buffer = new byte[1024]; int len; while ((len = zipIn.read(buffer)) > 0) { zipOut.write(buffer, 0, len); } zipIn.close(); zipOut.close(); // 删除临时文件 zipFile.delete(); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

matianlongg

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值