.Net平台开源可编辑Excel库ClosedXML,可代替Aspose.Cells

1. 库的引用

右键项目,点击管理NuGet程序包在浏览选项卡中输入ClosedXML,点击右侧箭头进行安装。
在这里插入图片描述
在这里插入图片描述

2. API的使用

2.1 创建工作簿

1
2
3
4
//新建工作簿
XLWorkbook workbook = new XLWorkbook();
//打开现有工作簿
XLWorkbook workbook2 = new XLWorkbook("C:\\Users\\Administrator\\Desktop\\ClosedXML_API_Test\\sampleWorkbook.xlsx");

2.2 创建工作表

1
2
//创建工作表
IXLWorksheet worksheet = workbook.AddWorksheet("Sample Sheet");

2.3 字体设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
IXLCell a1 = worksheet.Cell("A1");
a1.Value = "字体设置";
//1、更换字体
a1.Style.Font.FontName="宋体";
//2、调整字号
a1.Style.Font.FontSize=20;
//3、加粗
a1.Style.Font.Bold = true;
//4、斜体
a1.Style.Font.Italic = true;
//5、下划线
a1.Style.Font.Underline = XLFontUnderlineValues.Single;
//6、字体颜色
a1.Style.Font.FontColor = XLColor.Blue;

2.4 单元格设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//单元格设置
IXLCell a2 = worksheet.Cell("A2");
a2.Value = "单元格设置长长长长长长长";
//1、边框
a2.Style.Border.TopBorder = XLBorderStyleValues.Thin;
a2.Style.Border.BottomBorder = XLBorderStyleValues.Thin;
a2.Style.Border.LeftBorder = XLBorderStyleValues.Thin;
a2.Style.Border.RightBorder = XLBorderStyleValues.Thin;
//2、填充颜色
a2.Style.Fill.BackgroundColor = XLColor.Red;
//3、竖直对齐方式
a2.Style.Alignment.Vertical = XLAlignmentVerticalValues.Bottom;
//4、水平对其方式
a2.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Right;
//5、自动换行
a2.Style.Alignment.WrapText = true;
//6、单元格格式
IXLCell a3 = worksheet.Cell("A3");
a3.Value = 0.003125;
a3.Style.NumberFormat.NumberFormatId = (int)XLPredefinedFormat.Number.PercentPrecision2;

2.5 行高

1
2
3
4
//行高
IXLCell a4 = worksheet.Cell("A4");
a4.Value = "行高90";
worksheet.Row(4).Height = 90;

2.6 列宽

1
2
3
4
//列宽
IXLCell b1 = worksheet.Cell("B1");
b1.Value = "列宽60";
worksheet.Column(2).Width = 60;

2.7 合并单元格

1
2
3
4
5
//合并单元格
IXLCell c1 = worksheet.Cell("C1");
IXLCell d1 = worksheet.Cell("D1");
c1.Value = "合并单元格";
worksheet.Range(c1, d1).Merge();

2.8 插入公式

1
2
//插入公式
worksheet.Cell("C2").FormulaA1 = "MID(C1, 2, 1)";

2.9 查找

1
2
3
//查找
string id = worksheet.Search("列宽").First().Address.ToString(XLReferenceStyle.A1);
worksheet.Cell("B4").Value = $"查找列宽的位置为:{id}";

2.10 富文本

1
2
3
4
5
//富文本
IXLCell c4 = worksheet.Cell("C4");
IXLRichText c4RichText = c4.CreateRichText();
c4RichText.AddText("富").SetBold(true).SetFontSize(30);
c4RichText.AddText("文本").SetFontColor(XLColor.Red);

2.11 保存工作簿

1
2
3
4
5
//保存工作簿
//1、保存
workbook.Save();
//2、另存为
workbook.SaveAs("C:\\Users\\Administrator\\Desktop\\ClosedXML_API_Test\\HelloWorld.xlsx");

3. 完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
using ClosedXML.Excel;
using System.Linq;

