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

如何基于Flask与HTML在网页中展示Excel文件的指定工作表

问题描述

我正在用HTML和Flask搭建一个支持xlsx文件上传的网站,核心需求是查看文件里的工作表。目前已经实现了文件上传,并且把工作表名称输出到datalist中,现在需要实现选择目标工作表后在同一页面展示内容的功能,优先用Python实现,也可以结合JS,极端情况纯JS也可。

现有代码:

Python代码

from flask import Flask, render_template, request, jsonify
from fileinput import filename
import pandas as pd

app = Flask(__name__)

@app.route('/initialization', methods=['GET','POST'])
def readfile():
    file = request.files['file']
    file.save(file.filename)
    data = pd.ExcelFile(file)
    return render_template('readfile.html',sheets = data.sheet_names)

if __name__ == '__main__':
    app.run(debug=True)

HTML代码

<input type="text" name="sheet" list="sheet_list" placeholder="Choose sheet">
<datalist id="sheet_list">
      {% for sheet in sheets %}
       <option>{{sheet}}</option>
      {% endfor %}
</datalist>

解决方案

方案一:Flask后端主导实现(优先推荐)

通过表单提交选中的工作表名称,后端读取对应数据后渲染到页面,逻辑清晰且符合Python优先的要求。

1. 修改Flask后端代码

优化文件存储逻辑(避免同名文件覆盖),新增工作表查询路由:

from flask import Flask, render_template, request, session
import pandas as pd
import uuid
import os

app = Flask(__name__)
app.secret_key = 'your_custom_secret_key'  # 必须设置才能使用session
UPLOAD_FOLDER = 'uploads'
os.makedirs(UPLOAD_FOLDER, exist_ok=True)  # 自动创建上传目录

# 首页:处理文件上传
@app.route('/', methods=['GET', 'POST'])
def upload_file():
    if request.method == 'POST':
        file = request.files['file']
        if file.filename.endswith('.xlsx'):
            # 生成唯一文件名
            unique_filename = f"{uuid.uuid4()}.xlsx"
            file_path = os.path.join(UPLOAD_FOLDER, unique_filename)
            file.save(file_path)
            # 存储文件路径到session,后续查询使用
            session['file_path'] = file_path
            # 获取工作表名称
            excel_data = pd.ExcelFile(file_path)
            return render_template('readfile.html', sheets=excel_data.sheet_names, sheet_data=None)
    return render_template('upload.html')

# 处理工作表查询请求
@app.route('/show-sheet', methods=['POST'])
def show_sheet():
    file_path = session.get('file_path')
    if not file_path:
        return "请先上传文件", 400
    
    sheet_name = request.form.get('sheet')
    # 读取工作表并转成HTML表格
    df = pd.read_excel(file_path, sheet_name=sheet_name)
    df = df.fillna('')  # 替换空值避免显示NaN
    sheet_html = df.to_html(classes='table table-striped', index=False)
    
    # 重新获取工作表名称,保持下拉列表可用
    excel_data = pd.ExcelFile(file_path)
    return render_template('readfile.html', sheets=excel_data.sheet_names, sheet_data=sheet_html)

if __name__ == '__main__':
    app.run(debug=True)

2. 新增上传页面(upload.html)

<!DOCTYPE html>
<html>
<head>
    <title>上传Excel文件</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
    <div class="container mt-5">
        <h3>上传XLSX文件</h3>
        <form method="POST" action="/" enctype="multipart/form-data" class="mt-3">
            <div class="mb-3">
                <input type="file" name="file" class="form-control" accept=".xlsx" required>
            </div>
            <button type="submit" class="btn btn-success">上传并查看工作表</button>
        </form>
    </div>
</body>
</html>

3. 修改readfile.html模板

添加表单提交按钮和内容展示区域:

<!DOCTYPE html>
<html>
<head>
    <title>查看Excel工作表</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
    <div class="container mt-4">
        <h3>选择工作表</h3>
        <form method="POST" action="/show-sheet">
            <div class="mb-3">
                <input type="text" name="sheet" list="sheet_list" placeholder="选择工作表" class="form-control" required>
                <datalist id="sheet_list">
                    {% for sheet in sheets %}
                        <option value="{{ sheet }}">{{ sheet }}</option>
                    {% endfor %}
                </datalist>
            </div>
            <button type="submit" class="btn btn-primary">查看工作表</button>
        </form>

        {% if sheet_data %}
        <div class="mt-4">
            <h3>工作表内容:{{ request.form.sheet }}</h3>
            {{ sheet_data|safe }}
        </div>
        {% endif %}
    </div>
</body>
</html>

方案二:Flask + AJAX(无刷新展示)

如果需要页面不刷新就能展示内容,用JS发送AJAX请求后端获取数据,动态渲染到页面。

1. 后端新增API路由

在方案一的基础上,添加返回JSON数据的路由:

from flask import jsonify

