午夜视频在线观看区二区-午夜视频在线观看视频-午夜视频在线观看视频在线观看-午夜视频在线观看完整高清在线-午夜视频在线观看网站-午夜视频在线观看亚洲天堂

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

C#無需安裝Office使用NPOI處理xls到xlsx的轉(zhuǎn)換

admin
2023年12月30日 0:43 本文熱度 1264

當(dāng)前的工作里,需要實(shí)現(xiàn)xls格式到xlsx格式的轉(zhuǎn)換,因?yàn)閭€人常規(guī)使用c#編碼,所以使用的庫就是NPOI了,本來只想當(dāng)個代碼搬運(yùn)工,就想著在網(wǎng)上找點(diǎn)代碼copy一下,但是找了半天確實(shí)沒有找到合適的,就自己來處理了!
先講一些基本概念:

  • IWorkbook:在npoi中代表一個excel文件。

  • ISheet:代表excel中的一個sheet頁面。

  • IRow:代表excel中sheet頁面里的一行。

  • ICell:代表excel中的一個單元格。

NPOI現(xiàn)在很多地方都用這樣的接口形式來進(jìn)行封裝了,所以在不需要轉(zhuǎn)換格式的情況下,直接使用這樣的類型即可,但是在格式轉(zhuǎn)換地方就會存在一些坑,這個坑就在于如果直接調(diào)用方法和傳參,會告知你類型不對!說白了,就是有些地方不能用xls讀取的格式信息賦值給xlsx格式的處理方法。
因?yàn)楫?dāng)前是需要將xls轉(zhuǎn)為xlsx格式,所以就針對xls格式的頁面類進(jìn)行了方法擴(kuò)展,代碼如下:

主代碼

public static class HSheetExt

{

        /// <summary>

        /// 將xls中的sheet轉(zhuǎn)為xlsx格式的sheet(保留處理單元格格式以及字體格式)

        /// </summary>

        /// <param name="hSSFSheet"></param>

        /// <param name="dWb"></param>

        /// <returns></returns>

        public static XSSFSheet ConvertToXSheet(this HSSFSheet hSSFSheet, XSSFWorkbook dWb)

        {

            XSSFSheet xSSFSheet = dWb.CreateSheet() as XSSFSheet;

            var rowCount = hSSFSheet.LastRowNum;//行數(shù)

 

            #region 預(yù)定義樣式和字體信息

            List<XSSFCellStyle> xSSFCellStyles = new List<XSSFCellStyle>();

            List<XSSFFont> xSSFFonts = new List<XSSFFont>();   

            #endregion

            //列寬度處理

            int maxColumnWidth = 256 * 255;

            var xCommnetsDic = ConvertHCommentToXComment(xSSFSheet, hSSFSheet, xSSFFonts);

            for (var i = 0; i <= rowCount; i++)

            {

                var hRow = hSSFSheet.GetRow(i);

                if (hRow == null)

                {

                    continue;

                }

                var xRow = xSSFSheet.CreateRow(i);

                xRow.Height = hRow.Height;

                var curHRowColumnCount = hRow.LastCellNum;//列數(shù)

                for(var j = 0;j <= curHRowColumnCount; j++)

                {

                    var orgWidth = hSSFSheet.GetColumnWidth(i);

                    if (orgWidth > maxColumnWidth)

                    {

                        xSSFSheet.SetColumnWidth(i, maxColumnWidth);

                    }

                    else

                    {

                        xSSFSheet.SetColumnWidth(i, orgWidth);

                    }

 

                    XSSFCell xCell = xRow.CreateCell(j) as XSSFCell;

                    HSSFCell hCell = hRow.GetCell(j) as HSSFCell;

                   

                    ConvertHCellToXCell(hCell, xCell, xSSFCellStyles, xSSFFonts, xCommnetsDic, true);

                }

            }

 

            //最后處理合并單元格的相關(guān)情況

            int sheetMergerCount = hSSFSheet.NumMergedRegions;

            for (int k = 0; k < sheetMergerCount; k++)

                xSSFSheet.AddMergedRegion(hSSFSheet.GetMergedRegion(k));

 

            return xSSFSheet;

        }

}

