C# NPOI Excel 跨工作薄Workbook複製工作表Sheet

跨工作薄複製Sheet,並不是單純的將Sheet的數據複製到新Sheet中,需要將數據、公式等包括數據格式(DataFormat),單元格的風格(CellStyle)等等都複製到新Sheet中。

NPOI目前的版本爲2.5.1,其Excel處理已經可以較好的支持XSSF(2007及以上)與HSSF(2003及以下)各自的工作薄間的Sheet拷貝,但XSSF工作薄與HSSF工作薄間的Sheet拷貝仍未實現。而2.4.1版的HSSF的Sheet拷貝也並未完善,雖然大部分功能已實現,顏色上有異常,2.5.1版已正常。爲了處理各種情況下的Sheet的拷貝,網上有比較多的示例,比較成功的示例雖然有所不同但處理方式大同小異,有些處理考慮也有不到的地方。可參考:NPOI中如何複製Sheet,poi操作excel,複製sheet,複製行,複製單元格。由於某些原因,此處只考慮NPOI 2.4.1的版本下的處理,某些不同的版本可能會有些不同。

處理思路:Sheet的複製主要考慮的就是單元格Cell,分Cell的數據與風格。數據處理網上有許多成功示例,請自尋不贅述。風格處理包括:單元格的各種情況,其中重點是字體與顏色的處理(私設:這也是目前NPOI未解決得好的原因吧 :-p )。本人蔘考了許多示例,Sheet複製已經能夠基本解決,但一直未能處理好顏色情況(包括字體顏色),注意:此處指HSSF與XSSF間的相互或自我複製的不同情況。以下出現的代碼示例中,有關顏色部分被屏蔽,呵呵,雖未成功但一直努力中……如有哪位能夠解決並提供代碼的話,那麼基本上NPOI的Sheet複製基本上就成功了。當然,仍然有其它的方面需要解決(如:Chart、Picture……),但對於一般的代碼應用,估計差不多了吧。

不多說了……翠花,上酸菜——

public static class NPOIExt
{
    /// <summary>
    /// 跨工作薄Workbook複製工作表Sheet
    /// </summary>
    /// <param name="sSheet">源工作表Sheet</param>
    /// <param name="dWb">目標工作薄Workbook</param>
    /// <param name="dSheetName">目標工作表Sheet名</param>
    /// <param name="clonePrintSetup">是否複製打印設置</param>
    public static ISheet CrossCloneSheet(this ISheet sSheet, IWorkbook dWb, string dSheetName, bool clonePrintSetup)
    {
        ISheet dSheet;
        dSheetName = string.IsNullOrEmpty(dSheetName) ? sSheet.SheetName : dSheetName;
        dSheetName = (dWb.GetSheet(dSheetName) == null) ? dSheetName : dSheetName + "_拷貝";
        dSheet = dWb.GetSheet(dSheetName) ?? dWb.CreateSheet(dSheetName);
        CopySheet(sSheet, dSheet);
        if (clonePrintSetup)
            ClonePrintSetup(sSheet, dSheet);
        dWb.SetActiveSheet(dWb.GetSheetIndex(dSheet));  //當前Sheet作爲下次打開默認Sheet
        return dSheet;
    }
    /// <summary>
    /// 跨工作薄Workbook複製工作表Sheet
    /// </summary>
    /// <param name="sSheet">源工作表Sheet</param>
    /// <param name="dWb">目標工作薄Workbook</param>
    /// <param name="dSheetName">目標工作表Sheet名</param>
    public static ISheet CrossCloneSheet(this ISheet sSheet, IWorkbook dWb, string dSheetName)
    {
        bool clonePrintSetup = true;
        return CrossCloneSheet(sSheet, dWb, dSheetName, clonePrintSetup);
    }
    /// <summary>
    /// 跨工作薄Workbook複製工作表Sheet
    /// </summary>
    /// <param name="sSheet">源工作表Sheet</param>
    /// <param name="dWb">目標工作薄Workbook</param>
    public static ISheet CrossCloneSheet(this ISheet sSheet, IWorkbook dWb)
    {
        string dSheetName = sSheet.SheetName;
        bool clonePrintSetup = true;
        return CrossCloneSheet(sSheet, dWb, dSheetName, clonePrintSetup);
    }
 