namespace ClosedXML_API_Test
{
internal class Program
{
static void Main(string[] args)
{
//创建工作簿
//新建工作簿
XLWorkbook workbook = new XLWorkbook();
//打开现有工作簿
//XLWorkbook workbook2 = new XLWorkbook("C:\\Users\\Administrator\\Desktop\\ClosedXML_API_Test\\sampleWorkbook.xlsx");
//创建工作表
IXLWorksheet worksheet = workbook.AddWorksheet("Sample Sheet");

IXLCell a1 = worksheet.Cell("A1");
a1.Value = "字体设置";
//1、更换字体
a1.Style.Font.FontName = "宋体";
//2、调整字号
a1.Style.Font.FontSize = 20;
//3、加粗
a1.Style.Font.Bold = true;
//4、斜体
a1.Style.Font.Italic = true;
//5、下划线
a1.Style.Font.Underline = XLFontUnderlineValues.Single;
//6、字体颜色
a1.Style.Font.FontColor = XLColor.Blue;

//单元格设置
IXLCell a2 = worksheet.Cell("A2");
a2.Value = "单元格设置长长长长长长长";
//1、边框
a2.Style.Border.TopBorder = XLBorderStyleValues.Thin;
a2.Style.Border.BottomBorder = XLBorderStyleValues.Thin;
a2.Style.Border.LeftBorder = XLBorderStyleValues.Thin;
a2.Style.Border.RightBorder = XLBorderStyleValues.Thin;
//2、填充颜色
a2.Style.Fill.BackgroundColor = XLColor.Red;
//3、竖直对齐方式
a2.Style.Alignment.Vertical = XLAlignmentVerticalValues.Bottom;
//4、水平对其方式
a2.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Right;
//5、自动换行
a2.Style.Alignment.WrapText = true;
//6、单元格格式
IXLCell a3 = worksheet.Cell("A3");
a3.Value = 0.003125;
a3.Style.NumberFormat.NumberFormatId = (int)XLPredefinedFormat.Number.PercentPrecision2;

//行高
IXLCell a4 = worksheet.Cell("A4");
a4.Value = "行高90";
worksheet.Row(4).Height = 90;

//列宽
IXLCell b1 = worksheet.Cell("B1");
b1.Value = "列宽60";
worksheet.Column(2).Width = 60;

//合并单元格
IXLCell c1 = worksheet.Cell("C1");
IXLCell d1 = worksheet.Cell("D1");
c1.Value = "合并单元格";
worksheet.Range(c1, d1).Merge();

//插入公式
worksheet.Cell("C2").FormulaA1 = "MID(C1, 2, 1)";

//查找
string id = worksheet.Search("列宽").First().Address.ToString(XLReferenceStyle.A1);
worksheet.Cell("B4").Value = $"查找列宽的位置为:{id}";

//富文本
IXLCell c4 = worksheet.Cell("C4");
IXLRichText c4RichText = c4.CreateRichText();
c4RichText.AddText("富").SetBold(true).SetFontSize(30);
c4RichText.AddText("文本").SetFontColor(XLColor.Red);

//保存工作簿
////1、保存
//workbook.Save();
//2、另存为
workbook.SaveAs("C:\\Users\\Administrator\\Desktop\\ClosedXML_API_Test\\HelloWorld.xlsx");
}
}
}

4. 效果展示

在这里插入图片描述

5. 解决无法读取xls格式文件问题

5.1 使用Aspose.Cells免费版库进行格式转换

NuGet包管理器中搜索并安装Aspose.Cells库
在这里插入图片描述
安装完成后,执行以下代码进行格式转换:

1
2
3
Workbook workbook = new Workbook("C:\\Users\\Administrator\\Desktop\\ClosedXML_API_Test\\convertFormat.xls");
workbook.Save("C:\\Users\\Administrator\\Desktop\\ClosedXML_API_Test\\convertFormatAspose.xlsx",SaveFormat.Xlsx);
workbook.Dispose();

转换后效果如下:
在这里插入图片描述
存在问题:免费版会多一个水印,不过不影响使用
在这里插入图片描述

5.2 使用NPOI库进行内容复制

NuGet包管理器中搜索并安装NPOI库
在这里插入图片描述
安装完成后,执行以下代码进行内容复制:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// 读取xls格式文件
FileStream fs = new FileStream("C:\\Users\\Administrator\\Desktop\\ClosedXML_API_Test\\convertFormat.xls", FileMode.Open, FileAccess.Read);
HSSFWorkbook workbook = new HSSFWorkbook(fs);

// 创建xlsx格式文件
XSSFWorkbook newWorkbook = new XSSFWorkbook();