上面這段代碼有一些內(nèi)容需要說明,為啥要專門描述是給HSSFSheet類型進(jìn)行擴(kuò)展?因?yàn)閤ls格式的sheet頁面對應(yīng)的NPOI類型就是HSSFSheet,如果你擴(kuò)展ISheet進(jìn)行處理,如果讀取的是xlsx格式文件內(nèi)容,將會報錯!所以在這里會明確指定到底是xls格式還是xlsx格式!
在NPOI庫中,HSSF開頭的為xls格式文件中的各種處理類型,XSSF開頭的為xlsx格式文件中的各種處理類型。
中間為啥會設(shè)置maxColumnWidth = 256*255,因?yàn)橛行┝袑挻_實(shí)太長了,然后加載到NPOI處理轉(zhuǎn)換時就會報錯,所以在轉(zhuǎn)換時,需要設(shè)置最大值!

處理批注信息代碼

/// <summary>

/// 處理批注信息轉(zhuǎn)換

/// </summary>

/// <param name="xSSFSheet"></param>

/// <param name="hSSFSheet"></param>

/// <param name="xSSFFonts"></param>

/// <returns></returns>

private static Dictionary<CellAddress,XSSFComment> ConvertHCommentToXComment(XSSFSheet xSSFSheet,HSSFSheet hSSFSheet, List<XSSFFont> xSSFFonts)

{

    var hCommnetsDic = hSSFSheet.GetCellComments();

    var drawing = xSSFSheet.CreateDrawingPatriarch();

    Dictionary<CellAddress,XSSFComment> dic = new Dictionary<CellAddress, XSSFComment> ();

    foreach (var item in hCommnetsDic)

    {

        XSSFClientAnchor anchor = new XSSFClientAnchor();

        anchor.AnchorType = item.Value.ClientAnchor.AnchorType;

        anchor.Col1 = item.Value.ClientAnchor.Col1;

        anchor.Col2 = item.Value.ClientAnchor.Col2;

        anchor.Dx1 = item.Value.ClientAnchor.Dx1;

        anchor.Dx2 = item.Value.ClientAnchor.Dx2;

        anchor.Dy1 = item.Value.ClientAnchor.Dy1;

        anchor.Dy2 = item.Value.ClientAnchor.Dy2;

        anchor.Row1 = item.Value.ClientAnchor.Row1;

        anchor.Row2 = item.Value.ClientAnchor.Row2;

        var comment = drawing.CreateCellComment(anchor) as XSSFComment;

        comment.Visible = item.Value.Visible;

        HSSFRichTextString richText = (HSSFRichTextString)item.Value.String;

        int formattingRuns = richText.NumFormattingRuns;

        comment.String = new XSSFRichTextString(richText.String);

        for (int i = 0; i < formattingRuns; i++)

        {

            int startIdx = richText.GetIndexOfFormattingRun(i);

            short fontIndex = richText.GetFontOfFormattingRun(i);

            HSSFFont hSSFFont = hSSFSheet.Workbook.GetFontAt(fontIndex) as HSSFFont;

            var xFont = FindXFont(hSSFFont, xSSFFonts, xSSFSheet);

            comment.String.ApplyFont(startIdx, richText.Length, xFont);

        }

        dic.Add(item.Key,comment);

    }

    return dic;

}

因?yàn)榕⒅锌赡苌婕岸喾N字體樣式信息,故在傳入?yún)?shù)的時候,也將字體格式信息進(jìn)行傳入了!

轉(zhuǎn)換單元格信息

/// <summary>

/// 轉(zhuǎn)換單元格信息

/// </summary>

/// <param name="hSSFCell"></param>

/// <param name="xSSFCell"></param>

/// <param name="xSSFCellStyles"></param>

/// <param name="xSSFFonts"></param>

/// <param name="isConvertStyle"></param>

private static void ConvertHCellToXCell(HSSFCell hSSFCell,XSSFCell xSSFCell,List<XSSFCellStyle> xSSFCellStyles, List<XSSFFont> xSSFFonts, Dictionary<CellAddress,XSSFComment> xCommnetsDic, bool isConvertStyle = true)

