1 19 20 package jxl.write.biff; 21 22 import java.io.IOException ; 23 import java.util.ArrayList ; 24 import java.util.Iterator ; 25 import java.util.TreeSet ; 26 27 import common.Assert; 28 import common.Logger; 29 30 import jxl.Cell; 31 import jxl.Range; 32 import jxl.SheetSettings; 33 import jxl.WorkbookSettings; 34 import jxl.write.WritableWorkbook; 35 import jxl.write.WritableCell; 36 import jxl.write.WritableHyperlink; 37 import jxl.write.WriteException; 38 import jxl.write.Blank; 39 import jxl.write.WritableCellFormat; 40 import jxl.format.CellFormat; 41 import jxl.format.Border; 42 import jxl.format.BorderLineStyle; 43 import jxl.format.Colour; 44 import jxl.biff.XFRecord; 45 import jxl.biff.WorkspaceInformationRecord; 46 import jxl.biff.CountryCode; 47 import jxl.biff.drawing.Chart; 48 import jxl.biff.drawing.SheetDrawingWriter; 49 50 56 final class SheetWriter 57 { 58 61 private static Logger logger = Logger.getLogger(SheetWriter.class); 62 63 66 private File outputFile; 67 68 71 private RowRecord[] rows; 72 73 76 private int numRows; 77 78 81 private int numCols; 82 83 86 private HeaderRecord header; 87 90 private FooterRecord footer; 91 94 private SheetSettings settings; 95 98 private WorkbookSettings workbookSettings; 99 102 private ArrayList rowBreaks; 103 106 private ArrayList hyperlinks; 107 110 private DataValidation dataValidation; 111 112 115 private MergedCells mergedCells; 116 117 120 private PLSRecord plsRecord; 121 122 125 private ButtonPropertySetRecord buttonPropertySet; 126 127 130 private WorkspaceInformationRecord workspaceOptions; 131 134 private TreeSet columnFormats; 135 136 139 private SheetDrawingWriter drawingWriter; 140 141 145 private boolean chartOnly; 146 147 151 private WritableSheetImpl sheet; 152 153 154 159 public SheetWriter(File of, 160 WritableSheetImpl wsi, 161 WorkbookSettings ws) 162 { 163 outputFile = of; 164 sheet = wsi; 165 workspaceOptions = new WorkspaceInformationRecord(); 166 workbookSettings = ws; 167 chartOnly = false; 168 drawingWriter = new SheetDrawingWriter(ws); 169 } 170 171 179 public void write() throws IOException 180 { 181 Assert.verify(rows != null); 182 183 if (chartOnly) 185 { 186 drawingWriter.write(outputFile); 187 return; 188 } 189 190 int bofpos = outputFile.getPos(); 191 192 BOFRecord bof = new BOFRecord(BOFRecord.sheet); 193 outputFile.write(bof); 194 195 int numBlocks = numRows / 32; 197 if (numRows - numBlocks * 32 != 0) 198 { 199 numBlocks++; 200 } 201 202 int indexPos = outputFile.getPos(); 203 204 IndexRecord indexRecord = new IndexRecord(0, numRows, numBlocks); 207 outputFile.write(indexRecord); 208 209 CalcModeRecord cmr = new CalcModeRecord(CalcModeRecord.automatic); 210 outputFile.write(cmr); 211 212 CalcCountRecord ccr = new CalcCountRecord(0x64); 213 outputFile.write(ccr); 214 215 RefModeRecord rmr = new RefModeRecord(); 216 outputFile.write(rmr); 217 218 IterationRecord itr = new IterationRecord(false); 219 outputFile.write(itr); 220 221 DeltaRecord dtr = new DeltaRecord(0.001); 222 outputFile.write(dtr); 223 224 SaveRecalcRecord srr = new SaveRecalcRecord(true); 225 outputFile.write(srr); 226 227 PrintHeadersRecord phr = new PrintHeadersRecord 228 (settings.getPrintHeaders()); 229 outputFile.write(phr); 230 231 PrintGridLinesRecord pglr = new PrintGridLinesRecord 232 (settings.getPrintGridLines()); 233 outputFile.write(pglr); 234 235 GridSetRecord gsr = new GridSetRecord(true); 236 outputFile.write(gsr); 237 238 GuttersRecord gutr = new GuttersRecord(); 239 outputFile.write(gutr); 240 241 DefaultRowHeightRecord drhr = new DefaultRowHeightRecord 242 (settings.getDefaultRowHeight(), 243 settings.getDefaultRowHeight() != settings.DEFAULT_DEFAULT_ROW_HEIGHT); 244 outputFile.write(drhr); 245 246 workspaceOptions.setFitToPages(settings.getFitToPages()); 247 outputFile.write(workspaceOptions); 248 249 if (rowBreaks.size() > 0) 250 { 251 int[] rb = new int[rowBreaks.size()]; 252 253 for (int i = 0; i < rb.length; i++) 254 { 255 rb[i] = ( (Integer ) rowBreaks.get(i)).intValue(); 256 } 257 258 HorizontalPageBreaksRecord hpbr = new HorizontalPageBreaksRecord(rb); 259 outputFile.write(hpbr); 260 } 261 262 HeaderRecord header = new HeaderRecord(settings.getHeader().toString()); 263 outputFile.write(header); 264 265 FooterRecord footer = new FooterRecord(settings.getFooter().toString()); 266 outputFile.write(footer); 267 268 HorizontalCentreRecord hcr = new HorizontalCentreRecord(false); 269 outputFile.write(hcr); 270 271 VerticalCentreRecord vcr = new VerticalCentreRecord(false); 272 outputFile.write(vcr); 273 274 if (settings.getLeftMargin() != settings.getDefaultWidthMargin()) 276 { 277 MarginRecord mr = new LeftMarginRecord(settings.getLeftMargin()); 278 outputFile.write(mr); 279 } 280 281 if (settings.getRightMargin() != settings.getDefaultWidthMargin()) 282 { 283 MarginRecord mr = new RightMarginRecord(settings.getRightMargin()); 284 outputFile.write(mr); 285 } 286 287 if (settings.getTopMargin() != settings.getDefaultHeightMargin()) 288 { 289 MarginRecord mr = new TopMarginRecord(settings.getTopMargin()); 290 outputFile.write(mr); 291 } 292 293 if (settings.getBottomMargin() != settings.getDefaultHeightMargin()) 294 { 295 MarginRecord mr = new BottomMarginRecord(settings.getBottomMargin()); 296 outputFile.write(mr); 297 } 298 299 if (plsRecord != null) 300 { 301 outputFile.write(plsRecord); 302 } 303 304 SetupRecord setup = new SetupRecord(settings); 305 outputFile.write(setup); 306 307 if (settings.isProtected()) 308 { 309 ProtectRecord pr = new ProtectRecord(settings.isProtected()); 310 outputFile.write(pr); 311 312 ScenarioProtectRecord spr = new ScenarioProtectRecord 313 (settings.isProtected()); 314 outputFile.write(spr); 315 316 ObjectProtectRecord opr = new ObjectProtectRecord 317 (settings.isProtected()); 318 outputFile.write(opr); 319 320 if (settings.getPassword() != null) 321 { 322 PasswordRecord pw = new PasswordRecord(settings.getPassword()); 323 outputFile.write(pw); 324 } 325 else if (settings.getPasswordHash() != 0) 326 { 327 PasswordRecord pw = new PasswordRecord(settings.getPasswordHash()); 328 outputFile.write(pw); 329 } 330 } 331 332 indexRecord.setDataStartPosition(outputFile.getPos()); 333 DefaultColumnWidth dcw = 334 new DefaultColumnWidth(settings.getDefaultColumnWidth()); 335 outputFile.write(dcw); 336 337 WritableCellFormat normalStyle = 339 sheet.getWorkbook().getStyles().getNormalStyle(); 340 WritableCellFormat defaultDateFormat = 341 sheet.getWorkbook().getStyles().getDefaultDateFormat(); 342 343 ColumnInfoRecord cir = null; 345 int tmpi = 0; 346 for (Iterator colit = columnFormats.iterator(); colit.hasNext() ; ) 347 { 348 cir = (ColumnInfoRecord) colit.next(); 349 350 if (cir.getColumn() < 0x100) 352 { 353 outputFile.write(cir); 354 } 355 356 XFRecord xfr = cir.getCellFormat(); 357 358 if (xfr != normalStyle && cir.getColumn() < 0x100) 359 { 360 Cell[] cells = getColumn(cir.getColumn()); 362 363 for (int i = 0; i < cells.length; i++) 364 { 365 if (cells[i] != null && 366 (cells[i].getCellFormat() == normalStyle || 367 cells[i].getCellFormat() == defaultDateFormat)) 368 { 369 ((WritableCell) cells[i]).setCellFormat(xfr); 372 } 373 } 374 } 375 } 376 377 DimensionRecord dr = new DimensionRecord(numRows, numCols); 378 outputFile.write(dr); 379 380 for (int block = 0; block < numBlocks; block++) 382 { 383 DBCellRecord dbcell = new DBCellRecord(outputFile.getPos()); 384 385 int blockRows = Math.min(32, numRows - block * 32); 386 boolean firstRow = true; 387 388 for (int i = block * 32; i < block * 32 + blockRows; i++) 390 { 391 if (rows[i] != null) 392 { 393 rows[i].write(outputFile); 394 if (firstRow) 395 { 396 dbcell.setCellOffset(outputFile.getPos()); 397 firstRow = false; 398 } 399 } 400 } 401 402 for (int i = block * 32; i < block * 32 + blockRows; i++) 404 { 405 if (rows[i] != null) 406 { 407 dbcell.addCellRowPosition(outputFile.getPos()); 408 rows[i].writeCells(outputFile); 409 } 410 } 411 412 indexRecord.addBlockPosition(outputFile.getPos()); 414 415 dbcell.setPosition(outputFile.getPos()); 418 outputFile.write(dbcell); 419 } 420 421 if (dataValidation != null) 423 { 424 dataValidation.write(outputFile); 425 } 426 427 if (!workbookSettings.getDrawingsDisabled()) 429 { 430 drawingWriter.write(outputFile); 431 } 432 433 Window2Record w2r = new Window2Record(settings); 434 outputFile.write(w2r); 435 436 if (settings.getHorizontalFreeze() != 0 || 438 settings.getVerticalFreeze() != 0) 439 { 440 PaneRecord pr = new PaneRecord(settings.getHorizontalFreeze(), 441 settings.getVerticalFreeze()); 442 outputFile.write(pr); 443 444 SelectionRecord sr = new SelectionRecord 446 (SelectionRecord.upperLeft, 0, 0); 447 outputFile.write(sr); 448 449 if (settings.getHorizontalFreeze() != 0) 451 { 452 sr = new SelectionRecord 453 (SelectionRecord.upperRight, settings.getHorizontalFreeze(), 0); 454 outputFile.write(sr); 455 } 456 457 if (settings.getVerticalFreeze() != 0) 459 { 460 sr = new SelectionRecord 461 (SelectionRecord.lowerLeft, 0, settings.getVerticalFreeze()); 462 outputFile.write(sr); 463 } 464 465 if (settings.getHorizontalFreeze() != 0 && 467 settings.getVerticalFreeze() != 0) 468 { 469 sr = new SelectionRecord 470 (SelectionRecord.lowerRight, 471 settings.getHorizontalFreeze(), 472 settings.getVerticalFreeze()); 473 outputFile.write(sr); 474 } 475 476 Weird1Record w1r = new Weird1Record(); 477 outputFile.write(w1r); 478 } 479 else 480 { 481 SelectionRecord sr = new SelectionRecord 484 (SelectionRecord.upperLeft, 0, 0); 485 outputFile.write(sr); 486 } 487 488 if (settings.getZoomFactor() != 100) 490 { 491 SCLRecord sclr = new SCLRecord(settings.getZoomFactor()); 492 outputFile.write(sclr); 493 } 494 495 mergedCells.write(outputFile); 497 498 Iterator hi = hyperlinks.iterator(); 500 WritableHyperlink hlr = null; 501 while (hi.hasNext()) 502 { 503 hlr = (WritableHyperlink) hi.next(); 504 outputFile.write(hlr); 505 } 506 507 if (buttonPropertySet != null) 508 { 509 outputFile.write(buttonPropertySet); 510 } 511 512 513 EOFRecord eof = new EOFRecord(); 514 outputFile.write(eof); 515 516 outputFile.setData(indexRecord.getData(), indexPos+4); 519 } 520 521 526 final HeaderRecord getHeader() 527 { 528 return header; 529 } 530 531 536 final FooterRecord getFooter() 537 { 538 return footer; 539 } 540 541 547 void setWriteData(RowRecord[] rws, 548 ArrayList rb, 549 ArrayList hl, 550 MergedCells mc, 551 TreeSet cf) 552 { 553 rows = rws; 554 rowBreaks = rb; 555 hyperlinks = hl; 556 mergedCells = mc; 557 columnFormats = cf; 558 } 559 560 567 void setDimensions(int rws, int cls) 568 { 569 numRows = rws; 570 numCols = cls; 571 } 572 573 579 void setSettings(SheetSettings sr) 580 { 581 settings = sr; 582 } 583 584 589 WorkspaceInformationRecord getWorkspaceOptions() 590 { 591 return workspaceOptions; 592 } 593 594 599 void setWorkspaceOptions(WorkspaceInformationRecord wo) 600 { 601 workspaceOptions = wo; 602 } 603 604 605 610 void setCharts(Chart[] ch) 611 { 612 drawingWriter.setCharts(ch); 613 } 614 615 621 void setDrawings(ArrayList dr, boolean mod) 622 { 623 drawingWriter.setDrawings(dr, mod); 624 } 625 626 631 Chart[] getCharts() 632 { 633 return drawingWriter.getCharts(); 634 } 635 636 642 void checkMergedBorders() 643 { 644 Range[] mcells = mergedCells.getMergedCells(); 645 ArrayList borderFormats = new ArrayList (); 646 for (int mci = 0 ; mci < mcells.length ; mci++) 647 { 648 Range range = mcells[mci]; 649 Cell topLeft = range.getTopLeft(); 650 XFRecord tlformat = (XFRecord) topLeft.getCellFormat(); 651 652 if (tlformat != null && 653 tlformat.hasBorders() == true && 654 !tlformat.isRead()) 655 { 656 try 657 { 658 CellXFRecord cf1 = new CellXFRecord(tlformat); 659 Cell bottomRight = range.getBottomRight(); 660 661 cf1.setBorder(Border.ALL, BorderLineStyle.NONE, Colour.BLACK); 662 cf1.setBorder(Border.LEFT, 663 tlformat.getBorderLine(Border.LEFT), 664 tlformat.getBorderColour(Border.LEFT)); 665 cf1.setBorder(Border.TOP, 666 tlformat.getBorderLine(Border.TOP), 667 tlformat.getBorderColour(Border.TOP)); 668 669 if (topLeft.getRow() == bottomRight.getRow()) 670 { 671 cf1.setBorder(Border.BOTTOM, 672 tlformat.getBorderLine(Border.BOTTOM), 673 tlformat.getBorderColour(Border.BOTTOM)); 674 } 675 676 if (topLeft.getColumn() == bottomRight.getColumn()) 677 { 678 cf1.setBorder(Border.RIGHT, 679 tlformat.getBorderLine(Border.RIGHT), 680 tlformat.getBorderColour(Border.RIGHT)); 681 } 682 683 int index = borderFormats.indexOf(cf1); 684 if (index != -1) 685 { 686 cf1 = (CellXFRecord) borderFormats.get(index); 687 } 688 else 689 { 690 borderFormats.add(cf1); 691 } 692 ( (WritableCell) topLeft).setCellFormat(cf1); 693 694 if (bottomRight.getRow() > topLeft.getRow()) 696 { 697 if (bottomRight.getColumn() != topLeft.getColumn()) 699 { 700 CellXFRecord cf2 = new CellXFRecord(tlformat); 701 cf2.setBorder(Border.ALL, BorderLineStyle.NONE, Colour.BLACK); 702 cf2.setBorder(Border.LEFT, 703 tlformat.getBorderLine(Border.LEFT), 704 tlformat.getBorderColour(Border.LEFT)); 705 cf2.setBorder(Border.BOTTOM, 706 tlformat.getBorderLine(Border.BOTTOM), 707 tlformat.getBorderColour(Border.BOTTOM)); 708 709 index = borderFormats.indexOf(cf2); 710 if (index != -1) 711 { 712 cf2 = (CellXFRecord) borderFormats.get(index); 713 } 714 else 715 { 716 borderFormats.add(cf2); 717 } 718 719 sheet.addCell(new Blank(topLeft.getColumn(), 720 bottomRight.getRow(), cf2)); 721 } 722 723 for (int i = topLeft.getRow() + 1; i < bottomRight.getRow() ;i++) 726 { 727 CellXFRecord cf3 = new CellXFRecord(tlformat); 728 cf3.setBorder(Border.ALL, BorderLineStyle.NONE, Colour.BLACK); 729 cf3.setBorder(Border.LEFT, 730 tlformat.getBorderLine(Border.LEFT), 731 tlformat.getBorderColour(Border.LEFT)); 732 733 if (topLeft.getColumn() == bottomRight.getColumn()) 734 { 735 cf3.setBorder(Border.RIGHT, 736 tlformat.getBorderLine(Border.RIGHT), 737 tlformat.getBorderColour(Border.RIGHT)); 738 } 739 740 index = borderFormats.indexOf(cf3); 741 if (index != -1) 742 { 743 cf3 = (CellXFRecord) borderFormats.get(index); 744 } 745 else 746 { 747 borderFormats.add(cf3); 748 } 749 750 sheet.addCell(new Blank(topLeft.getColumn(), i, cf3)); 751 } 752 } 753 754 if (bottomRight.getColumn() > topLeft.getColumn()) 756 { 757 if (bottomRight.getRow() != topLeft.getRow()) 758 { 759 CellXFRecord cf6 = new CellXFRecord(tlformat); 761 cf6.setBorder(Border.ALL, BorderLineStyle.NONE, Colour.BLACK); 762 cf6.setBorder(Border.RIGHT, 763 tlformat.getBorderLine(Border.RIGHT), 764 tlformat.getBorderColour(Border.RIGHT)); 765 cf6.setBorder(Border.TOP, 766 tlformat.getBorderLine(Border.TOP), 767 tlformat.getBorderColour(Border.RIGHT)); 768 index = borderFormats.indexOf(cf6); 769 if (index != -1) 770 { 771 cf6 = (CellXFRecord) borderFormats.get(index); 772 } 773 else 774 { 775 borderFormats.add(cf6); 776 } 777 778 sheet.addCell(new Blank(bottomRight.getColumn(), 779 topLeft.getRow(), cf6)); 780 } 781 782 for (int i = topLeft.getRow() + 1; 784 i < bottomRight.getRow() ;i++) 785 { 786 CellXFRecord cf7 = new CellXFRecord(tlformat); 787 cf7.setBorder(Border.ALL, BorderLineStyle.NONE, Colour.BLACK); 788 cf7.setBorder(Border.RIGHT, 789 tlformat.getBorderLine(Border.RIGHT), 790 tlformat.getBorderColour(Border.RIGHT)); 791 792 index = borderFormats.indexOf(cf7); 793 if (index != -1) 794 { 795 cf7 = (CellXFRecord) borderFormats.get(index); 796 } 797 else 798 { 799 borderFormats.add(cf7); 800 } 801 802 sheet.addCell(new Blank(bottomRight.getColumn(), i, cf7)); 803 } 804 805 for (int i = topLeft.getColumn() + 1; 807 i < bottomRight.getColumn() ;i++) 808 { 809 CellXFRecord cf8 = new CellXFRecord(tlformat); 810 cf8.setBorder(Border.ALL, BorderLineStyle.NONE, Colour.BLACK); 811 cf8.setBorder(Border.TOP, 812 tlformat.getBorderLine(Border.TOP), 813 tlformat.getBorderColour(Border.TOP)); 814 815 if (topLeft.getRow() == bottomRight.getRow()) 816 { 817 cf8.setBorder(Border.BOTTOM, 818 tlformat.getBorderLine(Border.BOTTOM), 819 tlformat.getBorderColour(Border.BOTTOM)); 820 } 821 822 index = borderFormats.indexOf(cf8); 823 if (index != -1) 824 { 825 cf8 = (CellXFRecord) borderFormats.get(index); 826 } 827 else 828 { 829 borderFormats.add(cf8); 830 } 831 832 sheet.addCell(new Blank(i, topLeft.getRow(), cf8)); 833 } 834 } 835 836 if (bottomRight.getColumn() > topLeft.getColumn() || 838 bottomRight.getRow() > topLeft.getRow()) 839 { 840 CellXFRecord cf4 = new CellXFRecord(tlformat); 842 cf4.setBorder(Border.ALL, BorderLineStyle.NONE, Colour.BLACK); 843 cf4.setBorder(Border.RIGHT, 844 tlformat.getBorderLine(Border.RIGHT), 845 tlformat.getBorderColour(Border.RIGHT)); 846 cf4.setBorder(Border.BOTTOM, 847 tlformat.getBorderLine(Border.BOTTOM), 848 tlformat.getBorderColour(Border.BOTTOM)); 849 850 if (bottomRight.getRow() == topLeft.getRow()) 851 { 852 cf4.setBorder(Border.TOP, 853 tlformat.getBorderLine(Border.TOP), 854 tlformat.getBorderColour(Border.TOP)); 855 } 856 857 if (bottomRight.getColumn() == topLeft.getColumn()) 858 { 859 cf4.setBorder(Border.LEFT, 860 tlformat.getBorderLine(Border.LEFT), 861 tlformat.getBorderColour(Border.LEFT)); 862 } 863 864 index = borderFormats.indexOf(cf4); 865 if (index != -1) 866 { 867 cf4 = (CellXFRecord) borderFormats.get(index); 868 } 869 else 870 { 871 borderFormats.add(cf4); 872 } 873 874 sheet.addCell(new Blank(bottomRight.getColumn(), 875 bottomRight.getRow(), cf4)); 876 877 for (int i = topLeft.getColumn() + 1; 880 i < bottomRight.getColumn() ;i++) 881 { 882 CellXFRecord cf5 = new CellXFRecord(tlformat); 883 cf5.setBorder(Border.ALL, BorderLineStyle.NONE, Colour.BLACK); 884 cf5.setBorder(Border.BOTTOM, 885 tlformat.getBorderLine(Border.BOTTOM), 886 tlformat.getBorderColour(Border.BOTTOM)); 887 888 if (topLeft.getRow() == bottomRight.getRow()) 889 { 890 cf5.setBorder(Border.TOP, 891 tlformat.getBorderLine(Border.TOP), 892 tlformat.getBorderColour(Border.TOP)); 893 } 894 895 index = borderFormats.indexOf(cf5); 896 if (index != -1) 897 { 898 cf5 = (CellXFRecord) borderFormats.get(index); 899 } 900 else 901 { 902 borderFormats.add(cf5); 903 } 904 905 sheet.addCell(new Blank(i, bottomRight.getRow(), cf5)); 906 } 907 } 908 } 909 catch (WriteException e) 910 { 911 logger.warn(e.toString()); 913 } 914 } 915 } 916 } 917 918 923 private Cell[] getColumn(int col) 924 { 925 boolean found = false; 927 int row = numRows - 1; 928 929 while (row >= 0 && !found) 930 { 931 if (rows[row] != null && 932 rows[row].getCell(col) != null) 933 { 934 found = true; 935 } 936 else 937 { 938 row--; 939 } 940 } 941 942 Cell[] cells = new Cell[row+1]; 944 945 for (int i = 0; i <= row; i++) 946 { 947 cells[i] = rows[i] != null ? rows[i].getCell(col) : null; 948 } 949 950 return cells; 951 } 952 953 956 void setChartOnly() 957 { 958 chartOnly = true; 959 } 960 961 966 void setPLS(PLSRecord pls) 967 { 968 plsRecord = pls; 969 } 970 971 976 void setButtonPropertySet(ButtonPropertySetRecord bps) 977 { 978 buttonPropertySet = bps; 979 } 980 981 986 void setDataValidation(DataValidation dv) 987 { 988 dataValidation = dv; 989 } 990 } 991 | Popular Tags |