1 19 20 package jxl.write.biff; 21 22 import java.io.IOException ; 23 import java.util.TreeSet ; 24 import java.util.Comparator ; 25 import java.util.Iterator ; 26 import java.util.ArrayList ; 27 28 import common.Assert; 29 import common.Logger; 30 31 import jxl.Cell; 32 import jxl.LabelCell; 33 import jxl.NumberCell; 34 import jxl.CellType; 35 import jxl.Sheet; 36 import jxl.LabelCell; 37 import jxl.DateCell; 38 import jxl.BooleanCell; 39 import jxl.Hyperlink; 40 import jxl.Range; 41 import jxl.SheetSettings; 42 import jxl.WorkbookSettings; 43 import jxl.CellView; 44 import jxl.Image; 45 import jxl.HeaderFooter; 46 import jxl.format.CellFormat; 47 import jxl.format.Border; 48 import jxl.format.BorderLineStyle; 49 import jxl.format.PageOrientation; 50 import jxl.format.PaperSize; 51 import jxl.write.Blank; 52 import jxl.write.WritableWorkbook; 53 import jxl.write.WritableSheet; 54 import jxl.write.WritableCell; 55 import jxl.write.Label; 56 import jxl.write.Number; 57 import jxl.write.DateTime; 58 import jxl.write.WriteException; 59 import jxl.write.Boolean; 60 import jxl.write.WritableHyperlink; 61 import jxl.write.WritableImage; 62 63 import jxl.biff.IntegerHelper; 64 import jxl.biff.WritableRecordData; 65 import jxl.biff.FormattingRecords; 66 import jxl.biff.EmptyCell; 67 import jxl.biff.XFRecord; 68 import jxl.biff.NumFormatRecordsException; 69 import jxl.biff.FormulaData; 70 import jxl.biff.SheetRangeImpl; 71 import jxl.biff.IndexMapping; 72 import jxl.biff.WorkspaceInformationRecord; 73 74 import jxl.biff.drawing.Chart; 75 import jxl.biff.drawing.DrawingGroupObject; 76 import jxl.biff.drawing.Drawing; 77 78 82 class WritableSheetImpl implements WritableSheet 83 { 84 87 private static Logger logger = Logger.getLogger(WritableSheetImpl.class); 88 89 92 private String name; 93 96 private File outputFile; 97 100 private RowRecord[] rows; 101 104 private FormattingRecords formatRecords; 105 108 private SharedStrings sharedStrings; 109 110 113 private TreeSet columnFormats; 114 115 118 private ArrayList hyperlinks; 119 120 123 private MergedCells mergedCells; 124 125 128 private int numRows; 129 130 133 private int numColumns; 134 135 138 private PLSRecord plsRecord; 139 140 143 private ButtonPropertySetRecord buttonPropertySet; 144 145 148 private boolean chartOnly; 149 150 153 private DataValidation dataValidation; 154 155 158 private ArrayList rowBreaks; 159 160 163 private ArrayList drawings; 164 165 168 private ArrayList images; 169 170 174 private boolean drawingsModified; 175 176 179 private SheetSettings settings; 180 181 184 private SheetWriter sheetWriter; 185 186 189 private WorkbookSettings workbookSettings; 190 191 194 private WritableWorkbookImpl workbook; 195 196 199 private final static int rowGrowSize = 10; 200 201 204 private final static int numRowsPerSheet = 65536; 205 206 209 private final static int maxSheetNameLength = 31; 210 211 214 private final static char[] illegalSheetNameCharacters = 215 new char[] {'*', ':', '?', '\\'}; 216 217 220 private static final String [] imageTypes = new String [] {"png"}; 221 222 225 private static class ColumnInfoComparator implements Comparator 226 { 227 233 public boolean equals(Object o) 234 { 235 return o == this; 236 } 237 238 245 public int compare(Object o1, Object o2) 246 { 247 if (o1 == o2) 248 { 249 return 0; 250 } 251 252 Assert.verify(o1 instanceof ColumnInfoRecord); 253 Assert.verify(o2 instanceof ColumnInfoRecord); 254 255 ColumnInfoRecord ci1 = (ColumnInfoRecord) o1; 256 ColumnInfoRecord ci2 = (ColumnInfoRecord) o2; 257 258 return ci1.getColumn() - ci2.getColumn(); 259 } 260 } 261 262 272 public WritableSheetImpl(String n, 273 File of, 274 FormattingRecords fr, 275 SharedStrings ss, 276 WorkbookSettings ws, 277 WritableWorkbookImpl ww) 278 { 279 name = validateName(n); 280 outputFile = of; 281 rows = new RowRecord[0]; 282 numRows = 0; 283 numColumns = 0; 284 chartOnly = false; 285 workbook = ww; 286 287 formatRecords = fr; 288 sharedStrings = ss; 289 workbookSettings = ws; 290 drawingsModified = false; 291 columnFormats = new TreeSet (new ColumnInfoComparator()); 292 hyperlinks = new ArrayList (); 293 mergedCells = new MergedCells(this); 294 rowBreaks = new ArrayList (); 295 drawings = new ArrayList (); 296 images = new ArrayList (); 297 settings = new SheetSettings(); 298 299 300 sheetWriter = new SheetWriter(outputFile, 301 this, 302 workbookSettings); 303 } 304 305 312 public Cell getCell(int column, int row) 313 { 314 return getWritableCell(column, row); 315 } 316 317 324 public WritableCell getWritableCell(int column, int row) 325 { 326 WritableCell c = null; 327 328 if (row < rows.length && rows[row] != null) 329 { 330 c = rows[row].getCell(column); 331 } 332 333 if (c == null) 334 { 335 c = new EmptyCell(column, row); 336 } 337 338 return c; 339 } 340 341 346 public int getRows() 347 { 348 return numRows; 349 } 350 351 356 public int getColumns() 357 { 358 return numColumns; 359 } 360 361 370 public Cell findCell(String contents) 371 { 372 Cell cell = null; 373 boolean found = false; 374 375 for (int i = 0 ; i < getRows() && found == false; i++) 376 { 377 Cell[] row = getRow(i); 378 for (int j = 0 ; j < row.length && found == false; j++) 379 { 380 if (row[j].getContents().equals(contents)) 381 { 382 cell = row[j]; 383 found = true; 384 } 385 } 386 } 387 388 return cell; 389 } 390 391 403 public LabelCell findLabelCell(String contents) 404 { 405 LabelCell cell = null; 406 boolean found = false; 407 408 for (int i = 0 ; i < getRows() && found == false; i++) 409 { 410 Cell[] row = getRow(i); 411 for (int j = 0 ; j < row.length && found == false; j++) 412 { 413 if ( ( row[j].getType() == CellType.LABEL || 414 row[j].getType() == CellType.STRING_FORMULA) && 415 row[j].getContents().equals(contents)) 416 { 417 cell = (LabelCell) row[j]; 418 found = true; 419 } 420 } 421 } 422 423 return cell; 424 } 425 426 432 public Cell[] getRow(int row) 433 { 434 boolean found = false; 436 int col = numColumns - 1; 437 while (col >= 0 && !found) 438 { 439 if (getCell(col, row).getType() != CellType.EMPTY) 440 { 441 found = true; 442 } 443 else 444 { 445 col--; 446 } 447 } 448 449 Cell[] cells = new Cell[col+1]; 451 452 for (int i = 0; i <= col; i++) 453 { 454 cells[i] = getCell(i, row); 455 } 456 return cells; 457 } 458 459 465 public Cell[] getColumn(int col) 466 { 467 boolean found = false; 469 int row = numRows - 1; 470 471 while (row >= 0 && !found) 472 { 473 if (getCell(col, row).getType() != CellType.EMPTY) 474 { 475 found = true; 476 } 477 else 478 { 479 row--; 480 } 481 } 482 483 Cell[] cells = new Cell[row+1]; 485 486 for (int i = 0; i <= row; i++) 487 { 488 cells[i] = getCell(col, i); 489 } 490 return cells; 491 } 492 493 498 public String getName() 499 { 500 return name; 501 } 502 503 509 public void insertRow(int row) 510 { 511 if (row < 0 || row >= numRows) 512 { 513 return; 514 } 515 516 RowRecord[] oldRows = rows; 518 519 if (numRows == rows.length) 520 { 521 rows = new RowRecord[oldRows.length + rowGrowSize]; 522 } 523 else 524 { 525 rows = new RowRecord[oldRows.length]; 526 } 527 528 System.arraycopy(oldRows, 0, rows, 0, row); 530 531 System.arraycopy(oldRows, row, rows, row+1, numRows - row); 533 534 for (int i = row+1; i <= numRows; i++) 536 { 537 if (rows[i] != null) 538 { 539 rows[i].incrementRow(); 540 } 541 } 542 543 HyperlinkRecord hr = null; 545 Iterator i = hyperlinks.iterator(); 546 while (i.hasNext()) 547 { 548 hr = (HyperlinkRecord) i.next(); 549 hr.insertRow(row); 550 } 551 552 if (dataValidation != null) 554 { 555 dataValidation.insertRow(row); 556 } 557 558 mergedCells.insertRow(row); 560 561 ArrayList newRowBreaks = new ArrayList (); 563 Iterator ri = rowBreaks.iterator(); 564 while (ri.hasNext()) 565 { 566 int val = ( (Integer ) ri.next()).intValue(); 567 if (val >= row) 568 { 569 val++; 570 } 571 572 newRowBreaks.add(new Integer (val)); 573 } 574 rowBreaks = newRowBreaks; 575 576 if (workbookSettings.getFormulaAdjust()) 578 { 579 workbook.rowInserted(this, row); 580 } 581 582 numRows++; 584 } 585 586 592 public void insertColumn(int col) 593 { 594 if (col < 0 || col >= numColumns) 595 { 596 return; 597 } 598 599 for (int i = 0 ; i < numRows ; i++) 601 { 602 if (rows[i] != null) 603 { 604 rows[i].insertColumn(col); 605 } 606 } 607 608 HyperlinkRecord hr = null; 610 Iterator i = hyperlinks.iterator(); 611 while (i.hasNext()) 612 { 613 hr = (HyperlinkRecord) i.next(); 614 hr.insertColumn(col); 615 } 616 617 i = columnFormats.iterator(); 619 while (i.hasNext()) 620 { 621 ColumnInfoRecord cir = (ColumnInfoRecord) i.next(); 622 623 if (cir.getColumn() >= col) 624 { 625 cir.incrementColumn(); 626 } 627 } 628 629 if (dataValidation != null) 631 { 632 dataValidation.insertColumn(col); 633 } 634 635 mergedCells.insertColumn(col); 637 638 if (workbookSettings.getFormulaAdjust()) 640 { 641 workbook.columnInserted(this, col); 642 } 643 644 numColumns++; 645 } 646 647 653 public void removeColumn(int col) 654 { 655 if (col < 0 || col >= numColumns) 656 { 657 return; 658 } 659 660 for (int i = 0 ; i < numRows ; i++) 662 { 663 if (rows[i] != null) 664 { 665 rows[i].removeColumn(col); 666 } 667 } 668 669 HyperlinkRecord hr = null; 671 Iterator i = hyperlinks.iterator(); 672 while (i.hasNext()) 673 { 674 hr = (HyperlinkRecord) i.next(); 675 676 if (hr.getColumn() == col && 677 hr.getLastColumn() == col) 678 { 679 hyperlinks.remove(hyperlinks.indexOf(hr)); 682 } 683 else 684 { 685 hr.removeColumn(col); 686 } 687 } 688 689 if (dataValidation != null) 691 { 692 dataValidation.removeColumn(col); 693 } 694 695 mergedCells.removeColumn(col); 697 698 i = columnFormats.iterator(); 700 ColumnInfoRecord removeColumn = null; 701 while (i.hasNext()) 702 { 703 ColumnInfoRecord cir = (ColumnInfoRecord) i.next(); 704 705 if (cir.getColumn() == col) 706 { 707 removeColumn = cir; 708 } 709 else if (cir.getColumn() > col) 710 { 711 cir.decrementColumn(); 712 } 713 } 714 715 if (removeColumn != null) 716 { 717 columnFormats.remove(removeColumn); 718 } 719 720 if (workbookSettings.getFormulaAdjust()) 722 { 723 workbook.columnRemoved(this, col); 724 } 725 726 numColumns--; 727 } 728 729 735 public void removeRow(int row) 736 { 737 if (row < 0 || row >= numRows) 738 { 739 return; 740 } 741 742 RowRecord[] oldRows = rows; 744 745 rows = new RowRecord[oldRows.length]; 746 747 System.arraycopy(oldRows, 0, rows, 0, row); 749 750 System.arraycopy(oldRows, row + 1, rows, row, numRows - (row + 1)); 752 753 for (int i = row; i < numRows; i++) 755 { 756 if (rows[i] != null) 757 { 758 rows[i].decrementRow(); 759 } 760 } 761 762 HyperlinkRecord hr = null; 764 Iterator i = hyperlinks.iterator(); 765 while (i.hasNext()) 766 { 767 hr = (HyperlinkRecord) i.next(); 768 769 if (hr.getRow() == row && 770 hr.getLastRow() == row) 771 { 772 i.remove(); 775 } 776 else 777 { 778 hr.removeRow(row); 779 } 780 } 781 782 if (dataValidation != null) 784 { 785 dataValidation.removeRow(row); 786 } 787 788 mergedCells.removeRow(row); 790 791 ArrayList newRowBreaks = new ArrayList (); 793 Iterator ri = rowBreaks.iterator(); 794 while (ri.hasNext()) 795 { 796 int val = ( (Integer ) ri.next()).intValue(); 797 798 if (val != row) 799 { 800 if (val > row) 801 { 802 val--; 803 } 804 805 newRowBreaks.add(new Integer (val)); 806 } 807 } 808 809 rowBreaks = newRowBreaks; 810 811 if (workbookSettings.getFormulaAdjust()) 813 { 814 workbook.rowRemoved(this, row); 815 } 816 817 numRows--; 819 } 820 821 838 public void addCell(WritableCell cell) 839 throws WriteException, RowsExceededException 840 { 841 if (cell.getType() == CellType.EMPTY) 842 { 843 if (cell != null && cell.getCellFormat() == null) 844 { 845 return; 848 } 849 } 850 851 CellValue cv = (CellValue) cell; 852 853 if (cv.isReferenced()) 854 { 855 throw new JxlWriteException(JxlWriteException.cellReferenced); 856 } 857 858 int row = cell.getRow(); 859 RowRecord rowrec = getRowRecord(row); 860 rowrec.addCell(cv); 861 862 numRows = Math.max(row+1, numRows); 864 numColumns = Math.max(numColumns, rowrec.getMaxColumn()); 865 866 cv.setCellDetails(formatRecords, sharedStrings, this); 869 } 870 871 879 private RowRecord getRowRecord(int row) throws RowsExceededException 880 { 881 if (row >= numRowsPerSheet) 882 { 883 throw new RowsExceededException(); 884 } 885 886 if (row >= rows.length) 890 { 891 RowRecord[] oldRows = rows; 892 rows = new RowRecord[Math.max(oldRows.length + rowGrowSize, row+1)]; 893 System.arraycopy(oldRows, 0, rows, 0, oldRows.length); 894 oldRows = null; 895 } 896 897 RowRecord rowrec = rows[row]; 898 899 if (rowrec == null) 900 { 901 rowrec = new RowRecord(row); 902 rows[row] = rowrec; 903 } 904 905 return rowrec; 906 } 907 908 914 RowRecord getRowInfo(int r) 915 { 916 if (r < 0 || r > rows.length) 917 { 918 return null; 919 } 920 921 return rows[r]; 922 } 923 924 930 ColumnInfoRecord getColumnInfo(int c) 931 { 932 Iterator i = columnFormats.iterator(); 933 ColumnInfoRecord cir = null; 934 boolean stop = false; 935 936 while (i.hasNext() && !stop) 937 { 938 cir = (ColumnInfoRecord) i.next(); 939 940 if (cir.getColumn() >= c) 941 { 942 stop = true; 943 } 944 } 945 946 if (!stop) 947 { 948 return null; 949 } 950 951 return cir.getColumn() == c ? cir : null; 952 } 953 954 959 public void setName(String n) 960 { 961 name = n; 962 } 963 964 970 public void setHidden(boolean h) 971 { 972 settings.setHidden(h); 973 } 974 975 981 public void setProtected(boolean prot) 982 { 983 settings.setProtected(prot); 984 } 985 986 990 public void setSelected() 991 { 992 settings.setSelected(); 993 } 994 995 1001 public boolean isHidden() 1002 { 1003 return settings.isHidden(); 1004 } 1005 1006 1012 public void setColumnView(int col, int width) 1013 { 1014 CellView cv = new CellView(); 1015 cv.setSize(width * 256); 1016 setColumnView(col, cv); 1017 } 1018 1019 1027 public void setColumnView(int col, int width, CellFormat format) 1028 { 1029 CellView cv = new CellView(); 1030 cv.setSize(width * 256); 1031 cv.setFormat(format); 1032 setColumnView(col, cv); 1033 } 1034 1035 1041 public void setColumnView(int col, CellView view) 1042 { 1043 XFRecord xfr = (XFRecord) view.getFormat(); 1044 if (xfr == null) 1045 { 1046 Styles styles = getWorkbook().getStyles(); 1047 xfr = (XFRecord) styles.getNormalStyle(); 1048 } 1049 1050 try 1051 { 1052 if (!xfr.isInitialized()) 1053 { 1054 formatRecords.addStyle(xfr); 1055 } 1056 1057 int width = view.depUsed() ? view.getDimension() * 256 : view.getSize(); 1058 1059 ColumnInfoRecord cir = new ColumnInfoRecord(col, 1060 width, 1061 xfr); 1062 1063 if (view.isHidden()) 1064 { 1065 cir.setHidden(true); 1066 } 1067 1068 if (!columnFormats.contains(cir)) 1069 { 1070 columnFormats.add(cir); 1071 } 1072 else 1073 { 1074 boolean removed = columnFormats.remove(cir); 1075 columnFormats.add(cir); 1076 } 1077 } 1078 catch (NumFormatRecordsException e) 1079 { 1080 logger.warn("Maximum number of format records exceeded. Using " + 1081 "default format."); 1082 1083 ColumnInfoRecord cir = new ColumnInfoRecord 1084 (col, view.getDimension()*256, 1085 (XFRecord) WritableWorkbook.NORMAL_STYLE); 1086 if (!columnFormats.contains(cir)) 1087 { 1088 columnFormats.add(cir); 1089 } 1090 } 1091 } 1092 1093 1094 1101 public void setRowView(int row, int height) throws RowsExceededException 1102 { 1103 setRowView(row, height, false); 1104 } 1105 1106 1113 public void setRowView(int row, boolean collapsed) 1114 throws RowsExceededException 1115 { 1116 RowRecord rowrec = getRowRecord(row); 1117 rowrec.setCollapsed(collapsed); 1118 } 1119 1120 1129 public void setRowView(int row, int height, 1130 boolean collapsed) 1131 throws RowsExceededException 1132 { 1133 RowRecord rowrec = getRowRecord(row); 1134 rowrec.setRowHeight(height); 1135 rowrec.setCollapsed(collapsed); 1136 } 1137 1138 1145 public void write() throws IOException 1146 { 1147 boolean dmod = drawingsModified; 1148 if (workbook.getDrawingGroup() != null) 1149 { 1150 dmod |= workbook.getDrawingGroup().hasDrawingsOmitted(); 1151 } 1152 1153 sheetWriter.setWriteData(rows, 1154 rowBreaks, 1155 hyperlinks, 1156 mergedCells, 1157 columnFormats ); 1158 sheetWriter.setDimensions(getRows(), getColumns()); 1159 sheetWriter.setSettings(settings); 1160 sheetWriter.setPLS(plsRecord); 1161 sheetWriter.setDrawings(drawings, dmod); 1162 sheetWriter.setButtonPropertySet(buttonPropertySet); 1163 sheetWriter.setDataValidation(dataValidation); 1164 1165 sheetWriter.write(); 1166 } 1167 1168 1173 private void copyCells(Sheet s) 1174 { 1175 int cells = s.getRows(); 1177 Cell[] row = null; 1178 Cell cell = null; 1179 for (int i = 0; i < cells; i++) 1180 { 1181 row = s.getRow(i); 1182 1183 for (int j = 0; j < row.length; j++) 1184 { 1185 cell = row[j]; 1186 CellType ct = cell.getType(); 1187 1188 try 1194 { 1195 if (ct == CellType.LABEL) 1196 { 1197 Label l = new Label((LabelCell) cell); 1198 addCell(l); 1199 } 1200 else if (ct == CellType.NUMBER) 1201 { 1202 Number n = new Number ((NumberCell) cell); 1203 addCell(n); 1204 } 1205 else if (ct == CellType.DATE) 1206 { 1207 DateTime dt = new DateTime((DateCell) cell); 1208 addCell(dt); 1209 } 1210 else if (ct == CellType.BOOLEAN) 1211 { 1212 Boolean b = new Boolean ((BooleanCell) cell); 1213 addCell(b); 1214 } 1215 else if (ct == CellType.NUMBER_FORMULA) 1216 { 1217 ReadNumberFormulaRecord fr = new ReadNumberFormulaRecord 1218 ((FormulaData) cell); 1219 addCell(fr); 1220 } 1221 else if (ct == CellType.STRING_FORMULA) 1222 { 1223 ReadStringFormulaRecord fr = new ReadStringFormulaRecord 1224 ((FormulaData) cell); 1225 addCell(fr); 1226 } 1227 else if( ct == CellType.BOOLEAN_FORMULA) 1228 { 1229 ReadBooleanFormulaRecord fr = new ReadBooleanFormulaRecord 1230 ((FormulaData) cell); 1231 addCell(fr); 1232 } 1233 else if (ct == CellType.DATE_FORMULA) 1234 { 1235 ReadDateFormulaRecord fr = new ReadDateFormulaRecord 1236 ((FormulaData) cell); 1237 addCell(fr); 1238 } 1239 else if(ct == CellType.FORMULA_ERROR) 1240 { 1241 ReadErrorFormulaRecord fr = new ReadErrorFormulaRecord 1242 ((FormulaData) cell); 1243 addCell(fr); 1244 } 1245 else if (ct == CellType.EMPTY) 1246 { 1247 if (cell.getCellFormat() != null) 1248 { 1249 Blank b = new Blank(cell); 1253 addCell(b); 1254 } 1255 } 1256 } 1257 catch (WriteException e) 1258 { 1259 Assert.verify(false); 1260 } 1261 } 1262 } 1263 } 1264 1265 1270 void copy(Sheet s) 1271 { 1272 settings = new SheetSettings(s.getSettings()); 1274 1275 copyCells(s); 1276 1277 jxl.read.biff.SheetImpl si = (jxl.read.biff.SheetImpl) s; 1279 jxl.read.biff.ColumnInfoRecord[] readCirs = si.getColumnInfos(); 1280 1281 for (int i = 0 ; i < readCirs.length; i++) 1282 { 1283 jxl.read.biff.ColumnInfoRecord rcir = readCirs[i]; 1284 for (int j = rcir.getStartColumn(); j <= rcir.getEndColumn() ; j++) 1285 { 1286 ColumnInfoRecord cir = new ColumnInfoRecord(rcir, j, 1287 formatRecords); 1288 cir.setHidden(rcir.getHidden()); 1289 columnFormats.add(cir); 1290 } 1291 } 1292 1293 Hyperlink[] hls = s.getHyperlinks(); 1295 for (int i = 0 ; i < hls.length; i++) 1296 { 1297 WritableHyperlink hr = new WritableHyperlink 1298 (hls[i], this); 1299 hyperlinks.add(hr); 1300 } 1301 1302 Range[] merged = s.getMergedCells(); 1304 1305 for (int i = 0; i < merged.length; i++) 1306 { 1307 mergedCells.add(new SheetRangeImpl((SheetRangeImpl)merged[i], this)); 1308 } 1309 1310 try 1312 { 1313 jxl.read.biff.RowRecord[] rowprops = si.getRowProperties(); 1314 1315 for (int i = 0; i < rowprops.length; i++) 1316 { 1317 RowRecord rr = getRowRecord(rowprops[i].getRowNumber()); 1318 XFRecord format = rowprops[i].hasDefaultFormat() ? 1319 formatRecords.getXFRecord(rowprops[i].getXFIndex()) : null; 1320 rr.setRowDetails(rowprops[i].getRowHeight(), 1321 rowprops[i].matchesDefaultFontHeight(), 1322 rowprops[i].isCollapsed(), 1323 format); 1324 } 1325 } 1326 catch (RowsExceededException e) 1327 { 1328 Assert.verify(false); 1331 } 1332 1333 1337 int[] rowbreaks = si.getRowPageBreaks(); 1339 1340 if (rowbreaks != null) 1341 { 1342 for (int i = 0; i < rowbreaks.length; i++) 1343 { 1344 rowBreaks.add(new Integer (rowbreaks[i])); 1345 } 1346 } 1347 1348 jxl.read.biff.DataValidation rdv = si.getDataValidation(); 1350 if (rdv != null) 1351 { 1352 dataValidation = new DataValidation(rdv, workbook, workbookSettings); 1353 } 1354 1355 sheetWriter.setCharts(si.getCharts()); 1357 1358 DrawingGroupObject[] dr = si.getDrawings(); 1360 for (int i = 0 ; i < dr.length ; i++) 1361 { 1362 if (dr[i] instanceof jxl.biff.drawing.Drawing) 1363 { 1364 WritableImage wi = new WritableImage(dr[i], 1365 workbook.getDrawingGroup()); 1366 drawings.add(wi); 1367 images.add(wi); 1368 } 1369 else if (dr[i] instanceof jxl.biff.drawing.Comment) 1370 { 1371 jxl.biff.drawing.Comment c = 1372 new jxl.biff.drawing.Comment(dr[i], 1373 workbook.getDrawingGroup(), 1374 workbookSettings); 1375 drawings.add(c); 1376 1377 CellValue cv = (CellValue) getWritableCell(c.getColumn(), c.getRow()); 1379 Assert.verify(cv.getCellFeatures() != null); 1380 cv.getWritableCellFeatures().setCommentDrawing(c); 1381 } 1382 else if (dr[i] instanceof jxl.biff.drawing.Button) 1383 { 1384 jxl.biff.drawing.Button b = 1385 new jxl.biff.drawing.Button(dr[i], 1386 workbook.getDrawingGroup(), 1387 workbookSettings); 1388 drawings.add(b); 1389 } 1390 1391 } 1392 1393 sheetWriter.setWorkspaceOptions(si.getWorkspaceOptions()); 1395 1396 if (si.getSheetBof().isChart()) 1398 { 1399 chartOnly = true; 1400 sheetWriter.setChartOnly(); 1401 } 1402 1403 if (si.getPLS() != null) 1405 { 1406 if (si.getWorkbookBof().isBiff7()) 1407 { 1408 logger.warn("Cannot copy Biff7 print settings record - ignoring"); 1409 } 1410 else 1411 { 1412 plsRecord = new PLSRecord(si.getPLS()); 1413 } 1414 } 1415 1416 if (si.getButtonPropertySet() != null) 1418 { 1419 buttonPropertySet = new ButtonPropertySetRecord 1420 (si.getButtonPropertySet()); 1421 } 1422 } 1423 1424 1429 void copy(WritableSheet s) 1430 { 1431 settings = new SheetSettings(s.getSettings()); 1432 1433 copyCells(s); 1434 1435 columnFormats = ( (WritableSheetImpl) s).columnFormats; 1437 1438 Range[] merged = s.getMergedCells(); 1440 1441 for (int i = 0; i < merged.length; i++) 1442 { 1443 mergedCells.add(new SheetRangeImpl((SheetRangeImpl)merged[i], this)); 1444 } 1445 1446 try 1448 { 1449 RowRecord[] copyRows = ( (WritableSheetImpl) s).rows; 1450 RowRecord row = null; 1451 for (int i = 0; i < copyRows.length ; i++) 1452 { 1453 row = copyRows[i]; 1454 1455 if (row != null && 1456 (!row.isDefaultHeight() || 1457 row.isCollapsed())) 1458 { 1459 RowRecord rr = getRowRecord(i); 1460 rr.setRowDetails(row.getRowHeight(), 1461 row.matchesDefaultFontHeight(), 1462 row.isCollapsed(), 1463 row.getStyle()); 1464 } 1465 } 1466 } 1467 catch (RowsExceededException e) 1468 { 1469 Assert.verify(false); 1472 } 1473 1474 WritableSheetImpl si = (WritableSheetImpl) s; 1476 1477 1480 rowBreaks = new ArrayList (si.rowBreaks); 1482 1483 DataValidation rdv = si.dataValidation; 1485 if (rdv != null) 1486 { 1487 dataValidation = new DataValidation(rdv, 1488 workbook, 1489 workbookSettings); 1490 } 1491 1492 sheetWriter.setCharts(si.getCharts()); 1494 1495 DrawingGroupObject[] dr = si.getDrawings(); 1497 for (int i = 0 ; i < dr.length ; i++) 1498 { 1499 if (dr[i] instanceof jxl.biff.drawing.Drawing) 1500 { 1501 WritableImage wi = new WritableImage(dr[i], 1502 workbook.getDrawingGroup()); 1503 drawings.add(wi); 1504 images.add(wi); 1505 } 1506 else if (dr[i] instanceof jxl.biff.drawing.Comment) 1507 { 1508 jxl.biff.drawing.Comment c = new jxl.biff.drawing.Comment 1509 (dr[i], 1510 workbook.getDrawingGroup(), 1511 workbookSettings); 1512 drawings.add(c); 1513 } 1514 } 1515 1516 sheetWriter.setWorkspaceOptions(si.getWorkspaceOptions()); 1518 1519 if (si.plsRecord != null) 1521 { 1522 plsRecord = new PLSRecord(si.plsRecord); 1523 } 1524 1525 if (si.buttonPropertySet != null) 1527 { 1528 buttonPropertySet = new ButtonPropertySetRecord(si.buttonPropertySet); 1529 } 1530 } 1531 1532 1537 final HeaderRecord getHeader() 1538 { 1539 return sheetWriter.getHeader(); 1540 } 1541 1542 1547 final FooterRecord getFooter() 1548 { 1549 return sheetWriter.getFooter(); 1550 } 1551 1557 public boolean isProtected() 1558 { 1559 return settings.isProtected(); 1560 } 1561 1562 1567 public Hyperlink[] getHyperlinks() 1568 { 1569 Hyperlink[] hl = new Hyperlink[hyperlinks.size()]; 1570 1571 for (int i = 0; i < hyperlinks.size(); i++) 1572 { 1573 hl[i] = (Hyperlink) hyperlinks.get(i); 1574 } 1575 1576 return hl; 1577 } 1578 1579 1584 public Range[] getMergedCells() 1585 { 1586 return mergedCells.getMergedCells(); 1587 } 1588 1589 1594 public WritableHyperlink[] getWritableHyperlinks() 1595 { 1596 WritableHyperlink[] hl = new WritableHyperlink[hyperlinks.size()]; 1597 1598 for (int i = 0; i < hyperlinks.size(); i++) 1599 { 1600 hl[i] = (WritableHyperlink) hyperlinks.get(i); 1601 } 1602 1603 return hl; 1604 } 1605 1606 1618 public void removeHyperlink(WritableHyperlink h) 1619 { 1620 removeHyperlink(h, false); 1621 } 1622 1623 1637 public void removeHyperlink(WritableHyperlink h, boolean preserveLabel) 1638 { 1639 hyperlinks.remove(hyperlinks.indexOf(h)); 1641 1642 if (!preserveLabel) 1643 { 1644 Assert.verify(rows.length > h.getRow() && rows[h.getRow()] != null); 1647 rows[h.getRow()].removeCell(h.getColumn()); 1648 } 1649 } 1650 1651 1658 public void addHyperlink(WritableHyperlink h) 1659 throws WriteException, RowsExceededException 1660 { 1661 Cell c = getCell(h.getColumn(), h.getRow()); 1663 1664 String contents = null; 1665 if (h.isFile() || h.isUNC()) 1666 { 1667 String cnts = ( (HyperlinkRecord) h).getContents(); 1668 if (cnts == null) 1669 { 1670 contents = h.getFile().getPath(); 1671 } 1672 else 1673 { 1674 contents = cnts; 1675 } 1676 } 1677 else if (h.isURL()) 1678 { 1679 String cnts = ( (HyperlinkRecord) h).getContents(); 1680 if (cnts == null) 1681 { 1682 contents = h.getURL().toString(); 1683 } 1684 else 1685 { 1686 contents=cnts; 1687 } 1688 } 1689 else if (h.isLocation()) 1690 { 1691 contents = ( (HyperlinkRecord) h).getContents(); 1692 } 1693 1694 if (c.getType() == CellType.LABEL) 1695 { 1696 Label l = (Label) c; 1697 l.setString(contents); 1698 l.setCellFormat(WritableWorkbook.HYPERLINK_STYLE); 1699 } 1700 else 1701 { 1702 Label l = new Label(h.getColumn(), h.getRow(), contents, 1703 WritableWorkbook.HYPERLINK_STYLE); 1704 addCell(l); 1705 } 1706 1707 for (int i = h.getRow(); i <= h.getLastRow(); i++) 1709 { 1710 for (int j = h.getColumn(); j <= h.getLastColumn(); j++) 1711 { 1712 if (i != h.getRow() && j != h.getColumn()) 1713 { 1714 if (rows[i] != null) 1716 { 1717 rows[i].removeCell(j); 1718 } 1719 } 1720 } 1721 } 1722 1723 ((HyperlinkRecord) h).initialize(this); 1724 hyperlinks.add(h); 1725 } 1726 1727 1739 public Range mergeCells(int col1, int row1, int col2, int row2) 1740 throws WriteException, RowsExceededException 1741 { 1742 if (col2 < col1 || row2 < row1) 1744 { 1745 logger.warn("Cannot merge cells - top left and bottom right "+ 1746 "incorrectly specified"); 1747 } 1748 1749 if (col2 >= numColumns || row2 >= numRows) 1751 { 1752 addCell(new Blank(col2, row2)); 1753 } 1754 1755 SheetRangeImpl range = new SheetRangeImpl(this, col1, row1, col2, row2); 1756 mergedCells.add(range); 1757 1758 return range; 1759 } 1760 1761 1767 public void unmergeCells(Range r) 1768 { 1769 mergedCells.unmergeCells(r); 1770 } 1771 1772 1780 public void setHeader(String l, String c, String r) 1781 { 1782 HeaderFooter header = new HeaderFooter(); 1783 header.getLeft().append(l); 1784 header.getCentre().append(c); 1785 header.getRight().append(r); 1786 settings.setHeader(header); 1787 } 1788 1789 1797 public void setFooter(String l, String c, String r) 1798 { 1799 HeaderFooter footer = new HeaderFooter(); 1800 footer.getLeft().append(l); 1801 footer.getCentre().append(c); 1802 footer.getRight().append(r); 1803 settings.setFooter(footer); 1804 } 1805 1806 1812 public void setPageSetup(PageOrientation p) 1813 { 1814 settings.setOrientation(p); 1815 } 1816 1817 1825 public void setPageSetup(PageOrientation p, double hm, double fm) 1826 { 1827 settings.setOrientation(p); 1828 settings.setHeaderMargin(hm); 1829 settings.setFooterMargin(fm); 1830 } 1831 1832 1841 public void setPageSetup(PageOrientation p, PaperSize ps, 1842 double hm, double fm) 1843 { 1844 settings.setPaperSize(ps); 1845 settings.setOrientation(p); 1846 settings.setHeaderMargin(hm); 1847 settings.setFooterMargin(fm); 1848 } 1849 1850 1855 public SheetSettings getSettings() 1856 { 1857 return settings; 1858 } 1859 1860 1863 WorkbookSettings getWorkbookSettings() 1864 { 1865 return workbookSettings; 1866 } 1867 1868 1873 public void addRowPageBreak(int row) 1874 { 1875 Iterator i = rowBreaks.iterator(); 1877 boolean found = false; 1878 1879 while (i.hasNext() && !found) 1880 { 1881 if (( (Integer ) i.next()).intValue() == row) 1882 { 1883 found = true; 1884 } 1885 } 1886 1887 if (!found) 1888 { 1889 rowBreaks.add(new Integer (row)); 1890 } 1891 } 1892 1893 1898 private Chart[] getCharts() 1899 { 1900 return sheetWriter.getCharts(); 1901 } 1902 1903 1908 private DrawingGroupObject[] getDrawings() 1909 { 1910 DrawingGroupObject[] dr = new DrawingGroupObject[drawings.size()]; 1911 dr = (DrawingGroupObject[]) drawings.toArray(dr); 1912 return dr; 1913 } 1914 1915 1921 void checkMergedBorders() 1922 { 1923 sheetWriter.setWriteData(rows, 1924 rowBreaks, 1925 hyperlinks, 1926 mergedCells, 1927 columnFormats ); 1928 sheetWriter.setDimensions(getRows(), getColumns()); 1929 sheetWriter.checkMergedBorders(); 1930 } 1931 1932 1937 private WorkspaceInformationRecord getWorkspaceOptions() 1938 { 1939 return sheetWriter.getWorkspaceOptions(); 1940 } 1941 1942 1948 void rationalize(IndexMapping xfMapping, 1949 IndexMapping fontMapping, 1950 IndexMapping formatMapping) 1951 { 1952 for (Iterator i = columnFormats.iterator() ; i.hasNext() ;) 1954 { 1955 ColumnInfoRecord cir = (ColumnInfoRecord) i.next(); 1956 cir.rationalize(xfMapping); 1957 } 1958 1959 for (int i = 0; i < rows.length ; i++) 1961 { 1962 if (rows[i] != null) 1963 { 1964 rows[i].rationalize(xfMapping); 1965 } 1966 } 1967 1968 Chart[] charts = getCharts(); 1970 for (int c = 0; c < charts.length; c++) 1971 { 1972 charts[c].rationalize(xfMapping, fontMapping, formatMapping); 1973 } 1974 } 1975 1976 1980 WritableWorkbookImpl getWorkbook() 1981 { 1982 return workbook; 1983 } 1984 1985 1992 public CellFormat getColumnFormat(int col) 1993 { 1994 return getColumnView(col).getFormat(); 1995 } 1996 1997 2005 public int getColumnWidth(int col) 2006 { 2007 return getColumnView(col).getDimension(); 2008 } 2009 2010 2018 public int getRowHeight(int row) 2019 { 2020 return getRowView(row).getDimension(); 2021 } 2022 2023 2028 boolean isChartOnly() 2029 { 2030 return chartOnly; 2031 } 2032 2033 2040 public CellView getRowView(int row) 2041 { 2042 CellView cv = new CellView(); 2043 2044 try 2045 { 2046 RowRecord rr = getRowRecord(row); 2047 2048 if (rr == null || rr.isDefaultHeight()) 2049 { 2050 cv.setDimension(settings.getDefaultRowHeight()); 2051 cv.setSize(settings.getDefaultRowHeight()); 2052 } 2053 else if (rr.isCollapsed()) 2054 { 2055 cv.setHidden(true); 2056 } 2057 else 2058 { 2059 cv.setDimension(rr.getRowHeight()); 2060 cv.setSize(rr.getRowHeight()); 2061 } 2062 return cv; 2063 } 2064 catch (RowsExceededException e) 2065 { 2066 cv.setDimension(settings.getDefaultRowHeight()); 2068 cv.setSize(settings.getDefaultRowHeight()); 2069 return cv; 2070 } 2071 } 2072 2073 2080 public CellView getColumnView(int col) 2081 { 2082 ColumnInfoRecord cir = getColumnInfo(col); 2083 CellView cv = new CellView(); 2084 2085 if (cir != null) 2086 { 2087 cv.setDimension(cir.getWidth()/256); 2088 cv.setSize(cir.getWidth()); 2089 cv.setHidden(cir.getHidden()); 2090 cv.setFormat(cir.getCellFormat()); 2091 } 2092 else 2093 { 2094 cv.setDimension(settings.getDefaultColumnWidth()/256); 2095 cv.setSize(settings.getDefaultColumnWidth()); 2096 } 2097 2098 return cv; 2099 } 2100 2101 2106 public void addImage(WritableImage image) 2107 { 2108 boolean supported = false; 2109 java.io.File imageFile = image.getImageFile(); 2110 String fileType = "?"; 2111 2112 if (imageFile != null) 2113 { 2114 2115 String fileName = imageFile.getName(); 2116 int fileTypeIndex = fileName.lastIndexOf('.'); 2117 fileType = fileTypeIndex != -1 ? 2118 fileName.substring(fileTypeIndex+1) : ""; 2119 2120 for (int i = 0 ; i < imageTypes.length && !supported ; i++) 2121 { 2122 if (fileType.equalsIgnoreCase(imageTypes[i])) 2123 { 2124 supported = true; 2125 } 2126 } 2127 } 2128 else 2129 { 2130 supported = true; 2131 } 2132 2133 if (supported) 2134 { 2135 workbook.addDrawing(image); 2136 drawings.add(image); 2137 images.add(image); 2138 } 2139 else 2140 { 2141 StringBuffer message = new StringBuffer ("Image type "); 2142 message.append(fileType); 2143 message.append(" not supported. Supported types are "); 2144 message.append(imageTypes[0]); 2145 for (int i = 1 ; i < imageTypes.length ; i++) 2146 { 2147 message.append(", "); 2148 message.append(imageTypes[i]); 2149 } 2150 logger.warn(message.toString()); 2151 } 2152 } 2153 2154 2159 public int getNumberOfImages() 2160 { 2161 return images.size(); 2162 } 2163 2164 2170 public WritableImage getImage(int i) 2171 { 2172 return (WritableImage) images.get(i); 2173 } 2174 2175 2181 public Image getDrawing(int i) 2182 { 2183 return (Image) images.get(i); 2184 } 2185 2186 2192 public void removeImage(WritableImage wi) 2193 { 2194 boolean removed = drawings.remove(wi); 2195 images.remove(wi); 2196 drawingsModified = true; 2197 workbook.removeDrawing(wi); 2198 } 2199 2200 2203 private String validateName(String n) 2204 { 2205 if (n.length() > maxSheetNameLength) 2206 { 2207 logger.warn("Sheet name " + n + " too long - truncating"); 2208 n = n.substring(0, maxSheetNameLength); 2209 } 2210 2211 if (n.charAt(0) == '\'') 2212 { 2213 logger.warn("Sheet naming cannot start with \' - removing"); 2214 n = n.substring(1); 2215 } 2216 2217 for (int i = 0 ; i < illegalSheetNameCharacters.length ; i++) 2218 { 2219 String newname = n.replace(illegalSheetNameCharacters[i], '@'); 2220 if (n != newname) 2221 { 2222 logger.warn(illegalSheetNameCharacters[i] + 2223 " is not a valid character within a sheet name - replacing"); 2224 } 2225 n = newname; 2226 } 2227 2228 return n; 2229 } 2230 2231 2236 void addDrawing(DrawingGroupObject o) 2237 { 2238 drawings.add(o); 2239 Assert.verify(!(o instanceof Drawing)); 2240 } 2241} 2242 | Popular Tags |