Excel 发展历程

从 1985 年到 2026 年,Excel 的演进之路

1985

Excel 1.0 for Mac

Microsoft Excel 首次发布,专为 Macintosh 设计,引入图形界面和鼠标操作。

1987

Excel 2.0 for Windows

首个 Windows 版本发布,Excel 开始跨平台发展。

1993

Excel 5.0 - VBA 引入

首次引入 VBA(Visual Basic for Applications),开启自动化编程时代。

2007

Excel 2007 - OpenXML 格式

引入 xlsx 文件格式(基于 OpenXML),支持更大的数据量和更好的压缩。

2010

Excel 2010 - Sparklines

引入迷你图(Sparklines)、切片器和 Power Pivot 预览版。

2013

Excel 2013 - Power Query

引入 Power Query、Power Map 和 Power Formula 等强大数据分析工具。

2016

Excel 2016 - 云协作

增强 Office 365 云协作功能,支持实时共同编辑。

2026

Excel 2026 - AI 智能化

深度集成 AI 辅助功能,支持自然语言公式、智能数据分析和自动化建议。

📁 xlsx 文件格式详解

深入理解 Excel xlsx 文件的内部结构和 OpenXML 规范

什么是 xlsx 文件?

xlsx 是 Microsoft Excel 2007 及以后版本使用的默认文件格式。它基于 Office Open XML (OOXML) 标准, 本质上是一个 ZIP 压缩包,包含多个 XML 文件和资源文件。

📦 ZIP 压缩包结构

xlsx 文件实际上是一个 ZIP 压缩包。你可以将任何 .xlsx 文件的扩展名改为 .zip, 然后解压查看内部的所有 XML 文件和资源文件。

# 查看 xlsx 文件结构 unzip -l data.xlsx # 或重命名为 zip 后解压 mv report.xlsx report.zip unzip report.zip

📄 XML 为基础

所有数据、格式、样式都以 XML 格式存储。这种基于文本的格式使得 xlsx 文件 更容易被程序解析和生成,也便于版本控制和数据交换。

🔧 开放标准

xlsx 格式遵循 ECMA-376 和 ISO/IEC 29500 国际标准, 这意味着任何开发者都可以基于标准文档实现 xlsx 文件的读写功能。

📂 xlsx 文件核心结构

文件/文件夹 说明 重要性
[Content_Types].xml 定义包中所有部件的 MIME 类型 ●●● 必需
_rels/.rels 包级别的关系定义 ●●● 必需
xl/workbook.xml 工作簿定义,包含工作表列表和命名范围 ●●● 核心
xl/worksheets/sheet1.xml 工作表的实际数据(稀疏矩阵存储) ●●● 核心
xl/sharedStrings.xml 共享字符串表,存储所有文本内容 ●●○ 常用
xl/styles.xml 样式定义(字体、填充、边框等) ●●○ 常用
xl/theme/theme1.xml 主题定义(颜色方案、字体方案) ●○○ 可选
xl/calcChain.xml 公式计算链(公式依赖关系) ●○○ 可选

📊 xlsx 文件结构图

graph TD A[xlsx 文件] --> B[Content_Types.xml
MIME 类型定义] A --> C[_rels/.rels
包关系] A --> D[xl/ 文件夹] D --> E[workbook.xml
工作簿定义] D --> F[worksheets/sheet1.xml
工作表数据] D --> G[sharedStrings.xml
共享字符串] D --> H[styles.xml
样式定义] D --> I[theme/theme1.xml
主题] E --> J[工作表引用] F --> K[行/单元格数据] G --> L[字符串索引] H --> M[字体/填充/边框]

💡 开发者提示

  • 理解 xlsx 结构有助于更高效地处理 Excel 文件
  • 直接操作 XML 可以实现更精细的控制,但复杂度较高
  • 推荐使用成熟的库(如 openpyxl、excelize)来简化开发
  • 共享字符串表优化了文本存储,但会增加查找开销

典型工作流程

开发者处理 Excel 的常见场景和解决方案

flowchart LR subgraph Input[数据输入] A[数据库查询] B[API 响应] C[用户上传] D[系统日志] end subgraph Process[处理流程] E[数据清洗] F[格式转换] G[计算聚合] H[样式应用] end subgraph Output[输出结果] I[报表文件] J[邮件附件] K[云存储] L[下载链接] end Input --> Process Process --> Output
📤

数据导出

数据库 → Excel 报表,支持大数据量分页导出

📥

数据导入

Excel 上传 → 数据验证 → 批量入库

📋

报表生成

模板填充 → 数据计算 → 格式美化 → 输出

🔄

数据迁移

Excel ↔ CSV ↔ JSON ↔ 数据库 互转

📧

邮件报表

定时生成 → 邮件附件 → 自动发送

🌐

Web API

RESTful API 提供 Excel 导出/导入服务

代码示例

创建、修改、删除、图表操作的完整代码示例

创建 Excel

from openpyxl import Workbook

wb = Workbook()
ws = wb.active
ws.title = "数据表"

# 写入数据
ws.append(["姓名", "年龄", "城市"])
ws.append(["张三", 25, "北京"])
ws.append(["李四", 30, "上海"])

wb.save("created.xlsx")

修改 Excel

from openpyxl import load_workbook

wb = load_workbook("data.xlsx")
ws = wb.active

# 修改单元格
ws["B1"] = 26

# 删除行
ws.delete_rows(2)

wb.save("modified.xlsx")

插入图表

from openpyxl.chart import BarChart, Reference

wb = load_workbook("data.xlsx")
ws = wb.active

