在 C# 中使用 NPOI 将 xlsx 文件转换为 xls
Convert xlsx file to xls using NPOI in c#
我有一个 *.xlsx 格式的 excel 文件。我想在我的 MVC Web 应用程序中将此文件转换为 *.xls 格式。在我的应用程序托管服务器中没有 Microsoft.Office 包。请让我知道我们如何使用 C# 在 NPOI 中实现它。
提前致谢。
这是我的建议:
使用此库读取 excel 格式 2007 的文件 https://excelpackage.codeplex.com/
使用此库将文件保存为 2003 格式 https://code.google.com/p/excellibrary/
总的来说是可以的,但不是很容易。
XLS
文件格式由 HSSFWorkbook
class 处理(并根据 HSSFSheet
等)。
XLSX
文件格式由 XSSFWorkbook
class(以及 XSSFSheet
等)处理。
因此,为了将您的文件从 XLSX
转换为 XLS
,您需要:
- 创建
XSSFWorkbook
,从文件加载数据;
- 新建
HSSFWorkbook
;
- 为原始文件中的每个工作表创建
HSSFSheet
并将原始工作表中的所有数据复制到这个新工作表中
- 将您的
HSSFWorkbook
写入文件。
所以这里有很多工作要做,这是一项非常复杂的任务。
对于您的情况,NPOI 可能不是最佳解决方案。
我根据安迪的建议找到了解决方案。这是定制的将XLSX转换为XLS的源代码。
public static class ConvertXLSXToXLS
{
public static HSSFWorkbook ConvertWorkbookXSSFToHSSF(XSSFWorkbook source)
{
//Install-Package NPOI -Version 2.0.6
HSSFWorkbook retVal = new HSSFWorkbook();
for (int i = 0; i < source.NumberOfSheets; i++)
{
HSSFSheet hssfSheet = (HSSFSheet)retVal.CreateSheet(source.GetSheetAt(i).SheetName);
XSSFSheet xssfsheet = (XSSFSheet)source.GetSheetAt(i);
CopySheets(xssfsheet, hssfSheet, retVal);
}
return retVal;
}
private static void CopySheets(XSSFSheet source, HSSFSheet destination, HSSFWorkbook retVal)
{
int maxColumnNum = 0;
Dictionary<int, XSSFCellStyle> styleMap = new Dictionary<int, XSSFCellStyle>();
for (int i = source.FirstRowNum; i <= source.LastRowNum; i++)
{
XSSFRow srcRow = (XSSFRow)source.GetRow(i);
HSSFRow destRow = (HSSFRow)destination.CreateRow(i);
if (srcRow != null)
{
CopyRow(source, destination, srcRow, destRow, styleMap, retVal);
if (srcRow.LastCellNum > maxColumnNum)
{
maxColumnNum = srcRow.LastCellNum;
}
}
}
for (int i = 0; i <= maxColumnNum; i++)
{
destination.SetColumnWidth(i, source.GetColumnWidth(i));
}
}
private static void CopyRow(XSSFSheet srcSheet, HSSFSheet destSheet, XSSFRow srcRow, HSSFRow destRow,
Dictionary<int, XSSFCellStyle> styleMap, HSSFWorkbook retVal)
{
// manage a list of merged zone in order to not insert two times a
// merged zone
List<CellRangeAddress> mergedRegions = new List<CellRangeAddress>();
destRow.Height = srcRow.Height;
// pour chaque row
for (int j = srcRow.FirstCellNum; j <= srcRow.LastCellNum; j++)
{
XSSFCell oldCell = (XSSFCell)srcRow.GetCell(j); // ancienne cell
HSSFCell newCell = (HSSFCell)destRow.GetCell(j); // new cell
if (oldCell != null)
{
if (newCell == null)
{
newCell = (HSSFCell)destRow.CreateCell(j);
}
// copy chaque cell
CopyCell(oldCell, newCell, styleMap, retVal);
// copy les informations de fusion entre les cellules
CellRangeAddress mergedRegion = GetMergedRegion(srcSheet, srcRow.RowNum,
(short)oldCell.ColumnIndex);
if (mergedRegion != null)
{
CellRangeAddress newMergedRegion = new CellRangeAddress(mergedRegion.FirstRow,
mergedRegion.LastRow, mergedRegion.FirstColumn, mergedRegion.LastColumn);
if (IsNewMergedRegion(newMergedRegion, mergedRegions))
{
mergedRegions.Add(newMergedRegion);
destSheet.AddMergedRegion(newMergedRegion);
}
if (newMergedRegion.FirstColumn == 0 && newMergedRegion.LastColumn == 6 && newMergedRegion.FirstRow == newMergedRegion.LastRow)
{
HSSFCellStyle style2 = (HSSFCellStyle)retVal.CreateCellStyle();
style2.VerticalAlignment = VerticalAlignment.Center;
style2.Alignment = HorizontalAlignment.Left;
style2.FillForegroundColor = HSSFColor.Teal.Index;
style2.FillPattern = FillPattern.SolidForeground;
for (int i = destRow.FirstCellNum; i <= destRow.LastCellNum; i++)
{
if (destRow.GetCell(i) != null)
destRow.GetCell(i).CellStyle = style2;
}
}
}
}
}
}
private static void CopyCell(XSSFCell oldCell, HSSFCell newCell, Dictionary<int, XSSFCellStyle> styleMap, HSSFWorkbook retVal)
{
if (styleMap != null)
{
int stHashCode = oldCell.CellStyle.Index;
XSSFCellStyle sourceCellStyle = null;
if (styleMap.TryGetValue(stHashCode, out sourceCellStyle)) { }
HSSFCellStyle destnCellStyle = (HSSFCellStyle)newCell.CellStyle;
if (sourceCellStyle == null)
{
sourceCellStyle = (XSSFCellStyle)oldCell.Sheet.Workbook.CreateCellStyle();
}
// destnCellStyle.CloneStyleFrom(oldCell.CellStyle);
if (!styleMap.Any(p => p.Key == stHashCode))
{
styleMap.Add(stHashCode, sourceCellStyle);
}
destnCellStyle.VerticalAlignment = VerticalAlignment.Top;
newCell.CellStyle = (HSSFCellStyle)destnCellStyle;
}
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 CellRangeAddress GetMergedRegion(XSSFSheet sheet, int rowNum, short cellNum)
{
for (int i = 0; i < sheet.NumMergedRegions; i++)
{
CellRangeAddress merged = sheet.GetMergedRegion(i);
if (merged.IsInRange(rowNum, cellNum))
{
return merged;
}
}
return null;
}
private static bool IsNewMergedRegion(CellRangeAddress newMergedRegion,
List<CellRangeAddress> mergedRegions)
{
return !mergedRegions.Contains(newMergedRegion);
}
}
我有一个 *.xlsx 格式的 excel 文件。我想在我的 MVC Web 应用程序中将此文件转换为 *.xls 格式。在我的应用程序托管服务器中没有 Microsoft.Office 包。请让我知道我们如何使用 C# 在 NPOI 中实现它。
提前致谢。
这是我的建议:
使用此库读取 excel 格式 2007 的文件 https://excelpackage.codeplex.com/
使用此库将文件保存为 2003 格式 https://code.google.com/p/excellibrary/
总的来说是可以的,但不是很容易。
XLS
文件格式由 HSSFWorkbook
class 处理(并根据 HSSFSheet
等)。
XLSX
文件格式由 XSSFWorkbook
class(以及 XSSFSheet
等)处理。
因此,为了将您的文件从 XLSX
转换为 XLS
,您需要:
- 创建
XSSFWorkbook
,从文件加载数据; - 新建
HSSFWorkbook
; - 为原始文件中的每个工作表创建
HSSFSheet
并将原始工作表中的所有数据复制到这个新工作表中 - 将您的
HSSFWorkbook
写入文件。
所以这里有很多工作要做,这是一项非常复杂的任务。
对于您的情况,NPOI 可能不是最佳解决方案。
我根据安迪的建议找到了解决方案。这是定制的将XLSX转换为XLS的源代码。
public static class ConvertXLSXToXLS
{
public static HSSFWorkbook ConvertWorkbookXSSFToHSSF(XSSFWorkbook source)
{
//Install-Package NPOI -Version 2.0.6
HSSFWorkbook retVal = new HSSFWorkbook();
for (int i = 0; i < source.NumberOfSheets; i++)
{
HSSFSheet hssfSheet = (HSSFSheet)retVal.CreateSheet(source.GetSheetAt(i).SheetName);
XSSFSheet xssfsheet = (XSSFSheet)source.GetSheetAt(i);
CopySheets(xssfsheet, hssfSheet, retVal);
}
return retVal;
}
private static void CopySheets(XSSFSheet source, HSSFSheet destination, HSSFWorkbook retVal)
{
int maxColumnNum = 0;
Dictionary<int, XSSFCellStyle> styleMap = new Dictionary<int, XSSFCellStyle>();
for (int i = source.FirstRowNum; i <= source.LastRowNum; i++)
{
XSSFRow srcRow = (XSSFRow)source.GetRow(i);
HSSFRow destRow = (HSSFRow)destination.CreateRow(i);
if (srcRow != null)
{
CopyRow(source, destination, srcRow, destRow, styleMap, retVal);
if (srcRow.LastCellNum > maxColumnNum)
{
maxColumnNum = srcRow.LastCellNum;
}
}
}
for (int i = 0; i <= maxColumnNum; i++)
{
destination.SetColumnWidth(i, source.GetColumnWidth(i));
}
}
private static void CopyRow(XSSFSheet srcSheet, HSSFSheet destSheet, XSSFRow srcRow, HSSFRow destRow,
Dictionary<int, XSSFCellStyle> styleMap, HSSFWorkbook retVal)
{
// manage a list of merged zone in order to not insert two times a
// merged zone
List<CellRangeAddress> mergedRegions = new List<CellRangeAddress>();
destRow.Height = srcRow.Height;
// pour chaque row
for (int j = srcRow.FirstCellNum; j <= srcRow.LastCellNum; j++)
{
XSSFCell oldCell = (XSSFCell)srcRow.GetCell(j); // ancienne cell
HSSFCell newCell = (HSSFCell)destRow.GetCell(j); // new cell
if (oldCell != null)
{
if (newCell == null)
{
newCell = (HSSFCell)destRow.CreateCell(j);
}
// copy chaque cell
CopyCell(oldCell, newCell, styleMap, retVal);
// copy les informations de fusion entre les cellules
CellRangeAddress mergedRegion = GetMergedRegion(srcSheet, srcRow.RowNum,
(short)oldCell.ColumnIndex);
if (mergedRegion != null)
{
CellRangeAddress newMergedRegion = new CellRangeAddress(mergedRegion.FirstRow,
mergedRegion.LastRow, mergedRegion.FirstColumn, mergedRegion.LastColumn);
if (IsNewMergedRegion(newMergedRegion, mergedRegions))
{
mergedRegions.Add(newMergedRegion);
destSheet.AddMergedRegion(newMergedRegion);
}
if (newMergedRegion.FirstColumn == 0 && newMergedRegion.LastColumn == 6 && newMergedRegion.FirstRow == newMergedRegion.LastRow)
{
HSSFCellStyle style2 = (HSSFCellStyle)retVal.CreateCellStyle();
style2.VerticalAlignment = VerticalAlignment.Center;
style2.Alignment = HorizontalAlignment.Left;
style2.FillForegroundColor = HSSFColor.Teal.Index;
style2.FillPattern = FillPattern.SolidForeground;
for (int i = destRow.FirstCellNum; i <= destRow.LastCellNum; i++)
{
if (destRow.GetCell(i) != null)
destRow.GetCell(i).CellStyle = style2;
}
}
}
}
}
}
private static void CopyCell(XSSFCell oldCell, HSSFCell newCell, Dictionary<int, XSSFCellStyle> styleMap, HSSFWorkbook retVal)
{
if (styleMap != null)
{
int stHashCode = oldCell.CellStyle.Index;
XSSFCellStyle sourceCellStyle = null;
if (styleMap.TryGetValue(stHashCode, out sourceCellStyle)) { }
HSSFCellStyle destnCellStyle = (HSSFCellStyle)newCell.CellStyle;
if (sourceCellStyle == null)
{
sourceCellStyle = (XSSFCellStyle)oldCell.Sheet.Workbook.CreateCellStyle();
}
// destnCellStyle.CloneStyleFrom(oldCell.CellStyle);
if (!styleMap.Any(p => p.Key == stHashCode))
{
styleMap.Add(stHashCode, sourceCellStyle);
}
destnCellStyle.VerticalAlignment = VerticalAlignment.Top;
newCell.CellStyle = (HSSFCellStyle)destnCellStyle;
}
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 CellRangeAddress GetMergedRegion(XSSFSheet sheet, int rowNum, short cellNum)
{
for (int i = 0; i < sheet.NumMergedRegions; i++)
{
CellRangeAddress merged = sheet.GetMergedRegion(i);
if (merged.IsInRange(rowNum, cellNum))
{
return merged;
}
}
return null;
}
private static bool IsNewMergedRegion(CellRangeAddress newMergedRegion,
List<CellRangeAddress> mergedRegions)
{
return !mergedRegions.Contains(newMergedRegion);
}
}