    private static IFont FindFont(this IWorkbook dWb, IFont font, List<IFont> dFonts)
    {
        //IFont dFont = dWb.FindFont(font.Boldweight, font.Color, (short)font.FontHeight, font.FontName, font.IsItalic, font.IsStrikeout, font.TypeOffset, font.Underline);
        IFont dFont = null;
        foreach (IFont currFont in dFonts)
        {
            //if (currFont.Charset != font.Charset) continue;
            //else
            //if (currFont.Color != font.Color) continue;
            //else
            if (currFont.FontName != font.FontName) continue;
            else if (currFont.FontHeight != font.FontHeight) continue;
            else if (currFont.IsBold != font.IsBold) continue;
            else if (currFont.IsItalic != font.IsItalic) continue;
            else if (currFont.IsStrikeout != font.IsStrikeout) continue;
            else if (currFont.Underline != font.Underline) continue;
            else if (currFont.TypeOffset != font.TypeOffset) continue;
            else { dFont = currFont; break; }
        }
        return dFont;
    }
    private static ICellStyle FindStyle(this IWorkbook dWb, IWorkbook sWb, ICellStyle style, List<ICellStyle> dCellStyles, List<IFont> dFonts)
    {
        ICellStyle dStyle = null;
        foreach (ICellStyle currStyle in dCellStyles)
        {
            if (currStyle.Alignment != style.Alignment) continue;
            else if (currStyle.VerticalAlignment != style.VerticalAlignment) continue;
            else if (currStyle.BorderTop != style.BorderTop) continue;
            else if (currStyle.BorderBottom != style.BorderBottom) continue;
            else if (currStyle.BorderLeft != style.BorderLeft) continue;
            else if (currStyle.BorderRight != style.BorderRight) continue;
            else if (currStyle.TopBorderColor != style.TopBorderColor) continue;
            else if (currStyle.BottomBorderColor != style.BottomBorderColor) continue;
            else if (currStyle.LeftBorderColor != style.LeftBorderColor) continue;
            else if (currStyle.RightBorderColor != style.RightBorderColor) continue;
            //else if (currStyle.BorderDiagonal != style.BorderDiagonal) continue;
            //else if (currStyle.BorderDiagonalColor != style.BorderDiagonalColor) continue;
            //else if (currStyle.BorderDiagonalLineStyle != style.BorderDiagonalLineStyle) continue;
            //else if (currStyle.FillBackgroundColor != style.FillBackgroundColor) continue;
            //else if (currStyle.FillBackgroundColorColor != style.FillBackgroundColorColor) continue;
            //else if (currStyle.FillForegroundColor != style.FillForegroundColor) continue;
            //else if (currStyle.FillForegroundColorColor != style.FillForegroundColorColor) continue;
            //else if (currStyle.FillPattern != style.FillPattern) continue;
            else if (currStyle.Indention != style.Indention) continue;
            else if (currStyle.IsHidden != style.IsHidden) continue;
            else if (currStyle.IsLocked != style.IsLocked) continue;
            else if (currStyle.Rotation != style.Rotation) continue;
            else if (currStyle.ShrinkToFit != style.ShrinkToFit) continue;
            else if (currStyle.WrapText != style.WrapText) continue;
            else if (!currStyle.GetDataFormatString().Equals(style.GetDataFormatString())) continue;
            else
            {
                IFont sFont = sWb.GetFontAt(style.FontIndex);
                IFont dFont = dWb.FindFont(sFont, dFonts);
                if (dFont == null) continue;
                else
                {
                    currStyle.SetFont(dFont);
                    dStyle = currStyle;
                    break;
                }
            }
        }
        return dStyle;
    }
    private static IFont CopyFont(this IFont dFont, IFont sFont, List<IFont> dFonts)
    {
        //dFont.Charset = sFont.Charset;
        //dFont.Color = sFont.Color;
        dFont.FontHeight = sFont.FontHeight;
        dFont.FontName = sFont.FontName;
        dFont.IsBold = sFont.IsBold;
        dFont.IsItalic = sFont.IsItalic;
        dFont.IsStrikeout = sFont.IsStrikeout;
        dFont.Underline = sFont.Underline;
        dFont.TypeOffset = sFont.TypeOffset;
        dFonts.Add(dFont);
        return dFont;
    }
    private static ICellStyle CopyStyle(this ICellStyle dCellStyle, ICellStyle sCellStyle, IWorkbook dWb, IWorkbook sWb, List<ICellStyle> dCellStyles, List<IFont> dFonts)
    {
        ICellStyle currCellStyle = dCellStyle;
        currCellStyle.Alignment = sCellStyle.Alignment;
        currCellStyle.VerticalAlignment = sCellStyle.VerticalAlignment;
        currCellStyle.BorderTop = sCellStyle.BorderTop;
        currCellStyle.BorderBottom = sCellStyle.BorderBottom;
        currCellStyle.BorderLeft = sCellStyle.BorderLeft;
        currCellStyle.BorderRight = sCellStyle.BorderRight;
        currCellStyle.TopBorderColor = sCellStyle.TopBorderColor;
        currCellStyle.LeftBorderColor = sCellStyle.LeftBorderColor;
        currCellStyle.RightBorderColor = sCellStyle.RightBorderColor;
        currCellStyle.BottomBorderColor = sCellStyle.BottomBorderColor;
        //dCellStyle.BorderDiagonal = sCellStyle.BorderDiagonal;
        //dCellStyle.BorderDiagonalColor = sCellStyle.BorderDiagonalColor;
        //dCellStyle.BorderDiagonalLineStyle = sCellStyle.BorderDiagonalLineStyle;
        //dCellStyle.FillBackgroundColor = sCellStyle.FillBackgroundColor;
        //dCellStyle.FillForegroundColor = sCellStyle.FillForegroundColor;
        //dCellStyle.FillPattern = sCellStyle.FillPattern;
        currCellStyle.Indention = sCellStyle.Indention;
        currCellStyle.IsHidden = sCellStyle.IsHidden;
        currCellStyle.IsLocked = sCellStyle.IsLocked;
        currCellStyle.Rotation = sCellStyle.Rotation;
        currCellStyle.ShrinkToFit = sCellStyle.ShrinkToFit;
        currCellStyle.WrapText = sCellStyle.WrapText;
        currCellStyle.DataFormat = dWb.CreateDataFormat().GetFormat(sWb.CreateDataFormat().GetFormat(sCellStyle.DataFormat));
        IFont sFont = sCellStyle.GetFont(sWb);
        IFont dFont = dWb.FindFont(sFont, dFonts) ?? dWb.CreateFont().CopyFont(sFont, dFonts);
        currCellStyle.SetFont(dFont);
        dCellStyles.Add(currCellStyle);
        return currCellStyle;
    }
 