@app.route('/api/get-sheet', methods=['POST'])
def get_sheet_api():
    file_path = session.get('file_path')
    if not file_path:
        return jsonify({'error': '请先上传文件'}), 400
    
    sheet_name = request.json.get('sheet')
    df = pd.read_excel(file_path, sheet_name=sheet_name)
    df = df.fillna('')
    return jsonify({
        'data': df.to_dict('records'),
        'columns': df.columns.tolist()
    })

2. 修改readfile.html的前端逻辑

替换表单为无刷新交互:

<!DOCTYPE html>
<html>
<head>
    <title>查看Excel工作表</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
    <div class="container mt-4">
        <h3>选择工作表</h3>
        <div class="mb-3">
            <input type="text" id="sheetSelect" list="sheet_list" placeholder="选择工作表" class="form-control">
            <datalist id="sheet_list">
                {% for sheet in sheets %}
                    <option value="{{ sheet }}">{{ sheet }}</option>
                {% endfor %}
            </datalist>
            <button id="showBtn" class="btn btn-primary mt-2">查看工作表</button>
        </div>

        <div id="sheetContent" class="mt-4"></div>
    </div>

    <script>
        document.getElementById('showBtn').addEventListener('click', function() {
            const sheetName = document.getElementById('sheetSelect').value;
            if (!sheetName) {
                alert('请选择工作表');
                return;
            }

            fetch('/api/get-sheet', {
                method: 'POST',
                headers: {'Content-Type': 'application/json'},
                body: JSON.stringify({sheet: sheetName})
            })
            .then(res => res.json())
            .then(data => {
                if (data.error) {
                    alert(data.error);
                    return;
                }
                // 动态生成表格
                let tableHtml = `<h3>工作表内容:${sheetName}</h3><table class="table table-striped"><thead><tr>`;
                data.columns.forEach(col => tableHtml += `<th>${col}</th>`);
                tableHtml += `</tr></thead><tbody>`;
                data.data.forEach(row => {
                    tableHtml += `<tr>`;
                    data.columns.forEach(col => tableHtml += `<td>${row[col]}</td>`);
                    tableHtml += `</tr>`;
                });
                tableHtml += `</tbody></table>`;
                document.getElementById('sheetContent').innerHTML = tableHtml;
            })
            .catch(err => {
                console.error(err);
                alert('加载工作表失败');
            });
        });
    </script>
</body>
</html>

方案三:纯前端JS实现(极端场景)

无需后端,用SheetJS库在前端直接解析Excel文件:

<!DOCTYPE html>
<html>
<head>
    <title>前端解析Excel</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/xlsx@0.18.5/dist/xlsx.full.min.js"></script>
</head>
<body>
    <div class="container mt-4">
        <h3>上传并查看Excel工作表</h3>
        <div class="mb-3">
            <input type="file" id="fileInput" accept=".xlsx" class="form-control">
        </div>
        <div class="mb-3" id="sheetSelector" style="display: none;">
            <input type="text" id="sheetSelect" list="sheet_list" placeholder="选择工作表" class="form-control">
            <datalist id="sheet_list"></datalist>
            <button id="showBtn" class="btn btn-primary mt-2">查看工作表</button>
        </div>
        <div id="sheetContent" class="mt-4"></div>
    </div>

    <script>
        let workbook;

        // 解析上传的文件
        document.getElementById('fileInput').addEventListener('change', function(e) {
            const file = e.target.files[0];
            if (!file) return;

            const reader = new FileReader();
            reader.onload = function(e) {
                workbook = XLSX.read(e.target.result, {type: 'binary'});
                const sheetNames = workbook.SheetNames;
                // 填充工作表下拉列表
                const datalist = document.getElementById('sheet_list');
                datalist.innerHTML = sheetNames.map(name => `<option value="${name}">${name}</option>`).join('');
                document.getElementById('sheetSelector').style.display = 'block';
            };
            reader.readAsBinaryString(file);
        });

        // 展示选中的工作表
        document.getElementById('showBtn').addEventListener('click', function() {
            const sheetName = document.getElementById('sheetSelect').value;
            if (!sheetName || !workbook) {
                alert('请先上传文件并选择工作表');
                return;
            }

            const worksheet = workbook.Sheets[sheetName];
            const data = XLSX.utils.sheet_to_json(worksheet, {header: 1});
            // 生成表格HTML
            let tableHtml = `<h3>工作表内容:${sheetName}</h3><table class="table table-striped"><thead><tr>`;
            data[0].forEach(col => tableHtml += `<th>${col}</th>`);
            tableHtml += `</tr></thead><tbody>`;
            for (let i = 1; i < data.length; i++) {
                tableHtml += `<tr>`;
                data[i].forEach(cell => tableHtml += `<td>${cell || ''}</td>`);
                tableHtml += `</tr>`;
            }
            tableHtml += `</tbody></table>`;
            document.getElementById('sheetContent').innerHTML = tableHtml;
        });
    </script>
</body>
</html>

内容的提问来源于stack exchange,提问作者Chārry

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 22:10:11