# 创建柱状图
chart = BarChart()
data = Reference(ws, min_col=2, min_row=1, max_row=5)
chart.add_data(data)
ws.add_chart(chart, "E1")

wb.save("with_chart.xlsx")

创建 Excel

package main

import "github.com/xuri/excelize/v2"

func main() {
    f := excelize.NewFile()
    f.SetCellValue("Sheet1", "A1", "姓名")
    f.SetCellValue("Sheet1", "B1", "年龄")
    f.SetCellValue("Sheet1", "A2", "张三")
    f.SetCellValue("Sheet1", "B2", 25)
    f.SaveAs("created.xlsx")
}

修改 Excel

f, err := excelize.OpenFile("data.xlsx")
if err != nil { return }

// 修改单元格
f.SetCellValue("Sheet1", "B1", 26)

// 删除行
f.DeleteRow("Sheet1", 2)

f.SaveAs("modified.xlsx")

插入图表

import "github.com/xuri/excelize/v2"

f := excelize.NewFile()
defer f.Close()

// 创建柱状图
f.AddChart("Sheet1", "E1", &excelize.Chart{
    Type: excelize.Col,
    Series: []excelize.ChartSeries{
        {Name: "Sheet1!$A$1", Categories: "Sheet1!$A$2:$A$5", Values: "Sheet1!$B$2:$B$5"},
    },
})
f.SaveAs("with_chart.xlsx")

批量生成报表

使用 Python 和 Go 批量生成 Excel 报表的完整示例

示例 1:批量生成部门报表

from openpyxl import Workbook
from openpyxl.styles import Font, Alignment, PatternFill
import pandas as pd

# 模拟数据
data = {
    "销售部": [{"产品": "A", "销量": 100, "金额": 5000},
               {"产品": "B", "销量": 150, "金额": 7500}],
    "技术部": [{"产品": "C", "销量": 80, "金额": 4000},
               {"产品": "D", "销量": 120, "金额": 6000}],
}

def create_report(dept_name, dept_data):
    wb = Workbook()
    ws = wb.active
    ws.title = dept_name

    # 标题样式
    title_font = Font(size=16, bold=True, color="107C41")
    header_fill = PatternFill(start_color="107C41", end_color="107C41", fill_type="solid")
    header_font = Font(bold=True, color="FFFFFF")

    # 添加标题
    ws.merge_cells("A1:C1")
    ws["A1"] = f"{dept_name} - 月度销售报表"
    ws["A1"].font = title_font
    ws["A1"].alignment = Alignment(horizontal="center")

    # 添加表头
    headers = ["产品", "销量", "金额"]
    for col, header in enumerate(headers, 1):
        cell = ws.cell(row=2, column=col, value=header)
        cell.fill = header_fill
        cell.font = header_font
        cell.alignment = Alignment(horizontal="center")

    # 添加数据
    for row, item in enumerate(dept_data, 3):
        ws.cell(row=row, column=1, value=item["产品"])
        ws.cell(row=row, column=2, value=item["销量"])
        ws.cell(row=row, column=3, value=item["金额"])

    # 添加合计
    total_row = len(dept_data) + 3
    ws.cell(row=total_row, column=1, value="合计")
    ws.cell(row=total_row, column=2, value=f"=SUM(B3:B{total_row-1})")
    ws.cell(row=total_row, column=3, value=f"=SUM(C3:C{total_row-1})")

    wb.save(f"reports/{dept_name}_报表.xlsx")
    print(f"✓ {dept_name} 报表已生成")

# 批量生成
for dept, data in data.items():
    create_report(dept, data)

示例 2:使用 pandas 批量导出

import pandas as pd
from openpyxl import load_workbook

# 从数据库或 API 获取数据
df_sales = pd.DataFrame({
    "日期": ["2026-01-01", "2026-01-02", "2026-01-03"],
    "产品": ["A", "B", "C"],
    "销量": [100, 150, 120],
    "金额": [5000, 7500, 6000],
})

# 按产品分组,生成多个报表
for product, group in df_sales.groupby("产品"):
    with pd.ExcelWriter(f"reports/{product}_详细报表.xlsx", engine="openpyxl") as writer:
        group.to_excel(writer, sheet_name="销售明细", index=False)

        # 添加统计 sheet
        summary = group.describe()
        summary.to_excel(writer, sheet_name="统计分析")

    print(f"✓ {product} 报表已生成")

示例 1:批量生成部门报表

package main

import (
    "fmt"
    "github.com/xuri/excelize/v2"
)

type Product struct {
    Name  string
    Sales int
    Amount float64
}

func createReport(deptName string, data []Product) error {
    f := excelize.NewFile()
    defer f.Close()

    // 设置标题
    f.MergeCell("Sheet1", "A1", "C1")
    f.SetCellValue("Sheet1", "A1", deptName+" - 月度销售报表")

    // 设置表头样式
    style, _ := f.NewStyle(&excelize.Style{
        Font:      &excelize.Font{Bold: true, Color: "#FFFFFF"},
        Fill:      excelize.Fill{Type: "pattern", Color: []string{"#107C41"}, Pattern: 1},
        Alignment: &excelize.Alignment{Horizontal: "center"},
    })

    // 添加表头
    headers := []string{"产品", "销量", "金额"}
    for col, header := range headers {
        cell, _ := excelize.CoordinatesToCellName(col+1, 2)
        f.SetCellValue("Sheet1", cell, header)
        f.SetCellStyle("Sheet1", cell, cell, style)
    }

    // 添加数据
    for row, item := range data {
        rowNum := row + 3
        f.SetCellValue("Sheet1", fmt.Sprintf("A%d", rowNum), item.Name)
        f.SetCellValue("Sheet1", fmt.Sprintf("B%d", rowNum), item.Sales)
        f.SetCellValue("Sheet1", fmt.Sprintf("C%d", rowNum), item.Amount)
    }

    return f.SaveAs(fmt.Sprintf("reports/%s_报表.xlsx", deptName))
}