{

    if (hSSFCell != null)

    {

        var hCellType = hSSFCell.CellType;

        if (hSSFCell.CellComment != null)

        {

            var xCellComment = xCommnetsDic.Where(w => w.Key.Column == hSSFCell.CellComment.Address.Column && w.Key.Row == hSSFCell.CellComment.Address.Row).FirstOrDefault().Value;

            xSSFCell.CellComment = xCellComment;

        }

        switch (hCellType) 

        {

            case NPOI.SS.UserModel.CellType.Numeric:

                xSSFCell.SetCellValue(hSSFCell.NumericCellValue);

                break;

            case NPOI.SS.UserModel.CellType.Unknown:

                return;

            case NPOI.SS.UserModel.CellType.Boolean:

                xSSFCell.SetCellValue(hSSFCell.BooleanCellValue);

                break;

            case NPOI.SS.UserModel.CellType.Blank:

                return;

            case NPOI.SS.UserModel.CellType.Formula:

                xSSFCell.SetCellValue(hSSFCell.CellFormula);

                break;

            case NPOI.SS.UserModel.CellType.Error:

                xSSFCell.SetCellErrorValue(hSSFCell.ErrorCellValue);

                return;

            case NPOI.SS.UserModel.CellType.String:

                //xSSFCell.SetCellValue(hSSFCell.StringCellValue);

                HSSFRichTextString richText = (HSSFRichTextString)hSSFCell.RichStringCellValue;

                int formattingRuns = hSSFCell.RichStringCellValue.NumFormattingRuns;

                XSSFRichTextString xSSFRichTextString = new XSSFRichTextString(richText.String);

                for (int i = 0; i < formattingRuns; i++)

                {

                    int startIdx = richText.GetIndexOfFormattingRun(i);

                    short fontIndex = richText.GetFontOfFormattingRun(i);

                    HSSFFont hSSFFont = hSSFCell.Sheet.Workbook.GetFontAt(fontIndex) as HSSFFont;

                    var xFont = FindXFont(hSSFFont, xSSFFonts, (XSSFSheet)xSSFCell.Sheet);

                    xSSFRichTextString.ApplyFont(startIdx, richText.Length, xFont);

                }

                xSSFCell.SetCellValue(xSSFRichTextString);

                break;

        }

        if (isConvertStyle)

        {

            //獲取需要處理的一些需要處理的樣式元素信息

            HSSFCellStyle hSSFCellStyle = hSSFCell.CellStyle as HSSFCellStyle;

            

            if (hSSFCellStyle != null) 

            {

                var xStyle = FindXStyle(hSSFCellStyle, xSSFCellStyles, (XSSFSheet)xSSFCell.Sheet);

                if (xStyle != null)

                {

                    xSSFCell.CellStyle = xStyle;

                }

            }

        }

    }

    return;

}

大家可以看到,上面的方法中傳入了style樣式信息,為啥要這樣做呢?NPOI中對單元格樣式的創(chuàng)建數(shù)量是有上限的,所以如果存在我們認(rèn)為相同格式的樣式時,就從已有的樣式庫中去獲取就可以了,這樣可以減少創(chuàng)建樣式信息,以避免因樣式問題報錯!上限值我記得應(yīng)該是4000個,這很容易超限啊,4000個樣式定義也就20列200行的數(shù)量級。

處理樣式定義

/// <summary>

/// 獲取并處理單元格背景色信息

/// </summary>

/// <param name="hSSFCellStyle"></param>

/// <param name="xSSFCellStyles"></param>

/// <param name="xSSFSheet"></param>

/// <returns></returns>

private static XSSFCellStyle FindXStyle(HSSFCellStyle hSSFCellStyle, List<XSSFCellStyle> xSSFCellStyles, XSSFSheet xSSFSheet)

