从 1985 年到 2026 年,Excel 的演进之路
Microsoft Excel 首次发布,专为 Macintosh 设计,引入图形界面和鼠标操作。
首个 Windows 版本发布,Excel 开始跨平台发展。
首次引入 VBA(Visual Basic for Applications),开启自动化编程时代。
引入 xlsx 文件格式(基于 OpenXML),支持更大的数据量和更好的压缩。
引入迷你图(Sparklines)、切片器和 Power Pivot 预览版。
引入 Power Query、Power Map 和 Power Formula 等强大数据分析工具。
增强 Office 365 云协作功能,支持实时共同编辑。
深度集成 AI 辅助功能,支持自然语言公式、智能数据分析和自动化建议。
深入理解 Excel xlsx 文件的内部结构和 OpenXML 规范
xlsx 是 Microsoft Excel 2007 及以后版本使用的默认文件格式。它基于 Office Open XML (OOXML) 标准, 本质上是一个 ZIP 压缩包,包含多个 XML 文件和资源文件。
xlsx 文件实际上是一个 ZIP 压缩包。你可以将任何 .xlsx 文件的扩展名改为 .zip, 然后解压查看内部的所有 XML 文件和资源文件。
所有数据、格式、样式都以 XML 格式存储。这种基于文本的格式使得 xlsx 文件 更容易被程序解析和生成,也便于版本控制和数据交换。
xlsx 格式遵循 ECMA-376 和 ISO/IEC 29500 国际标准, 这意味着任何开发者都可以基于标准文档实现 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 | 公式计算链(公式依赖关系) | ●○○ 可选 |
开发者处理 Excel 的常见场景和解决方案
数据库 → Excel 报表,支持大数据量分页导出
Excel 上传 → 数据验证 → 批量入库
模板填充 → 数据计算 → 格式美化 → 输出
Excel ↔ CSV ↔ JSON ↔ 数据库 互转
定时生成 → 邮件附件 → 自动发送
RESTful API 提供 Excel 导出/导入服务
创建、修改、删除、图表操作的完整代码示例
from openpyxl import Workbook wb = Workbook() ws = wb.active ws.title = "数据表" # 写入数据 ws.append(["姓名", "年龄", "城市"]) ws.append(["张三", 25, "北京"]) ws.append(["李四", 30, "上海"]) wb.save("created.xlsx")
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")
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") }
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 报表的完整示例
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)
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} 报表已生成")
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, "报表已生成") } } }
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("所有报表生成完毕!") }
使用 Python 和 Go 发送邮件,支持附件与非附件两种格式
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("✓ 邮件已发送(带附件)")
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 表格)")
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("✓ 邮件已发送(带附件)") } }
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 公式与计算
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("✓ 公式已写入")
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 未安装,无法执行实时计算")
# 常用 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("✓ 常用公式已保存")
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("✓ 公式已写入") } }
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() } }
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("✓ 常用公式已保存") } }
使用编程语言高效处理 Excel 文件
Python 是数据处理的首选,拥有丰富的 Excel 处理库。
| 库 | 特点 | 适用场景 | 安装 |
|---|---|---|---|
| openpyxl | 支持.xlsx 格式,功能全面 | 读写现代 Excel 文件 | pip install openpyxl |
| pandas | 数据分析强大,简洁易用 | 数据分析和转换 | pip install pandas |
| xlsxwriter | 只写,支持图表和格式 | 生成报表 | pip install xlsxwriter |
| xlrd | 支持.xls 旧格式 | 读取旧版 Excel | pip install xlrd |
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")
Go 语言以高性能和并发著称,适合大规模 Excel 处理场景。
| 库 | 特点 | 适用场景 | 安装 |
|---|---|---|---|
| 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 |
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("所有文件处理完成!") }
Microsoft 365 原生集成的 Python 和 AI 功能,无需安装任何库
Microsoft 365 用户现在可以直接在 Excel 中使用 Python,无需安装任何环境或库。 基于 Pyodide 技术,Python 代码在浏览器中运行,数据不出 Excel。
Alt + P)Ctrl + Enter 运行xl - Excel 对象,访问工作表pd - pandas 库(已预装)np - numpy 库(已预装)# 方法 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 # 输出清洗后的数据
Copilot 是 Microsoft 365 的 AI 助手,可以直接在 Excel 中帮助你分析数据、创建公式、生成洞察。