/** * This method attempt to find an already existing HSSFCellStyle that matches * what you want the style to be. If it does not find the style, then it * Creates a new one. If it does Create a new one, then it applies the * propertyName and propertyValue to the style. This is necessary because * Excel has an upper limit on the number of Styles that it supports. * *@param workbook The workbook that is being worked with. *@param propertyName The name of the property that is to be * changed. *@param propertyValue The value of the property that is to be * changed. *@param cell The cell that needs it's style changes *@exception NestableException Thrown if an error happens. */ public static void SetCellStyleProperty(Fruit.Utils.NPOI.SS.UserModel.ICell cell, HSSFWorkbook workbook, String propertyName, Object propertyValue) { Fruit.Utils.NPOI.SS.UserModel.ICellStyle originalStyle = cell.CellStyle; Fruit.Utils.NPOI.SS.UserModel.ICellStyle newStyle = null; Hashtable values = GetFormatProperties(originalStyle); values[propertyName] = propertyValue; // index seems like what index the cellstyle is in the list of styles for a workbook. // not good to compare on! short numberCellStyles = workbook.NumCellStyles; for (short i = 0; i < numberCellStyles; i++) { Fruit.Utils.NPOI.SS.UserModel.ICellStyle wbStyle = workbook.GetCellStyleAt(i); Hashtable wbStyleMap = GetFormatProperties(wbStyle); if (wbStyleMap.Equals(values)) { newStyle = wbStyle; break; } } if (newStyle == null) { newStyle = workbook.CreateCellStyle(); SetFormatProperties(newStyle, workbook, values); } cell.CellStyle = (newStyle); }
/// <summary> /// Returns a map containing the format properties of the given cell style. /// </summary> /// <param name="style">cell style</param> /// <returns>map of format properties (String -> Object)</returns> private static Hashtable GetFormatProperties(Fruit.Utils.NPOI.SS.UserModel.ICellStyle style) { Hashtable properties = new Hashtable(); PutShort(properties, ALIGNMENT, (short)style.Alignment); PutShort(properties, BORDER_BOTTOM, (short)style.BorderBottom); PutShort(properties, BORDER_LEFT, (short)style.BorderLeft); PutShort(properties, BORDER_RIGHT, (short)style.BorderRight); PutShort(properties, BORDER_TOP, (short)style.BorderTop); PutShort(properties, BOTTOM_BORDER_COLOR, style.BottomBorderColor); PutShort(properties, DATA_FORMAT, style.DataFormat); PutShort(properties, FILL_BACKGROUND_COLOR, style.FillBackgroundColor); PutShort(properties, FILL_FOREGROUND_COLOR, style.FillForegroundColor); PutShort(properties, FILL_PATTERN, (short)style.FillPattern); PutShort(properties, FONT, style.FontIndex); PutBoolean(properties, HIDDEN, style.IsHidden); PutShort(properties, INDENTION, style.Indention); PutShort(properties, LEFT_BORDER_COLOR, style.LeftBorderColor); PutBoolean(properties, LOCKED, style.IsLocked); PutShort(properties, RIGHT_BORDER_COLOR, style.RightBorderColor); PutShort(properties, ROTATION, style.Rotation); PutShort(properties, TOP_BORDER_COLOR, style.TopBorderColor); PutShort(properties, VERTICAL_ALIGNMENT, (short)style.VerticalAlignment); PutBoolean(properties, WRAP_TEXT, style.WrapText); return(properties); }
/// <summary> /// Sets the format properties of the given style based on the given map. /// </summary> /// <param name="style">The cell style</param> /// <param name="workbook">The parent workbook.</param> /// <param name="properties">The map of format properties (String -> Object).</param> private static void SetFormatProperties( Fruit.Utils.NPOI.SS.UserModel.ICellStyle style, HSSFWorkbook workbook, Hashtable properties) { style.Alignment = (Fruit.Utils.NPOI.SS.UserModel.HorizontalAlignment)GetShort(properties, ALIGNMENT); style.BorderBottom = (Fruit.Utils.NPOI.SS.UserModel.BorderStyle)GetShort(properties, BORDER_BOTTOM); style.BorderLeft = (Fruit.Utils.NPOI.SS.UserModel.BorderStyle)GetShort(properties, BORDER_LEFT); style.BorderRight = (Fruit.Utils.NPOI.SS.UserModel.BorderStyle)GetShort(properties, BORDER_RIGHT); style.BorderTop = (Fruit.Utils.NPOI.SS.UserModel.BorderStyle)GetShort(properties, BORDER_TOP); style.BottomBorderColor = (GetShort(properties, BOTTOM_BORDER_COLOR)); style.DataFormat = (GetShort(properties, DATA_FORMAT)); style.FillBackgroundColor = (GetShort(properties, FILL_BACKGROUND_COLOR)); style.FillForegroundColor = (GetShort(properties, FILL_FOREGROUND_COLOR)); style.FillPattern = (Fruit.Utils.NPOI.SS.UserModel.FillPatternType)GetShort(properties, FILL_PATTERN); style.SetFont(workbook.GetFontAt(GetShort(properties, FONT))); style.IsHidden = (GetBoolean(properties, HIDDEN)); style.Indention = (GetShort(properties, INDENTION)); style.LeftBorderColor = (GetShort(properties, LEFT_BORDER_COLOR)); style.IsLocked = (GetBoolean(properties, LOCKED)); style.RightBorderColor = (GetShort(properties, RIGHT_BORDER_COLOR)); style.Rotation = (GetShort(properties, ROTATION)); style.TopBorderColor = (GetShort(properties, TOP_BORDER_COLOR)); style.VerticalAlignment = (Fruit.Utils.NPOI.SS.UserModel.VerticalAlignment)GetShort(properties, VERTICAL_ALIGNMENT); style.WrapText = (GetBoolean(properties, WRAP_TEXT)); }
/// <summary> /// Goes through the Wokrbook, optimising the cell styles /// by removing duplicate ones. /// For best results, optimise the fonts via a call to /// OptimiseFonts(HSSFWorkbook) first /// </summary> /// <param name="workbook">The workbook in which to optimise the cell styles</param> public static void OptimiseCellStyles(HSSFWorkbook workbook) { // Where each style has ended up, and if we need to // delete the record for it. Start off with no change short[] newPos = new short[workbook.Workbook.NumExFormats]; bool[] zapRecords = new bool[newPos.Length]; for (int i = 0; i < newPos.Length; i++) { newPos[i] = (short)i; zapRecords[i] = false; } // Get each style record, so we can do deletes // without Getting confused ExtendedFormatRecord[] xfrs = new ExtendedFormatRecord[newPos.Length]; for (int i = 0; i < newPos.Length; i++) { xfrs[i] = workbook.Workbook.GetExFormatAt(i); } // Loop over each style, seeing if it is the same // as an earlier one. If it is, point users of the // later duplicate copy to the earlier one, and // mark the later one as needing deleting // Only work on user added ones, which come after 20 for (int i = 21; i < newPos.Length; i++) { // Check this one for being a duplicate // of an earlier one int earlierDuplicate = -1; for (int j = 0; j < i && earlierDuplicate == -1; j++) { ExtendedFormatRecord xfCheck = workbook.Workbook.GetExFormatAt(j); if (xfCheck.Equals(xfrs[i])) { earlierDuplicate = j; } } // If we got a duplicate, mark it as such if (earlierDuplicate != -1) { newPos[i] = (short)earlierDuplicate; zapRecords[i] = true; } } // Update the new positions based on // deletes that have occurred between // the start and them // Only work on user added ones, which come after 20 for (int i = 21; i < newPos.Length; i++) { // Find the number deleted to that // point, and adjust short preDeletePos = newPos[i]; short newPosition = preDeletePos; for (int j = 0; j < preDeletePos; j++) { if (zapRecords[j]) { newPosition--; } } // Update the new position newPos[i] = newPosition; } // Zap the un-needed user style records for (int i = 21; i < newPos.Length; i++) { if (zapRecords[i]) { workbook.Workbook.RemoveExFormatRecord( xfrs[i] ); } } // Finally, update the cells to point at // their new extended format records for (int sheetNum = 0; sheetNum < workbook.NumberOfSheets; sheetNum++) { HSSFSheet s = (HSSFSheet)workbook.GetSheetAt(sheetNum); IEnumerator rIt = s.GetRowEnumerator(); while (rIt.MoveNext()) { HSSFRow row = (HSSFRow)rIt.Current; IEnumerator cIt = row.GetEnumerator(); while (cIt.MoveNext()) { ICell cell = (HSSFCell)cIt.Current; short oldXf = ((HSSFCell)cell).CellValueRecord.XFIndex; Fruit.Utils.NPOI.SS.UserModel.ICellStyle newStyle = workbook.GetCellStyleAt( newPos[oldXf] ); cell.CellStyle = (newStyle); } } } }