{

    foreach (var item in xSSFCellStyles)

    {

        if (item.Alignment != hSSFCellStyle.Alignment)

            continue;

        else if (item.BorderLeft != hSSFCellStyle.BorderLeft)

            continue;

        else if (item.BorderRight != hSSFCellStyle.BorderRight)

            continue;

        else if (item.BorderTop != hSSFCellStyle.BorderTop)

            continue;

        else if (item.BorderBottom != hSSFCellStyle.BorderBottom)

            continue;

        else if (item.FillBackgroundColor != hSSFCellStyle.FillBackgroundColor)

            continue;

        else if (item.VerticalAlignment != hSSFCellStyle.VerticalAlignment)

            continue;

        else if (item.IsHidden != hSSFCellStyle.IsHidden)

            continue;

        else if (item.WrapText != hSSFCellStyle.WrapText)

            continue;

        else if (item.FillForegroundColor != hSSFCellStyle.FillForegroundColor)

            continue;

        else if (item.FillPattern != hSSFCellStyle.FillPattern)

            continue;

        else

        {

            return item;

        }

    }

    var xSSFCellStyle = xSSFSheet.Workbook.CreateCellStyle() as XSSFCellStyle;

    xSSFCellStyle.Alignment = hSSFCellStyle.Alignment;

    xSSFCellStyle.BorderLeft = hSSFCellStyle.BorderLeft;

    xSSFCellStyle.BorderRight = hSSFCellStyle.BorderRight;

    xSSFCellStyle.BorderTop = hSSFCellStyle.BorderTop;

    xSSFCellStyle.BorderBottom = hSSFCellStyle.BorderBottom;

    xSSFCellStyle.FillBackgroundColor = hSSFCellStyle.FillBackgroundColor;

    xSSFCellStyle.VerticalAlignment = hSSFCellStyle.VerticalAlignment;

    xSSFCellStyle.IsHidden = hSSFCellStyle.IsHidden;

    xSSFCellStyle.WrapText = hSSFCellStyle.WrapText;

    xSSFCellStyle.FillForegroundColor = hSSFCellStyle.FillForegroundColor;

    xSSFCellStyle.FillPattern = hSSFCellStyle.FillPattern;

    xSSFCellStyles.Add(xSSFCellStyle);

    return xSSFCellStyle;

}

處理字體格式信息

/// <summary>

/// 獲取并處理文字格式信息

/// </summary>

/// <param name="hSSFFont"></param>

/// <param name="xSSFFonts"></param>

/// <param name="xSSFSheet"></param>

/// <returns></returns>

private static XSSFFont FindXFont(HSSFFont hSSFFont,List<XSSFFont>  xSSFFonts, XSSFSheet xSSFSheet)

{

    foreach (var item in xSSFFonts)

    {

        if (item.IsBold != hSSFFont.IsBold)

            continue;

        else if (item.Charset != hSSFFont.Charset)

            continue;

        else if (item.Color != hSSFFont.Color)

            continue;

        else if (item.FontHeight != hSSFFont.FontHeight)

            continue;

        //else if (item.FontHeightInPoints != hSSFFont.FontHeightInPoints)

        //    continue;

        else if (item.FontName != hSSFFont.FontName)

            continue;

        else if (item.IsItalic != hSSFFont.IsItalic)

            continue;

        else if (item.IsStrikeout != hSSFFont.IsStrikeout)

            continue;

        else if (item.TypeOffset != hSSFFont.TypeOffset)

            continue;

        else if (item.Underline != hSSFFont.Underline)

            continue;

        else

        {

            return item;

        }

    }

    var xSSFFont = xSSFSheet.Workbook.CreateFont() as XSSFFont;

    xSSFFont.IsBold = hSSFFont.IsBold;

    xSSFFont.Charset = hSSFFont.Charset;

    xSSFFont.Color = hSSFFont.Color;

    xSSFFont.FontHeight = hSSFFont.FontHeight;

    //xSSFFont.FontHeightInPoints = hSSFFont.FontHeightInPoints;

    xSSFFont.FontName = hSSFFont.FontName;

    xSSFFont.IsItalic = hSSFFont.IsItalic;

    xSSFFont.IsStrikeout = hSSFFont.IsStrikeout;

    xSSFFont.TypeOffset = hSSFFont.TypeOffset;

    xSSFFont.Underline = hSSFFont.Underline;

    xSSFFonts.Add(xSSFFont);

    return xSSFFont;

}

之前在網(wǎng)上找的代碼,轉(zhuǎn)換格式花費(fèi)的時間實(shí)在是不能接受(超過一分鐘了),現(xiàn)在工作中要轉(zhuǎn)換的文件大概在50份上下,轉(zhuǎn)換時間不超過10s,還能接受。
前面的調(diào)用方法如下:

