diff --git a/poi/src/org/apache/poi/hssf/usermodel/HSSFOptimiser.java b/poi/src/org/apache/poi/hssf/usermodel/HSSFOptimiser.java
index 238b89e..738b942 100644
--- a/poi/src/org/apache/poi/hssf/usermodel/HSSFOptimiser.java
+++ b/poi/src/org/apache/poi/hssf/usermodel/HSSFOptimiser.java
@@ -18,10 +18,13 @@ package org.apache.poi.hssf.usermodel;
 
 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;
 
 /**
@@ -171,22 +174,46 @@ public class HSSFOptimiser {
      * @param workbook The workbook in which to optimise the cell styles
      */
     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()];
+        // Where each style has start up, and if we need to
+        // delete the record for it. The object is no bultin record.
+        // refer to 2.5.282 XFIndex
+        final short off = 16;
+        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];
+        final int colmin = 0;
+        final int colmax = 255;
+
         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();
+            }
+
+            //cell style is used if style exists.
+            StyleRecord sr = iwb.getStyleRecord(i);
+            if (sr != null) {
+                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);
+            xfrs[i] = iwb.getExFormatAt(i);
         }
 
         // Loop over each style, seeing if it is the same
@@ -194,14 +221,20 @@ public class HSSFOptimiser {
         // 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);
+            for (int j = 0; j < i; j++) {
+                ExtendedFormatRecord xfCheck = iwb.getExFormatAt(j);
                 if (xfCheck.equals(xfrs[i])) {
                     earlierDuplicate = j;
+                    break;
                 }
             }
 
@@ -210,30 +243,52 @@ public class HSSFOptimiser {
                 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)
         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;
+
+                }
+
+            }
+
+            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,47 +296,96 @@ public class HSSFOptimiser {
         // 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];
             short newPosition = preDeletePos;
             for (int j = 0; j < preDeletePos; j++) {
-               if(zapRecords[j]) newPosition--;
+                if (zapRecords[j])
+                    newPosition--;
             }
 
             // Update the new position
             newPos[i] = newPosition;
         }
 
+        // 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;
+
+                    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);
+                }
+
+            }
+
+        }
+
+
+
         // 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)
+        // 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);
                 i--;
                 max--;
                 removed++;
             }
         }
 
-       // Finally, update the cells to point at their new extended format records
-       for(int sheetNum=0; sheetNum<workbook.getNumberOfSheets(); sheetNum++) {
-           HSSFSheet s = workbook.getSheetAt(sheetNum);
-           for (Row row : s) {
-               for (Cell cellI : row) {
-                   HSSFCell cell = (HSSFCell)cellI;
-                   short oldXf = cell.getCellValueRecord().getXFIndex();
+        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]]);
+
+                //Style record move to the new position.
+                if(newPos[i] < i) {
+
+                    //Move style record.
+                    StyleRecord sr = iwb.getStyleRecord(i);
+                    if(sr!=null) {
+                        sr.setXFIndex(newPos[i]);
+                    }
 
-                   HSSFCellStyle newStyle = workbook.getCellStyleAt(
-                           newPos[oldXf]
-                           );
-                   cell.setCellStyle(newStyle);
                 }
             }
+
         }
+
     }
+
 }