func main() {
    data := mapstring[]Product{
        "销售部": {{"A", 100, 5000}, {"B", 150, 7500}},
        "技术部": {{"C", 80, 4000}, {"D", 120, 6000}},
    }

    for dept, deptData := range data {
        if err := createReport(dept, deptData); err != nil {
            fmt.Println("✗", dept, "报表生成失败:", err)
        } else {
            fmt.Println("✓", dept, "报表已生成")
        }
    }
}

示例 2:并发批量生成

package main

import (
    "fmt"
    "sync"
    "github.com/xuri/excelize/v2"
)

func generateReportConcurrent(deptName string, data []Product, wg *sync.WaitGroup) {
    defer wg.Done()

    f := excelize.NewFile()
    defer f.Close()

    f.SetCellValue("Sheet1", "A1", deptName+" 报表")

    for i, item := range data {
        row := i + 2
        f.SetCellValue("Sheet1", fmt.Sprintf("A%d", row), item.Name)
        f.SetCellValue("Sheet1", fmt.Sprintf("B%d", row), item.Sales)
    }

    if err := f.SaveAs(fmt.Sprintf("reports/%s_报表.xlsx", deptName)); err != nil {
        fmt.Println("✗", deptName, err)
    } else {
        fmt.Println("✓", deptName, "已完成")
    }
}

func main() {
    data := mapstring[]Product{
        "华北区": {{"A", 100, 5000}},
        "华东区": {{"B", 150, 7500}},
        "华南区": {{"C", 80, 4000}},
        "西南区": {{"D", 120, 6000}},
    }

    var wg sync.WaitGroup
    for dept, deptData := range data {
        wg.Add(1)
        go generateReportConcurrent(dept, deptData, &wg)
    }
    wg.Wait()
    fmt.Println("所有报表生成完毕!")
}

邮件发送 Excel

使用 Python 和 Go 发送邮件,支持附件与非附件两种格式

方式 1:带附件发送

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
from openpyxl import Workbook

# 创建 Excel 报表
wb = Workbook()
ws = wb.active
ws.append(["姓名", "部门", "工资"])
ws.append(["张三", "技术部", 15000])
ws.append(["李四", "销售部", 12000])

excel_file = "report.xlsx"
wb.save(excel_file)

# 配置邮件
msg = MIMEMultipart()
msg["From"] = "sender@company.com"
msg["To"] = "receiver@company.com"
msg["Subject"] = "月度工资报表"

# 邮件正文
body = """
<html>
<body>
    <h2>月度工资报表</h2>
    <p>您好,请查收本月的工资报表。</p>
    <p style="color:#666;">此邮件由系统自动发送</p>
</body>
</html>
"""
msg.attach(MIMEText(body, "html"))

# 添加 Excel 附件
with open(excel_file, "rb") as f:
    attachment = MIMEApplication(f.read(), Name="report.xlsx")
attachment["Content-Disposition"] = 'attachment; filename="report.xlsx"'
msg.attach(attachment)

# 发送邮件
smtp = smtplib.SMTP("smtp.company.com", 587)
smtp.starttls()
smtp.login("sender@company.com", "password")
smtp.send_message(msg)
smtp.quit()

print("✓ 邮件已发送(带附件)")

方式 2:非附件(HTML 表格)

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import pandas as pd

# 准备数据
data = {
    "姓名": ["张三", "李四", "王五"],
    "部门": ["技术部", "销售部", "财务部"],
    "工资": [15000, 12000, 13000],
}
df = pd.DataFrame(data)

# 创建 HTML 表格
html_table = df.to_html(index=False, border=0)

# 配置邮件
msg = MIMEMultipart("related")
msg["From"] = "sender@company.com"
msg["To"] = "receiver@company.com"
msg["Subject"] = "员工工资明细"

# HTML 邮件正文(内嵌表格)
html_body = f"""
<html>
<head>
    <style>
        table {{ border-collapse: collapse; width: 100%; }}
        th, td {{ border: 1px solid #ddd; padding: 12px; text-align: left; }}
        th {{ background-color: #107C41; color: white; }}
        tr:nth-child(even) {{ background-color: #f2f2f2; }}
        tr:hover {{ background-color: #e6f2ea; }}
    </style>
</head>
<body>
    <h2 style="color:#107C41;">员工工资明细表</h2>
    {html_table}
    <p style="margin-top:20px;color:#666;font-size:12px;">
        数据生成时间:{pd.Timestamp.now().strftime('%Y-%m-%d %H:%M')}
    </p>
</body>
</html>
"""
msg.attach(MIMEText(html_body, "html"))

# 发送邮件
smtp = smtplib.SMTP("smtp.company.com", 587)
smtp.starttls()
smtp.login("sender@company.com", "password")
smtp.send_message(msg)
smtp.quit()

print("✓ 邮件已发送(HTML 表格)")

方式 1:带附件发送

package main

import (
    "bytes"
    "encoding/base64"
    "fmt"
    "mime/multipart"
    "net/smtp"
    "github.com/xuri/excelize/v2"
)

