本文是工作中用到的笔记📒,记录使用 reactjs 在浏览器端直接导出 excel 功能。
目录:
安装依赖包
$ yarn add exceljs file-saver
import React from 'react'
import ExcelJS from 'exceljs'
import { saveAs } from 'file-saver'
const ExportExcel = () => {
const exportToExcel = async () => {
// 创建工作簿
const workbook = new ExcelJS.Workbook()
// 添加工作表
const worksheet = workbook.addWorksheet('Sheet1')
// 填充数据
worksheet.addRow([ 'Name', 'Age', 'City' ])
worksheet.addRow([ 'Alice', 25, 'New York' ])
worksheet.addRow([ 'Bob', 30, 'London' ])
// 生成 Excel 文件并下载
const buffer = await workbook.xlsx.writeBuffer()
const blob = new Blob([ buffer ], {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
})
saveAs(blob, 'users.xlsx')
}
return (
<div>
<h2>Export Excel (Basic)</h2>
<button onClick={exportToExcel}>Download Excel</button>
</div>
)
}
export default ExportExcel
import React from 'react'
import ExcelJS from 'exceljs'
import { saveAs } from 'file-saver'
const MergeCellsExample = () => {
const exportWithMergedCells = async () => {
// 创建工作簿
const workbook = new ExcelJS.Workbook()
// 添加工作表
const worksheet = workbook.addWorksheet('Merged Cells')
// 填充数据(合并单元格前)
worksheet.addRow([ 'Region', 'Sales', 'Notes' ])
worksheet.addRow([ 'East', 1000, 'Good performance' ])
worksheet.addRow([ 'West', 800, 'Needs improvement' ])
worksheet.addRow([ 'North', 1200, 'Excellent' ])
worksheet.addRow([ 'South', 900, 'Stable' ])
// 合并单元格(从 A1 到 C1)
worksheet.mergeCells('A1:C1') // 合并第一行的 A、B、C 列
worksheet.getCell('A1').value = 'Sales Report' // 设置合并后的单元格值
worksheet.getCell('A1').font = { bold: true, size: 14 } // 设置样式
// 合并其他单元格(从 B2 到 B3)
worksheet.mergeCells('B2:B3') // 合并第二行和第三行的 B 列
worksheet.getCell('B2').value = 'Total East & West' // 设置合并后的单元格值
worksheet.getCell('B2').fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FFFF00' } } // 黄色背景
// 合并单元格(从 C2 到 C4)
worksheet.mergeCells('C2:C4') // 合并第二行到第四行的 C 列
worksheet.getCell('C2').value = 'Regional Notes' // 设置合并后的单元格值
worksheet.getCell('C2').font = { italic: true } // 斜体
// 生成 Excel 文件并下载
const buffer = await workbook.xlsx.writeBuffer()
const blob = new Blob([ buffer ], {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
})
saveAs(blob, 'merged_cells_example.xlsx')
}
return (
<div>
<h2>ExcelJS 合并单元格示例</h2>
<button onClick={exportWithMergedCells}>导出 Excel(带合并单元格)</button>
</div>
)
}
export default MergeCellsExample
import React from 'react'
import ExcelJS from 'exceljs'
import { saveAs } from 'file-saver'
const ExcelFontColorExample = () => {
const exportWithFontColor = async () => {
// 创建工作簿
const workbook = new ExcelJS.Workbook()
// 添加工作表
const worksheet = workbook.addWorksheet('Font Color Example')
// 填充数据
worksheet.addRow([ 'Apple', 10, 'In Stock' ])
worksheet.addRow([ 'Banana', 5, 'Low Stock' ])
worksheet.addRow([ 'Orange', 8, 'Out of Stock' ])
// 设置字体颜色(使用 ARGB 格式)
// 第一行数据(Apple)
worksheet.getCell('A1').font = { color: { argb: 'FF0000' } } // 红色
worksheet.getCell('B1').font = { color: { argb: '00FF00' } } // 绿色
worksheet.getCell('C1').font = { color: { argb: '0000FF' } } // 蓝色
// 第二行数据(Banana)
worksheet.getCell('A2').font = { color: { argb: 'FFA500' } } // 橙色
worksheet.getCell('B2').font = { color: { argb: '800080' } } // 紫色
worksheet.getCell('C2').font = { color: { argb: 'FF00FF' } } // 品红
// 第三行数据(Orange)
worksheet.getCell('A3').font = { color: { argb: '000000' } } // 黑色
worksheet.getCell('B3').font = { color: { argb: '808080' } } // 灰色
worksheet.getCell('C3').font = { color: { argb: 'A52A2A' } } // 棕色
// 生成 Excel 文件并下载
const buffer = await workbook.xlsx.writeBuffer()
const blob = new Blob([ buffer ], {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
})
saveAs(blob, 'font_color_example.xlsx')
}
return (
<div>
<h2>ExcelJS 设置字体颜色示例</h2>
<button onClick={exportWithFontColor}>导出带字体颜色的 Excel</button>
</div>
)
}
export default ExcelFontColorExample
import React from 'react'
import ExcelJS from 'exceljs'
import { saveAs } from 'file-saver'
const ExcelBoldFontExample = () => {
const exportWithBoldFont = async () => {
// 创建工作簿
const workbook = new ExcelJS.Workbook()
// 添加工作表
const worksheet = workbook.addWorksheet('Bold Font Example')
// 填充数据
worksheet.addRow([ 'Product', 'Price', 'Status' ])
worksheet.addRow([ 'Apple', 10, 'In Stock' ])
worksheet.addRow([ 'Banana', 5, 'Low Stock' ])
worksheet.addRow([ 'Orange', 8, 'Out of Stock' ])
// 设置字体加粗样式
// 方法1:设置整行加粗(表头)
worksheet.getRow(1).font = { bold: true }
// 方法2:设置特定单元格加粗
worksheet.getCell('A2').font = { bold: true } // Apple 产品名称加粗
worksheet.getCell('B3').font = { bold: true } // Banana 价格加粗
worksheet.getCell('C4').font = { bold: true } // Orange 状态加粗
// 方法3:设置整列加粗(价格列)
worksheet.getColumn(2).font = { bold: true }
// 生成 Excel 文件并下载
const buffer = await workbook.xlsx.writeBuffer()
const blob = new Blob([ buffer ], {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
})
saveAs(blob, 'bold_font_example.xlsx')
}
return (
<div>
<h2>ExcelJS 设置字体加粗示例</h2>
<button onClick={exportWithBoldFont}>导出带加粗字体的 Excel</button>
</div>
)
}
export default ExcelBoldFontExample
import React from 'react'
import ExcelJS from 'exceljs'
import { saveAs } from 'file-saver'
const ExcelAlignmentExample = () => {
const exportWithAlignment = async () => {
// 创建工作簿
const workbook = new ExcelJS.Workbook()
// 添加工作表
const worksheet = workbook.addWorksheet('Alignment Example')
// 填充数据
worksheet.addRow([ 'Product', 'Price', 'Stock' ])
worksheet.addRow([ 'Apple', 10, 100 ])
worksheet.addRow([ 'Banana', 5, 200 ])
worksheet.addRow([ 'Orange', 8, 150 ])
// 设置字体对齐方式
// 方法1:设置整行对齐(表头)
worksheet.getRow(1).alignment = {
horizontal: 'center', // 水平居中
vertical: 'middle', // 垂直居中
}
// 方法2:设置特定单元格对齐
worksheet.getCell('A2').alignment = { horizontal: 'left' } // Product 名称左对齐
worksheet.getCell('B2').alignment = { horizontal: 'right' } // Price 右对齐
worksheet.getCell('C2').alignment = { horizontal: 'center' } // Stock 居中对齐
// 方法3:设置整列对齐(价格列右对齐)
worksheet.getColumn(2).alignment = { horizontal: 'right' }
// 生成 Excel 文件并下载
const buffer = await workbook.xlsx.writeBuffer()
const blob = new Blob([ buffer ], {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
})
saveAs(blob, 'alignment_example.xlsx')
}
return (
<div>
<h2>ExcelJS 设置字体对齐方式示例</h2>
<button onClick={exportWithAlignment}>导出带对齐方式的 Excel</button>
</div>
)
}
export default ExcelAlignmentExample
比如 10000 在单元格中显示 10,000
比如 0.1 在单元格中显示 10%
import React from 'react'
import ExcelJS from 'exceljs'
import { saveAs } from 'file-saver'
const ExcelFormattingExample = () => {
const exportFormattedExcel = async () => {
// 创建工作簿
const workbook = new ExcelJS.Workbook()
// 添加工作表
const worksheet = workbook.addWorksheet('Formatted Numbers')
// 定义自定义数字格式
// 这里定义了几种常见的数字格式
const numberFormats = {
INTEGER: '0', // 整数,例如 10000 显示为 10000
COMMA_SEPARATED: '0,0', // 带千位分隔符,例如 10000 显示为 10,000
DECIMAL_TWO_PLACES: '0.00', // 两位小数,例如 10000.5 显示为 10000.50
CURRENCY: '$#,##0.00', // 货币格式,例如 10000 显示为 $10,000.00
PERCENTAGE: '0%', // 百分比,例如 0.1 显示为 10%
}
// 填充数据
worksheet.addRow([ 'Item', 'Quantity', 'Price', 'Discount' ])
worksheet.addRow([ 'Apples', 10000, 5.5, 0.1 ])
worksheet.addRow([ 'Bananas', 5000, 3.2, 0.05 ])
worksheet.addRow([ 'Oranges', 7500, 4.0, 0.15 ])
// 应用自定义数字格式
worksheet.getColumn(2).numFmt = numberFormats.COMMA_SEPARATED // Quantity 列,带千位分隔符
worksheet.getColumn(3).numFmt = numberFormats.CURRENCY // Price 列,货币格式
worksheet.getColumn(4).numFmt = numberFormats.PERCENTAGE // Discount 列,百分比
// 生成 Excel 文件并下载
const buffer = await workbook.xlsx.writeBuffer()
const blob = new Blob([ buffer ], {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
})
saveAs(blob, 'formatted_numbers.xlsx')
}
return (
<div>
<h2>ExcelJS 数字格式化示例</h2>
<button onClick={exportFormattedExcel}>导出带格式化的 Excel</button>
</div>
)
}
export default ExcelFormattingExample
import React from 'react'
import ExcelJS from 'exceljs'
import { saveAs } from 'file-saver'
const ExcelBackgroundColorExample = () => {
const exportWithBackgroundColor = async () => {
// 创建工作簿
const workbook = new ExcelJS.Workbook()
// 添加工作表
const worksheet = workbook.addWorksheet('Background Color Example')
// 填充数据
worksheet.addRow([ 'ID', '姓名', '年龄', '销售额', '状态' ])
worksheet.addRow([ 1, '张三', 28, 50000, '已完成' ])
worksheet.addRow([ 2, '李四', 34, 75000, '进行中' ])
worksheet.addRow([ 3, '王五', 45, 60000, '已完成' ])
worksheet.addRow([ 4, '赵六', 23, 40000, '未开始' ])
worksheet.addRow([ 5, '孙七', 30, 55000, '进行中' ])
// 设置单元格背景颜色
// 方法1:设置单个单元格背景颜色
worksheet.getCell('A1').fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'FF999999' }, // 灰色背景
}
// 方法2:设置整行背景颜色(例如,表头行)
worksheet.getRow(1).fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'FF4472C4' }, // 蓝色背景
}
// 方法3:设置整列背景颜色(例如,销售额列)
worksheet.getColumn(4).fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'FFE2FFE2' }, // 浅绿色背景
}
// 方法4:根据条件设置背景颜色
worksheet.eachRow({ includeEmpty: true }, (row, rowNumber) => {
if (rowNumber > 1) { // 跳过表头
const status = row.getCell('E').value
if (status === '已完成') {
row.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'FF00FF00' }, // 绿色背景
}
} else if (status === '进行中') {
row.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'FFFF9900' }, // 橙色背景
}
} else if (status === '未开始') {
row.fill = {
type: 'pattern',
pattern: 'solid',
fgColor: { argb: 'FFFF0000' }, // 红色背景
}
}
}
})
// 生成 Excel 文件并下载
const buffer = await workbook.xlsx.writeBuffer()
const blob = new Blob([ buffer ], {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
})
saveAs(blob, 'background_color_example.xlsx')
}
return (
<div>
<h2>ExcelJS 设置单元格背景颜色示例</h2>
<button onClick={exportWithBackgroundColor}>导出带背景颜色的 Excel</button>
</div>
)
}
export default ExcelBackgroundColorExample
import React from 'react'
import ExcelJS from 'exceljs'
import { saveAs } from 'file-saver'
const ExcelBordersExample = () => {
const exportWithBorders = async () => {
// 创建工作簿
const workbook = new ExcelJS.Workbook()
// 添加工作表
const worksheet = workbook.addWorksheet('Borders Example')
// 填充数据
worksheet.addRow([ 'ID', '姓名', '年龄', '销售额', '状态' ])
worksheet.addRow([ 1, '张三', 28, 50000, '已完成' ])
worksheet.addRow([ 2, '李四', 34, 75000, '进行中' ])
worksheet.addRow([ 3, '王五', 45, 60000, '已完成' ])
worksheet.addRow([ 4, '赵六', 23, 40000, '未开始' ])
worksheet.addRow([ 5, '孙七', 30, 55000, '进行中' ])
// 设置单元格边框
// 方法1:设置单个单元格边框
const cellA1 = worksheet.getCell('A1')
cellA1.border = {
top: { style: 'thin', color: { argb: 'FF000000' } },
left: { style: 'thin', color: { argb: 'FF000000' } },
bottom: { style: 'thin', color: { argb: 'FF000000' } },
right: { style: 'thin', color: { argb: 'FF000000' } },
}
// 方法2:设置整行边框
const headerRow = worksheet.getRow(1)
headerRow.border = {
top: { style: 'double', color: { argb: 'FF0000FF' } },
left: { style: 'thin', color: { argb: 'FF000000' } },
bottom: { style: 'double', color: { argb: 'FF0000FF' } },
right: { style: 'thin', color: { argb: 'FF000000' } },
}
// 方法3:设置整列边框
worksheet.getColumn(4).border = {
top: { style: 'dashed', color: { argb: 'FFFF0000' } },
left: { style: 'thin', color: { argb: 'FF000000' } },
bottom: { style: 'dashed', color: { argb: 'FFFF0000' } },
right: { style: 'thin', color: { argb: 'FF000000' } },
}
// 方法4:根据条件设置边框
worksheet.eachRow({ includeEmpty: true }, (row, rowNumber) => {
if (rowNumber > 1) { // 跳过表头
const status = row.getCell('E').value
if (status === '已完成') {
row.border = {
top: { style: 'medium', color: { argb: 'FF00FF00' } },
left: { style: 'thin', color: { argb: 'FF000000' } },
bottom: { style: 'medium', color: { argb: 'FF00FF00' } },
right: { style: 'thin', color: { argb: 'FF000000' } },
}
} else if (status === '进行中') {
row.border = {
top: { style: 'dotted', color: { argb: 'FFFFFF00' } },
left: { style: 'thin', color: { argb: 'FF000000' } },
bottom: { style: 'dotted', color: { argb: 'FFFFFF00' } },
right: { style: 'thin', color: { argb: 'FF000000' } },
}
} else if (status === '未开始') {
row.border = {
top: { style: 'hair', color: { argb: 'FFFF0000' } },
left: { style: 'thin', color: { argb: 'FF000000' } },
bottom: { style: 'hair', color: { argb: 'FFFF0000' } },
right: { style: 'thin', color: { argb: 'FF000000' } },
}
}
}
})
// 生成 Excel 文件并下载
const buffer = await workbook.xlsx.writeBuffer()
const blob = new Blob([ buffer ], {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
})
saveAs(blob, 'borders_example.xlsx')
}
return (
<div>
<h2>ExcelJS 设置单元格边框示例</h2>
<button onClick={exportWithBorders}>导出带边框的 Excel</button>
</div>
)
}
export default ExcelBordersExample
import React from 'react'
import ExcelJS from 'exceljs'
import { saveAs } from 'file-saver'
const ExcelDimensionsExample = () => {
const exportWithDimensions = async () => {
// 创建工作簿
const workbook = new ExcelJS.Workbook()
// 添加工作表
const worksheet = workbook.addWorksheet('Dimensions Example')
// 填充数据
worksheet.addRow([ 'ID', '姓名', '年龄', '销售额', '状态' ])
worksheet.addRow([ 1, '张三', 28, 50000, '已完成' ])
worksheet.addRow([ 2, '李四', 34, 75000, '进行中' ])
worksheet.addRow([ 3, '王五', 45, 60000, '已完成' ])
worksheet.addRow([ 4, '赵六', 23, 40000, '未开始' ])
worksheet.addRow([ 5, '孙七', 30, 55000, '进行中' ])
// 设置列宽
worksheet.columns = [
{ key: 'id', header: 'ID', width: 8 },
{ key: 'name', header: '姓名', width: 12 },
{ key: 'age', header: '年龄', width: 10 },
{ key: 'sales', header: '销售额', width: 15 },
{ key: 'status', header: '状态', width: 15 },
]
// 设置行高
worksheet.getRow(1).height = 30 // 设置表头行高为 30
worksheet.getRow(2).height = 25 // 设置第二行行高为 25
worksheet.getRow(3).height = 25
worksheet.getRow(4).height = 25
worksheet.getRow(5).height = 25
// 生成 Excel 文件并下载
const buffer = await workbook.xlsx.writeBuffer()
const blob = new Blob([ buffer ], {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
})
saveAs(blob, 'dimensions_example.xlsx')
}
return (
<div>
<h2>ExcelJS 设置单元格宽度和高度示例</h2>
<button onClick={exportWithDimensions}>导出带尺寸的 Excel</button>
</div>
)
}
export default ExcelDimensionsExample
import React from 'react'
import ExcelJS from 'exceljs'
import { saveAs } from 'file-saver'
const ExcelImageExample = () => {
const exportWithImage = async () => {
// 创建工作簿
const workbook = new ExcelJS.Workbook()
// 添加工作表
const worksheet = workbook.addWorksheet('Image Example')
// 填充数据(可选)
worksheet.addRow([ '产品', '描述' ])
worksheet.addRow([ '苹果', '新鲜的红色苹果' ])
worksheet.addRow([ '香蕉', '黄色的香蕉' ])
worksheet.addRow([ '橙子', '多汁的橙子' ])
// 定义图片 URL
const imageUrl = 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSGqDZK9waX9I8CnvoI0GhVUF6Q3i6Z0v7Rmg&s'
try {
// 获取图片数据(Buffer)
const response = await fetch(imageUrl)
if (!response.ok) {
throw new Error(`无法加载图片: ${response.statusText}`)
}
const imageBuffer = await response.arrayBuffer()
// 添加图片到工作簿
const imageId = workbook.addImage({
buffer: imageBuffer,
extension: 'jpeg', // 根据实际图片类型调整(如 png, jpg 等)
})
// 插入图片到指定单元格(例如 A5)
// 参数:图片ID, 插入位置('A5'),宽度, 高度
worksheet.addImage(imageId, {
tl: { col: 0, row: 4 }, // A5 单元格(列从0开始计数)
ext: { width: 200, height: 200 }, // 图片尺寸(像素)
})
} catch (error) {
console.error('插入图片失败:', error)
alert('无法插入图片,请检查图片 URL 是否有效。')
return
}
// 生成 Excel 文件并下载
const buffer = await workbook.xlsx.writeBuffer()
const blob = new Blob([ buffer ], {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
})
saveAs(blob, 'image_example.xlsx')
}
return (
<div>
<h2>将图片插入到 Excel 示例</h2>
<button onClick={exportWithImage}>导出带图片的 Excel</button>
</div>
)
}
export default ExcelImageExample
↶ 返回首页 ↶