数据处理--生成Excel文档

一、实现路径总览

  1. 安装必要库 → 2. 准备 / 处理数据 (列表、字典、DataFrame 等) → 3. 创建 Excel 文件 (基础写入) → 4. 高级格式化 (可选,如单元格样式、合并单元格、公式等) → 5. 保存文件

二、详细步骤与代码示例

1. 安装必要库
  • pandas:核心数据处理库,提供简洁的 Excel 操作接口
  • openpyxl:用于写入.xlsx格式文件的引擎(支持 Excel 2007+)
  • xlsxwriter:可选引擎,支持更多高级功能(如图表、条件格式)
2. 数据准备与处理

假设我们有一组处理后的结构化数据(例如:学生成绩、销售数据等),可以是列表、字典或 pandas 的 DataFrame(推荐,最便捷)。

复制代码
import pandas as pd

# 方法1:从字典创建DataFrame(最常用)
data = {
    "姓名": ["张三", "李四", "王五", "赵六"],
    "语文": [88, 92, 78, 95],
    "数学": [95, 89, 92, 85],
    "英语": [90, 85, 88, 92]
}
df = pd.DataFrame(data)

# 数据处理:计算平均分(新增一列)
df["平均分"] = df[["语文", "数学", "英语"]].mean(axis=1).round(1)  # 保留1位小数

print("处理后的数据:")
print(df)

运行结果:

该代码可以进阶为更方便维护的具体代码:

python 复制代码
import pandas as pd
import logging
from typing import Dict, List, Optional

# 配置日志系统
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s'
)


def create_score_dataframe(data: Dict[str, List]) -> Optional[pd.DataFrame]:
    """
    从字典数据创建成绩DataFrame并进行基本验证

    参数:
        data: 包含学生信息和成绩的字典

    返回:
        验证通过的DataFrame,若验证失败则返回None
    """
    try:
        # 创建DataFrame
        df = pd.DataFrame(data)

        # 基本数据验证
        required_columns = ['姓名']
        score_columns = [col for col in df.columns if col not in required_columns]

        if not score_columns:
            logging.error("数据中未包含成绩列")
            return None

        # 检查成绩是否为数值类型
        for col in score_columns:
            if not pd.api.types.is_numeric_dtype(df[col]):
                logging.error(f"成绩列 '{col}' 包含非数值数据,请检查")
                return None

        # 检查是否有缺失值
        if df.isnull().any().any():
            logging.warning("数据中存在缺失值,将自动填充为0")
            df[score_columns] = df[score_columns].fillna(0)

        logging.info(f"成功创建成绩数据框 | 学生数量: {len(df)} | 科目: {', '.join(score_columns)}")
        return df

    except Exception as e:
        logging.error(f"创建数据框时出错: {str(e)}", exc_info=True)
        return None


def calculate_average_score(df: pd.DataFrame,
                            score_columns: Optional[List[str]] = None,
                            round_decimals: int = 1) -> pd.DataFrame:
    """
    计算学生平均分并添加到DataFrame中

    参数:
        df: 包含成绩数据的DataFrame
        score_columns: 用于计算平均分的科目列,若为None则自动检测
        round_decimals: 保留的小数位数

    返回:
        添加了平均分列的DataFrame
    """
    try:
        # 确定用于计算平均分的列
        if not score_columns:
            score_columns = [col for col in df.columns if col != '姓名']
            logging.info(f"自动检测到成绩列: {', '.join(score_columns)}")

        # 计算平均分
        df['平均分'] = df[score_columns].mean(axis=1).round(round_decimals)
        logging.info(f"成功计算平均分 | 保留 {round_decimals} 位小数")

        return df

    except KeyError as e:
        logging.error(f"计算平均分时出错: 缺少列 {str(e)}")
        raise
    except Exception as e:
        logging.error(f"计算平均分时出错: {str(e)}", exc_info=True)
        raise


def display_dataframe(df: pd.DataFrame, title: str = "数据预览") -> None:
    """展示DataFrame内容"""
    print(f"\n{title}:")
    print(df.to_string(index=False))  # 不显示索引列


