001package com.hfg.xml.msofficexml.xlsx.spreadsheetml; 002 003 004import java.io.Writer; 005import java.util.*; 006import java.util.regex.Pattern; 007 008import com.hfg.exception.InvalidValueException; 009import com.hfg.exception.ProgrammingException; 010import com.hfg.util.StringBuilderPlus; 011import com.hfg.util.collection.CollectionUtil; 012import com.hfg.util.StringUtil; 013import com.hfg.xml.XMLNamespace; 014import com.hfg.xml.XMLNode; 015import com.hfg.xml.XMLTag; 016import com.hfg.xml.msofficexml.OfficeOpenXmlException; 017import com.hfg.xml.msofficexml.OfficeXML; 018import com.hfg.xml.msofficexml.docx.RelationshipXML; 019import com.hfg.xml.msofficexml.xlsx.CellRef; 020import com.hfg.xml.msofficexml.xlsx.spreadsheetDrawing.WorksheetDrawing; 021import com.hfg.xml.msofficexml.xlsx.CellRange; 022import com.hfg.xml.msofficexml.xlsx.Xlsx; 023import com.hfg.xml.msofficexml.xlsx.part.SsmlCommentsPart; 024import com.hfg.xml.msofficexml.xlsx.part.SsmlDrawingPart; 025import com.hfg.xml.msofficexml.xlsx.part.TablePart; 026import com.hfg.xml.msofficexml.xlsx.part.WorksheetPart; 027 028//------------------------------------------------------------------------------ 029/** 030 Represents an Office Open XML sheet (<ssml:worksheet>) tag. 031 <div> 032 @author J. Alex Taylor, hairyfatguy.com 033 </div> 034 */ 035//------------------------------------------------------------------------------ 036// com.hfg XML/HTML Coding Library 037// 038// This library is free software; you can redistribute it and/or 039// modify it under the terms of the GNU Lesser General Public 040// License as published by the Free Software Foundation; either 041// version 2.1 of the License, or (at your option) any later version. 042// 043// This library is distributed in the hope that it will be useful, 044// but WITHOUT ANY WARRANTY; without even the implied warranty of 045// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 046// Lesser General Public License for more details. 047// 048// You should have received a copy of the GNU Lesser General Public 049// License along with this library; if not, write to the Free Software 050// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 051// 052// J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com 053// jataylor@hairyfatguy.com 054//------------------------------------------------------------------------------ 055 056public class SsmlWorksheet extends SsmlXMLTag 057{ 058 //########################################################################### 059 // PRIVATE FIELDS 060 //########################################################################### 061 062 private WorksheetPart mParentWorksheetPart; 063 private SsmlCommentsPart mCommentsPart; 064 private String mName; 065 private SsmlSheetData mSheetData; 066 private SsmlPageMargins mPageMargins; 067 private SsmlSheetFormatProperties mSheetFormatPropertiesTag; 068 private XMLTag mSheetViewsTag; 069 private XMLTag mTablePartsTag; 070 private XMLTag mMergeCellsTag; 071 private XMLTag mColumnsTag; 072 private XMLTag mDimensionTag; 073 private XMLTag mDataValidationsTag; 074 private SsmlHeaderFooter mHeaderFooterTag; 075 private XMLTag mExtLst; 076 private SsmlSortState mSortState; 077 078 private Map<String, TablePart> mTableParts; 079 private Map<String, SsmlDrawingPart> mDrawingParts; 080 081 // Each sheet needs a unique GUID 082 private final String mUID = UUID.randomUUID().toString().toUpperCase(); 083 084 // There are seven bad characters for sheet names: \ / * [ ] : ? 085 private static final Pattern BAD_SHEET_NAME_CHAR_PATTERN = Pattern.compile("[\\\\\\/\\*\\[\\]\\:\\?+]"); 086 087 private static final int MAX_SHEET_NAME_LENGTH = 31; 088 089 private static final String PRINT_AREA_NAME = "_xlnm.Print_Area"; 090 091 092 //########################################################################### 093 // CONSTRUCTORS 094 //########################################################################### 095 096 //--------------------------------------------------------------------------- 097 public SsmlWorksheet(WorksheetPart inParentWorksheetPart) 098 { 099 super(SsmlXML.WORKSHEET, (Xlsx) inParentWorksheetPart.getParentDoc()); 100 101 mParentWorksheetPart = inParentWorksheetPart; 102 103 addXMLNamespaceDeclaration(RelationshipXML.RELATIONSHIP_NAMESPACE); 104 addXMLNamespaceDeclaration(OfficeXML.MARKUP_CAPABILITY_NAMESPACE); 105 addXMLNamespaceDeclaration(OfficeXML.MAC_VML_NAMESPACE); 106 addXMLNamespaceDeclaration(SsmlXML.SPREADSHEETML_2009AC_NAMESPACE); 107 addXMLNamespaceDeclaration(SsmlXML.SPREADSHEETML_REVISION1_NAMESPACE); 108 addXMLNamespaceDeclaration(SsmlXML.SPREADSHEETML_REVISION2_NAMESPACE); 109 addXMLNamespaceDeclaration(SsmlXML.SPREADSHEETML_REVISION3_NAMESPACE); 110 111 StringBuilderPlus ignorableBuffer = new StringBuilderPlus().setDelimiter(" ") 112 .delimitedAppend(SsmlXML.SPREADSHEETML_2009AC_NAMESPACE.getPrefix()) 113 .delimitedAppend(SsmlXML.SPREADSHEETML_REVISION1_NAMESPACE.getPrefix()) 114 .delimitedAppend(SsmlXML.SPREADSHEETML_REVISION2_NAMESPACE.getPrefix()) 115 .delimitedAppend(SsmlXML.SPREADSHEETML_REVISION3_NAMESPACE.getPrefix()); 116 117 setAttribute(OfficeXML.IGNORABLE_ATT, ignorableBuffer.toString()); 118 119 // Specify the sheet's GUID 120 setAttribute(SsmlXML.XR_UID_ATT, "{" + mUID + "}"); 121 122 getPageMargins(); 123 } 124 125 //--------------------------------------------------------------------------- 126 public SsmlWorksheet(WorksheetPart inParentWorksheetPart, String inName, XMLTag inSheetTag) 127 { 128 this(inParentWorksheetPart); 129 130 String name = inSheetTag.getAttributeValue(SsmlXML.NAME_ATT); 131 setName(StringUtil.isSet(name) ? name : inName); 132 133 try 134 { 135 XMLTag sheetDataTag = inSheetTag.getRequiredSubtagByName(SsmlXML.SHEET_DATA); 136 mSheetData = new SsmlSheetData(this, sheetDataTag); 137 138 // TODO: Parse other pieces 139 } 140 catch (Exception e) 141 { 142 throw new OfficeOpenXmlException("Problem parsing worksheet " + StringUtil.singleQuote(getName()) + "!", e); 143 } 144 } 145 146 //########################################################################### 147 // PUBLIC METHODS 148 //########################################################################### 149 150 //--------------------------------------------------------------------------- 151 public List<String> toTSV() 152 { 153 List<String> lines = new ArrayList<>(); 154 155 for (SsmlRow row : getSheetData().getRows()) 156 { 157 // Fill in missing lines 158 while (lines.size() < row.getRowIndex() - 1) 159 { 160 lines.add(""); 161 } 162 163 StringBuilderPlus lineBuffer = new StringBuilderPlus().setDelimiter("\t"); 164 List<SsmlCell> cells = row.getCells(); 165 if (CollectionUtil.hasValues(cells)) 166 { 167 SsmlCell prevCell = null; 168 int cellCount = 0; 169 for (SsmlCell cell : cells) 170 { 171 cellCount++; 172 173 int leadingEmptyCells = cell.getRef().getColIndex() - (prevCell != null ? prevCell.getRef().getColIndex() : 0) - 1; 174 if (leadingEmptyCells > 0) 175 { 176 lineBuffer.delimitedAppend(StringUtil.polyChar('\t', leadingEmptyCells)); 177 } 178 179 Object value = cell.getValue(); 180 String stringValue = (value != null ? value.toString() : ""); 181 // Handle multi-line cells 182 if (stringValue.indexOf('\n', 0) > 0) 183 { 184 stringValue = StringUtil.quote(StringUtil.replaceAllRegexp(stringValue, "\r?\n", "\\n")); 185 } 186 187 // Was using delimitedAppend() but it won't separate blank cells 188 if (cellCount > 1) 189 { 190 lineBuffer.append("\t"); 191 } 192 lineBuffer.append(stringValue); 193 194 prevCell = cell; 195 } 196 197 lines.add(lineBuffer.toString()); 198 } 199 } 200 201 return lines; 202 } 203 //--------------------------------------------------------------------------- 204 @Override 205 public String toString() 206 { 207 return getName(); 208 } 209 210 //--------------------------------------------------------------------------- 211 public WorksheetPart getParentWorksheetPart() 212 { 213 return mParentWorksheetPart; 214 } 215 216 //--------------------------------------------------------------------------- 217 public SsmlCommentsPart getCommentsPart() 218 { 219 if (null == mCommentsPart) 220 { 221 mCommentsPart = new SsmlCommentsPart(this); 222 } 223 224 return mCommentsPart; 225 } 226 227 //--------------------------------------------------------------------------- 228 public SsmlWorksheet setName(String inValue) 229 { 230 mName = null; 231 232 if (StringUtil.isSet(inValue)) 233 { 234 mName = inValue; 235 236 // Remove illegal sheet name characters 237 mName = StringUtil.replaceAllRegexp(mName, BAD_SHEET_NAME_CHAR_PATTERN, "_"); 238 239 // Truncate sheet names that are too long 240 if (mName.length() > MAX_SHEET_NAME_LENGTH) 241 { 242 mName = mName.substring(0, MAX_SHEET_NAME_LENGTH); 243 } 244 } 245 246 setAttribute(SsmlXML.NAME_ATT, mName); 247 248 return this; 249 } 250 251 //--------------------------------------------------------------------------- 252 public String getName() 253 { 254 return mName; 255 } 256 257 //--------------------------------------------------------------------------- 258 public SsmlSheetData getSheetData() 259 { 260 if (null == mSheetData) 261 { 262 // Check it it has been added via addSubtag()... 263 mSheetData = getOptionalSubtagByName(SsmlXML.SHEET_DATA); 264 if (null == mSheetData) 265 { 266 mSheetData = new SsmlSheetData(this); 267 addSubtag(mSheetData); 268 } 269 } 270 271 return mSheetData; 272 } 273 274 //--------------------------------------------------------------------------- 275 public void mergeCells(CellRange inCellRange) 276 { 277 XMLTag mergeCellsTag = getMergeCellsTag(); 278 279 XMLTag mergeCellTag = new XMLTag(SsmlXML.MERGE_CELL); 280 mergeCellTag.setAttribute(SsmlXML.REF_RANGE_ATT, inCellRange); 281 282 mergeCellsTag.addSubtag(mergeCellTag); 283 284 mergeCellsTag.setAttribute(SsmlXML.COUNT_ATT, mergeCellsTag.getSubtags().size()); 285 } 286 287 //--------------------------------------------------------------------------- 288 public void removeMergeCell(CellRange inCellRange) 289 { 290 XMLTag mergeCellsTag = getMergeCellsTag(); 291 for (XMLNode mergeCellTag : mergeCellsTag.getSubtagsByName(SsmlXML.MERGE_CELL)) 292 { 293 if (mergeCellTag.getAttributeValue(SsmlXML.REF_RANGE_ATT).equals(inCellRange.toString())) 294 { 295 mergeCellsTag.removeSubtag(mergeCellTag); 296 break; 297 } 298 } 299 300 mergeCellsTag.setAttribute(SsmlXML.COUNT_ATT, mergeCellsTag.getSubtags().size()); 301 } 302 303 //--------------------------------------------------------------------------- 304 public SsmlCol addColumn() 305 { 306 if (null == mColumnsTag) 307 { 308 // Check it it has been added via addSubtag()... 309 mColumnsTag = getOptionalSubtagByName(SsmlXML.COLUMNS); 310 if (null == mColumnsTag) 311 { 312 mColumnsTag = new XMLTag(SsmlXML.COLUMNS); 313 addSubtag(mColumnsTag); 314 } 315 } 316 317 SsmlCol col = new SsmlCol(this); 318 mColumnsTag.addSubtag(col); 319 320 return col; 321 } 322 323 //--------------------------------------------------------------------------- 324 public SsmlTable addTable() 325 { 326 if (null == mTableParts) 327 { 328 mTableParts = new HashMap<>(10); 329 330 mTablePartsTag = new XMLTag(SsmlXML.TABLE_PARTS); 331 addSubtag(mTablePartsTag); 332 } 333 334 TablePart tablePart = new TablePart(getParentWorksheetPart()).setTableIndex(mTableParts.size() + 1); 335 addTablePart(tablePart); 336 337 return tablePart.getRootNode(); 338 } 339 340 //--------------------------------------------------------------------------- 341 public SsmlDataValidation addDataValidation(CellRange inCellRange) 342 { 343 if (null == mDataValidationsTag) 344 { 345 // Check it it has been added via addSubtag()... 346 mDataValidationsTag = getOptionalSubtagByName(SsmlXML.DATA_VALIDATIONS); 347 if (null == mDataValidationsTag) 348 { 349 mDataValidationsTag = new XMLTag(SsmlXML.DATA_VALIDATIONS); 350 addSubtag(mDataValidationsTag); 351 } 352 } 353 354 355 SsmlDataValidation dataValidation = new SsmlDataValidation(getParentDoc(), inCellRange); 356 mDataValidationsTag.addSubtag(dataValidation); 357 358 359 mDataValidationsTag.setAttribute(SsmlXML.COUNT_ATT, mDataValidationsTag.getSubtagsByName(SsmlXML.DATA_VALIDATION).size()); 360 361 362 return dataValidation; 363 } 364 365 //--------------------------------------------------------------------------- 366 /** 367 Returns all table definitions. 368 */ 369 public Collection<SsmlTable> getTables() 370 { 371 ArrayList<SsmlTable> tables = new ArrayList<SsmlTable>(mTableParts.size()); 372 if (CollectionUtil.hasValues(mTableParts)) 373 { 374 for (TablePart part : mTableParts.values()) 375 { 376 tables.add(part.getRootNode()); 377 } 378 } 379 380 return tables; 381 } 382 383 //--------------------------------------------------------------------------- 384 /** 385 Returns a table by name. 386 * @param inTableName the name of the table 387 * @return SsmlTable 388 */ 389 public SsmlTable getTable(String inTableName) 390 { 391 TablePart part = mTableParts.get(inTableName); 392 return (part != null ? part.getRootNode() : null); 393 } 394 395 396 //--------------------------------------------------------------------------- 397 public SsmlWorksheet setDimension(CellRange inCellRange) 398 { 399 if (null == mDimensionTag) 400 { 401 // Check it it has been added via addSubtag()... 402 mDimensionTag = getOptionalSubtagByName(SsmlXML.DIMENSION); 403 if (null == mDimensionTag) 404 { 405 mDimensionTag = new XMLTag(SsmlXML.DIMENSION); 406 addSubtag(mDimensionTag); 407 } 408 } 409 410 mDimensionTag.setAttribute(SsmlXML.REF_RANGE_ATT, inCellRange); 411 412 return this; 413 } 414 415 //--------------------------------------------------------------------------- 416 public SsmlSheetFormatProperties getSheetFormatProperties() 417 { 418 if (null == mSheetFormatPropertiesTag) 419 { 420 // Check it it has been added via addSubtag()... 421 mSheetFormatPropertiesTag = getOptionalSubtagByName(SsmlXML.SHEET_FORMAT_PROPS); 422 if (null == mSheetFormatPropertiesTag) 423 { 424 mSheetFormatPropertiesTag = new SsmlSheetFormatProperties(getParentDoc()); 425 addSubtag(mSheetFormatPropertiesTag); 426 } 427 } 428 429 return mSheetFormatPropertiesTag; 430 } 431 432 433 //--------------------------------------------------------------------------- 434 public SsmlPageMargins getPageMargins() 435 { 436 if (null == mPageMargins) 437 { 438 // Check it it has been added via addSubtag()... 439 mPageMargins = getOptionalSubtagByName(SsmlXML.PAGE_MARGINS); 440 if (null == mPageMargins) 441 { 442 mPageMargins = new SsmlPageMargins(getParentDoc()); 443 addSubtag(mPageMargins); 444 } 445 } 446 447 return mPageMargins; 448 } 449 450 //--------------------------------------------------------------------------- 451 public SsmlSheetView addSheetView() 452 { 453 if (null == mSheetViewsTag) 454 { 455 mSheetViewsTag = new XMLTag(SsmlXML.SHEET_VIEWS); 456 addSubtag(mSheetViewsTag); 457 } 458 459 SsmlSheetView sheetView = new SsmlSheetView(getParentDoc()); 460 mSheetViewsTag.addSubtag(sheetView); 461 462 return sheetView; 463 } 464 465 //--------------------------------------------------------------------------- 466 public List<SsmlSheetView> getSheetViews() 467 { 468 List<SsmlSheetView> views = null; 469 470 if (mSheetViewsTag != null) 471 { 472 views = mSheetViewsTag.getSubtagsByName(SsmlXML.SHEET_VIEW); 473 } 474 475 return views; 476 } 477 478 479 //--------------------------------------------------------------------------- 480 public SsmlWorksheet setHeader(String inValue) 481 { 482 if (null == mHeaderFooterTag) 483 { 484 // Check it it has been added via addSubtag()... 485 mHeaderFooterTag = getOptionalSubtagByName(SsmlXML.HEADER_FOOTER); 486 } 487 488 if (StringUtil.isSet(inValue)) 489 { 490 if (null == mHeaderFooterTag) 491 { 492 mHeaderFooterTag = new SsmlHeaderFooter(getParentDoc()); 493 addSubtag(mHeaderFooterTag); 494 } 495 496 mHeaderFooterTag.setHeader(inValue); 497 } 498 else if (mHeaderFooterTag != null) 499 { 500 mHeaderFooterTag.setHeader(null); 501 } 502 503 return this; 504 } 505 506 //--------------------------------------------------------------------------- 507 public String getHeader() 508 { 509 if (null == mHeaderFooterTag) 510 { 511 // Check it it has been added via addSubtag()... 512 mHeaderFooterTag = getOptionalSubtagByName(SsmlXML.HEADER_FOOTER); 513 } 514 515 return (mHeaderFooterTag != null ? mHeaderFooterTag.getHeader() : null); 516 } 517 518 //--------------------------------------------------------------------------- 519 public SsmlWorksheet setFooter(String inValue) 520 { 521 if (null == mHeaderFooterTag) 522 { 523 // Check it it has been added via addSubtag()... 524 mHeaderFooterTag = getOptionalSubtagByName(SsmlXML.HEADER_FOOTER); 525 } 526 527 if (StringUtil.isSet(inValue)) 528 { 529 if (null == mHeaderFooterTag) 530 { 531 mHeaderFooterTag = new SsmlHeaderFooter(getParentDoc()); 532 addSubtag(mHeaderFooterTag); 533 } 534 535 mHeaderFooterTag.setFooter(inValue); 536 } 537 else if (mHeaderFooterTag != null) 538 { 539 mHeaderFooterTag.setFooter(null); 540 } 541 542 return this; 543 } 544 545 //--------------------------------------------------------------------------- 546 public String getFooter() 547 { 548 if (null == mHeaderFooterTag) 549 { 550 // Check it it has been added via addSubtag()... 551 mHeaderFooterTag = getOptionalSubtagByName(SsmlXML.HEADER_FOOTER); 552 } 553 554 return (mHeaderFooterTag != null ? mHeaderFooterTag.getFooter() : null); 555 } 556 557 558 559 //--------------------------------------------------------------------------- 560 public WorksheetDrawing addDrawing() 561 { 562 SsmlDrawingPart drawingPart = new SsmlDrawingPart(getParentWorksheetPart()); 563 getParentDoc().addDrawingPart(drawingPart);// This will set the drawing part's index 564 565 addDrawingPart(drawingPart); 566 567 return drawingPart.getRootNode(); 568 } 569 570 //--------------------------------------------------------------------------- 571 public SsmlConditionalFormatting addConditionalFormatting(CellRange inCellRange) 572 { 573 SsmlConditionalFormatting conditionalFormatting = new SsmlConditionalFormatting(this, inCellRange); 574 addSubtag(conditionalFormatting); 575 576 return conditionalFormatting; 577 } 578 579 //--------------------------------------------------------------------------- 580 public SsmlExtension getOrAddExtension(XMLNamespace inNamespace, SsmlExtension.URI_Type inURI_Type) 581 { 582 // Extensions are collected under an extLst tag 583 if (null == mExtLst) 584 { 585 // Check if it has been added via addSubtag()... 586 mExtLst = getOptionalSubtagByName(SsmlXML.EXTENSION_LIST); 587 if (null == mExtLst) 588 { 589 mExtLst = new XMLTag(SsmlXML.EXTENSION_LIST); 590 addSubtag(mExtLst); 591 } 592 } 593 594 SsmlExtension extension = mExtLst.getSubtagByAttribute(SsmlXML.URI_ATT, inURI_Type.getURI()); 595 if (null == extension) 596 { 597 extension = new SsmlExtension(this, inNamespace, inURI_Type); 598 mExtLst.addSubtag(extension); 599 } 600 601 return extension; 602 } 603 604 //--------------------------------------------------------------------------- 605 public void setPrintArea(CellRange inPrintArea) 606 { 607 getParentDoc().getWorkbookPart().getRootNode() 608 .setDefinedName(PRINT_AREA_NAME, this, StringUtil.singleQuote(getName()) 609 + "!$" + inPrintArea.getBeginCell().getCol() + "$" + inPrintArea.getBeginCell().getRowIndex() 610 + ":$" + inPrintArea.getEndCell().getCol() + "$" + inPrintArea.getEndCell().getRowIndex()); 611 } 612 613 //--------------------------------------------------------------------------- 614 @Override 615 public void toXML(Writer inWriter) 616 { 617 finalizeSheet(); 618 super.toXML(inWriter); 619 } 620 621 //--------------------------------------------------------------------------- 622 @Override 623 public void toIndentedXML(Writer inWriter, int inInitialIndentLevel, int inIndentSize) 624 { 625 finalizeSheet(); 626 super.toIndentedXML(inWriter, inInitialIndentLevel, inIndentSize); 627 } 628 629 //--------------------------------------------------------------------------- 630 public SsmlWorksheet setSortState(SsmlSortState inValue) 631 { 632 mSortState = inValue; 633 if (inValue != null) 634 { 635 addSubtag(mSortState); 636 } 637 else 638 { 639 // Remove the subtag if it was already added 640 XMLTag subtag = getOptionalSubtagByName(SsmlXML.SORT_STATE); 641 if (subtag != null) 642 { 643 removeSubtag(subtag); 644 } 645 } 646 647 return this; 648 } 649 650 651 //########################################################################### 652 // PROTECTED METHODS 653 //########################################################################### 654 655 //--------------------------------------------------------------------------- 656 /** 657 Called by the table when the user calls setName(). 658 */ 659 protected void renameTable(String inOldName, String inNewName) 660 { 661 if (! mTableParts.containsKey(inOldName)) 662 { 663 throw new ProgrammingException("No table was found in this sheet with name " + StringUtil.singleQuote(inOldName) + "!"); 664 } 665 else if (mTableParts.containsKey(inNewName)) 666 { 667 throw new InvalidValueException("A table with name " + StringUtil.singleQuote(inNewName) + " already exists in this worksheet!"); 668 } 669 670 TablePart tablePart = mTableParts.remove(inOldName); 671 mTableParts.put(inNewName, tablePart); 672 } 673 674 //########################################################################### 675 // PRIVATE METHODS 676 //########################################################################### 677 678 //--------------------------------------------------------------------------- 679 private void addTablePart(TablePart inValue) 680 { 681 if (inValue != null) 682 { 683 SsmlTable table = inValue.getRootNode(); 684 685 // Ensure that the table has a unique name 686 if (! StringUtil.isSet(table.getName())) 687 { 688 table.setName("Table" + (mTableParts.size() + 1)); 689 } 690 691 if (mTableParts.containsKey(table.getName())) 692 { 693 throw new OfficeOpenXmlException("The sheet name " + StringUtil.singleQuote(table.getName()) + " must be unique!"); 694 } 695 696 mTableParts.put(table.getName(), inValue); 697 698 String relationshipId = getParentWorksheetPart().getWorksheetRelationshipPart().addTable(inValue); 699 700 XMLTag tablePartTag = new XMLTag(SsmlXML.TABLE_PART); 701 tablePartTag.setAttribute(RelationshipXML.ID_ATT, relationshipId); 702 mTablePartsTag.addSubtag(tablePartTag); 703 704 mTablePartsTag.setAttribute(SsmlXML.COUNT_ATT, mTableParts.size()); 705 } 706 } 707 708 //--------------------------------------------------------------------------- 709 private void addDrawingPart(SsmlDrawingPart inValue) 710 { 711 if (inValue != null) 712 { 713 String relationshipId = getParentWorksheetPart().getWorksheetRelationshipPart().addDrawing(inValue); 714 715 XMLTag drawingTag = new XMLTag(SsmlXML.DRAWING); 716 drawingTag.setAttribute(RelationshipXML.ID_ATT, relationshipId); 717 addSubtag(drawingTag); 718 } 719 } 720 721 //--------------------------------------------------------------------------- 722 // Called before writing the sheet to XML. 723 private void finalizeSheet() 724 { 725 setDimension(); 726 727 if (null == mSheetViewsTag) 728 { 729 addSheetView(); 730 } 731 } 732 733 //--------------------------------------------------------------------------- 734 // Adds (or adjusts) a dimension tag (ex: <dimension ref="A1:B2"/>). 735 private void setDimension() 736 { 737 // Determine the dimensions of the sheet 738 List<XMLTag> rowTags = getSheetData().getSubtagsByName(SsmlXML.ROW); 739 if (CollectionUtil.hasValues(rowTags)) 740 { 741 Integer minRow = null; 742 Integer maxRow = null; 743 Integer minCol = null; 744 Integer maxCol = null; 745 for (XMLTag rowTag : rowTags) 746 { 747 List<XMLTag> cellTags = rowTag.getSubtagsByName(SsmlXML.CELL); 748 if (CollectionUtil.hasValues(cellTags)) 749 { 750 CellRef firstCell = new CellRef(cellTags.get(0).getAttributeValue(SsmlXML.REF_ATT)); 751 if (null == minRow) 752 { 753 minRow = firstCell.getRowIndex(); 754 } 755 756 maxRow = firstCell.getRowIndex(); 757 758 if (null == minCol 759 || firstCell.getColIndex() < minCol) 760 { 761 minCol = firstCell.getColIndex(); 762 } 763 764 CellRef lastCell = new CellRef(cellTags.get(cellTags.size() - 1).getAttributeValue(SsmlXML.REF_ATT)); 765 766 if (null == maxCol 767 || lastCell.getColIndex() > maxCol) 768 { 769 maxCol = lastCell.getColIndex(); 770 } 771 } 772 } 773 774 CellRef minCell = new CellRef().setRowIndex(minRow).setColIndex(minCol); 775 CellRef maxCell = new CellRef().setRowIndex(maxRow).setColIndex(maxCol); 776 /* 777 String minCell = ""; 778 List<XMLTag> cellTags = rowTags.get(0).getSubtagsByName(SsmlXML.CELL); 779 if (CollectionUtil.hasValues(cellTags)) 780 { 781 minCell = cellTags.get(0).getAttributeValue(SsmlXML.REF_ATT); 782 } 783 784 String maxCell = ""; 785 cellTags = rowTags.get(rowTags.size() - 1).getSubtagsByName(SsmlXML.CELL); 786 if (CollectionUtil.hasValues(cellTags)) 787 { 788 maxCell = cellTags.get(cellTags.size() - 1).getAttributeValue(SsmlXML.REF_ATT); 789 } 790*/ 791 setDimension(new CellRange(minCell, maxCell)); 792 } 793 } 794 795 796 //--------------------------------------------------------------------------- 797 private XMLTag getMergeCellsTag() 798 { 799 if (null == mMergeCellsTag) 800 { 801 // Check if it has been added via addSubtag()... 802 mMergeCellsTag = getOptionalSubtagByName(SsmlXML.MERGE_CELLS); 803 if (null == mMergeCellsTag) 804 { 805 mMergeCellsTag = new XMLTag(SsmlXML.MERGE_CELLS); 806 addSubtag(mMergeCellsTag); 807 } 808 } 809 810 return mMergeCellsTag; 811 } 812 813}