func sendEmailWithAttachment() error {
    // 创建 Excel 文件
    f := excelize.NewFile()
    defer f.Close()

    f.SetCellValue("Sheet1", "A1", "姓名")
    f.SetCellValue("Sheet1", "B1", "部门")
    f.SetCellValue("Sheet1", "C1", "工资")
    f.SetCellValue("Sheet1", "A2", "张三")
    f.SetCellValue("Sheet1", "B2", "技术部")
    f.SetCellValue("Sheet1", "C2", 15000)

    // 保存到 buffer
    buf := new(bytes.Buffer)
    if err := f.Write(buf); err != nil {
        return err
    }

    // 创建 MIME 邮件
    body := new(bytes.Buffer)
    writer := multipart.NewWriter(body)

    // 添加 HTML 正文
    htmlPart, _ := writer.CreatePart(map[string]string{
        "Content-Type": "text/html; charset=utf-8",
    })
    htmlContent := `<html><body>
        <h2>月度工资报表</h2>
        <p>您好,请查收本月的工资报表。</p>
    </body></html>`
    htmlPart.Write([]byte(htmlContent))

    // 添加 Excel 附件
    attachment, _ := writer.CreatePart(map[string]string{
        "Content-Type": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
        "Content-Disposition": `attachment; filename="report.xlsx"`,
        "Content-Transfer-Encoding": "base64",
    })
    encoder := base64.NewEncoder(base64.StdEncoding, attachment)
    encoder.Write(buf.Bytes())
    encoder.Close()

    writer.Close()

    // 发送邮件
    auth := smtp.PlainAuth("", "sender@company.com", "password", "smtp.company.com")

    msg := make(map[string]string)
    msg["From"] = "sender@company.com"
    msg["To"] = "receiver@company.com"
    msg["Subject"] = "月度工资报表"
    msg["MIME-Version"] = "1.0"
    msg["Content-Type"] = writer.FormDataContentType()

    var header string
    for k, v := range msg {
        header += fmt.Sprintf("%s: %s\r\n", k, v)
    }
    header += "\r\n"

    emailMsg := header + body.String()

    return smtp.SendMail("smtp.company.com:587", auth,
        msg["From"], []string{msg["To"]}, []byte(emailMsg))
}

func main() {
    if err := sendEmailWithAttachment(); err != nil {
        fmt.Println("✗ 发送失败:", err)
    } else {
        fmt.Println("✓ 邮件已发送(带附件)")
    }
}

方式 2:非附件(HTML 表格)

package main

import (
    "bytes"
    "fmt"
    "net/smtp"
    "time"
)

type Employee struct {
    Name   string
    Dept   string
    Salary float64
}

func sendEmailWithHTMLTable() error {
    // 准备数据
    employees := []Employee{
        {"张三", "技术部", 15000},
        {"李四", "销售部", 12000},
        {"王五", "财务部", 13000},
    }

    // 构建 HTML 表格
    var tableRows string
    for _, emp := range employees {
        tableRows += fmt.Sprintf(`<tr>
            <td>%s</td>
            <td>%s</td>
            <td>%.0f</td>
        </tr>`, emp.Name, emp.Dept, emp.Salary)
    }

    // HTML 邮件正文
    htmlBody := fmt.Sprintf(`<html>
<head>
    <style>
        table { border-collapse: collapse; width: 100%%; }
        th, td { border: 1px solid #ddd; padding: 12px; text-align: left; }
        th { background-color: #107C41; color: white; }
        tr:nth-child(even) { background-color: #f2f2f2; }
        tr:hover { background-color: #e6f2ea; }
    </style>
</head>
<body>
    <h2 style="color:#107C41;">员工工资明细表</h2>
    <table>
        <thead>
            <tr><th>姓名</th><th>部门</th><th>工资</th></tr>
        </thead>
        <tbody>%s</tbody>
    </table>
    <p style="margin-top:20px;color:#666;font-size:12px;">
        数据生成时间:%s
    </p>
</body>
</html>`, tableRows, time.Now().Format("2006-01-02 15:04"))

    // 构建邮件
    var buf bytes.Buffer
    buf.WriteString("From: sender@company.com\r\n")
    buf.WriteString("To: receiver@company.com\r\n")
    buf.WriteString("Subject: 员工工资明细\r\n")
    buf.WriteString("MIME-Version: 1.0\r\n")
    buf.WriteString("Content-Type: text/html; charset=utf-8\r\n")
    buf.WriteString("\r\n")
    buf.WriteString(htmlBody)

    // 发送邮件
    auth := smtp.PlainAuth("", "sender@company.com", "password", "smtp.company.com")

    return smtp.SendMail("smtp.company.com:587", auth,
        "sender@company.com", []string{"receiver@company.com"}, buf.Bytes())
}

func main() {
    if err := sendEmailWithHTMLTable(); err != nil {
        fmt.Println("✗ 发送失败:", err)
    } else {
        fmt.Println("✓ 邮件已发送(HTML 表格)")
    }
}

公式计算

使用 Python 和 Go 处理 Excel 公式与计算

示例 1:写入公式

from openpyxl import Workbook
from openpyxl.formula.translate import Translator

# 创建工作簿
wb = Workbook()
ws = wb.active
ws.title = "公式示例"

# 基础数据
ws.append(["产品", "单价", "数量", "金额"])
ws.append(["苹果", 10, 5, "=B2*C2"])
ws.append(["香蕉", 8, 10, "=B3*C3"])
ws.append(["橙子", 12, 8, "=B4*C4"])

# 合计公式
ws.cell(row=5, column=1, value="合计")
ws.cell(row=5, column=4, value="=SUM(D2:D4)")