private void ConvertXLSToXLSX(string srcFilePath, string targetFilePath){

    using (var fs = new FileStream(srcFilePath, FileMode.Open, FileAccess.Read, FileShare.Read))

    {

        var oldWorkbook = WorkbookFactory.Create(fs);

        if(oldWorkbook is HSSFWorkbook)

        {

            var numberOfSheets = oldWorkbook.NumberOfSheets;

            if(numberOfSheets == 1)

            {

                //先處理第一個sheet

                var oldWorksheet = oldWorkbook.GetSheetAt(0) as HSSFSheet;

                using (var fileStream = new FileStream(targetFilePath, FileMode.Create))

                {

                    var newWorkBook = new XSSFWorkbook();

                    var sheet = oldWorksheet.ConvertToXSheet(newWorkBook);

                    newWorkBook.Add(sheet);

                    newWorkBook.Write(fileStream);

                    newWorkBook.Close();

                }

                oldWorkbook.Close();

            }

            else if(numberOfSheets > 1)

            {

                using (var fileStream = new FileStream(targetFilePath, FileMode.Create))

                {

                    var newWorkBook = new XSSFWorkbook();

                    for (int i = 0; i < numberOfSheets; i++)

                    {

                        var oldWorksheet = oldWorkbook.GetSheetAt(i) as HSSFSheet;

                        var sheet = oldWorksheet.ConvertToXSheet(newWorkBook);

                        newWorkBook.Add(sheet);

                    }

                    newWorkBook.Write(fileStream);

                    newWorkBook.Close();

                }

                oldWorkbook.Close();

            }

        }

        if(oldWorkbook is XSSFWorkbook)

        {

            if (File.Exists(targetFilePath))

            {

                File.Delete(targetFilePath);

            }

            File.Copy(srcFilePath, targetFilePath);

        }                 

    }


}

建議大家使用WorkbookFactory.Create(fs);方式進(jìn)行讀取,并進(jìn)行類型判斷if(oldWorkbook is HSSFWorkbook)if(oldWorkbook is XSSFWorkbook),因?yàn)橛行┛影。”砻婵粗莤ls格式,但是讀取結(jié)果是xlsx格式的,如果這樣的情況,直接文件copy過去改后綴就行了!


該文章在 2025/4/30 13:08:49 編輯過
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點(diǎn)晴ERP是一款針對中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國內(nèi)大量中小企業(yè)的青睞。
點(diǎn)晴PMS碼頭管理系統(tǒng)主要針對港口碼頭集裝箱與散貨日常運(yùn)作、調(diào)度、堆場、車隊、財務(wù)費(fèi)用、相關(guān)報表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點(diǎn),圍繞調(diào)度、堆場作業(yè)而開發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點(diǎn)晴WMS倉儲管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質(zhì)期管理,貨位管理,庫位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號管理軟件。
點(diǎn)晴免費(fèi)OA是一款軟件和通用服務(wù)都免費(fèi),不限功能、不限時間、不限用戶的免費(fèi)OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved

主站蜘蛛池模板: 91精品无码国产在线观看 | 91美剧网| 国产一区二区三区精品区在线 | 99久久无码一区人妻久久 | 国产精品一线免费观看 | 国产a精品 | 国产一区二区不卡在线 | 国产亚洲第一午夜福利合集 | 国产亚洲综合视频 | 国产精品无圣光一 | 国产成人精品一二三区 | 2025国产精品每日更新在线 | 国产三级小视频在线播放完整 | 国产成人午夜福利在线观看视频 | 国产精品女人呻吟 | 国产精品麻豆久久一区无码片 | 91精品国产自产 | 国产高清女同学巨大乳在线 | 精品无码国产一区二区三区51安 | 国产精品无码免费专区午夜 | 成年永久一区二区三区免费视频 | av人片在线观看不卡 | 国产亚洲精久久久久久无码浪潮 | 国产va免费精品高清在线观看 | 91精品国产免费久久久久久 | 国产无码专区亚洲 | 国产无套精品 | 成人亚洲欧美日韩 | 国产在线欧美精品中文一区 | 激情欧美日韩一区二 | 国产一区日韩二区欧美三区在线 | 国产精品国一 | 国产成人a视频 | 国产一区视频在线播放 | 国产美女裸体无遮挡免费视频 | 国产成人手机在线播放 | 国产精品国产三级国产av | 国产美女精品在线 | 爆乳一区二区三区无码 | 国产成人精品一区二区日出白浆 | 精品无码av一区二区三区不卡 |