You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

PropertyTemplate.java 34KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966
  1. /* ====================================================================
  2. Licensed to the Apache Software Foundation (ASF) under one or more
  3. contributor license agreements. See the NOTICE file distributed with
  4. this work for additional information regarding copyright ownership.
  5. The ASF licenses this file to You under the Apache License, Version 2.0
  6. (the "License"); you may not use this file except in compliance with
  7. the License. You may obtain a copy of the License at
  8. http://www.apache.org/licenses/LICENSE-2.0
  9. Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is distributed on an "AS IS" BASIS,
  11. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. See the License for the specific language governing permissions and
  13. limitations under the License.
  14. ==================================================================== */
  15. package org.apache.poi.ss.util;
  16. import java.util.HashMap;
  17. import java.util.HashSet;
  18. import java.util.Map;
  19. import java.util.Set;
  20. import org.apache.poi.hssf.usermodel.HSSFWorkbook;
  21. import org.apache.poi.ss.SpreadsheetVersion;
  22. import org.apache.poi.ss.usermodel.BorderExtent;
  23. import org.apache.poi.ss.usermodel.BorderStyle;
  24. import org.apache.poi.ss.usermodel.Cell;
  25. import org.apache.poi.ss.usermodel.IndexedColors;
  26. import org.apache.poi.ss.usermodel.Row;
  27. import org.apache.poi.ss.usermodel.Sheet;
  28. import org.apache.poi.ss.usermodel.Workbook;
  29. /**
  30. * <p>
  31. * A {@link PropertyTemplate} is a template that can be applied to any sheet in
  32. * a project. It contains all the border type and color attributes needed to
  33. * draw all the borders for a single sheet. That template can be applied to any
  34. * sheet in any workbook.
  35. *
  36. * This class requires the full spreadsheet to be in memory, so
  37. * {@link org.apache.poi.xssf.streaming.SXSSFWorkbook} Spreadsheets are not
  38. * supported. The same {@link PropertyTemplate} can, however, be applied to both
  39. * {@link HSSFWorkbook} and {@link org.apache.poi.xssf.usermodel.XSSFWorkbook}
  40. * objects if necessary. Portions of the border that fall outside the max range
  41. * of the {@link Workbook} sheet are ignored.
  42. * </p>
  43. *
  44. * <p>
  45. * This would replace {@link RegionUtil}.
  46. * </p>
  47. */
  48. public final class PropertyTemplate {
  49. /**
  50. * This is a list of cell properties for one shot application to a range of
  51. * cells at a later time.
  52. */
  53. private Map<CellAddress, Map<String, Object>> _propertyTemplate;
  54. /**
  55. * Create a PropertyTemplate object
  56. */
  57. public PropertyTemplate() {
  58. _propertyTemplate = new HashMap<>();
  59. }
  60. /**
  61. * Create a PropertyTemplate object from another PropertyTemplate
  62. *
  63. * @param template a PropertyTemplate object
  64. */
  65. public PropertyTemplate(PropertyTemplate template) {
  66. this();
  67. for(Map.Entry<CellAddress, Map<String, Object>> entry : template.getTemplate().entrySet()) {
  68. _propertyTemplate.put(new CellAddress(entry.getKey()), cloneCellProperties(entry.getValue()));
  69. }
  70. }
  71. private Map<CellAddress,Map<String, Object>> getTemplate() {
  72. return _propertyTemplate;
  73. }
  74. private static Map<String, Object> cloneCellProperties(Map<String, Object> properties) {
  75. Map<String, Object> newProperties = new HashMap<>();
  76. for(Map.Entry<String, Object> entry : properties.entrySet()) {
  77. newProperties.put(entry.getKey(), entry.getValue());
  78. }
  79. return newProperties;
  80. }
  81. /**
  82. * Draws a group of cell borders for a cell range. The borders are not
  83. * applied to the cells at this time, just the template is drawn. To apply
  84. * the drawn borders to a sheet, use {@link #applyBorders}.
  85. *
  86. * @param range
  87. * - {@link CellRangeAddress} range of cells on which borders are
  88. * drawn.
  89. * @param borderType
  90. * - Type of border to draw. {@link BorderStyle}.
  91. * @param extent
  92. * - {@link BorderExtent} of the borders to be
  93. * applied.
  94. */
  95. public void drawBorders(CellRangeAddress range, BorderStyle borderType,
  96. BorderExtent extent) {
  97. switch (extent) {
  98. case NONE:
  99. removeBorders(range);
  100. break;
  101. case ALL:
  102. drawHorizontalBorders(range, borderType, BorderExtent.ALL);
  103. drawVerticalBorders(range, borderType, BorderExtent.ALL);
  104. break;
  105. case INSIDE:
  106. drawHorizontalBorders(range, borderType, BorderExtent.INSIDE);
  107. drawVerticalBorders(range, borderType, BorderExtent.INSIDE);
  108. break;
  109. case OUTSIDE:
  110. drawOutsideBorders(range, borderType, BorderExtent.ALL);
  111. break;
  112. case TOP:
  113. drawTopBorder(range, borderType);
  114. break;
  115. case BOTTOM:
  116. drawBottomBorder(range, borderType);
  117. break;
  118. case LEFT:
  119. drawLeftBorder(range, borderType);
  120. break;
  121. case RIGHT:
  122. drawRightBorder(range, borderType);
  123. break;
  124. case HORIZONTAL:
  125. drawHorizontalBorders(range, borderType, BorderExtent.ALL);
  126. break;
  127. case INSIDE_HORIZONTAL:
  128. drawHorizontalBorders(range, borderType, BorderExtent.INSIDE);
  129. break;
  130. case OUTSIDE_HORIZONTAL:
  131. drawOutsideBorders(range, borderType, BorderExtent.HORIZONTAL);
  132. break;
  133. case VERTICAL:
  134. drawVerticalBorders(range, borderType, BorderExtent.ALL);
  135. break;
  136. case INSIDE_VERTICAL:
  137. drawVerticalBorders(range, borderType, BorderExtent.INSIDE);
  138. break;
  139. case OUTSIDE_VERTICAL:
  140. drawOutsideBorders(range, borderType, BorderExtent.VERTICAL);
  141. break;
  142. }
  143. }
  144. /**
  145. * Draws a group of cell borders for a cell range. The borders are not
  146. * applied to the cells at this time, just the template is drawn. To apply
  147. * the drawn borders to a sheet, use {@link #applyBorders}.
  148. *
  149. * @param range
  150. * - {@link CellRangeAddress} range of cells on which borders are
  151. * drawn.
  152. * @param borderType
  153. * - Type of border to draw. {@link BorderStyle}.
  154. * @param color
  155. * - Color index from {@link IndexedColors} used to draw the
  156. * borders.
  157. * @param extent
  158. * - {@link BorderExtent} of the borders to be
  159. * applied.
  160. */
  161. public void drawBorders(CellRangeAddress range, BorderStyle borderType,
  162. short color, BorderExtent extent) {
  163. drawBorders(range, borderType, extent);
  164. if (borderType != BorderStyle.NONE) {
  165. drawBorderColors(range, color, extent);
  166. }
  167. }
  168. /**
  169. * <p>
  170. * Draws the top border for a range of cells
  171. * </p>
  172. *
  173. * @param range
  174. * - {@link CellRangeAddress} range of cells on which borders are
  175. * drawn.
  176. * @param borderType
  177. * - Type of border to draw. {@link BorderStyle}.
  178. */
  179. private void drawTopBorder(CellRangeAddress range, BorderStyle borderType) {
  180. int row = range.getFirstRow();
  181. int firstCol = range.getFirstColumn();
  182. int lastCol = range.getLastColumn();
  183. for (int i = firstCol; i <= lastCol; i++) {
  184. addProperty(row, i, CellUtil.BORDER_TOP, borderType);
  185. if (borderType == BorderStyle.NONE && row > 0) {
  186. addProperty(row - 1, i, CellUtil.BORDER_BOTTOM, borderType);
  187. }
  188. }
  189. }
  190. /**
  191. * <p>
  192. * Draws the bottom border for a range of cells
  193. * </p>
  194. *
  195. * @param range
  196. * - {@link CellRangeAddress} range of cells on which borders are
  197. * drawn.
  198. * @param borderType
  199. * - Type of border to draw. {@link BorderStyle}.
  200. */
  201. private void drawBottomBorder(CellRangeAddress range,
  202. BorderStyle borderType) {
  203. int row = range.getLastRow();
  204. int firstCol = range.getFirstColumn();
  205. int lastCol = range.getLastColumn();
  206. for (int i = firstCol; i <= lastCol; i++) {
  207. addProperty(row, i, CellUtil.BORDER_BOTTOM, borderType);
  208. if (borderType == BorderStyle.NONE
  209. && row < SpreadsheetVersion.EXCEL2007.getMaxRows() - 1) {
  210. addProperty(row + 1, i, CellUtil.BORDER_TOP, borderType);
  211. }
  212. }
  213. }
  214. /**
  215. * <p>
  216. * Draws the left border for a range of cells
  217. * </p>
  218. *
  219. * @param range
  220. * - {@link CellRangeAddress} range of cells on which borders are
  221. * drawn.
  222. * @param borderType
  223. * - Type of border to draw. {@link BorderStyle}.
  224. */
  225. private void drawLeftBorder(CellRangeAddress range,
  226. BorderStyle borderType) {
  227. int firstRow = range.getFirstRow();
  228. int lastRow = range.getLastRow();
  229. int col = range.getFirstColumn();
  230. for (int i = firstRow; i <= lastRow; i++) {
  231. addProperty(i, col, CellUtil.BORDER_LEFT, borderType);
  232. if (borderType == BorderStyle.NONE && col > 0) {
  233. addProperty(i, col - 1, CellUtil.BORDER_RIGHT, borderType);
  234. }
  235. }
  236. }
  237. /**
  238. * <p>
  239. * Draws the right border for a range of cells
  240. * </p>
  241. *
  242. * @param range
  243. * - {@link CellRangeAddress} range of cells on which borders are
  244. * drawn.
  245. * @param borderType
  246. * - Type of border to draw. {@link BorderStyle}.
  247. */
  248. private void drawRightBorder(CellRangeAddress range,
  249. BorderStyle borderType) {
  250. int firstRow = range.getFirstRow();
  251. int lastRow = range.getLastRow();
  252. int col = range.getLastColumn();
  253. for (int i = firstRow; i <= lastRow; i++) {
  254. addProperty(i, col, CellUtil.BORDER_RIGHT, borderType);
  255. if (borderType == BorderStyle.NONE
  256. && col < SpreadsheetVersion.EXCEL2007.getMaxColumns() - 1) {
  257. addProperty(i, col + 1, CellUtil.BORDER_LEFT, borderType);
  258. }
  259. }
  260. }
  261. /**
  262. * <p>
  263. * Draws the outside borders for a range of cells.
  264. * </p>
  265. *
  266. * @param range
  267. * - {@link CellRangeAddress} range of cells on which borders are
  268. * drawn.
  269. * @param borderType
  270. * - Type of border to draw. {@link BorderStyle}.
  271. * @param extent
  272. * - {@link BorderExtent} of the borders to be
  273. * applied. Valid Values are:
  274. * <ul>
  275. * <li>BorderExtent.ALL</li>
  276. * <li>BorderExtent.HORIZONTAL</li>
  277. * <li>BorderExtent.VERTICAL</li>
  278. * </ul>
  279. */
  280. private void drawOutsideBorders(CellRangeAddress range,
  281. BorderStyle borderType, BorderExtent extent) {
  282. switch (extent) {
  283. case ALL:
  284. case HORIZONTAL:
  285. case VERTICAL:
  286. if (extent == BorderExtent.ALL || extent == BorderExtent.HORIZONTAL) {
  287. drawTopBorder(range, borderType);
  288. drawBottomBorder(range, borderType);
  289. }
  290. if (extent == BorderExtent.ALL || extent == BorderExtent.VERTICAL) {
  291. drawLeftBorder(range, borderType);
  292. drawRightBorder(range, borderType);
  293. }
  294. break;
  295. default:
  296. throw new IllegalArgumentException(
  297. "Unsupported PropertyTemplate.Extent, valid Extents are ALL, HORIZONTAL, and VERTICAL");
  298. }
  299. }
  300. /**
  301. * <p>
  302. * Draws the horizontal borders for a range of cells.
  303. * </p>
  304. *
  305. * @param range
  306. * - {@link CellRangeAddress} range of cells on which borders are
  307. * drawn.
  308. * @param borderType
  309. * - Type of border to draw. {@link BorderStyle}.
  310. * @param extent
  311. * - {@link BorderExtent} of the borders to be
  312. * applied. Valid Values are:
  313. * <ul>
  314. * <li>BorderExtent.ALL</li>
  315. * <li>BorderExtent.INSIDE</li>
  316. * </ul>
  317. */
  318. private void drawHorizontalBorders(CellRangeAddress range,
  319. BorderStyle borderType, BorderExtent extent) {
  320. switch (extent) {
  321. case ALL:
  322. case INSIDE:
  323. int firstRow = range.getFirstRow();
  324. int lastRow = range.getLastRow();
  325. int firstCol = range.getFirstColumn();
  326. int lastCol = range.getLastColumn();
  327. for (int i = firstRow; i <= lastRow; i++) {
  328. CellRangeAddress row = new CellRangeAddress(i, i, firstCol,
  329. lastCol);
  330. if (extent == BorderExtent.ALL || i > firstRow) {
  331. drawTopBorder(row, borderType);
  332. }
  333. if (extent == BorderExtent.ALL || i < lastRow) {
  334. drawBottomBorder(row, borderType);
  335. }
  336. }
  337. break;
  338. default:
  339. throw new IllegalArgumentException(
  340. "Unsupported PropertyTemplate.Extent, valid Extents are ALL and INSIDE");
  341. }
  342. }
  343. /**
  344. * <p>
  345. * Draws the vertical borders for a range of cells.
  346. * </p>
  347. *
  348. * @param range
  349. * - {@link CellRangeAddress} range of cells on which borders are
  350. * drawn.
  351. * @param borderType
  352. * - Type of border to draw. {@link BorderStyle}.
  353. * @param extent
  354. * - {@link BorderExtent} of the borders to be
  355. * applied. Valid Values are:
  356. * <ul>
  357. * <li>BorderExtent.ALL</li>
  358. * <li>BorderExtent.INSIDE</li>
  359. * </ul>
  360. */
  361. private void drawVerticalBorders(CellRangeAddress range,
  362. BorderStyle borderType, BorderExtent extent) {
  363. switch (extent) {
  364. case ALL:
  365. case INSIDE:
  366. int firstRow = range.getFirstRow();
  367. int lastRow = range.getLastRow();
  368. int firstCol = range.getFirstColumn();
  369. int lastCol = range.getLastColumn();
  370. for (int i = firstCol; i <= lastCol; i++) {
  371. CellRangeAddress row = new CellRangeAddress(firstRow, lastRow,
  372. i, i);
  373. if (extent == BorderExtent.ALL || i > firstCol) {
  374. drawLeftBorder(row, borderType);
  375. }
  376. if (extent == BorderExtent.ALL || i < lastCol) {
  377. drawRightBorder(row, borderType);
  378. }
  379. }
  380. break;
  381. default:
  382. throw new IllegalArgumentException(
  383. "Unsupported PropertyTemplate.Extent, valid Extents are ALL and INSIDE");
  384. }
  385. }
  386. /**
  387. * Removes all border properties from this {@link PropertyTemplate} for the
  388. * specified range.
  389. *
  390. * @parm range - {@link CellRangeAddress} range of cells to remove borders.
  391. */
  392. private void removeBorders(CellRangeAddress range) {
  393. Set<String> properties = new HashSet<>();
  394. properties.add(CellUtil.BORDER_TOP);
  395. properties.add(CellUtil.BORDER_BOTTOM);
  396. properties.add(CellUtil.BORDER_LEFT);
  397. properties.add(CellUtil.BORDER_RIGHT);
  398. for (int row = range.getFirstRow(); row <= range.getLastRow(); row++) {
  399. for (int col = range.getFirstColumn(); col <= range
  400. .getLastColumn(); col++) {
  401. removeProperties(row, col, properties);
  402. }
  403. }
  404. removeBorderColors(range);
  405. }
  406. /**
  407. * Applies the drawn borders to a Sheet. The borders that are applied are
  408. * the ones that have been drawn by the {@link #drawBorders} and
  409. * {@link #drawBorderColors} methods.
  410. *
  411. * @param sheet
  412. * - {@link Sheet} on which to apply borders
  413. */
  414. public void applyBorders(Sheet sheet) {
  415. Workbook wb = sheet.getWorkbook();
  416. for (Map.Entry<CellAddress, Map<String, Object>> entry : _propertyTemplate
  417. .entrySet()) {
  418. CellAddress cellAddress = entry.getKey();
  419. if (cellAddress.getRow() < wb.getSpreadsheetVersion().getMaxRows()
  420. && cellAddress.getColumn() < wb.getSpreadsheetVersion()
  421. .getMaxColumns()) {
  422. Map<String, Object> properties = entry.getValue();
  423. Row row = CellUtil.getRow(cellAddress.getRow(), sheet);
  424. Cell cell = CellUtil.getCell(row, cellAddress.getColumn());
  425. CellUtil.setCellStyleProperties(cell, properties);
  426. }
  427. }
  428. }
  429. /**
  430. * Sets the color for a group of cell borders for a cell range. The borders
  431. * are not applied to the cells at this time, just the template is drawn. If
  432. * the borders do not exist, a BORDER_THIN border is used. To apply the
  433. * drawn borders to a sheet, use {@link #applyBorders}.
  434. *
  435. * @param range
  436. * - {@link CellRangeAddress} range of cells on which colors are
  437. * set.
  438. * @param color
  439. * - Color index from {@link IndexedColors} used to draw the
  440. * borders.
  441. * @param extent
  442. * - {@link BorderExtent} of the borders for which
  443. * colors are set.
  444. */
  445. public void drawBorderColors(CellRangeAddress range, short color,
  446. BorderExtent extent) {
  447. switch (extent) {
  448. case NONE:
  449. removeBorderColors(range);
  450. break;
  451. case ALL:
  452. drawHorizontalBorderColors(range, color, BorderExtent.ALL);
  453. drawVerticalBorderColors(range, color, BorderExtent.ALL);
  454. break;
  455. case INSIDE:
  456. drawHorizontalBorderColors(range, color, BorderExtent.INSIDE);
  457. drawVerticalBorderColors(range, color, BorderExtent.INSIDE);
  458. break;
  459. case OUTSIDE:
  460. drawOutsideBorderColors(range, color, BorderExtent.ALL);
  461. break;
  462. case TOP:
  463. drawTopBorderColor(range, color);
  464. break;
  465. case BOTTOM:
  466. drawBottomBorderColor(range, color);
  467. break;
  468. case LEFT:
  469. drawLeftBorderColor(range, color);
  470. break;
  471. case RIGHT:
  472. drawRightBorderColor(range, color);
  473. break;
  474. case HORIZONTAL:
  475. drawHorizontalBorderColors(range, color, BorderExtent.ALL);
  476. break;
  477. case INSIDE_HORIZONTAL:
  478. drawHorizontalBorderColors(range, color, BorderExtent.INSIDE);
  479. break;
  480. case OUTSIDE_HORIZONTAL:
  481. drawOutsideBorderColors(range, color, BorderExtent.HORIZONTAL);
  482. break;
  483. case VERTICAL:
  484. drawVerticalBorderColors(range, color, BorderExtent.ALL);
  485. break;
  486. case INSIDE_VERTICAL:
  487. drawVerticalBorderColors(range, color, BorderExtent.INSIDE);
  488. break;
  489. case OUTSIDE_VERTICAL:
  490. drawOutsideBorderColors(range, color, BorderExtent.VERTICAL);
  491. break;
  492. }
  493. }
  494. /**
  495. * <p>
  496. * Sets the color of the top border for a range of cells.
  497. * </p>
  498. *
  499. * @param range
  500. * - {@link CellRangeAddress} range of cells on which colors are
  501. * set.
  502. * @param color
  503. * - Color index from {@link IndexedColors} used to draw the
  504. * borders.
  505. */
  506. private void drawTopBorderColor(CellRangeAddress range, short color) {
  507. int row = range.getFirstRow();
  508. int firstCol = range.getFirstColumn();
  509. int lastCol = range.getLastColumn();
  510. for (int i = firstCol; i <= lastCol; i++) {
  511. if (getBorderStyle(row, i,
  512. CellUtil.BORDER_TOP) == BorderStyle.NONE) {
  513. drawTopBorder(new CellRangeAddress(row, row, i, i),
  514. BorderStyle.THIN);
  515. }
  516. addProperty(row, i, CellUtil.TOP_BORDER_COLOR, color);
  517. }
  518. }
  519. /**
  520. * <p>
  521. * Sets the color of the bottom border for a range of cells.
  522. * </p>
  523. *
  524. * @param range
  525. * - {@link CellRangeAddress} range of cells on which colors are
  526. * set.
  527. * @param color
  528. * - Color index from {@link IndexedColors} used to draw the
  529. * borders.
  530. */
  531. private void drawBottomBorderColor(CellRangeAddress range, short color) {
  532. int row = range.getLastRow();
  533. int firstCol = range.getFirstColumn();
  534. int lastCol = range.getLastColumn();
  535. for (int i = firstCol; i <= lastCol; i++) {
  536. if (getBorderStyle(row, i,
  537. CellUtil.BORDER_BOTTOM) == BorderStyle.NONE) {
  538. drawBottomBorder(new CellRangeAddress(row, row, i, i),
  539. BorderStyle.THIN);
  540. }
  541. addProperty(row, i, CellUtil.BOTTOM_BORDER_COLOR, color);
  542. }
  543. }
  544. /**
  545. * <p>
  546. * Sets the color of the left border for a range of cells.
  547. * </p>
  548. *
  549. * @param range
  550. * - {@link CellRangeAddress} range of cells on which colors are
  551. * set.
  552. * @param color
  553. * - Color index from {@link IndexedColors} used to draw the
  554. * borders.
  555. */
  556. private void drawLeftBorderColor(CellRangeAddress range, short color) {
  557. int firstRow = range.getFirstRow();
  558. int lastRow = range.getLastRow();
  559. int col = range.getFirstColumn();
  560. for (int i = firstRow; i <= lastRow; i++) {
  561. if (getBorderStyle(i, col,
  562. CellUtil.BORDER_LEFT) == BorderStyle.NONE) {
  563. drawLeftBorder(new CellRangeAddress(i, i, col, col),
  564. BorderStyle.THIN);
  565. }
  566. addProperty(i, col, CellUtil.LEFT_BORDER_COLOR, color);
  567. }
  568. }
  569. /**
  570. * <p>
  571. * Sets the color of the right border for a range of cells. If the border is
  572. * not drawn, it defaults to BORDER_THIN
  573. * </p>
  574. *
  575. * @param range
  576. * - {@link CellRangeAddress} range of cells on which colors are
  577. * set.
  578. * @param color
  579. * - Color index from {@link IndexedColors} used to draw the
  580. * borders.
  581. */
  582. private void drawRightBorderColor(CellRangeAddress range, short color) {
  583. int firstRow = range.getFirstRow();
  584. int lastRow = range.getLastRow();
  585. int col = range.getLastColumn();
  586. for (int i = firstRow; i <= lastRow; i++) {
  587. if (getBorderStyle(i, col,
  588. CellUtil.BORDER_RIGHT) == BorderStyle.NONE) {
  589. drawRightBorder(new CellRangeAddress(i, i, col, col),
  590. BorderStyle.THIN);
  591. }
  592. addProperty(i, col, CellUtil.RIGHT_BORDER_COLOR, color);
  593. }
  594. }
  595. /**
  596. * <p>
  597. * Sets the color of the outside borders for a range of cells.
  598. * </p>
  599. *
  600. * @param range
  601. * - {@link CellRangeAddress} range of cells on which colors are
  602. * set.
  603. * @param color
  604. * - Color index from {@link IndexedColors} used to draw the
  605. * borders.
  606. * @param extent
  607. * - {@link BorderExtent} of the borders for which
  608. * colors are set. Valid Values are:
  609. * <ul>
  610. * <li>BorderExtent.ALL</li>
  611. * <li>BorderExtent.HORIZONTAL</li>
  612. * <li>BorderExtent.VERTICAL</li>
  613. * </ul>
  614. */
  615. private void drawOutsideBorderColors(CellRangeAddress range, short color,
  616. BorderExtent extent) {
  617. switch (extent) {
  618. case ALL:
  619. case HORIZONTAL:
  620. case VERTICAL:
  621. if (extent == BorderExtent.ALL || extent == BorderExtent.HORIZONTAL) {
  622. drawTopBorderColor(range, color);
  623. drawBottomBorderColor(range, color);
  624. }
  625. if (extent == BorderExtent.ALL || extent == BorderExtent.VERTICAL) {
  626. drawLeftBorderColor(range, color);
  627. drawRightBorderColor(range, color);
  628. }
  629. break;
  630. default:
  631. throw new IllegalArgumentException(
  632. "Unsupported PropertyTemplate.Extent, valid Extents are ALL, HORIZONTAL, and VERTICAL");
  633. }
  634. }
  635. /**
  636. * <p>
  637. * Sets the color of the horizontal borders for a range of cells.
  638. * </p>
  639. *
  640. * @param range
  641. * - {@link CellRangeAddress} range of cells on which colors are
  642. * set.
  643. * @param color
  644. * - Color index from {@link IndexedColors} used to draw the
  645. * borders.
  646. * @param extent
  647. * - {@link BorderExtent} of the borders for which
  648. * colors are set. Valid Values are:
  649. * <ul>
  650. * <li>BorderExtent.ALL</li>
  651. * <li>BorderExtent.INSIDE</li>
  652. * </ul>
  653. */
  654. private void drawHorizontalBorderColors(CellRangeAddress range, short color,
  655. BorderExtent extent) {
  656. switch (extent) {
  657. case ALL:
  658. case INSIDE:
  659. int firstRow = range.getFirstRow();
  660. int lastRow = range.getLastRow();
  661. int firstCol = range.getFirstColumn();
  662. int lastCol = range.getLastColumn();
  663. for (int i = firstRow; i <= lastRow; i++) {
  664. CellRangeAddress row = new CellRangeAddress(i, i, firstCol,
  665. lastCol);
  666. if (extent == BorderExtent.ALL || i > firstRow) {
  667. drawTopBorderColor(row, color);
  668. }
  669. if (extent == BorderExtent.ALL || i < lastRow) {
  670. drawBottomBorderColor(row, color);
  671. }
  672. }
  673. break;
  674. default:
  675. throw new IllegalArgumentException(
  676. "Unsupported PropertyTemplate.Extent, valid Extents are ALL and INSIDE");
  677. }
  678. }
  679. /**
  680. * <p>
  681. * Sets the color of the vertical borders for a range of cells.
  682. * </p>
  683. *
  684. * @param range
  685. * - {@link CellRangeAddress} range of cells on which colors are
  686. * set.
  687. * @param color
  688. * - Color index from {@link IndexedColors} used to draw the
  689. * borders.
  690. * @param extent
  691. * - {@link BorderExtent} of the borders for which
  692. * colors are set. Valid Values are:
  693. * <ul>
  694. * <li>BorderExtent.ALL</li>
  695. * <li>BorderExtent.INSIDE</li>
  696. * </ul>
  697. */
  698. private void drawVerticalBorderColors(CellRangeAddress range, short color,
  699. BorderExtent extent) {
  700. switch (extent) {
  701. case ALL:
  702. case INSIDE:
  703. int firstRow = range.getFirstRow();
  704. int lastRow = range.getLastRow();
  705. int firstCol = range.getFirstColumn();
  706. int lastCol = range.getLastColumn();
  707. for (int i = firstCol; i <= lastCol; i++) {
  708. CellRangeAddress row = new CellRangeAddress(firstRow, lastRow,
  709. i, i);
  710. if (extent == BorderExtent.ALL || i > firstCol) {
  711. drawLeftBorderColor(row, color);
  712. }
  713. if (extent == BorderExtent.ALL || i < lastCol) {
  714. drawRightBorderColor(row, color);
  715. }
  716. }
  717. break;
  718. default:
  719. throw new IllegalArgumentException(
  720. "Unsupported PropertyTemplate.Extent, valid Extents are ALL and INSIDE");
  721. }
  722. }
  723. /**
  724. * Removes all border properties from this {@link PropertyTemplate} for the
  725. * specified range.
  726. *
  727. * @parm range - {@link CellRangeAddress} range of cells to remove borders.
  728. */
  729. private void removeBorderColors(CellRangeAddress range) {
  730. Set<String> properties = new HashSet<>();
  731. properties.add(CellUtil.TOP_BORDER_COLOR);
  732. properties.add(CellUtil.BOTTOM_BORDER_COLOR);
  733. properties.add(CellUtil.LEFT_BORDER_COLOR);
  734. properties.add(CellUtil.RIGHT_BORDER_COLOR);
  735. for (int row = range.getFirstRow(); row <= range.getLastRow(); row++) {
  736. for (int col = range.getFirstColumn(); col <= range
  737. .getLastColumn(); col++) {
  738. removeProperties(row, col, properties);
  739. }
  740. }
  741. }
  742. /**
  743. * Adds a property to this {@link PropertyTemplate} for a given cell
  744. *
  745. * @param row
  746. * @param col
  747. * @param property
  748. * @param value
  749. */
  750. private void addProperty(int row, int col, String property, short value) {
  751. addProperty(row, col, property, Short.valueOf(value));
  752. }
  753. /**
  754. * Adds a property to this {@link PropertyTemplate} for a given cell
  755. *
  756. * @param row
  757. * @param col
  758. * @param property
  759. * @param value
  760. */
  761. private void addProperty(int row, int col, String property, Object value) {
  762. CellAddress cell = new CellAddress(row, col);
  763. Map<String, Object> cellProperties = _propertyTemplate.get(cell);
  764. if (cellProperties == null) {
  765. cellProperties = new HashMap<>();
  766. }
  767. cellProperties.put(property, value);
  768. _propertyTemplate.put(cell, cellProperties);
  769. }
  770. /**
  771. * Removes a set of properties from this {@link PropertyTemplate} for a
  772. * given cell
  773. *
  774. * @param row
  775. * @param col
  776. * @param properties
  777. */
  778. private void removeProperties(int row, int col, Set<String> properties) {
  779. CellAddress cell = new CellAddress(row, col);
  780. Map<String, Object> cellProperties = _propertyTemplate.get(cell);
  781. if (cellProperties != null) {
  782. cellProperties.keySet().removeAll(properties);
  783. if (cellProperties.isEmpty()) {
  784. _propertyTemplate.remove(cell);
  785. } else {
  786. _propertyTemplate.put(cell, cellProperties);
  787. }
  788. }
  789. }
  790. /**
  791. * Retrieves the number of borders assigned to a cell
  792. *
  793. * @param cell
  794. */
  795. public int getNumBorders(CellAddress cell) {
  796. Map<String, Object> cellProperties = _propertyTemplate.get(cell);
  797. if (cellProperties == null) {
  798. return 0;
  799. }
  800. int count = 0;
  801. for (String property : cellProperties.keySet()) {
  802. if (property.equals(CellUtil.BORDER_TOP))
  803. count += 1;
  804. if (property.equals(CellUtil.BORDER_BOTTOM))
  805. count += 1;
  806. if (property.equals(CellUtil.BORDER_LEFT))
  807. count += 1;
  808. if (property.equals(CellUtil.BORDER_RIGHT))
  809. count += 1;
  810. }
  811. return count;
  812. }
  813. /**
  814. * Retrieves the number of borders assigned to a cell
  815. *
  816. * @param row
  817. * @param col
  818. */
  819. public int getNumBorders(int row, int col) {
  820. return getNumBorders(new CellAddress(row, col));
  821. }
  822. /**
  823. * Retrieves the number of border colors assigned to a cell
  824. *
  825. * @param cell
  826. */
  827. public int getNumBorderColors(CellAddress cell) {
  828. Map<String, Object> cellProperties = _propertyTemplate.get(cell);
  829. if (cellProperties == null) {
  830. return 0;
  831. }
  832. int count = 0;
  833. for (String property : cellProperties.keySet()) {
  834. if (property.equals(CellUtil.TOP_BORDER_COLOR))
  835. count += 1;
  836. if (property.equals(CellUtil.BOTTOM_BORDER_COLOR))
  837. count += 1;
  838. if (property.equals(CellUtil.LEFT_BORDER_COLOR))
  839. count += 1;
  840. if (property.equals(CellUtil.RIGHT_BORDER_COLOR))
  841. count += 1;
  842. }
  843. return count;
  844. }
  845. /**
  846. * Retrieves the number of border colors assigned to a cell
  847. *
  848. * @param row
  849. * @param col
  850. */
  851. public int getNumBorderColors(int row, int col) {
  852. return getNumBorderColors(new CellAddress(row, col));
  853. }
  854. /**
  855. * Retrieves the border style for a given cell
  856. *
  857. * @param cell
  858. * @param property
  859. */
  860. public BorderStyle getBorderStyle(CellAddress cell, String property) {
  861. BorderStyle value = BorderStyle.NONE;
  862. Map<String, Object> cellProperties = _propertyTemplate.get(cell);
  863. if (cellProperties != null) {
  864. Object obj = cellProperties.get(property);
  865. if (obj instanceof BorderStyle) {
  866. value = (BorderStyle) obj;
  867. }
  868. }
  869. return value;
  870. }
  871. /**
  872. * Retrieves the border style for a given cell
  873. *
  874. * @param row
  875. * @param col
  876. * @param property
  877. */
  878. public BorderStyle getBorderStyle(int row, int col, String property) {
  879. return getBorderStyle(new CellAddress(row, col), property);
  880. }
  881. /**
  882. * Retrieves the border style for a given cell
  883. *
  884. * @param cell
  885. * @param property
  886. */
  887. public short getTemplateProperty(CellAddress cell, String property) {
  888. short value = 0;
  889. Map<String, Object> cellProperties = _propertyTemplate.get(cell);
  890. if (cellProperties != null) {
  891. Object obj = cellProperties.get(property);
  892. if (obj != null) {
  893. value = getShort(obj);
  894. }
  895. }
  896. return value;
  897. }
  898. /**
  899. * Retrieves the border style for a given cell
  900. *
  901. * @param row
  902. * @param col
  903. * @param property
  904. */
  905. public short getTemplateProperty(int row, int col, String property) {
  906. return getTemplateProperty(new CellAddress(row, col), property);
  907. }
  908. /**
  909. * Converts a Short object to a short value or 0 if the object is not a
  910. * Short
  911. *
  912. * @param value Potentially short value to convert
  913. * @return short value, or 0 if not a short
  914. */
  915. private static short getShort(Object value) {
  916. if (value instanceof Number) {
  917. return ((Number) value).shortValue();
  918. }
  919. return 0;
  920. }
  921. }