日本xxxx18视频在线观看-日本xxxx1819-日本xxxwww在线观看-日本xxx-日本xx-日本www在线视频

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

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

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

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

  • IWorkbook:在npoi中代表一個(gè)excel文件。

  • ISheet:代表excel中的一個(gè)sheet頁(yè)面。

  • IRow:代表excel中sheet頁(yè)面里的一行。

  • ICell:代表excel中的一個(gè)單元格。

NPOI現(xiàn)在很多地方都用這樣的接口形式來(lái)進(jìn)行封裝了,所以在不需要轉(zhuǎn)換格式的情況下,直接使用這樣的類型即可,但是在格式轉(zhuǎn)換地方就會(huì)存在一些坑,這個(gè)坑就在于如果直接調(diào)用方法和傳參,會(huì)告知你類型不對(duì)!說(shuō)白了,就是有些地方不能用xls讀取的格式信息賦值給xlsx格式的處理方法。
因?yàn)楫?dāng)前是需要將xls轉(zhuǎn)為xlsx格式,所以就針對(duì)xls格式的頁(yè)面類進(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)容需要說(shuō)明,為啥要專門描述是給HSSFSheet類型進(jìn)行擴(kuò)展?因?yàn)閤ls格式的sheet頁(yè)面對(duì)應(yīng)的NPOI類型就是HSSFSheet,如果你擴(kuò)展ISheet進(jìn)行處理,如果讀取的是xlsx格式文件內(nèi)容,將會(huì)報(bào)錯(cuò)!所以在這里會(huì)明確指定到底是xls格式還是xlsx格式!
在NPOI庫(kù)中,HSSF開頭的為xls格式文件中的各種處理類型,XSSF開頭的為xlsx格式文件中的各種處理類型。
中間為啥會(huì)設(shè)置maxColumnWidth = 256*255,因?yàn)橛行┝袑挻_實(shí)太長(zhǎng)了,然后加載到NPOI處理轉(zhuǎn)換時(shí)就會(huì)報(bào)錯(cuò),所以在轉(zhuǎn)換時(shí),需要設(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ù)的時(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中對(duì)單元格樣式的創(chuàng)建數(shù)量是有上限的,所以如果存在我們認(rèn)為相同格式的樣式時(shí),就從已有的樣式庫(kù)中去獲取就可以了,這樣可以減少創(chuàng)建樣式信息,以避免因樣式問(wèn)題報(bào)錯(cuò)!上限值我記得應(yīng)該是4000個(gè),這很容易超限啊,4000個(gè)樣式定義也就20列200行的數(shù)量級(jí)。

處理樣式定義

/// <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í)間實(shí)在是不能接受(超過(guò)一分鐘了),現(xiàn)在工作中要轉(zhuǎn)換的文件大概在50份上下,轉(zhuǎn)換時(shí)間不超過(guò)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)

            {

                //先處理第一個(gè)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過(guò)去改后綴就行了!


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

主站蜘蛛池模板: 欧美特黄高清免费观 | 日韩亚洲精品影视 | 精品欧美激情在线观看 | 欧美日韩国产免费一区在线观看 | 欧美日韩国产在线yw | 麻花传媒免费网站在线观看 | 国产精品永久视频免费 | 成人国产一区二区三区精品 | 成人国内免费精品视频在线观看 | 日韩一区二精品服务 | 国产高清视频在线播放 | 国产mv在线观看免费 | 人妖欧美精品二区 | 国产又大又硬又粗又猛的视频 | 99国产第一页在线 | 日韩在线观看一区二区不卡视频 | 国产精品自在线观看剧情 | 国产剧情精品v国产在线观看 | 日本精品一区二区三区不卡 | 麻花影院 | 日韩精品综 | 日本精品网站在线中文 | 欧美人做人爱a全程免费 | 日韩精品中文字幕在线 | 男人的天堂v在线播放 | 国产性自爱拍偷在拍线播放 | 国产在线精品50页 | 国产乱理伦片a级在线观看 国产又色又亚洲免费小视频 | 日韩专区精品中文字幕 | 成品网站w在线观看 | 精品国产福利第一区二区三区 | 欧美狂野乱码一二三四区 | 日韩怡红院亚洲精品二区 | 国产午夜一区二区三区影院 | 国内精品自在自线视频香 | 国产v的在线观看 | 777米奇影院狠狠狠 日韩a级片 | 午夜性又黄又爽免费看尤物 | 免费大片黄 | 国产一区二区三区在线观看视 | 国产免费乱伦精品一区二区三区 |