View | Details | Raw Unified | Return to bug 57517
Collapse All | Expand All

(-)a/poi/src/org/apache/poi/hssf/usermodel/HSSFOptimiser.java (-31 / +135 lines)
Lines 18-27 package org.apache.poi.hssf.usermodel; Link Here
18
18
19
import java.util.HashSet;
19
import java.util.HashSet;
20
20
21
import org.apache.poi.hssf.model.InternalWorkbook;
21
import org.apache.poi.hssf.record.ExtendedFormatRecord;
22
import org.apache.poi.hssf.record.ExtendedFormatRecord;
22
import org.apache.poi.hssf.record.FontRecord;
23
import org.apache.poi.hssf.record.FontRecord;
24
import org.apache.poi.hssf.record.StyleRecord;
23
import org.apache.poi.hssf.record.common.UnicodeString;
25
import org.apache.poi.hssf.record.common.UnicodeString;
24
import org.apache.poi.ss.usermodel.Cell;
26
import org.apache.poi.ss.usermodel.Cell;
27
import org.apache.poi.ss.usermodel.CellStyle;
25
import org.apache.poi.ss.usermodel.Row;
28
import org.apache.poi.ss.usermodel.Row;
26
29
27
/**
30
/**
Lines 171-192 public class HSSFOptimiser { Link Here
171
     * @param workbook The workbook in which to optimise the cell styles
174
     * @param workbook The workbook in which to optimise the cell styles
172
     */
175
     */
