You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django读取Excel数据填充Word书签并导出为PDF的问题求助

现有代码问题梳理
  • 技术选型错误:reportlab是直接生成PDF内容的库,无法解析、编辑Word文档结构,也不支持书签替换操作,和需求方向不匹配
  • 文档操作逻辑错误:docx是二进制压缩格式,不能直接用open()以文本模式读写,会直接损坏原文件
  • 语法存在多处错误:函数定义嵌套在循环内、括号不匹配、未初始化HttpResponse对象就直接赋值属性、错误使用字典语法包裹代码块
  • 逻辑流程错误:跳过表头的逻辑存在疏漏,且循环内直接return会导致仅处理第一行有效数据就终止执行,无法批量生成文件
正确实现步骤

首先安装所需依赖:

pip install openpyxl python-docx docx2pdf

注:docx2pdf用于将填充好的Word文档转为PDF,Windows环境只要安装了Office即可直接使用,Linux/macOS环境需要提前安装LibreOffice支持转换。

修正后代码示例

from django.shortcuts import render
from django.http import HttpResponse
from django.conf import settings
import openpyxl
from docx import Document
from docx2pdf import convert
import io
import os

def index(request):
    if request.method == "GET":
        return render(request, 'letters/index.html', {})
    
    excel_file = request.FILES["excel_file"]
    # 加载Excel
    wb = openpyxl.load_workbook(excel_file)
    excel_data = []
    # 这里示例按单条记录生成单个PDF返回,批量生成可以调整逻辑打包返回
    output_buffer = io.BytesIO()

    for sheet_name in wb.sheetnames:
        sheet = wb[sheet_name]
        # 跳过表头行,从第二行开始读取数据
        for row_idx, row in enumerate(sheet.iter_rows(values_only=True)):
            if row_idx == 0:
                continue
            row_data = [str(cell) if cell is not None else "" for cell in row]
            excel_data.append(row_data)
            
            # 加载Word模板
            template_path = os.path.join(settings.MEDIA_ROOT, "template.docx")
            doc = Document(template_path)
            
            # 替换书签逻辑,示例替换两个书签:name、Admission,可根据实际书签数量扩展
            bookmark_map = {
                "name": row_data[0],
                "Admission": row_data[2]
            }
            for bk_name, replace_text in bookmark_map.items():
                for bookmark in doc.bookmarks:
                    if bookmark.name == bk_name:
                        runner = bookmark.start.parent
                        runner.text = replace_text
                        break
            
            # 先保存填充后的Word到临时缓存
            temp_doc_buffer = io.BytesIO()
            doc.save(temp_doc_buffer)
            temp_doc_buffer.seek(0)
            
            # 转PDF
            convert(temp_doc_buffer, output_buffer)
            output_buffer.seek(0)
            
            # 返回PDF文件
            response = HttpResponse(output_buffer, content_type="application/pdf")
            response["Content-Disposition"] = f"attachment;filename=Admission_{row_data[0]}.pdf"
            return response

    return render(request, 'letters/index.html', {"excel_data": excel_data})
补充说明

如果需要批量生成多个PDF,可以将生成的所有PDF打包为zip文件后返回,不需要每条数据都return;如果服务器环境不方便安装LibreOffice/Office,也可以选择用python-docx生成Word后直接返回Word文件,不需要转PDF的步骤可以直接删掉转换逻辑,返回docx格式即可。

内容的提问来源于stack exchange,提问作者sasvi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 21:36:04