# 平均值
ws.cell(row=6, column=1, value="平均")
ws.cell(row=6, column=4, value="=AVERAGE(D2:D4)")

# 使用 Translator 转换公式(兼容不同语言版本)
translator = Translator("=SUM(D2:D4)", origin="D5")
ws["D7"] = translator.translate_formula("=SUM(D2:D4)")

wb.save("formulas.xlsx")
print("✓ 公式已写入")

示例 2:计算公式结果

from openpyxl import load_workbook
from openpyxl.utils.exceptions import InvalidFormulaException

# 加载工作簿
wb = load_workbook("formulas.xlsx", data_only=True)
ws = wb.active

# 读取公式计算结果(data_only=True 时读取缓存值)
for row in ws.iter_rows(min_row=2, max_row=5, max_col=4):
    for cell in row:
        print(f"{cell.coordinate}: {cell.value}")

# 使用 xlwings 执行公式计算(需要安装 Excel)
try:
    import xlwings as xw

    app = xw.App(visible=False)
    wb_xw = app.books.open("formulas.xlsx")
    ws_xw = wb_xw.sheets[0]

    # 强制重新计算
    app.api.Calculate()

    # 读取计算结果
    total = ws_xw.range("D5").value
    avg = ws_xw.range("D6").value
    print(f"合计:{total}, 平均:{avg}")

    wb_xw.close()
    app.quit()
except ImportError:
    print("xlwings 未安装,无法执行实时计算")

示例 3:常用公式

# 常用 Excel 公式示例
formulas = {
    "求和": "=SUM(A1:A10)",
    "平均值": "=AVERAGE(A1:A10)",
    "计数": "=COUNT(A1:A10)",
    "最大值": "=MAX(A1:A10)",
    "最小值": "=MIN(A1:A10)",
    "条件求和": "=SUMIF(A1:A10, \">100\")",
    "条件计数": "=COUNTIF(A1:A10, \">100\")",
    "VLOOKUP": "=VLOOKUP(E1, A1:B10, 2, FALSE)",
    "XLOOKUP": "=XLOOKUP(E1, A1:A10, B1:B10)",
    "IF 条件": "=IF(A1>100, \"达标\", \"未达标\")",
    "CONCATENATE": "=CONCATENATE(A1, \" \", B1)",
    "TEXT 格式化": "=TEXT(A1, \"¥0.00\")",
}

wb = Workbook()
ws = wb.active

ws.append(["公式名称", "公式"])
for name, formula in formulas.items():
    ws.append([name, formula])

wb.save("common_formulas.xlsx")
print("✓ 常用公式已保存")

示例 1:写入公式

package main

import (
    "fmt"
    "github.com/xuri/excelize/v2"
)

func main() {
    // 创建工作簿
    f := excelize.NewFile()
    defer f.Close()

    // 设置表头
    f.SetCellValue("Sheet1", "A1", "产品")
    f.SetCellValue("Sheet1", "B1", "单价")
    f.SetCellValue("Sheet1", "C1", "数量")
    f.SetCellValue("Sheet1", "D1", "金额")

    // 基础数据
    products := []struct {
        Name  string
        Price float64
        Qty   int
    }{
        {"苹果", 10, 5},
        {"香蕉", 8, 10},
        {"橙子", 12, 8},
    }

    for i, p := range products {
        row := i + 2
        f.SetCellValue("Sheet1", fmt.Sprintf("A%d", row), p.Name)
        f.SetCellValue("Sheet1", fmt.Sprintf("B%d", row), p.Price)
        f.SetCellValue("Sheet1", fmt.Sprintf("C%d", row), p.Qty)
        // 写入公式:单价 × 数量
        f.SetCellFormula("Sheet1", fmt.Sprintf("D%d", row),
            fmt.Sprintf("=B%d*C%d", row, row))
    }

    // 合计公式
    f.SetCellValue("Sheet1", "A5", "合计")
    f.SetCellFormula("Sheet1", "D5", "=SUM(D2:D4)")

    // 平均值公式
    f.SetCellValue("Sheet1", "A6", "平均")
    f.SetCellFormula("Sheet1", "D6", "=AVERAGE(D2:D4)")

    // 最大值/最小值
    f.SetCellFormula("Sheet1", "D7", "=MAX(D2:D4)")
    f.SetCellFormula("Sheet1", "D8", "=MIN(D2:D4)")

    if err := f.SaveAs("formulas.xlsx"); err != nil {
        fmt.Println("✗ 保存失败:", err)
    } else {
        fmt.Println("✓ 公式已写入")
    }
}

示例 2:读取公式

package main

import (
    "fmt"
    "github.com/xuri/excelize/v2"
)

func main() {
    // 加载工作簿
    f, err := excelize.OpenFile("formulas.xlsx")
    if err != nil {
        fmt.Println("✗ 打开失败:", err)
        return
    }
    defer f.Close()

    // 读取公式(返回公式字符串)
    formula, _ := f.GetCellFormula("Sheet1", "D5")
    fmt.Printf("D5 公式:%s\n", formula)

    // 读取计算结果(需要设置 calc_param)
    result, _ := f.GetCellValue("Sheet1", "D5",
        excelize.Options{UnzipSizeLimit: 100 << 20})
    fmt.Printf("D5 结果:%s\n", result)

    // 遍历所有单元格
    rows, _ := f.GetRows("Sheet1")
    for i, row := range rows {
        for j, cell := range row {
            fmt.Printf("[%d,%d]: %s  ", i+1, j+1, cell)
        }
        fmt.Println()
    }
}