// 遍历所有sheet
for (int i = 0; i < workbook.NumberOfSheets; i++)
{
ISheet sheet = workbook.GetSheetAt(i);
ISheet newSheet = newWorkbook.CreateSheet(sheet.SheetName);

//复制合并单元格
for (int k = 0; k < sheet.NumMergedRegions; k++)
{
CellRangeAddress cellRangeAddress = sheet.GetMergedRegion(k);
if (sheet.IsMergedRegion(cellRangeAddress))
{
newSheet.AddMergedRegion(cellRangeAddress);
}
}


// 遍历所有row
for (int j = 0; j <= sheet.LastRowNum; j++)
{
IRow row = sheet.GetRow(j);
IRow newRow = newSheet.CreateRow(j);
//复制行高
newRow.Height = row.Height;

// 遍历所有cell
if (row != null)
{
for (int k = row.FirstCellNum; k < row.LastCellNum; k++)
{
ICell cell = row.GetCell(k);
ICell newCell = newRow.CreateCell(k);

// 复制cell的值和类型
if (cell != null)
{
//设置列宽
newCell.Sheet.SetColumnWidth(cell.ColumnIndex, cell.Sheet.GetColumnWidth(cell.ColumnIndex));

//逐个复制样式
ICellStyle style = newWorkbook.CreateCellStyle();
style.Alignment = cell.CellStyle.Alignment;
style.BorderBottom = cell.CellStyle.BorderBottom;
style.BorderDiagonal = cell.CellStyle.BorderDiagonal;
style.BorderDiagonalColor = cell.CellStyle.BorderDiagonalColor;
style.BorderDiagonalLineStyle = cell.CellStyle.BorderDiagonalLineStyle;
style.BorderLeft = cell.CellStyle.BorderLeft;
style.BorderRight = cell.CellStyle.BorderRight;
style.BorderTop = cell.CellStyle.BorderTop;
style.BottomBorderColor = cell.CellStyle.BottomBorderColor;
style.DataFormat = cell.CellStyle.DataFormat;
style.FillBackgroundColor = cell.CellStyle.FillBackgroundColor;
style.FillForegroundColor = cell.CellStyle.FillForegroundColor;
style.FillPattern = cell.CellStyle.FillPattern;
style.Indention = cell.CellStyle.Indention;
style.IsHidden = cell.CellStyle.IsHidden;
style.IsLocked = cell.CellStyle.IsLocked;
style.LeftBorderColor = cell.CellStyle.LeftBorderColor;
style.RightBorderColor = cell.CellStyle.RightBorderColor;
style.Rotation = cell.CellStyle.Rotation;
style.ShrinkToFit = cell.CellStyle.ShrinkToFit;
style.TopBorderColor = cell.CellStyle.TopBorderColor;
style.VerticalAlignment = cell.CellStyle.VerticalAlignment;
style.WrapText = cell.CellStyle.WrapText;

//复制字体
var cellFont = cell.CellStyle.GetFont(workbook);
IFont font = newWorkbook.CreateFont();
font.Color = cellFont.Color;
font.FontHeight = cellFont.FontHeight;
font.FontHeightInPoints = cellFont.FontHeightInPoints;
font.FontName = cellFont.FontName;
font.IsBold = cellFont.IsBold;
font.IsItalic = cellFont.IsItalic;
font.IsStrikeout = cellFont.IsStrikeout;
font.TypeOffset = cellFont.TypeOffset;
font.Underline = cellFont.Underline;
style.SetFont(font);

newCell.CellStyle = style;

newCell.SetCellType(cell.CellType);
switch (cell.CellType)
{
case CellType.Blank:
newCell.SetCellValue(cell.StringCellValue);
break;
case CellType.Boolean:
newCell.SetCellValue(cell.BooleanCellValue);
break;
case CellType.Error:
newCell.SetCellValue(cell.ErrorCellValue);
break;
case CellType.Formula:
newCell.SetCellFormula(cell.CellFormula);
break;
case CellType.Numeric:
newCell.SetCellValue(cell.NumericCellValue);
break;
case CellType.String:
newCell.SetCellValue(cell.StringCellValue);
break;
case CellType.Unknown:
newCell.SetCellValue(cell.StringCellValue);
break;
}
}
}
}
}
}

// 写入xlsx格式文件
FileStream newFs = new FileStream("C:\\Users\\Administrator\\Desktop\\ClosedXML_API_Test\\convertFormatNPOI.xlsx", FileMode.Create, FileAccess.Write);
newWorkbook.Write(newFs);

// 关闭文件流
newFs.Close();
fs.Close();

复制效果如下:
在这里插入图片描述
存在问题
1、对于以下这种提示损坏的xls文件,NPOI和Sylvan.Data.Excel均无法打开,但Aspose.Cells可打开。
在这里插入图片描述
2、NPOI将xls转换为xlsx的方式并非进行格式转换,而是进行内容1:1复制,但富文本无法进行复制

5.3 使用Sylvan.Data.Excel库进行格式转换

NuGet包管理器中搜索并安装Sylvan.Data.Excel库
在这里插入图片描述
执行以下代码进行格式转换:

1
2
3
4
5
6
7
8
9
ExcelDataReader edr = ExcelDataReader.Create("C:\\Users\\Administrator\\Desktop\\ClosedXML_API_Test\\convertFormat.xls");
// 创建一个ExcelDataWriter对象,写入xlsx文件
ExcelDataWriter edw = ExcelDataWriter.Create("C:\\Users\\Administrator\\Desktop\\ClosedXML_API_Test\\convertFormatSylvan.xlsx");
// 将ExcelDataReader对象中的数据写入到ExcelDataWriter对象中
edw.Write(edr);
// 关闭ExcelDataReader对象
edr.Close();
// 关闭ExcelDataWriter对象
edw.Dispose();

转换效果如下:
在这里插入图片描述
存在问题:转换后无法保留单元格格式,仅可用于内容查询。