def main():
    """主函数:处理学生成绩数据"""
    # 学生成绩数据(可根据实际情况修改或从外部加载)
    score_data = {
        "姓名": ["张三", "李四", "王五", "赵六"],
        "语文": [88, 92, 78, 95],
        "数学": [95, 89, 92, 85],
        "英语": [90, 85, 88, 92]
    }

    # 创建并验证数据框
    df = create_score_dataframe(score_data)
    if df is None:
        logging.error("数据处理失败,退出程序")
        return

    # 计算平均分
    df = calculate_average_score(
        df=df,
        # 可指定科目列,如: score_columns=["语文", "数学"],
        round_decimals=1
    )

    # 展示结果
    display_dataframe(df, title="处理后的学生成绩数据")

    # 可选:保存结果到文件
    # output_path = "student_scores.csv"
    # df.to_csv(output_path, index=False, encoding="utf-8")
    # logging.info(f"成绩数据已保存至: {output_path}")


if __name__ == "__main__":
    main()

代码:

python 复制代码
import pandas as pd

# 方法1:从字典创建DataFrame(最常用)
data = {
    "姓名": ["张三", "李四", "王五", "赵六"],
    "语文": [88, 92, 78, 95],
    "数学": [95, 89, 92, 85],
    "英语": [90, 85, 88, 92]
}
df = pd.DataFrame(data)

# 数据处理:计算平均分(新增一列)
df["平均分"] = df[["语文", "数学", "英语"]].mean(axis=1).round(1)  # 保留1位小数

print("处理后的数据:")
print(df)

# 基础写入:生成Excel文件
output_path = "学生成绩表基础版.xlsx"

# index=False:不保留DataFrame的行索引
df.to_excel(output_path, sheet_name="成绩表", index=False, engine="openpyxl")

print(f"基础版Excel已生成:{output_path}")

运行结果:

其中:

  • sheet_name:指定工作表名称(默认为 "Sheet1")
  • index=False:避免将 DataFrame 的行号写入 Excel
  • 生成的文件可直接用 Excel 打开,包含所有数据列(在执行文件所在的pychace里面)
3. 进阶:生成带格式的 Excel 文件

如果需要美化 Excel(如标题样式、单元格颜色、列宽调整等),可结合openpyxlxlsxwriter进行高级格式化。

python 复制代码
import pandas as pd
from openpyxl import load_workbook
from openpyxl.styles import Font, Alignment, PatternFill, Border, Side
from openpyxl.utils import get_column_letter  # 用于安全获取列字母
import os


def create_formatted_score_excel(df, output_path="学生成绩表进阶版.xlsx"):
    try:
        # 确保输出目录存在
        output_dir = os.path.dirname(output_path)
        if output_dir and not os.path.exists(output_dir):
            os.makedirs(output_dir)

        # 1. 写入基础数据
        df.to_excel(output_path, sheet_name="成绩表", index=False, startrow=1, engine="openpyxl")

        # 2. 加载Excel文件准备格式化
        wb = load_workbook(output_path)
        ws = wb["成绩表"]

        # 3. 设置标题行
        title = "2023年秋季学期学生成绩表"
        max_col_letter = chr(65 + len(df.columns) - 1)  # 自动计算最后一列字母
        ws.merge_cells(range_string=f"A1:{max_col_letter}1")
        ws["A1"].value = title
        ws["A1"].font = Font(name="微软雅黑", size=14, bold=True, color="FFFFFF")
        ws["A1"].alignment = Alignment(horizontal="center", vertical="center")
        ws["A1"].fill = PatternFill(fgColor="4F81BD", fill_type="solid")

        # 4. 设置表头样式(第2行)
        header_font = Font(name="微软雅黑", size=11, bold=True)
        header_fill = PatternFill(fgColor="C0C0C0", fill_type="solid")
        for cell in ws[2]:  # 第2行是表头,无合并单元格
            cell.font = header_font
            cell.fill = header_fill
            cell.alignment = Alignment(horizontal="center")

        # 5. 调整列宽(修复核心:用列索引获取字母,而非合并单元格)
        column_widths = {
            "姓名": 10,
            "语文": 8,
            "数学": 8,
            "英语": 8,
            "平均分": 10
        }

        # 遍历表头所在的第2行,获取列名和对应列索引(避免合并单元格)
        for col_idx, cell in enumerate(ws[2], 1):  # col_idx从1开始(Excel列索引从1开始)
            col_name = cell.value
            col_letter = get_column_letter(col_idx)  # 用索引安全获取列字母
            if col_name in column_widths:
                ws.column_dimensions[col_letter].width = column_widths[col_name]
            else:
                ws.column_dimensions[col_letter].width = 10

        # 6. 条件格式
        green_fill = PatternFill(fgColor="92D050", fill_type="solid")
        red_fill = PatternFill(fgColor="FF0000", fill_type="solid")

        avg_col_letter = None
        # 遍历表头找"平均分"列
        for col_idx, cell in enumerate(ws[2], 1):
            if cell.value == "平均分":
                avg_col_letter = get_column_letter(col_idx)
                break

        if avg_col_letter:
            for row in range(3, ws.max_row + 1):
                avg_cell = ws[f"{avg_col_letter}{row}"]
                try:
                    avg_value = float(avg_cell.value)
                    if avg_value >= 90:
                        avg_cell.fill = green_fill
                    elif avg_value < 60:
                        avg_cell.fill = red_fill
                except (ValueError, TypeError):
                    continue

        # 7. 添加边框
        thin_border = Border(
            left=Side(style='thin'),
            right=Side(style='thin'),
            top=Side(style='thin'),
            bottom=Side(style='thin')
        )
        for row in ws.iter_rows(min_row=2, max_row=ws.max_row,
                                min_col=1, max_col=len(df.columns)):
            for cell in row:
                cell.border = thin_border

        # 8. 保存文件
        wb.save(output_path)
        print(f"格式化Excel已生成:{os.path.abspath(output_path)}")

    except Exception as e:
        print(f"生成Excel时出错:{str(e)}")