示例 3:常用公式

package main

import (
    "fmt"
    "github.com/xuri/excelize/v2"
)

func main() {
    f := excelize.NewFile()
    defer f.Close()

    // 常用公式示例
    formulas := map[string]string{
        "A1": "=SUM(A1:A10)",           // 求和
        "A2": "=AVERAGE(A1:A10)",      // 平均值
        "A3": "=COUNT(A1:A10)",        // 计数
        "A4": "=MAX(A1:A10)",          // 最大值
        "A5": "=MIN(A1:A10)",          // 最小值
        "A6": "=SUMIF(A1:A10, \">100\")", // 条件求和
        "A7": "=COUNTIF(A1:A10, \">100\")", // 条件计数
        "A8": "=IF(A1>100, \"达标\", \"未达标\")", // IF 条件
    }

    f.SetCellValue("Sheet1", "B1", "公式名称")
    f.SetCellValue("Sheet1", "C1", "公式")

    row := 2
    for cell, formula := range formulas {
        f.SetCellValue("Sheet1", fmt.Sprintf("B%d", row), cell)
        f.SetCellFormula("Sheet1", fmt.Sprintf("C%d", row), formula)
        row++
    }

    if err := f.SaveAs("common_formulas.xlsx"); err != nil {
        fmt.Println("✗ 保存失败:", err)
    } else {
        fmt.Println("✓ 常用公式已保存")
    }
}

💻 Python/Go 处理 Excel

使用编程语言高效处理 Excel 文件

Excel 处理方案选择流程图

flowchart TD A[需要处理 Excel?] --> B{处理场景?} B -->|数据分析/ML| C[Python] C --> D{数据量?} D -->|小/中 | E[pandas + openpyxl] D -->|大 | F[pandas + 分块处理] D -->|超大 | G[polars 或 Dask] B -->|高性能/并发 | H[Go] H --> I{功能需求?} I -->|读写简单 | J[excelize] I -->|复杂格式 | K[unioffice] I -->|超大规模 | L[并发处理] B -->|快速脚本 | M[Python] M --> N[openpyxl / xlrd] B -->|Web 服务 | O[Go] O --> P[excelize + Gin] E --> Q[完成] F --> Q G --> Q J --> Q K --> Q L --> Q N --> Q P --> Q

1. Python 处理 Excel

Python 是数据处理的首选,拥有丰富的 Excel 处理库。

1.1 常用库对比

特点 适用场景 安装
openpyxl 支持.xlsx 格式,功能全面 读写现代 Excel 文件 pip install openpyxl
pandas 数据分析强大,简洁易用 数据分析和转换 pip install pandas
xlsxwriter 只写,支持图表和格式 生成报表 pip install xlsxwriter
xlrd 支持.xls 旧格式 读取旧版 Excel pip install xlrd

1.2 基础操作示例

from openpyxl import load_workbook
import pandas as pd

# 方法 1: openpyxl 读取
wb = load_workbook("data.xlsx")
ws = wb.active

for row in ws.iter_rows(min_row=2, values_only=True):
    name, age, city = row
    print(f"{name} - {age}岁 - {city}")

# 方法 2: pandas 读取 (推荐)
df = pd.read_excel("data.xlsx", sheet_name="Sheet1")
print(df.head())
print(df.describe())  # 统计信息
from openpyxl import Workbook
import pandas as pd

# 方法 1: openpyxl 写入
wb = Workbook()
ws = wb.active
ws.title = "员工信息"

# 写入表头
ws.append(["姓名", "年龄", "城市"])

# 写入数据
data = [
    ["张三", 28, "北京"],
    ["李四", 32, "上海"],
    ["王五", 25, "广州"]
]
for row in data:
    ws.append(row)

wb.save("output.xlsx")

# 方法 2: pandas 写入 (推荐)
df = pd.DataFrame({
    "姓名": ["张三", "李四", "王五"],
    "年龄": [28, 32, 25],
    "城市": ["北京", "上海", "广州"]
})
df.to_excel("output_pandas.xlsx", index=False)
import pandas as pd

# 读取数据
df = pd.read_excel("sales_data.xlsx")

# 数据筛选
high_sales = df[df["销售额"] > 10000]

# 分组聚合
region_summary = df.groupby("地区").agg({
    "销售额": "sum",
    "数量": "mean"
}).reset_index()

# 数据透视表
pivot = pd.pivot_table(
    df,
    values="销售额",
    index="产品",
    columns="地区",
    aggfunc="sum",
    fill_value=0
)

# 数据排序
sorted_df = df.sort_values("销售额", ascending=False)

# 保存结果
with pd.ExcelWriter("analysis_result.xlsx") as writer:
    high_sales.to_excel(writer, sheet_name="高销售额", index=False)
    region_summary.to_excel(writer, sheet_name="地区汇总", index=False)
    pivot.to_excel(writer, sheet_name="产品透视")
from openpyxl import Workbook
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side

wb = Workbook()
ws = wb.active

# 定义样式
header_font = Font(bold=True, color="FFFFFF", size=12)
header_fill = PatternFill(start_color="107c41", end_color="107c41", fill_type="solid")
center_align = Alignment(horizontal="center", vertical="center")

thin_border = Border(
    left=Side(style="thin"),
    right=Side(style="thin"),
    top=Side(style="thin"),
    bottom=Side(style="thin")
)

# 写入数据并应用样式
headers = ["姓名", "销售额", "完成率"]
for col, header in enumerate(headers, 1):
    cell = ws.cell(row=1, column=col, value=header)
    cell.font = header_font
    cell.fill = header_fill
    cell.alignment = center_align
    cell.border = thin_border

