There's the same bug in POI https://bz.apache.org/bugzilla/show_bug.cgi?id=54443
Comments: ** Comment from web user: curiousKoala **
A ported solution from the link provided in the question:
/// <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
var newPos = new short[workbook.Workbook.NumExFormats];
var isUsed = new bool[newPos.Length];
var zapRecords = new bool[newPos.Length];
for (var i = 0; i < newPos.Length; i++)
{
isUsed[i] = false;
newPos[i] = (short)i;
zapRecords[i] = false;
}
// Get each style record, so we can do deletes
// without Getting confused
var xfrs = new ExtendedFormatRecord[newPos.Length];
for (var 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 (var i = 21; i < newPos.Length; i++)
{
// Check this one for being a duplicate
// of an earlier one
var earlierDuplicate = -1;
for (var j = 0; j < i && earlierDuplicate == -1; j++)
{
var 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;
}
}
// Loop over all the cells in the file, and identify any user defined
// styles aren't actually being used (don't touch built-in ones)
for(var sheetNum=0; sheetNum < workbook.NumberOfSheets; sheetNum++) {
var s = workbook.GetSheetAt(sheetNum);
foreach (IRow row in s)
{
foreach (var cellI in row)
{
var cell = (HSSFCell)cellI;
var oldXf = cell.CellValueRecord.XFIndex;
if (isUsed[oldXf] == false)
{
isUsed[newPos[oldXf]] = true;
}
}
}
}
// Mark any that aren't used as needing zapping
for (var i = 21; i < isUsed.Length; i++)
{
if (isUsed[i])
{
continue;
}
if (zapRecords[i])
{
continue;
}
zapRecords[i] = true;
newPos[i] = 0;
}
// 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 (var i = 21; i < newPos.Length; i++)
{
// Find the number deleted to that
// point, and adjust
var preDeletePos = newPos[i];
var newPosition = preDeletePos;
for (var j = 0; j < preDeletePos; j++)
{
if (zapRecords[j]) newPosition--;
}
// Update the new position
newPos[i] = newPosition;
}
// Zap the un-needed user style records
// removing by index, because removing by object may delete
// styles we did not intend to (the ones that _were_ duplicated and not the duplicates)
var max = newPos.Length;
var removed = 0; // to adjust index after deletion
for (var i = 21; i < max; i++)
{
if (!zapRecords[i + removed])
{
continue;
}
workbook.Workbook.RemoveExFormatRecord(i);
i--;
max--;
removed++;
}
// Finally, update the cells to point at
// their new extended format records
for (var sheetNum = 0; sheetNum < workbook.NumberOfSheets; sheetNum++)
{
var s = (HSSFSheet)workbook.GetSheetAt(sheetNum);
foreach (IRow row in s)
{
foreach (ICell cell in row)
{
var oldXf = ((HSSFCell)cell).CellValueRecord.XFIndex;
var newStyle = workbook.GetCellStyleAt(
newPos[oldXf]
);
cell.CellStyle = (newStyle);
}
}
}
}