173
    public static void optimiseCellStyles(HSSFWorkbook workbook) {
176
    public static void optimiseCellStyles(HSSFWorkbook workbook) {
174
       // Where each style has ended up, and if we need to
177
        // Where each style has start up, and if we need to
175
       //  delete the record for it. Start off with no change
178
        // delete the record for it. The object is no bultin record.
176
       short[] newPos = new short[workbook.getWorkbook().getNumExFormats()];
179
        // refer to 2.5.282 XFIndex
180
        final short off = 16;
181
        InternalWorkbook iwb = workbook.getWorkbook();
182
        short[] newPos = new short[iwb.getNumExFormats()];
177
        boolean[] isUsed = new boolean[newPos.length];
183
        boolean[] isUsed = new boolean[newPos.length];
178
        boolean[] zapRecords = new boolean[newPos.length];
184
        boolean[] zapRecords = new boolean[newPos.length];
185
        short[] oldParent = new short[newPos.length];
186
        final int colmin = 0;
187
        final int colmax = 255;
188
179
        for (int i = 0; i < newPos.length; i++) {
189
        for (int i = 0; i < newPos.length; i++) {
190
            HSSFCellStyle cs, csp;
180
            isUsed[i] = false;
191
            isUsed[i] = false;
181
            newPos[i] = (short) i;
192
            newPos[i] = (short) i;
182
            zapRecords[i] = false;
193
            zapRecords[i] = false;
194
195
            // Preserve parent indexes.
196
            oldParent[i] = 0;
197
            cs = workbook.getCellStyleAt((short) i);
198
            csp = cs.getParentStyle();
199
            if (csp != null) {
200
                oldParent[i] = csp.getIndex();
201
            }
202
203
            //cell style is used if style exists.
204
            StyleRecord sr = iwb.getStyleRecord(i);
205
            if (sr != null) {
206
                isUsed[i] = true;
207
            }
208
183
        }
209
        }
184
210
185
        // Get each style record, so we can do deletes
211
        // Get each style record, so we can do deletes
186
        // without getting confused
212
        // without getting confused
187
        ExtendedFormatRecord[] xfrs = new ExtendedFormatRecord[newPos.length];
213
        ExtendedFormatRecord[] xfrs = new ExtendedFormatRecord[newPos.length];
214
188
        for (int i = 0; i < newPos.length; i++) {
215
        for (int i = 0; i < newPos.length; i++) {
189
           xfrs[i] = workbook.getWorkbook().getExFormatAt(i);
216
            xfrs[i] = iwb.getExFormatAt(i);
190
        }
217
        }
191
218
192
        // Loop over each style, seeing if it is the same
219
        // Loop over each style, seeing if it is the same
Lines 194-207 public class HSSFOptimiser { Link Here
194
        // later duplicate copy to the earlier one, and
221
        // later duplicate copy to the earlier one, and
195
        // mark the later one as needing deleting
222
        // mark the later one as needing deleting
196
        // Only work on user added ones, which come after 20
223
        // Only work on user added ones, which come after 20
197
       for(int i=21; i<newPos.length; i++) {
224
        for (int i = off; i < newPos.length; i++) {
225
226
            if (isUsed[i]) {
227
                continue;
228
            }
229
198
            // Check this one for being a duplicate
230
            // Check this one for being a duplicate
199
            // of an earlier one
231
            // of an earlier one
200
            int earlierDuplicate = -1;
232
            int earlierDuplicate = -1;
201
           for(int j=0; j<i && earlierDuplicate == -1; j++) {
233
            for (int j = 0; j < i; j++) {
202
               ExtendedFormatRecord xfCheck = workbook.getWorkbook().getExFormatAt(j);
234
                ExtendedFormatRecord xfCheck = iwb.getExFormatAt(j);
203
                if (xfCheck.equals(xfrs[i])) {
235
                if (xfCheck.equals(xfrs[i])) {
204
                    earlierDuplicate = j;
236
                    earlierDuplicate = j;
237
                    break;
205
                }
238
                }
206
            }
239
            }
207
240
Lines 210-239 public class HSSFOptimiser { Link Here
210
                newPos[i] = (short) earlierDuplicate;
243
                newPos[i] = (short) earlierDuplicate;
211
                zapRecords[i] = true;
244
                zapRecords[i] = true;
212
            }
245
            }
213
           // If we got a duplicate, mark the one we're keeping as used
214
           if(earlierDuplicate != -1) {
215
               isUsed[earlierDuplicate] = true;
216
           }
217
        }
246
        }
218
247
219
        // Loop over all the cells in the file, and identify any user defined
248
        // Loop over all the cells in the file, and identify any user defined
220
        // styles aren't actually being used (don't touch built-in ones)
249
        // styles aren't actually being used (don't touch built-in ones)
221
        for (int sheetNum = 0; sheetNum < workbook.getNumberOfSheets(); sheetNum++) {
250
        for (int sheetNum = 0; sheetNum < workbook.getNumberOfSheets(); sheetNum++) {
251
            int ci;
252
            CellStyle cs;
253
            short oldXf;
254
222
            HSSFSheet s = workbook.getSheetAt(sheetNum);
255
            HSSFSheet s = workbook.getSheetAt(sheetNum);
256
223
            for (Row row : s) {
257
            for (Row row : s) {
258
259
                cs = row.getRowStyle();
260
                if (cs != null) {
261
                    oldXf = cs.getIndex();
262
                    isUsed[newPos[oldXf]] = true;
263
                    isUsed[oldParent[oldXf]] = true;
264
                }
265
224
                for (Cell cellI : row) {
266
                for (Cell cellI : row) {
225
                    HSSFCell cell = (HSSFCell) cellI;
267
                    HSSFCell cell = (HSSFCell) cellI;
226
                   short oldXf = cell.getCellValueRecord().getXFIndex();
268
                    oldXf = cell.getCellValueRecord().getXFIndex();
227
                   isUsed[oldXf] = true;
269
                    isUsed[newPos[oldXf]] = true;
270
                    isUsed[oldParent[oldXf]] = true;
271
272
                }
273
274
            }
275
276
            for (ci = colmin; ci <= colmax; ci++) {
277
                cs = s.getColumnStyle(ci);
278
                if (cs != null) {
279
                    oldXf = cs.getIndex();
280
                    isUsed[newPos[oldXf]] = true;
281
                    isUsed[oldParent[oldXf]] = true;
228
                }
282
                }
283
229
            }
284
            }
285
230
        }
286
        }
231
        // Mark any that aren't used as needing zapping
287
        // Mark any that aren't used as needing zapping
232
       for (int i=21; i<isUsed.length; i++) {
288
        for (int i = off; i < isUsed.length; i++) {
233
            if (!isUsed[i]) {
289
            if (!isUsed[i]) {
234
                // Un-used style, can be removed
290
                // Un-used style, can be removed
235
                zapRecords[i] = true;
291
                zapRecords[i] = true;
236
               newPos[i] = 0;
237
            }
292
            }
238
        }
293
        }
239
294
Lines 241-287 public class HSSFOptimiser { Link Here
241
        // deletes that have occurred between
296
        // deletes that have occurred between
242
        // the start and them
297
        // the start and them
243
        // Only work on user added ones, which come after 20
298
        // Only work on user added ones, which come after 20
244
       for(int i=21; i<newPos.length; i++) {
299
        for (int i = off; i < newPos.length; i++) {
245
            // Find the number deleted to that
300
            // Find the number deleted to that
246
            // point, and adjust
301
            // point, and adjust
247
            short preDeletePos = newPos[i];
302
            short preDeletePos = newPos[i];
248
            short newPosition = preDeletePos;
303
            short newPosition = preDeletePos;
249
            for (int j = 0; j < preDeletePos; j++) {
304
            for (int j = 0; j < preDeletePos; j++) {
250
               if(zapRecords[j]) newPosition--;
305
                if (zapRecords[j])
306
                    newPosition--;
251
            }
307
            }
252
308
253
            // Update the new position
309
            // Update the new position
254
            newPos[i] = newPosition;
310
            newPos[i] = newPosition;
255
        }
311
        }
256
312
313
        // Finally, update the cells to point at their new extended format
314
        // records
315
        for (int sheetNum = 0; sheetNum < workbook.getNumberOfSheets(); sheetNum++) {
316
            short oldXf;
317
            HSSFCellStyle newStyle;
318
            HSSFSheet s = workbook.getSheetAt(sheetNum);
319
320
            for (Row row : s) {
321
322
                newStyle = (HSSFCellStyle) row.getRowStyle();
323
                if (newStyle != null) {
324
                    oldXf = newStyle.getIndex();
325
                    newStyle = workbook.getCellStyleAt(newPos[oldXf]);
326
                    row.setRowStyle(newStyle);
327
                }
328
329
                for (Cell cellI : row) {
330
                    HSSFCell cell = (HSSFCell) cellI;
331
332
                    oldXf = cell.getCellValueRecord().getXFIndex();
333
                    newStyle = workbook.getCellStyleAt(newPos[oldXf]);
334
                    cell.setCellStyle(newStyle);
335
                }
336
            }
337
338
            for (int ci = colmin; ci <= colmax; ci++) {
339
340
                newStyle = s.getColumnStyle(ci);
341
                if (newStyle != null) {
342
                    oldXf = newStyle.getIndex();
343
                    newStyle = workbook.getCellStyleAt(newPos[oldXf]);
344
                    s.setDefaultColumnStyle(ci, newStyle);
345
                }
346
347
            }
348
349
        }
350
351
352
257
        // Zap the un-needed user style records
353
        // Zap the un-needed user style records
258
        // removing by index, because removing by object may delete
354
        // removing by index, because removing by object may delete
259
       // styles we did not intend to (the ones that _were_ duplicated and not the duplicates)
355
        // styles we did not intend to (the ones that _were_ duplicated and not
356
        // the duplicates)
260
        int max = newPos.length;
357
        int max = newPos.length;
261
        int removed = 0; // to adjust index after deletion
358
        int removed = 0; // to adjust index after deletion
262
       for(int i=21; i<max; i++) {
359
        for (int i = off; i < max; i++) {
263
            if (zapRecords[i + removed]) {
360
            if (zapRecords[i + removed]) {
264
               workbook.getWorkbook().removeExFormatRecord(i);
361
                iwb.removeExFormatRecord(i);
265
                i--;
362
                i--;
266
                max--;
363
                max--;
267
                removed++;
364
                removed++;
268
            }
365
            }
269
        }
366
        }
270
367
271
       // Finally, update the cells to point at their new extended format records
368
        for (int i = off; i < newPos.length; i++) {
272
       for(int sheetNum=0; sheetNum<workbook.getNumberOfSheets(); sheetNum++) {
369
            if (!zapRecords[i]) {
273
           HSSFSheet s = workbook.getSheetAt(sheetNum);
370
                // Edit existing record infomation.
274
           for (Row row : s) {
371
275
               for (Cell cellI : row) {
372
                // Change parent index.
276
                   HSSFCell cell = (HSSFCell)cellI;
373
                iwb.getExFormatAt(newPos[i]).setParentIndex(newPos[oldParent[i]]);
277
                   short oldXf = cell.getCellValueRecord().getXFIndex();
374
375
                //Style record move to the new position.
376
                if(newPos[i] < i) {
377
378
                    //Move style record.
379
                    StyleRecord sr = iwb.getStyleRecord(i);
380
                    if(sr!=null) {
381
                        sr.setXFIndex(newPos[i]);
382
                    }
278
383
279
                   HSSFCellStyle newStyle = workbook.getCellStyleAt(
280
                           newPos[oldXf]
281
                           );
282
                   cell.setCellStyle(newStyle);
283
                }
384
                }
284
            }
385
            }
386
285
        }
387
        }
388
286
    }
389
    }
390
287
}
391
}

Return to bug 57517