data = [
    ["张三", 150000, "120%"],
    ["李四", 120000, "96%"],
    ["王五", 98000, "78%"]
]

for row_idx, row_data in enumerate(data, 2):
    for col_idx, value in enumerate(row_data, 1):
        cell = ws.cell(row=row_idx, column=col_idx, value=value)
        cell.alignment = center_align
        cell.border = thin_border
        # 条件格式:完成率低于 90% 标红
        if col_idx == 3 and float(value.rstrip("%")) < 90:
            cell.font = Font(color="FF0000", bold=True)

# 调整列宽
ws.column_dimensions["A"].width = 15
ws.column_dimensions["B"].width = 12
ws.column_dimensions["C"].width = 10

wb.save("formatted_report.xlsx")

1.3 高级功能

📊 创建图表

from openpyxl.chart import BarChart, Reference

wb = Workbook()
ws = wb.active

# 准备数据
data = [
    ["产品", "Q1", "Q2", "Q3", "Q4"],
    ["产品 A", 100, 150, 200, 180],
    ["产品 B", 80, 120, 160, 140],
    ["产品 C", 60, 90, 130, 110]
]

for row in data:
    ws.append(row)

# 创建柱状图
chart = BarChart()
chart.type = "col"
chart.style = 10
chart.title = "季度销售"

data_ref = Reference(ws, min_col=2, min_row=1, max_row=4, max_col=5)
cats = Reference(ws, min_col=1, min_row=2, max_row=4)

chart.add_data(data_ref, titles_from_data=True)
chart.set_categories(cats)
chart.shape = 4

ws.add_chart(chart, "A10")
wb.save("chart_example.xlsx")

🔄 批量处理

import pandas as pd
from pathlib import Path

def merge_excel_files(folder_path, output_file):
    """合并多个 Excel 文件"""
    all_data = []

    for file in Path(folder_path).glob("*.xlsx"):
        df = pd.read_excel(file)
        df["来源文件"] = file.name
        all_data.append(df)

    merged = pd.concat(all_data, ignore_index=True)
    merged.to_excel(output_file, index=False)
    return merged

def split_excel_by_column(input_file, column, output_folder):
    """按列值拆分 Excel 文件"""
    df = pd.read_excel(input_file)

    for value in df[column].unique():
        subset = df[df[column] == value]
        output = f"{output_folder}/{column}_{value}.xlsx"
        subset.to_excel(output, index=False)

# 使用示例
merge_excel_files("./monthly_reports", "year_summary.xlsx")
split_excel_by_column("sales.xlsx", "地区", "./regions")

2. Go 处理 Excel

Go 语言以高性能和并发著称,适合大规模 Excel 处理场景。

2.1 常用库对比

特点 适用场景 安装
excelize 纯 Go 实现,性能好 读写.xlsx 文件 go get github.com/xuri/excelize/v2
unioffice 功能全面,支持 Office 所有格式 复杂文档处理 go get github.com/unidoc/unioffice
xlsx 轻量级,只读 快速读取数据 go get github.com/tealeg/xlsx

2.2 基础操作示例

package main

import (
    "fmt"
    "log"
    "github.com/xuri/excelize/v2"
)

func main() {
    // 打开 Excel 文件
    f, err := excelize.OpenFile("data.xlsx")
    if err != nil {
        log.Fatal(err)
    }
    defer f.Close()

    // 获取默认工作表名
    sheetName := f.GetSheetName(0)
    fmt.Println("工作表:", sheetName)

    // 读取单元格
    cellValue, _ := f.GetCellValue(sheetName, "A1")
    fmt.Println("A1 的值:", cellValue)

    // 获取所有行
    rows, _ := f.GetRows(sheetName)
    for _, row := range rows {
        for _, colCell := range row {
            fmt.Print(colCell, "\t")
        }
        fmt.Println()
    }
}
package main

import (
    "fmt"
    "github.com/xuri/excelize/v2"
)

func main() {
    // 创建新工作簿
    f := excelize.NewFile()
    defer f.Close()

    // 设置工作表名
    f.SetSheetName("Sheet1", "员工信息")

    // 写入表头
    headers := []string{"姓名", "年龄", "城市"}
    for i, h := range headers {
        cell, _ := excelize.CoordinatesToCellName(i+1, 1)
        f.SetCellValue("Sheet1", cell, h)
    }

    // 写入数据
    data := [][]interface{}{
        {"张三", 28, "北京"},
        {"李四", 32, "上海"},
        {"王五", 25, "广州"},
    }

    for i, row := range data {
        for j, value := range row {
            cell, _ := excelize.CoordinatesToCellName(j+1, i+2)
            f.SetCellValue("Sheet1", cell, value)
        }
    }

    // 保存文件
    if err := f.SaveAs("output.xlsx"); err != nil {
        fmt.Println("保存失败:", err)
    }
}
package main

import (
    "fmt"
    "github.com/xuri/excelize/v2"
)

func main() {
    f := excelize.NewFile()
    defer f.Close()

    // 定义样式
    style, _ := f.NewStyle(&excelize.Style{
        Font: &excelize.Font{
            Bold:  true,
            Color: "#FFFFFF",
            Size:  12,
        },
        Fill: excelize.Fill{
            Type:    "pattern",
            Color:   []string{"#107C41"},
            Pattern: 1,
        },
        Alignment: &excelize.Alignment{
            Horizontal: "center",
            Vertical:   "center",
        },
    })

    // 应用样式到表头
    headers := []string{"姓名", "销售额", "完成率"}
    for i, h := range headers {
        cell, _ := excelize.CoordinatesToCellName(i+1, 1)
        f.SetCellValue("Sheet1", cell, h)
        f.SetCellStyle("Sheet1", cell, cell, style)
    }

    // 调整列宽
    f.SetColWidth("Sheet1", "A", "C", 15)

    if err := f.SaveAs("formatted.xlsx"); err != nil {
        fmt.Println("保存失败:", err)
    }
}
package main