    private static void CopySheet(ISheet sSheet, ISheet dSheet)
    {
        var maxColumnNum = 0;
        List<ICellStyle> dCellStyles = new List<ICellStyle>();
        List<IFont> dFonts = new List<IFont>();
        MergerRegion(sSheet, dSheet);
        for (int i = sSheet.FirstRowNum; i <= sSheet.LastRowNum; i++)
        {
            IRow sRow = sSheet.GetRow(i);
            IRow dRow = dSheet.CreateRow(i);
            if (sRow != null)
            {
                CopyRow(sRow, dRow, dCellStyles, dFonts);
                if (sRow.LastCellNum > maxColumnNum)
                    maxColumnNum = sRow.LastCellNum;
            }
        }
        for (int i = 0; i <= maxColumnNum; i++)
            dSheet.SetColumnWidth(i, sSheet.GetColumnWidth(i));
    }
    private static void CopyRow(IRow sRow, IRow dRow, List<ICellStyle> dCellStyles, List<IFont> dFonts)
    {
        dRow.Height = sRow.Height;
        ISheet sSheet = sRow.Sheet;
        ISheet dSheet = dRow.Sheet;
        for (int j = sRow.FirstCellNum; j <= sRow.LastCellNum; j++)
        {
            NPOI.SS.UserModel.ICell sCell = sRow.GetCell(j);
            NPOI.SS.UserModel.ICell dCell = dRow.GetCell(j);
            if (sCell != null)
            {
                if (dCell == null)
                    dCell = dRow.CreateCell(j);
                CopyCell(sCell, dCell, dCellStyles, dFonts);
            }
        }
    }
    private static void CopyCell(NPOI.SS.UserModel.ICell sCell, NPOI.SS.UserModel.ICell dCell, List<ICellStyle> dCellStyles, List<IFont> dFonts)
    {
        ICellStyle currCellStyle = dCell.Sheet.Workbook.FindStyle(sCell.Sheet.Workbook, sCell.CellStyle, dCellStyles, dFonts);
        if (currCellStyle == null)
            currCellStyle = dCell.Sheet.Workbook.CreateCellStyle().CopyStyle(sCell.CellStyle, dCell.Sheet.Workbook, sCell.Sheet.Workbook, dCellStyles, dFonts);
        dCell.CellStyle = currCellStyle;
        switch (sCell.CellType)
        {
            case CellType.String:
                dCell.SetCellValue(sCell.StringCellValue);
                break;
            case CellType.Numeric:
                dCell.SetCellValue(sCell.NumericCellValue);
                break;
            case CellType.Blank:
                dCell.SetCellType(CellType.Blank);
                break;
            case CellType.Boolean:
                dCell.SetCellValue(sCell.BooleanCellValue);
                break;
            case CellType.Error:
                dCell.SetCellValue(sCell.ErrorCellValue);
                break;
            case CellType.Formula:
                dCell.SetCellFormula(sCell.CellFormula);
                break;
            default:
                break;
        }
    }
 
