diff -urBb old/HSSFOptimiser.java new/HSSFOptimiser.java
--- old/HSSFOptimiser.java	2014-12-16 10:55:23.000000000 +0900
+++ new/HSSFOptimiser.java	2015-01-31 17:58:31.253810364 +0900
@@ -18,10 +18,13 @@
 
 import java.util.HashSet;
 
+import org.apache.poi.hssf.model.InternalWorkbook;
 import org.apache.poi.hssf.record.ExtendedFormatRecord;
 import org.apache.poi.hssf.record.FontRecord;
+import org.apache.poi.hssf.record.StyleRecord;
 import org.apache.poi.hssf.record.common.UnicodeString;
 import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellStyle;
 import org.apache.poi.ss.usermodel.Row;
 
 /**
@@ -173,20 +176,49 @@
    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.getWorkbook().getNumExFormats()];
+       final short off = 1;
+       InternalWorkbook iwb = workbook.getWorkbook();
+       short[] newPos = new short[iwb.getNumExFormats()];
        boolean[] isUsed = new boolean[newPos.length];
        boolean[] zapRecords = new boolean[newPos.length];
+       short[] oldParent = new short[newPos.length];
+       int colmin;
+       int colmax;
+
        for(int i=0; i<newPos.length; i++) {
+           HSSFCellStyle cs, csp;
            isUsed[i] = false;
            newPos[i] = (short)i;
            zapRecords[i] = false;
+
+           //Preserve parent indexes. 
+           oldParent[i] = 0;
+           cs = workbook.getCellStyleAt((short)i);
+           csp = cs.getParentStyle();
+           if(csp != null) {
+               oldParent[i] = csp.getIndex();
+           }
+
+           //User defined styles is used.
+           if(cs.getUserStyleName() != null) {
+               isUsed[i] = true;
+           }
+
+           //Builtin style is used.
+           StyleRecord sr = iwb.getStyleRecord(i);
+           if(sr != null) {
+               if(sr.isBuiltin()) {
+                   isUsed[i] = true;
+               }
+           }
+
        }
 
        // 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.getWorkbook().getExFormatAt(i);
+       for(short i=0; i<newPos.length; i++) {
+           xfrs[i] = iwb.getExFormatAt(i);
        }
 
        // Loop over each style, seeing if it is the same
@@ -194,14 +226,21 @@
        //  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++) {
+       for(int i=off; i<newPos.length; i++) {
+
+           if(isUsed[i])
+           {
+               continue;
+           }
+
            // 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.getWorkbook().getExFormatAt(j);
-               if(xfCheck.equals(xfrs[i])) {
+           for(short j=0; j<i; j++) {
+               HSSFCellStyle xfCheck = workbook.getCellStyleAt(j);
+               if(xfCheck.equals(xfrs[i]) ) {
                    earlierDuplicate = j;
+                   break;
                }
            }
 
@@ -210,30 +249,72 @@
                newPos[i] = (short)earlierDuplicate;
                zapRecords[i] = true;
            }
-           // If we got a duplicate, mark the one we're keeping as used
-           if(earlierDuplicate != -1) {
-               isUsed[earlierDuplicate] = 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)
+       colmin = 0;
+       colmax = -1;
        for(int sheetNum=0; sheetNum<workbook.getNumberOfSheets(); sheetNum++) {
+           int ci;
+           CellStyle cs;
+           short oldXf;
+
            HSSFSheet s = workbook.getSheetAt(sheetNum);
+
            for (Row row : s) {
+
+               cs = row.getRowStyle();
+               if(cs!=null) {
+                   oldXf = cs.getIndex();
+                   isUsed[newPos[oldXf]] = true;
+                   isUsed[oldParent[oldXf]] = true;
+               }
+
                for (Cell cellI : row) {
                    HSSFCell cell = (HSSFCell)cellI;
-                   short oldXf = cell.getCellValueRecord().getXFIndex();
-                   isUsed[oldXf] = true;
+                   oldXf = cell.getCellValueRecord().getXFIndex();
+                   isUsed[newPos[oldXf]] = true;
+                   isUsed[oldParent[oldXf]] = true;
+
+                   ci = cellI.getColumnIndex();
+                   if(colmin <= colmax) {
+
+                       if(ci < colmin) {
+                           colmin = ci;
+                       }
+                       else if(ci > colmax) {
+                           colmax = ci;
+                       }
+
+                   }
+                   else {
+                       colmin = ci;
+                       colmax = ci;
                }
+
            }
+
+           }
+
+           for(ci = colmin; ci <= colmax; ci++)
+           {
+               cs = s.getColumnStyle(ci);
+               if(cs!=null)
+               {
+                   oldXf = cs.getIndex();
+                   isUsed[newPos[oldXf]] = true;
+                   isUsed[oldParent[oldXf]] = true;
+               }
+
+           }
+
        }
        // Mark any that aren't used as needing zapping
-       for (int i=21; i<isUsed.length; i++) {
+       for (int i=off; i<isUsed.length; i++) {
            if (! isUsed[i]) {
                // Un-used style, can be removed
                zapRecords[i] = true;
-               newPos[i] = 0;
            }
        }
 
@@ -241,7 +322,7 @@
        //  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++) {
+       for(int i=off; i<newPos.length; i++) {
            // Find the number deleted to that
            //  point, and adjust
            short preDeletePos = newPos[i];
@@ -259,29 +340,82 @@
        // styles we did not intend to (the ones that _were_ duplicated and not the duplicates)
        int max = newPos.length;
        int removed = 0; // to adjust index after deletion
-       for(int i=21; i<max; i++) {
+       for(int i=off; i<max; i++) {
            if(zapRecords[i + removed]) {
-               workbook.getWorkbook().removeExFormatRecord(i);
+               iwb.removeExFormatRecord(i);
+               //Delete the old record.
+               StyleRecord sr = iwb.getStyleRecord(i + removed);
+               if(sr != null)
+               {
+                   iwb.getRecords().remove(sr);
+               }
                i--;
                max--;
                removed++;
            }
        }
 
+
+       for(int i=off; i<newPos.length; i++) {
+           if(!zapRecords[i] ) {
+               //Edit existing record infomation.
+
+               //Change parent index.
+               iwb.getExFormatAt(newPos[i]).setParentIndex(newPos[oldParent[i]]);
+
+               //Delete the old record before record move the new position.
+               if(newPos[i] < i) {
+
+                   //Move style record.
+                   StyleRecord sr = iwb.getStyleRecord(i);
+                   if(sr!=null) {
+                       sr.setXFIndex(newPos[i]);
+                   }
+
+               }
+
+           }
+
+       }
+
        // Finally, update the cells to point at their new extended format records
        for(int sheetNum=0; sheetNum<workbook.getNumberOfSheets(); sheetNum++) {
+           short oldXf;
+           HSSFCellStyle newStyle;
            HSSFSheet s = workbook.getSheetAt(sheetNum);
+
            for (Row row : s) {
+
+               newStyle = (HSSFCellStyle) row.getRowStyle();
+               if(newStyle != null) {
+                   oldXf = newStyle.getIndex();
+                   newStyle = workbook.getCellStyleAt(newPos[oldXf]);
+                   row.setRowStyle(newStyle);                    
+               }
+
                for (Cell cellI : row) {
                    HSSFCell cell = (HSSFCell)cellI;
-                   short oldXf = cell.getCellValueRecord().getXFIndex();
 
-                   HSSFCellStyle newStyle = workbook.getCellStyleAt(
-                           newPos[oldXf]
-                           );
+                   oldXf = cell.getCellValueRecord().getXFIndex();
+                   newStyle = workbook.getCellStyleAt(newPos[oldXf]);
                    cell.setCellStyle(newStyle);
                }
+
            }
+
+           for(int ci = colmin; ci < colmax; ci++) {
+
+               newStyle = s.getColumnStyle(ci);
+               if(newStyle!=null) {
+                   oldXf = newStyle.getIndex();
+                   newStyle = workbook.getCellStyleAt(newPos[oldXf]);
+                   s.setDefaultColumnStyle(ci, newStyle);
        }
+
+           }
+
    }
+
+   }
+
 }