import (
    "fmt"
    "sync"
    "github.com/xuri/excelize/v2"
)

func processFile(filename string, wg *sync.WaitGroup) {
    defer wg.Done()

    f, err := excelize.OpenFile(filename)
    if err != nil {
        fmt.Printf("打开失败 %s: %v\n", filename, err)
        return
    }
    defer f.Close()

    // 处理数据...
    rows, _ := f.GetRows("Sheet1")
    fmt.Printf("%s: %d 行数据\n", filename, len(rows))
}

func main() {
    files := []string{
        "report1.xlsx",
        "report2.xlsx",
        "report3.xlsx",
    }

    var wg sync.WaitGroup
    for _, file := range files {
        wg.Add(1)
        go processFile(file, &wg)
    }
    wg.Wait()

    fmt.Println("所有文件处理完成!")
}

🐍 Excel 内置 Python & AI 核心用法

Microsoft 365 原生集成的 Python 和 AI 功能,无需安装任何库

💡 什么是 Excel 内置 Python?

Microsoft 365 用户现在可以直接在 Excel 中使用 Python,无需安装任何环境或库。 基于 Pyodide 技术,Python 代码在浏览器中运行,数据不出 Excel。

✅ 无需安装 ✅ 数据安全 ✅ 云端运行 ✅ 自动保存

1. 快速开始

📌 如何插入 Python 代码

  1. 在 Excel 功能区点击 "公式" 选项卡
  2. 点击 "Python" 按钮(或按 Alt + P
  3. 在代码单元格中输入 Python 代码
  4. Ctrl + Enter 运行

🔑 核心对象

  • xl - Excel 对象,访问工作表
  • pd - pandas 库(已预装)
  • np - numpy 库(已预装)

2. 核心用法示例

读取当前工作表数据

# 方法 1: 使用 xl 对象读取
df = xl("A1:D100")
print(df.head())

# 方法 2: 读取整个工作表
df = xl("SalesData")  # 按工作表名

# 方法 3: 读取命名区域
df = xl("MyRange")

# 查看数据基本信息
print(df.info())
print(df.describe())

数据分析核心操作

# 读取数据
df = xl("A1:F500")

# 分组聚合
summary = df.groupby("地区").agg({
    "销售额": "sum",
    "数量": "mean",
    "利润": "mean"
}).reset_index()

# 数据透视表
pivot = pd.pivot_table(
    df,
    values="销售额",
    index="产品",
    columns="季度",
    aggfunc="sum",
    fill_value=0
)

# 排序和筛选
top10 = df.nlargest(10, "销售额")
high_value = df[df["销售额"] > 10000]

# 输出结果到 Excel
summary  # 直接显示结果

创建可视化图表

# Excel 内置 Python 支持 matplotlib
import matplotlib.pyplot as plt

# 读取数据
df = xl("A1:C13")

# 创建柱状图
fig, ax = plt.subplots(figsize=(10, 6))
ax.bar(df["产品"], df["销售额"], color="#107c41")
ax.set_title("产品销售对比")
ax.set_xlabel("产品")
ax.set_ylabel("销售额")
plt.xticks(rotation=45)
plt.tight_layout()

# 显示图表(自动嵌入 Excel)
fig

数据清洗核心操作

# 读取原始数据
df = xl("A1:F1000")

# 删除重复值
df = df.drop_duplicates()

# 处理缺失值
df["销售额"] = df["销售额"].fillna(0)  # 填充 0
df["地区"] = df["地区"].fillna("未知")  # 填充默认值

# 删除空行
df = df.dropna()

# 数据类型转换
df["日期"] = pd.to_datetime(df["日期"])
df["销售额"] = pd.to_numeric(df["销售额"])

# 字符串处理
df["产品名称"] = df["产品名称"].str.strip()
df["产品名称"] = df["产品名称"].str.upper()

# 添加计算列
df["利润率"] = (df["利润"] / df["销售额"] * 100).round(2)

df  # 输出清洗后的数据

3. AI 功能核心用法

🤖 Microsoft Copilot in Excel

Copilot 是 Microsoft 365 的 AI 助手,可以直接在 Excel 中帮助你分析数据、创建公式、生成洞察。

💬 Copilot 核心功能

  • 分析数据 - "帮我分析销售趋势"
  • 创建公式 - "计算每个产品的利润率"
  • 生成洞察 - "找出销售额最高的地区"
  • 数据可视化 - "为这些数据创建图表"
  • 假设分析 - "如果价格上涨 10% 会怎样"

📝 常用 AI 提示词

🔹 "Highlight the top 10 products by sales"
🔹 "Create a formula to calculate YoY growth"
🔹 "Show me insights about regional performance"
🔹 "Add conditional formatting for values > 10000"
🔹 "Summarize this data in 3 bullet points"

⚠️ 注意事项

  • Excel 内置 Python 需要 Microsoft 365 订阅
  • 部分功能仅在 Excel for Web 中可用
  • Copilot 需要额外的 Copilot for Microsoft 365 订阅
  • 数据在云端处理,敏感数据请注意隐私