001package com.hfg.xml.msofficexml.xlsx.spreadsheetml; 002 003import java.util.Collection; 004import java.util.List; 005 006import com.hfg.graphics.units.GfxSize; 007import com.hfg.graphics.units.GfxUnits; 008import com.hfg.util.StringUtil; 009import com.hfg.util.collection.CollectionUtil; 010import com.hfg.xml.XMLAttribute; 011import com.hfg.xml.XMLName; 012import com.hfg.xml.XMLTag; 013import com.hfg.xml.XMLizable; 014import com.hfg.xml.msofficexml.xlsx.CellRef; 015 016//------------------------------------------------------------------------------ 017/** 018 Represents an Office Open XML worksheet data row (<ssml:r>) tag. 019 020 @author J. Alex Taylor, hairyfatguy.com 021 */ 022//------------------------------------------------------------------------------ 023// com.hfg XML/HTML Coding Library 024// 025// This library is free software; you can redistribute it and/or 026// modify it under the terms of the GNU Lesser General Public 027// License as published by the Free Software Foundation; either 028// version 2.1 of the License, or (at your option) any later version. 029// 030// This library is distributed in the hope that it will be useful, 031// but WITHOUT ANY WARRANTY; without even the implied warranty of 032// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 033// Lesser General Public License for more details. 034// 035// You should have received a copy of the GNU Lesser General Public 036// License along with this library; if not, write to the Free Software 037// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 038// 039// J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com 040// jataylor@hairyfatguy.com 041//------------------------------------------------------------------------------ 042 043public class SsmlRow extends SsmlXMLTag 044{ 045 private SsmlWorksheet mParentWorksheet; 046 047 // Cached values 048 private List<SsmlCell> mCells; 049 050 //########################################################################## 051 // CONSTRUCTORS 052 //########################################################################## 053 054 //--------------------------------------------------------------------------- 055 public SsmlRow(SsmlWorksheet inParentWorksheet) 056 { 057 super(SsmlXML.ROW, inParentWorksheet.getParentDoc()); 058 mParentWorksheet = inParentWorksheet; 059 } 060 061 //--------------------------------------------------------------------------- 062 public SsmlRow(SsmlWorksheet inParentWorksheet, XMLTag inXMLTag) 063 { 064 this(inParentWorksheet); 065 inXMLTag.verifyTagName(SsmlXML.ROW); 066 067 setRowIndex(Integer.parseInt(inXMLTag.getAttributeValue(SsmlXML.ROW_IDX_ATT))); 068 069 // Copy subtags over to this tag 070 if (CollectionUtil.hasValues(inXMLTag.getSubtags())) 071 { 072 for (XMLTag subtag : (List<XMLTag>) (Object) inXMLTag.getSubtags()) 073 { 074 if (subtag.getTagName().equals(SsmlXML.CELL.getLocalName())) 075 { 076 addCell(new SsmlCell(inParentWorksheet, subtag)); 077 } 078 else 079 { 080 addSubtag(subtag); 081 } 082 } 083 } 084 } 085 086 //########################################################################## 087 // PUBLIC METHODS 088 //########################################################################## 089 090 091 //--------------------------------------------------------------------------- 092 public SsmlRow setRowIndex(int inValue) 093 { 094 setAttribute(SsmlXML.ROW_IDX_ATT, inValue); 095 096 return this; 097 } 098 099 //--------------------------------------------------------------------------- 100 public Integer getRowIndex() 101 { 102 XMLAttribute attr = getAttribute(SsmlXML.ROW_IDX_ATT); 103 104 return attr != null ? Integer.parseInt(attr.getValue()) : null; 105 } 106 107 //--------------------------------------------------------------------------- 108 public SsmlCell addCell() 109 { 110 String column = "A"; 111 // How many cells do we already have? 112 CellRef maxCell = getMaxCellRef(); 113 if (maxCell != null) 114 { 115 column = maxCell.nextCol(); 116 } 117 118 // They might set the column later but we want to be sure that it has a value. 119 SsmlCell cell = new SsmlCell(mParentWorksheet).setRef(new CellRef(column + getRowIndex())); 120 addSubtag(cell); 121 122 clearCachedValues(); 123 124 return cell; 125 } 126 127 //--------------------------------------------------------------------------- 128 public SsmlCell setCell(int inColIndex, String inValue) 129 { 130 return addCellByColIndex(inColIndex).setValue(inValue); 131 } 132 133 //--------------------------------------------------------------------------- 134 public SsmlCell addCellByColIndex(int inColIndex) 135 { 136 CellRef cellRef = new CellRef().setColIndex(inColIndex).setRowIndex(getRowIndex()); 137 138 SsmlCell cell = new SsmlCell(mParentWorksheet).setRef(cellRef); 139 addCell(cell); 140 141 return cell; 142 } 143 144 //--------------------------------------------------------------------------- 145 public void addCell(SsmlCell inValue) 146 { 147 int maxColIndex = 0; 148 149 CellRef maxCellRef = getMaxCellRef(); 150 if (maxCellRef != null) 151 { 152 maxColIndex = maxCellRef.getColIndex(); 153 } 154 155 if (null == inValue.getRef()) 156 { 157 // No column specified. Add to the end of the row. 158 inValue.setRef(new CellRef().setColIndex(maxColIndex + 1).setRowIndex(getRowIndex())); 159 } 160 161 162 if (inValue.getRef().getColIndex() > maxColIndex) 163 { 164 // It's the highest value. Just add it to the end. 165 addSubtag(inValue); 166 } 167 else 168 { 169 List<SsmlCell> cells = getCells(); 170 for (int i = 0; i < cells.size(); i++) 171 { 172 SsmlCell cell = cells.get(i); 173 if (cell.getRef().equals(inValue.getRef())) 174 { 175 // Replace this cell. 176 addSubtag(getContentPlusSubtagList().indexOf(cells.get(i)), inValue); 177 removeSubtag(cell); 178 break; 179 } 180 else if (cell.getRef().getColIndex() > inValue.getRef().getColIndex()) 181 { 182 // Insert before this cell. 183 addSubtag(getContentPlusSubtagList().indexOf(cells.get(i)), inValue); 184 break; 185 } 186 } 187 } 188 189 clearCachedValues(); 190 } 191 192 //--------------------------------------------------------------------------- 193 public SsmlCell addCell(Object inValue) 194 { 195 return addCell().setValue(inValue); 196 } 197 198 //--------------------------------------------------------------------------- 199 public SsmlCell addCell(SsmlTextRun inValue) 200 { 201 return addCell().setValue(inValue); 202 } 203 204 //--------------------------------------------------------------------------- 205 public SsmlCell addCell(List<SsmlTextRun> inValue) 206 { 207 return addCell().setValue(inValue); 208 } 209 210 //--------------------------------------------------------------------------- 211 public SsmlCell addCell(String inValue) 212 { 213 return addCell().setValue(inValue); 214 } 215 216 //--------------------------------------------------------------------------- 217 public SsmlCell addCell(int inValue) 218 { 219 return addCell().setValue(inValue); 220 } 221 222 //--------------------------------------------------------------------------- 223 public SsmlCell addCell(long inValue) 224 { 225 return addCell().setValue(inValue); 226 } 227 228 //--------------------------------------------------------------------------- 229 public SsmlCell addCell(float inValue) 230 { 231 return addCell().setValue(inValue); 232 } 233 234 //--------------------------------------------------------------------------- 235 public SsmlCell addCell(double inValue) 236 { 237 return addCell().setValue(inValue); 238 } 239 240 //--------------------------------------------------------------------------- 241 public List<SsmlCell> getCells() 242 { 243 if (null == mCells) 244 { 245 mCells = (List<SsmlCell>) (Object) getSubtagsByName(SsmlXML.CELL); 246 } 247 248 return mCells; 249 } 250 251 //--------------------------------------------------------------------------- 252 /** 253 * Returns whether or not any cell in this row contains content. 254 * @return whether or not any cell in this row contains content 255 */ 256 public boolean isEmpty() 257 { 258 return null == getFirstCellWithContent(); 259 } 260 261 //--------------------------------------------------------------------------- 262 /** 263 * Returns the first cell in this row that contains content. 264 * @return the first cell in this row that contains content 265 */ 266 public SsmlCell getFirstCellWithContent() 267 { 268 SsmlCell firstCellWithContent = null; 269 List<SsmlCell> cells = getCells(); 270 if (CollectionUtil.hasValues(cells)) 271 { 272 for (SsmlCell cell : cells) 273 { 274 Object value = cell.getValue(); 275 if (value != null 276 && StringUtil.isSet(value.toString())) 277 { 278 firstCellWithContent = cell; 279 break; 280 } 281 } 282 } 283 284 return firstCellWithContent; 285 } 286 287 //--------------------------------------------------------------------------- 288 public SsmlCell getCellByColIndex(int inColIndex) 289 { 290 SsmlCell requestedCell = null; 291 292 if (CollectionUtil.hasValues(getCells())) 293 { 294 for (SsmlCell cell : getCells()) 295 { 296 if (cell.getRef().getColIndex() == inColIndex) 297 { 298 requestedCell = cell; 299 break; 300 } 301 } 302 } 303 304 return requestedCell; 305 } 306 307 //--------------------------------------------------------------------------- 308 public CellRef getMinCellRef() 309 { 310 // How many cells do we already have? 311 CellRef cellRef = null; 312 313 List<XMLTag> cellTags = getSubtagsByName(SsmlXML.CELL); 314 if (CollectionUtil.hasValues(cellTags)) 315 { 316 XMLTag firstCell = cellTags.get(0); 317 XMLAttribute attr = firstCell.getAttribute(SsmlXML.REF_ATT); 318 if (attr != null) 319 { 320 cellRef = new CellRef(attr.getValue()); 321 } 322 } 323 324 return cellRef; 325 } 326 327 //--------------------------------------------------------------------------- 328 public CellRef getMaxCellRef() 329 { 330 // How many cells do we already have? 331 CellRef cellRef = null; 332 333 List<XMLTag> cellTags = getSubtagsByName(SsmlXML.CELL); 334 if (CollectionUtil.hasValues(cellTags)) 335 { 336 XMLTag lastCell = cellTags.get(cellTags.size() - 1); 337 XMLAttribute attr = lastCell.getAttribute(SsmlXML.REF_ATT); 338 if (attr != null) 339 { 340 cellRef = new CellRef(attr.getValue()); 341 } 342 } 343 344 return cellRef; 345 } 346 347 //--------------------------------------------------------------------------- 348 public SsmlRow setHeight(GfxSize inValue) 349 { 350 setAttribute(SsmlXML.HEIGHT_ATT, inValue.to(GfxUnits.points)); 351 setAttribute(SsmlXML.CUSTOM_HEIGHT_ATT, "1"); 352 return this; 353 } 354 355 //--------------------------------------------------------------------------- 356 @Override 357 public synchronized void addSubtags(Collection<? extends XMLizable> inSubtags) 358 { 359 clearCachedValues(); 360 super.addSubtags(inSubtags); 361 } 362 363 //--------------------------------------------------------------------------- 364 @Override 365 public void addSubtag(XMLizable inSubtag) 366 { 367 clearCachedValues(); 368 super.addSubtag(inSubtag); 369 } 370 371 //--------------------------------------------------------------------------- 372 @Override 373 public void addSubtag(int inIndex, XMLizable inSubtag) 374 { 375 clearCachedValues(); 376 super.addSubtag(inIndex, inSubtag); 377 } 378 379 //-------------------------------------------------------------------------- 380 @Override 381 public XMLTag addSubtag(String inTagName) 382 { 383 clearCachedValues(); 384 return super.addSubtag(inTagName); 385 } 386 387 //-------------------------------------------------------------------------- 388 @Override 389 public XMLTag addSubtag(XMLName inTagName) 390 { 391 clearCachedValues(); 392 return super.addSubtag(inTagName); 393 } 394 395 //--------------------------------------------------------------------------- 396 private void clearCachedValues() 397 { 398 mCells = null; 399 } 400}