【问题标题】:Convert xlsx file to xls using NPOI in c#在c#中使用NPOI将xlsx文件转换为xls
【发布时间】:2021-11-23 16:37:34
【问题描述】:

我有一个 *.xlsx 格式的 excel 文件。我想在我的 MVC Web 应用程序中将此文件转换为 *.xls 格式。在我的应用程序托管服务器中,没有 Microsoft.Office 包。请让我知道我们如何使用 c# 在 NPOI 中实现它。

提前致谢。

【问题讨论】:

    标签: c# asp.net-mvc npoi


    【解决方案1】:

    我根据安迪的建议找到了解决方案。这是自定义的将 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);
        }
    }
    

    【讨论】:

      【解决方案2】:

      这是我的建议:

      【讨论】:

        【解决方案3】:

        一般来说是可以的,但不是很容易。

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

        因此,要将您的文件从 XLSX 转换为 XLS,您需要:

        • 创建XSSFWorkbook,从文件中加载数据;
        • 新建HSSFWorkbook;
        • 为原始文件中的每个工作表创建 HSSFSheet 并将原始工作表中的所有数据复制到这个新工作表中
        • 将您的HSSFWorkbook 写入文件。

        所以这里有很多工作要做,这是非常复杂的任务。

        在您的情况下,NPOI 可能不是最佳解决方案。

        【讨论】:

        • 好主意安迪,我会尝试以这种方式实现。
        • 我按照安迪所说的那样遵循了这个解决方案,stackoverflow.com/questions/7230819/… 刚刚将此代码转换为 C#,它对我来说很好。
        猜你喜欢
        • 1970-01-01
        • 2015-03-27
        • 1970-01-01
        • 2012-09-06
        • 2016-06-22
        • 1970-01-01
        • 2013-05-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多