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 173-192
public class HSSFOptimiser {
Link Here
|
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 ended up, and if we need to |
175 |
// delete the record for it. Start off with no change |
178 |
// delete the record for it. Start off with no change |
176 |
short[] newPos = new short[workbook.getWorkbook().getNumExFormats()]; |
179 |
final short off = 1; |
|
|
180 |
InternalWorkbook iwb = workbook.getWorkbook(); |
181 |
short[] newPos = new short[iwb.getNumExFormats()]; |
177 |
boolean[] isUsed = new boolean[newPos.length]; |
182 |
boolean[] isUsed = new boolean[newPos.length]; |
178 |
boolean[] zapRecords = new boolean[newPos.length]; |
183 |
boolean[] zapRecords = new boolean[newPos.length]; |
|
|
184 |
short[] oldParent = new short[newPos.length]; |
185 |
int colmin; |
186 |
int colmax; |
187 |
|
179 |
for(int i=0; i<newPos.length; i++) { |
188 |
for(int i=0; i<newPos.length; i++) { |
|
|
189 |
HSSFCellStyle cs, csp; |
180 |
isUsed[i] = false; |
190 |
isUsed[i] = false; |
181 |
newPos[i] = (short)i; |
191 |
newPos[i] = (short)i; |
182 |
zapRecords[i] = false; |
192 |
zapRecords[i] = false; |
|
|
193 |
|
194 |
//Preserve parent indexes. |
195 |
oldParent[i] = 0; |
196 |
cs = workbook.getCellStyleAt((short)i); |
197 |
csp = cs.getParentStyle(); |
198 |
if(csp != null) { |
199 |
oldParent[i] = csp.getIndex(); |
200 |
} |
201 |
|
202 |
//User defined styles is used. |
203 |
if(cs.getUserStyleName() != null) { |
204 |
isUsed[i] = true; |
205 |
} |
206 |
|
207 |
//Builtin style is used. |
208 |
StyleRecord sr = iwb.getStyleRecord(i); |
209 |
if(sr != null) { |
210 |
if(sr.isBuiltin()) { |
211 |
isUsed[i] = true; |
212 |
} |
213 |
} |
214 |
|
183 |
} |
215 |
} |
184 |
|
216 |
|
185 |
// Get each style record, so we can do deletes |
217 |
// Get each style record, so we can do deletes |
186 |
// without getting confused |
218 |
// without getting confused |
187 |
ExtendedFormatRecord[] xfrs = new ExtendedFormatRecord[newPos.length]; |
219 |
ExtendedFormatRecord[] xfrs = new ExtendedFormatRecord[newPos.length]; |
188 |
for(int i=0; i<newPos.length; i++) { |
220 |
for(int i=0; i<newPos.length; i++) { |
189 |
xfrs[i] = workbook.getWorkbook().getExFormatAt(i); |
221 |
xfrs[i] = iwb.getExFormatAt(i); |
190 |
} |
222 |
} |
191 |
|
223 |
|
192 |
// Loop over each style, seeing if it is the same |
224 |
// 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 |
226 |
// later duplicate copy to the earlier one, and |
195 |
// mark the later one as needing deleting |
227 |
// mark the later one as needing deleting |
196 |
// Only work on user added ones, which come after 20 |
228 |
// Only work on user added ones, which come after 20 |
197 |
for(int i=21; i<newPos.length; i++) { |
229 |
for(int i=off; i<newPos.length; i++) { |
|
|
230 |
|
231 |
if(isUsed[i]) |
232 |
{ |
233 |
continue; |
234 |
} |
235 |
|
198 |
// Check this one for being a duplicate |
236 |
// Check this one for being a duplicate |
199 |
// of an earlier one |
237 |
// of an earlier one |
200 |
int earlierDuplicate = -1; |
238 |
int earlierDuplicate = -1; |
201 |
for(int j=0; j<i && earlierDuplicate == -1; j++) { |
239 |
for(int j=0; j<i; j++) { |
202 |
ExtendedFormatRecord xfCheck = workbook.getWorkbook().getExFormatAt(j); |
240 |
ExtendedFormatRecord xfCheck = iwb.getExFormatAt(j); |
203 |
if(xfCheck.equals(xfrs[i])) { |
241 |
if(xfCheck.equals(xfrs[i]) ) { |
204 |
earlierDuplicate = j; |
242 |
earlierDuplicate = j; |
|
|
243 |
break; |
205 |
} |
244 |
} |
206 |
} |
245 |
} |
207 |
|
246 |
|
Lines 210-239
public class HSSFOptimiser {
Link Here
|
210 |
newPos[i] = (short)earlierDuplicate; |
249 |
newPos[i] = (short)earlierDuplicate; |
211 |
zapRecords[i] = true; |
250 |
zapRecords[i] = true; |
212 |
} |
251 |
} |
213 |
// If we got a duplicate, mark the one we're keeping as used |
|
|
214 |
if(earlierDuplicate != -1) { |
215 |
isUsed[earlierDuplicate] = true; |
216 |
} |
217 |
} |
252 |
} |
218 |
|
253 |
|
219 |
// Loop over all the cells in the file, and identify any user defined |
254 |
// 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) |
255 |
// styles aren't actually being used (don't touch built-in ones) |
|
|
256 |
colmin = 0; |
257 |
colmax = -1; |
221 |
for(int sheetNum=0; sheetNum<workbook.getNumberOfSheets(); sheetNum++) { |
258 |
for(int sheetNum=0; sheetNum<workbook.getNumberOfSheets(); sheetNum++) { |
|
|
259 |
int ci; |
260 |
CellStyle cs; |
261 |
short oldXf; |
262 |
|
222 |
HSSFSheet s = workbook.getSheetAt(sheetNum); |
263 |
HSSFSheet s = workbook.getSheetAt(sheetNum); |
|
|
264 |
|
223 |
for (Row row : s) { |
265 |
for (Row row : s) { |
|
|
266 |
|
267 |
cs = row.getRowStyle(); |
268 |
if(cs!=null) { |
269 |
oldXf = cs.getIndex(); |
270 |
isUsed[newPos[oldXf]] = true; |
271 |
isUsed[oldParent[oldXf]] = true; |
272 |
} |
273 |
|
224 |
for (Cell cellI : row) { |
274 |
for (Cell cellI : row) { |
225 |
HSSFCell cell = (HSSFCell)cellI; |
275 |
HSSFCell cell = (HSSFCell)cellI; |
226 |
short oldXf = cell.getCellValueRecord().getXFIndex(); |
276 |
oldXf = cell.getCellValueRecord().getXFIndex(); |
227 |
isUsed[oldXf] = true; |
277 |
isUsed[newPos[oldXf]] = true; |
|
|
278 |
isUsed[oldParent[oldXf]] = true; |
279 |
|
280 |
ci = cellI.getColumnIndex(); |
281 |
if(colmin <= colmax) { |
282 |
|
283 |
if(ci < colmin) { |
284 |
colmin = ci; |
285 |
} |
286 |
else if(ci > colmax) { |
287 |
colmax = ci; |
288 |
} |
289 |
|
290 |
} |
291 |
else { |
292 |
colmin = ci; |
293 |
colmax = ci; |
294 |
} |
295 |
|
296 |
} |
297 |
|
298 |
} |
299 |
|
300 |
for(ci = colmin; ci <= colmax; ci++) |
301 |
{ |
302 |
cs = s.getColumnStyle(ci); |
303 |
if(cs!=null) |
304 |
{ |
305 |
oldXf = cs.getIndex(); |
306 |
isUsed[newPos[oldXf]] = true; |
307 |
isUsed[oldParent[oldXf]] = true; |
228 |
} |
308 |
} |
|
|
309 |
|
229 |
} |
310 |
} |
|
|
311 |
|
230 |
} |
312 |
} |
231 |
// Mark any that aren't used as needing zapping |
313 |
// Mark any that aren't used as needing zapping |
232 |
for (int i=21; i<isUsed.length; i++) { |
314 |
for (int i=off; i<isUsed.length; i++) { |
233 |
if (! isUsed[i]) { |
315 |
if (! isUsed[i]) { |
234 |
// Un-used style, can be removed |
316 |
// Un-used style, can be removed |
235 |
zapRecords[i] = true; |
317 |
zapRecords[i] = true; |
236 |
newPos[i] = 0; |
|
|
237 |
} |
318 |
} |
238 |
} |
319 |
} |
239 |
|
320 |
|
Lines 241-247
public class HSSFOptimiser {
Link Here
|
241 |
// deletes that have occurred between |
322 |
// deletes that have occurred between |
242 |
// the start and them |
323 |
// the start and them |
243 |
// Only work on user added ones, which come after 20 |
324 |
// Only work on user added ones, which come after 20 |
244 |
for(int i=21; i<newPos.length; i++) { |
325 |
for(int i=off; i<newPos.length; i++) { |
245 |
// Find the number deleted to that |
326 |
// Find the number deleted to that |
246 |
// point, and adjust |
327 |
// point, and adjust |
247 |
short preDeletePos = newPos[i]; |
328 |
short preDeletePos = newPos[i]; |
Lines 259-287
public class HSSFOptimiser {
Link Here
|
259 |
// styles we did not intend to (the ones that _were_ duplicated and not the duplicates) |
340 |
// styles we did not intend to (the ones that _were_ duplicated and not the duplicates) |
260 |
int max = newPos.length; |
341 |
int max = newPos.length; |
261 |
int removed = 0; // to adjust index after deletion |
342 |
int removed = 0; // to adjust index after deletion |
262 |
for(int i=21; i<max; i++) { |
343 |
for(int i=off; i<max; i++) { |
263 |
if(zapRecords[i + removed]) { |
344 |
if(zapRecords[i + removed]) { |
264 |
workbook.getWorkbook().removeExFormatRecord(i); |
345 |
iwb.removeExFormatRecord(i); |
|
|
346 |
//Delete the old record. |
347 |
StyleRecord sr = iwb.getStyleRecord(i + removed); |
348 |
if(sr != null) |
349 |
{ |
350 |
iwb.getRecords().remove(sr); |
351 |
} |
265 |
i--; |
352 |
i--; |
266 |
max--; |
353 |
max--; |
267 |
removed++; |
354 |
removed++; |
268 |
} |
355 |
} |
269 |
} |
356 |
} |
270 |
|
357 |
|
|
|
358 |
|
359 |
for(int i=off; i<newPos.length; i++) { |
360 |
if(!zapRecords[i] ) { |
361 |
//Edit existing record infomation. |
362 |
|
363 |
//Change parent index. |
364 |
iwb.getExFormatAt(newPos[i]).setParentIndex(newPos[oldParent[i]]); |
365 |
|
366 |
//Delete the old record before record move the new position. |
367 |
if(newPos[i] < i) { |
368 |
|
369 |
//Move style record. |
370 |
StyleRecord sr = iwb.getStyleRecord(i); |
371 |
if(sr!=null) { |
372 |
sr.setXFIndex(newPos[i]); |
373 |
} |
374 |
|
375 |
} |
376 |
|
377 |
} |
378 |
|
379 |
} |
380 |
|
271 |
// Finally, update the cells to point at their new extended format records |
381 |
// Finally, update the cells to point at their new extended format records |
272 |
for(int sheetNum=0; sheetNum<workbook.getNumberOfSheets(); sheetNum++) { |
382 |
for(int sheetNum=0; sheetNum<workbook.getNumberOfSheets(); sheetNum++) { |
|
|
383 |
short oldXf; |
384 |
HSSFCellStyle newStyle; |
273 |
HSSFSheet s = workbook.getSheetAt(sheetNum); |
385 |
HSSFSheet s = workbook.getSheetAt(sheetNum); |
|
|
386 |
|
274 |
for (Row row : s) { |
387 |
for (Row row : s) { |
|
|
388 |
|
389 |
newStyle = (HSSFCellStyle) row.getRowStyle(); |
390 |
if(newStyle != null) { |
391 |
oldXf = newStyle.getIndex(); |
392 |
newStyle = workbook.getCellStyleAt(newPos[oldXf]); |
393 |
row.setRowStyle(newStyle); |
394 |
} |
395 |
|
275 |
for (Cell cellI : row) { |
396 |
for (Cell cellI : row) { |
276 |
HSSFCell cell = (HSSFCell)cellI; |
397 |
HSSFCell cell = (HSSFCell)cellI; |
277 |
short oldXf = cell.getCellValueRecord().getXFIndex(); |
|
|
278 |
|
398 |
|
279 |
HSSFCellStyle newStyle = workbook.getCellStyleAt( |
399 |
oldXf = cell.getCellValueRecord().getXFIndex(); |
280 |
newPos[oldXf] |
400 |
newStyle = workbook.getCellStyleAt(newPos[oldXf]); |
281 |
); |
|
|
282 |
cell.setCellStyle(newStyle); |
401 |
cell.setCellStyle(newStyle); |
283 |
} |
402 |
} |
|
|
403 |
|
284 |
} |
404 |
} |
|
|
405 |
|
406 |
for(int ci = colmin; ci < colmax; ci++) { |
407 |
|
408 |
newStyle = s.getColumnStyle(ci); |
409 |
if(newStyle!=null) { |
410 |
oldXf = newStyle.getIndex(); |
411 |
newStyle = workbook.getCellStyleAt(newPos[oldXf]); |
412 |
s.setDefaultColumnStyle(ci, newStyle); |
285 |
} |
413 |
} |
|
|
414 |
|
415 |
} |
416 |
|
286 |
} |
417 |
} |
|
|
418 |
|
419 |
} |
420 |
|
287 |
} |
421 |
} |