001package com.hfg.xml.msofficexml.xlsx.spreadsheetml.style; 002 003import java.awt.Font; 004 005import com.hfg.util.CompareUtil; 006import com.hfg.util.StringUtil; 007import com.hfg.xml.XMLAttribute; 008import com.hfg.xml.XMLTag; 009import com.hfg.xml.msofficexml.xlsx.Xlsx; 010import com.hfg.xml.msofficexml.xlsx.spreadsheetml.SsmlXML; 011import com.hfg.xml.msofficexml.xlsx.spreadsheetml.SsmlXMLTag; 012 013 014//------------------------------------------------------------------------------ 015/** 016 Represents an Office Open XML spreadsheetml (<ssml:xf>) tag. 017 <div> 018 @author J. Alex Taylor, hairyfatguy.com 019 </div> 020 */ 021//------------------------------------------------------------------------------ 022// com.hfg XML/HTML Coding Library 023// 024// This library is free software; you can redistribute it and/or 025// modify it under the terms of the GNU Lesser General Public 026// License as published by the Free Software Foundation; either 027// version 2.1 of the License, or (at your option) any later version. 028// 029// This library is distributed in the hope that it will be useful, 030// but WITHOUT ANY WARRANTY; without even the implied warranty of 031// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 032// Lesser General Public License for more details. 033// 034// You should have received a copy of the GNU Lesser General Public 035// License along with this library; if not, write to the Free Software 036// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 037// 038// J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com 039// jataylor@hairyfatguy.com 040//------------------------------------------------------------------------------ 041 042public class SsmlCellFormat extends SsmlXMLTag implements Comparable 043{ 044 private Integer mIndex; 045 private SsmlAlignment mAlignmentTag; 046 047 //########################################################################## 048 // CONSTRUCTORS 049 //########################################################################## 050 051 //--------------------------------------------------------------------------- 052 public SsmlCellFormat(Xlsx inXlsx) 053 { 054 this(inXlsx.getStylesPart()); 055 } 056 057 //--------------------------------------------------------------------------- 058 public SsmlCellFormat(StylesPart inStylesPart) 059 { 060 super(SsmlXML.CELL_FORMAT, inStylesPart.getParentDoc()); 061 // Register with the styles part 062 mIndex = inStylesPart.defineCellFormat(this); 063 064 setDefaults(inStylesPart); 065 } 066 067 //--------------------------------------------------------------------------- 068 public SsmlCellFormat(Xlsx inXlsx, XMLTag inXMLTag) 069 { 070 super(SsmlXML.CELL_FORMAT, inXlsx); 071 072 for (XMLAttribute attr : inXMLTag.getAttributes()) 073 { 074 setAttribute(attr); 075 } 076 } 077 078 //--------------------------------------------------------------------------- 079 private void setDefaults(StylesPart inStylesPart) 080 { 081 setStyleFormat(inStylesPart.getStyleFormat(0)); 082 } 083 084 //########################################################################## 085 // PUBLIC METHODS 086 //########################################################################## 087 088 //--------------------------------------------------------------------------- 089 @Override 090 public SsmlCellFormat clone() 091 { 092 SsmlCellFormat clone = new SsmlCellFormat(getParentDoc()); 093 094 if (hasAttribute(SsmlXML.FONT_ID_ATT)) 095 { 096 clone.setAttribute(SsmlXML.FONT_ID_ATT, getAttributeValue(SsmlXML.FONT_ID_ATT)); 097 } 098 099 if (hasAttribute(SsmlXML.FILL_ID_ATT)) 100 { 101 clone.setAttribute(SsmlXML.FONT_ID_ATT, getAttributeValue(SsmlXML.FILL_ID_ATT)); 102 } 103 104 if (hasAttribute(SsmlXML.BORDER_ID_ATT)) 105 { 106 clone.setAttribute(SsmlXML.BORDER_ID_ATT, getAttributeValue(SsmlXML.BORDER_ID_ATT)); 107 } 108 109 if (hasAttribute(SsmlXML.NUM_FORMAT_ID_ATT)) 110 { 111 clone.setAttribute(SsmlXML.NUM_FORMAT_ID_ATT, getAttributeValue(SsmlXML.NUM_FORMAT_ID_ATT)); 112 } 113 114 if (mAlignmentTag != null) 115 { 116 clone.mAlignmentTag = mAlignmentTag.clone(); 117 } 118 119 120 // Register with the styles part 121 clone.mIndex = getParentDoc().getStylesPart().defineCellFormat(clone); 122 123 return clone; 124 } 125 126 //-------------------------------------------------------------------------- 127 @Override 128 public boolean equals(Object inObj2) 129 { 130 return (0 == compareTo(inObj2)); 131 } 132 133 //-------------------------------------------------------------------------- 134 @Override 135 public int compareTo(Object inObj2) 136 { 137 int result = -1; 138 139 if (inObj2 instanceof SsmlCellFormat) 140 { 141 SsmlCellFormat cellFormat2 = (SsmlCellFormat) inObj2; 142 143 result = CompareUtil.compare(getFontId(), cellFormat2.getFontId()); 144 145 if (0 == result) 146 { 147 result = CompareUtil.compare(getFillId(), cellFormat2.getFillId()); 148 149 if (0 == result) 150 { 151 result = CompareUtil.compare(getBorderId(), cellFormat2.getBorderId()); 152 153 if (0 == result) 154 { 155 result = CompareUtil.compare(getNumberFormatId(), cellFormat2.getNumberFormatId()); 156 157 if (0 == result) 158 { 159 if (hasAlignment()) 160 { 161 if (cellFormat2.hasAlignment()) 162 { 163 result = CompareUtil.compare(getAlignment(), cellFormat2.getAlignment()); 164 } 165 else 166 { 167 result = 1; 168 } 169 } 170 else if (cellFormat2.hasAlignment()) 171 { 172 result = -1; 173 } 174 } 175 } 176 } 177 } 178 } 179 180 return result; 181 } 182 183 //--------------------------------------------------------------------------- 184 public Integer getIndex() 185 { 186 return mIndex; 187 } 188 189 //--------------------------------------------------------------------------- 190 public SsmlCellFormat setFont(Font inValue) 191 { 192 return setFont(inValue != null ? new SsmlFont(inValue, getParentDoc()) : null); 193 } 194 195 //--------------------------------------------------------------------------- 196 public SsmlCellFormat setFont(SsmlFont inValue) 197 { 198 if (inValue != null) 199 { 200 setAttribute(SsmlXML.FONT_ID_ATT, inValue.getIndex()); 201 } 202 else 203 { 204 removeAttribute(SsmlXML.FONT_ID_ATT); 205 } 206 207 return this; 208 } 209 210 //--------------------------------------------------------------------------- 211 // TODO: Should we be returning a new SsmlFont when one hasn't been set yet? 212 public SsmlFont getFont() 213 { 214 SsmlFont font; 215 216 if (hasAttribute(SsmlXML.FONT_ID_ATT)) 217 { 218 int fontId = Integer.parseInt(getAttributeValue(SsmlXML.FONT_ID_ATT)); 219 font = getParentDoc().getStylesPart().getFonts().get(fontId); 220 } 221 else 222 { 223 font = new SsmlFont(getParentDoc()); 224 setFont(font); 225 } 226 227 return font; 228 } 229 230 //--------------------------------------------------------------------------- 231 public int getFontId() 232 { 233 String value = getAttributeValue(SsmlXML.FONT_ID_ATT); 234 return (StringUtil.isSet(value) ? Integer.parseInt(value) : 0); 235 } 236 237 //--------------------------------------------------------------------------- 238 public SsmlCellFormat setFill(SsmlFill inValue) 239 { 240 if (inValue != null) 241 { 242 setAttribute(SsmlXML.FILL_ID_ATT, inValue.getIndex()); 243 } 244 else 245 { 246 removeAttribute(SsmlXML.FILL_ID_ATT); 247 } 248 249 return this; 250 } 251 252 //--------------------------------------------------------------------------- 253 // TODO: Should we be returning a new SsmlFill when one hasn't been set yet? 254 public SsmlFill getFill() 255 { 256 SsmlFill fill; 257 258 if (hasAttribute(SsmlXML.FILL_ID_ATT)) 259 { 260 int fillId = Integer.parseInt(getAttributeValue(SsmlXML.FILL_ID_ATT)); 261 fill = getParentDoc().getStylesPart().getFills().get(fillId); 262 } 263 else 264 { 265 fill = new SsmlFill(getParentDoc()); 266 setFill(fill); 267 } 268 269 return fill; 270 } 271 272 //--------------------------------------------------------------------------- 273 public int getFillId() 274 { 275 String value = getAttributeValue(SsmlXML.FILL_ID_ATT); 276 return (StringUtil.isSet(value) ? Integer.parseInt(value) : 0); 277 } 278 279 //--------------------------------------------------------------------------- 280 public SsmlCellFormat setBorder(SsmlBorder inValue) 281 { 282 if (inValue != null) 283 { 284 setAttribute(SsmlXML.BORDER_ID_ATT, inValue.getIndex()); 285 } 286 else 287 { 288 removeAttribute(SsmlXML.BORDER_ID_ATT); 289 } 290 291 return this; 292 } 293 294 //--------------------------------------------------------------------------- 295 // TODO: Should we be returning a new SsmlBorder when one hasn't been set yet? 296 public SsmlBorder getBorder() 297 { 298 SsmlBorder border; 299 300 if (hasAttribute(SsmlXML.BORDER_ID_ATT)) 301 { 302 int borderId = Integer.parseInt(getAttributeValue(SsmlXML.BORDER_ID_ATT)); 303 border = getParentDoc().getStylesPart().getBorders().get(borderId); 304 } 305 else 306 { 307 border = new SsmlBorder(getParentDoc()); 308 setBorder(border); 309 } 310 311 return border; 312 } 313 314 //--------------------------------------------------------------------------- 315 public int getBorderId() 316 { 317 String value = getAttributeValue(SsmlXML.BORDER_ID_ATT); 318 return (StringUtil.isSet(value) ? Integer.parseInt(value) : 0); 319 } 320 321 //--------------------------------------------------------------------------- 322 public SsmlCellFormat setNumberFormat(SsmlNumberFormat inValue) 323 { 324 if (inValue != null) 325 { 326 if (null == inValue.getParentDoc()) 327 { 328 // This may be true if it was a standard format 329 inValue.setParentDoc(getParentDoc()); 330 } 331 332 setAttribute(SsmlXML.NUM_FORMAT_ID_ATT, inValue.getIndex()); 333 } 334 else 335 { 336 removeAttribute(SsmlXML.NUM_FORMAT_ID_ATT); 337 } 338 339 return this; 340 } 341 342 //--------------------------------------------------------------------------- 343 public SsmlNumberFormat getNumberFormat() 344 { 345 SsmlNumberFormat numberFormat = null; 346 347 if (hasAttribute(SsmlXML.NUM_FORMAT_ID_ATT)) 348 { 349 int numFormatId = Integer.parseInt(getAttributeValue(SsmlXML.NUM_FORMAT_ID_ATT)); 350 if (numFormatId >= 164) // Custom num format? 351 { 352 for (SsmlNumberFormat customNumFormat : getParentDoc().getStylesPart().getNumberFormats()) 353 { 354 if (customNumFormat.getIndex().equals(numFormatId)) 355 { 356 numberFormat = customNumFormat; 357 break; 358 } 359 } 360 } 361 else 362 { 363 for (SsmlNumberFormat defaultFormat : SsmlNumberFormat.getDefaultValues()) 364 { 365 if (defaultFormat.getIndex().equals(numFormatId)) 366 { 367 numberFormat = defaultFormat; 368 break; 369 } 370 } 371 } 372 } 373 374 return numberFormat; 375 } 376 377 //--------------------------------------------------------------------------- 378 public int getNumberFormatId() 379 { 380 String value = getAttributeValue(SsmlXML.NUM_FORMAT_ID_ATT); 381 return (StringUtil.isSet(value) ? Integer.parseInt(value) : 0); 382 } 383 384 //--------------------------------------------------------------------------- 385 public boolean hasAlignment() 386 { 387 return (mAlignmentTag != null 388 || getOptionalSubtagByName(SsmlXML.ALIGNMENT) != null); 389 } 390 391 //--------------------------------------------------------------------------- 392 public SsmlAlignment getAlignment() 393 { 394 if (null == mAlignmentTag) 395 { 396 // Check if it has been added via addSubtag()... 397 mAlignmentTag = getOptionalSubtagByName(SsmlXML.ALIGNMENT); 398 399 if (null == mAlignmentTag) 400 { 401 setAlignment(new SsmlAlignment(getParentDoc())); 402 } 403 } 404 405 return mAlignmentTag; 406 } 407 408 //--------------------------------------------------------------------------- 409 public SsmlCellFormat setAlignment(SsmlAlignment inValue) 410 { 411 removeSubtagsByName(SsmlXML.ALIGNMENT); 412 413 mAlignmentTag = inValue; 414 if (mAlignmentTag != null) 415 { 416 addSubtag(mAlignmentTag); 417 } 418 419 return this; 420 } 421 422 //--------------------------------------------------------------------------- 423 public SsmlCellFormat setStyle(SsmlCellStyle inValue) 424 { 425 return setStyleFormat(inValue != null ? inValue.getStyleFormat() : null); 426 } 427 428 //--------------------------------------------------------------------------- 429 public SsmlCellFormat setStyleFormat(SsmlStyleFormat inValue) 430 { 431 if (inValue != null) 432 { 433 setAttribute(SsmlXML.STYLE_FORMAT_ID_ATT, inValue.getIndex()); 434 435 // TODO: The ECMA-376 documentation indicates that the cell style format should 436 // be inherited but that does not appear to be true. For now it seems that 437 // we have to copy format properties from the style. 438 // See old post about cellStyleXfs being ignored: http://openxmldeveloper.org/discussions/formats/f/14/p/717/1755.aspx#1755 439 if (inValue.getAlignment() != null) 440 { 441 setAlignment(inValue.getAlignment()); 442 } 443 444 if (inValue.getBorder() != null) 445 { 446 setBorder(inValue.getBorder()); 447 } 448 449 if (inValue.getFill() != null) 450 { 451 setFill(inValue.getFill()); 452 } 453 454 if (inValue.getFont() != null) 455 { 456 setFont(inValue.getFont()); 457 } 458 459 if (inValue.getNumberFormat() != null) 460 { 461 setNumberFormat(inValue.getNumberFormat()); 462 } 463 464 } 465 else 466 { 467 removeAttribute(SsmlXML.STYLE_FORMAT_ID_ATT); 468 } 469 470 return this; 471 } 472 473 //--------------------------------------------------------------------------- 474 /** 475 Only for use by the StylesPart when setting a new value for the default font. 476 * @param inValue the new index value 477 * @return this object to enable chaining 478 */ 479 protected SsmlCellFormat setIndex(Integer inValue) 480 { 481 mIndex = inValue; 482 return this; 483 } 484 485}