前言
以前写过 EPPlus 的笔记, 但后来 EPPlus 开始收费了.... (这好像是 .NET 生态的宿命)
在找替代方案中看中了微软的 Open XML SDK.
但经过一番折腾, 它确实太底层了, 学习资源又少. 于是找到了它的上层版本 ClosedXML
ClosedXML 是社区因为 Open XML 真的太底层了, 而 wrap 的上层. 它满足了绝大部分需求.
虽然它没有一直保持更新, 但已经足够小项目使用了. 非到万不得已还是不要去碰 Open XML SDK 比较好. 年纪大了少折腾自己.
以前写的笔记
ClosedXML
它的结构很简单 Book > Sheets > Sheet > Row/Column > Cell
创建 Book
var book = new XLWorkbook();
打开 Book
using var book = new XLWorkbook(@"ExcelExcel.xlsx");
创建 Sheet
var sheet = book.Worksheets.Add("Sheet1");
获取 Cell
var cell1 = sheet.Row(1).Cell(1); var cell2 = sheet.Cell("A1");
Row(1) 是拿第一行, 没有第 0 行的哦. start from 1, column 也是一样
定义值和类型
cell.DataType = XLDataType.Text; cell.Value = "value";
类型有 5 种
Set custom format
我的做法通常是去 excel set 然后查看 custom, 复制过来, 比如下面这个是 Accounting 的
cell.Style.NumberFormat.Format = "_ [$USD] * #,##0.00_ ;_ [$USD] * -#,##0.00_ ;_ [$USD] * "-"??_ ;_ @_ ";
Set hyperlink
cell.Hyperlink = new XLHyperlink(@"https://www.stooges.com.my");
Set alignment
cell.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Right;
cell.Style.Alignment.Vertical = XLAlignmentVerticalValues.Top;
Set Color
cell.Style.Font.FontColor = XLColor.Blue;
cell.Style.Fill.BackgroundColor = XLColor.FromHtml("#FF0000");
Set wrap text
cell.Style.Alignment.SetWrapText(true);
Set date format
cell.Style.DateFormat.Format = "dd-MM-yyyy"; cell.Style.DateFormat.Format = "dd-MM-yyyy hh:mm:ss AM/PM";
Set column width
sheet.Column(1).Width = 10;
10 的单位是字数 (number of characters)
Set column width / row height base on content
sheet.Column(1).AdjustToContents(10d, 20d); sheet.Row(2).AdjustToContents(0d, 20d);
参数是 min, max (是 double 哦)
保存
book.SaveAs(@"ExcelExcel.xlsx"); book.Save();
通常新建配 SaveAs, 修改配 Save
一开始折腾后来放弃的 Open XML SDK
参考:
Cell styles in OpenXML spreadsheet (SpreadsheetML)
Open XML 的结构非常绕. 很多层. 我对 Excel 的理解就是 file > sheets > sheet = table, row, column, cell
但是 Open XML 的结构是
Document 是 file
Part 是 container
SheetData 就 table
其余的我不清楚...为什么要搞这么多东东出来
Create Excel File
add nuget package
dotnet add package DocumentFormat.OpenXml
ExcelController.cs
[HttpPost("CreateExcel")] public ActionResult CreateExcel([FromBody] CreateExcelDto dto) { // create doc using var doc = SpreadsheetDocument.Create(@"ExcelExcel.xlsx", SpreadsheetDocumentType.Workbook); // create workbook part var workbookpart = doc.AddWorkbookPart(); // create workbook workbookpart.Workbook = new Workbook(); // create worksheet part var worksheetPart = workbookpart.AddNewPart<WorksheetPart>(); // create sheet data var sheetData = new SheetData(); // create header var headerRow = new Row(); var headerCell = new Cell { DataType = new EnumValue<CellValues>(CellValues.String), CellValue = new CellValue("FirstName") }; headerRow.Append(headerCell); sheetData.Append(headerRow); // create row var firstRow = new Row(); var firstRowCell = new Cell { DataType = new EnumValue<CellValues>(CellValues.String), CellValue = new CellValue("Derrick Yam") }; firstRow.Append(firstRowCell); sheetData.Append(firstRow); // create worksheet worksheetPart.Worksheet = new Worksheet(sheetData); // create sheets var sheets = workbookpart.Workbook.AppendChild<Sheets>(new Sheets()); // create sheet var sheet = new Sheet() { Id = workbookpart.GetIdOfPart(worksheetPart), // connect sheet to worksheet part SheetId = 1, Name = "Sheet1" }; sheets.Append(sheet); workbookpart.Workbook.Save(); return Ok(); }
需要注意的是它的结构很多层, 不要搞错. 顺序做就对了.