if __name__ == "__main__":
    # 准备数据
    data = {
        "姓名": ["张三", "李四", "王五", "赵六", "钱七"],
        "语文": [88, 92, 78, 95, 59],
        "数学": [95, 89, 92, 85, 76],
        "英语": [90, 85, 88, 92, 63]
    }
    df = pd.DataFrame(data)
    df["平均分"] = df[["语文", "数学", "英语"]].mean(axis=1).round(1)

    # 输出路径
    output_file = "学生成绩表进阶版.xlsx"
    # output_file = r"C:\Users\你的用户名\Desktop\学生成绩表.xlsx"  # 绝对路径

    create_formatted_score_excel(df, output_file)

运行结果:

4、总结

  1. 基础需求 :用pandas.to_excel()快速生成 Excel,适合简单数据导出。
  2. 格式美化 :结合openpyxl设置单元格样式、合并单元格等,提升可读性。
  3. 数据可视化 :用xlsxwriter插入图表,实现 Excel 内的数据可视化。
  4. 灵活性:支持多工作表、大数据处理和已有文件修改,满足各类场景。
相关推荐
Evan芙8 小时前
用fping编写脚本扫描10.0.0.0/24网段在线主机
linux·运维·网络·excel
SamDeepThinking13 小时前
基于CompletableFuture的主子任务并行处理架构实战:多渠道账单并发导入性能提升5倍的技术方案
java·后端·excel
SamDeepThinking13 小时前
88MB Excel文件导致系统崩溃?看我如何将内存占用降低
java·excel
ChrisitineTX14 小时前
警惕数据“陷阱”:Python 如何自动发现并清洗 Excel 中的异常值?
开发语言·python·excel
wtsolutions14 小时前
Excel to JSON by WTSolutions 4.0.0 版本更新公告
json·excel·wps·插件·转换·加载项·wtsolutions
wtsolutions14 小时前
Excel to JSON by WTSolutions 4.0.0 Update Announcement
json·excel·wps·addin·wtsolutions·conversion
癫狂的兔子1 天前
【Office】【Excel】常用函数公式总结
excel
毛飞龙2 天前
Excel迷你图:在单元格中嵌入趋势洞察
excel·迷你图·sparklines
Tatalaluola2 天前
Unity使用EPPlus读取写入表格
unity·c#·游戏引擎·excel
缺点内向2 天前
如何在 C# 中将 Excel 工作表拆分为多个窗格
开发语言·c#·.net·excel