如何使用NPOI c#将xls文件保存为xlsx文件?

我正在使用NPOI打开XLS文件,然后对XLS文件添加一些修改。 最后我想将其保存为XLSX文件。

我正在使用此代码将其保存为XLS文件:

using (var fs = new FileStream(Name, FileMode.Create, FileAccess.Write)) { wb.Write(fs); } 

是否可以在C#中使用NPOI将此XLS文件保存为XLSX文件

在此先感谢您的回复

这通常是可能的,但不是很容易,而是非常复杂的任务。

XLS文件格式由HSSFWorkbook类(并根据HSSFSheet等)处理。
XLSX文件格式由XSSFWorkbook类(和XSSFSheet等)处理。

因此,为了在使用NPOI打开并修改文件后将文件保存为XLSX,您需要创建新的XSSFWorkbook ,然后对于源文件的每个工作表,您需要创建适当的XSSFSheet ,从原始工作表中复制数据等等。直到您将获得数据的完整副本,然后将工作簿保存到文件。

这是一个老问题,但我遇到过类似的问题。 此代码使用来自https://npoi.codeplex.com/releases的 NPOI 2.2.1。 此代码基于使用c#问题中的NPOI将转换xlsx文件转换为xls的代码,但它转换xls-> xlsx,而不是xlsx-> xls。 此外,它还可以转换样式并修复范围错误。 此代码适用于没有图表和其他复杂内容的简单工作簿。

 using NPOI.XSSF.UserModel; using NPOI.SS.UserModel; using NPOI.SS.Util; using NPOI.HSSF.UserModel; using System.Collections.Generic; using System.Linq; using System.IO; namespace XlsToXlsxConverter { public static class XLSToXLSXConverter { public static byte[] Convert(Stream sourceStream) { var source = new HSSFWorkbook(sourceStream); var destination = new XSSFWorkbook(); for (int i = 0; i < source.NumberOfSheets; i++) { var xssfSheet = (XSSFSheet)destination.CreateSheet(source.GetSheetAt(i).SheetName); var hssfSheet = (HSSFSheet)source.GetSheetAt(i); CopyStyles(hssfSheet, xssfSheet); CopySheets(hssfSheet, xssfSheet); } using (var ms = new MemoryStream()) { destination.Write(ms); return ms.ToArray(); } } private static void CopyStyles(HSSFSheet from, XSSFSheet to) { for (short i = 0; i <= from.Workbook.NumberOfFonts; i++) { CopyFont(to.Workbook.CreateFont(), from.Workbook.GetFontAt(i)); } for (short i = 0; i < from.Workbook.NumCellStyles; i++) { CopyStyle(to.Workbook.CreateCellStyle(), from.Workbook.GetCellStyleAt(i), to.Workbook, from.Workbook); } } private static void CopyFont(IFont toFront, IFont fontFrom) { toFront.Boldweight = fontFrom.Boldweight; toFront.Charset = fontFrom.Charset; toFront.Color = fontFrom.Color; toFront.FontHeightInPoints = fontFrom.FontHeightInPoints; toFront.FontName = fontFrom.FontName; toFront.IsBold = fontFrom.IsBold; toFront.IsItalic = fontFrom.IsItalic; toFront.IsStrikeout = fontFrom.IsStrikeout; //toFront.Underline = fontFrom.Underline; <- bug in npoi setter } private static void CopyStyle(ICellStyle toCellStyle, ICellStyle fromCellStyle, IWorkbook toWorkbook, IWorkbook fromWorkbook) { toCellStyle.Alignment = fromCellStyle.Alignment; toCellStyle.BorderBottom = fromCellStyle.BorderBottom; toCellStyle.BorderDiagonal = fromCellStyle.BorderDiagonal; toCellStyle.BorderDiagonalColor = fromCellStyle.BorderDiagonalColor; toCellStyle.BorderDiagonalLineStyle = fromCellStyle.BorderDiagonalLineStyle; toCellStyle.BorderLeft = fromCellStyle.BorderLeft; toCellStyle.BorderRight = fromCellStyle.BorderRight; toCellStyle.BorderTop = fromCellStyle.BorderTop; toCellStyle.BottomBorderColor = fromCellStyle.BottomBorderColor; toCellStyle.DataFormat = fromCellStyle.DataFormat; toCellStyle.FillBackgroundColor = fromCellStyle.FillBackgroundColor; toCellStyle.FillForegroundColor = fromCellStyle.FillForegroundColor; toCellStyle.FillPattern = fromCellStyle.FillPattern; toCellStyle.Indention = fromCellStyle.Indention; toCellStyle.IsHidden = fromCellStyle.IsHidden; toCellStyle.IsLocked = fromCellStyle.IsLocked; toCellStyle.LeftBorderColor = fromCellStyle.LeftBorderColor; toCellStyle.RightBorderColor = fromCellStyle.RightBorderColor; toCellStyle.Rotation = fromCellStyle.Rotation; toCellStyle.ShrinkToFit = fromCellStyle.ShrinkToFit; toCellStyle.TopBorderColor = fromCellStyle.TopBorderColor; toCellStyle.VerticalAlignment = fromCellStyle.VerticalAlignment; toCellStyle.WrapText = fromCellStyle.WrapText; toCellStyle.SetFont(toWorkbook.GetFontAt((short)(fromCellStyle.GetFont(fromWorkbook).Index + 1 ))); } private static void CopySheets(HSSFSheet source, XSSFSheet destination) { var maxColumnNum = 0; var mergedRegions = new List(); var styleMap = new Dictionary(); for (int i = source.FirstRowNum; i <= source.LastRowNum; i++) { var srcRow = (HSSFRow)source.GetRow(i); var destRow = (XSSFRow)destination.CreateRow(i); if (srcRow != null) { CopyRow(source, destination, srcRow, destRow, mergedRegions); if (srcRow.LastCellNum > maxColumnNum) { maxColumnNum = srcRow.LastCellNum; } } } for (int i = 0; i <= maxColumnNum; i++) { destination.SetColumnWidth(i, source.GetColumnWidth(i)); } } private static void CopyRow(HSSFSheet srcSheet, XSSFSheet destSheet, HSSFRow srcRow, XSSFRow destRow, List mergedRegions) { destRow.Height = srcRow.Height; for (int j = srcRow.FirstCellNum; srcRow.LastCellNum >= 0 && j <= srcRow.LastCellNum; j++) { var oldCell = (HSSFCell)srcRow.GetCell(j); var newCell = (XSSFCell)destRow.GetCell(j); if (oldCell != null) { if (newCell == null) { newCell = (XSSFCell)destRow.CreateCell(j); } CopyCell(oldCell, newCell); var mergedRegion = GetMergedRegion(srcSheet, srcRow.RowNum, (short)oldCell.ColumnIndex); if (mergedRegion != null) { var newMergedRegion = new CellRangeAddress(mergedRegion.FirstRow, mergedRegion.LastRow, mergedRegion.FirstColumn, mergedRegion.LastColumn); if (IsNewMergedRegion(newMergedRegion, mergedRegions)) { mergedRegions.Add(newMergedRegion); destSheet.AddMergedRegion(newMergedRegion); } } } } } private static void CopyCell(HSSFCell oldCell, XSSFCell newCell) { CopyCellStyle(oldCell, newCell); CopyCellValue(oldCell, newCell); } private static void CopyCellValue(HSSFCell oldCell, XSSFCell newCell) { switch (oldCell.CellType) { case CellType.String: newCell.SetCellValue(oldCell.StringCellValue); break; case CellType.Numeric: newCell.SetCellValue(oldCell.NumericCellValue); break; case CellType.Blank: newCell.SetCellType(CellType.Blank); break; case CellType.Boolean: newCell.SetCellValue(oldCell.BooleanCellValue); break; case CellType.Error: newCell.SetCellErrorValue(oldCell.ErrorCellValue); break; case CellType.Formula: newCell.SetCellFormula(oldCell.CellFormula); break; default: break; } } private static void CopyCellStyle(HSSFCell oldCell, XSSFCell newCell) { if (oldCell.CellStyle == null) return; newCell.CellStyle = newCell.Sheet.Workbook.GetCellStyleAt((short)(oldCell.CellStyle.Index + 1)); } private static CellRangeAddress GetMergedRegion(HSSFSheet sheet, int rowNum, short cellNum) { for (var i = 0; i < sheet.NumMergedRegions; i++) { var merged = sheet.GetMergedRegion(i); if (merged.IsInRange(rowNum, cellNum)) { return merged; } } return null; } private static bool IsNewMergedRegion(CellRangeAddress newMergedRegion, List mergedRegions) { return !mergedRegions.Any(r => r.FirstColumn == newMergedRegion.FirstColumn && r.LastColumn == newMergedRegion.LastColumn && r.FirstRow == newMergedRegion.FirstRow && r.LastRow == newMergedRegion.LastRow); } } }