    private static void MergerRegion(ISheet sSheet, ISheet dSheet)
    {
        int sheetMergerCount = sSheet.NumMergedRegions;
        for (int i = 0; i < sheetMergerCount; i++)
            dSheet.AddMergedRegion(sSheet.GetMergedRegion(i));
    }
    private static void ClonePrintSetup(ISheet sSheet, ISheet dSheet)
    {
        //工作表Sheet頁面打印設置
        dSheet.PrintSetup.Copies = 1;                               //打印份數
        dSheet.PrintSetup.PaperSize = sSheet.PrintSetup.PaperSize;  //紙張大小
        dSheet.PrintSetup.Landscape = sSheet.PrintSetup.Landscape;  //紙張方向:默認縱向false(橫向true)
        dSheet.PrintSetup.Scale = sSheet.PrintSetup.Scale;          //縮放方式比例
        dSheet.PrintSetup.FitHeight = sSheet.PrintSetup.FitHeight;  //調整方式頁高
        dSheet.PrintSetup.FitWidth = sSheet.PrintSetup.FitWidth;    //調整方式頁寬
        dSheet.PrintSetup.FooterMargin = sSheet.PrintSetup.FooterMargin;
        dSheet.PrintSetup.HeaderMargin = sSheet.PrintSetup.HeaderMargin;
        //頁邊距
        dSheet.SetMargin(MarginType.TopMargin, sSheet.GetMargin(MarginType.TopMargin));
        dSheet.SetMargin(MarginType.BottomMargin, sSheet.GetMargin(MarginType.BottomMargin));
        dSheet.SetMargin(MarginType.LeftMargin, sSheet.GetMargin(MarginType.LeftMargin));
        dSheet.SetMargin(MarginType.RightMargin, sSheet.GetMargin(MarginType.RightMargin));
        dSheet.SetMargin(MarginType.HeaderMargin, sSheet.GetMargin(MarginType.HeaderMargin));
        dSheet.SetMargin(MarginType.FooterMargin, sSheet.GetMargin(MarginType.FooterMargin));
        //頁眉頁腳
        dSheet.Header.Left = sSheet.Header.Left;
        dSheet.Header.Center = sSheet.Header.Center;
        dSheet.Header.Right = sSheet.Header.Right;
        dSheet.Footer.Left = sSheet.Footer.Left;
        dSheet.Footer.Center = sSheet.Footer.Center;
        dSheet.Footer.Right = sSheet.Footer.Right;
        //工作表Sheet參數設置
        dSheet.IsPrintGridlines = sSheet.IsPrintGridlines;          //true: 打印整表網格線。不單獨設置CellStyle時外框實線內框虛線。 false: 自己設置網格線
        dSheet.FitToPage = sSheet.FitToPage;                        //自適應頁面
        dSheet.HorizontallyCenter = sSheet.HorizontallyCenter;      //打印頁面爲水平居中
        dSheet.VerticallyCenter = sSheet.VerticallyCenter;          //打印頁面爲垂直居中
        dSheet.RepeatingRows = sSheet.RepeatingRows;                //工作表頂端標題行範圍
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章