PageRenderTime 29ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/projects/poi-3.6/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 1387 lines | 711 code | 133 blank | 543 comment | 130 complexity | 35d5f03f5a96457fd4187f01ab4590b8 MD5 | raw file
  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.xssf.usermodel;
  16. import java.io.IOException;
  17. import java.io.InputStream;
  18. import java.io.OutputStream;
  19. import java.util.ArrayList;
  20. import java.util.Arrays;
  21. import java.util.HashMap;
  22. import java.util.Iterator;
  23. import java.util.List;
  24. import java.util.Map;
  25. import java.util.TreeMap;
  26. import javax.xml.namespace.QName;
  27. import org.apache.poi.POIXMLDocumentPart;
  28. import org.apache.poi.POIXMLException;
  29. import org.apache.poi.hssf.record.formula.FormulaShifter;
  30. import org.apache.poi.hssf.util.PaneInformation;
  31. import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
  32. import org.apache.poi.openxml4j.opc.PackagePart;
  33. import org.apache.poi.openxml4j.opc.PackageRelationship;
  34. import org.apache.poi.openxml4j.opc.PackageRelationshipCollection;
  35. import org.apache.poi.ss.SpreadsheetVersion;
  36. import org.apache.poi.ss.usermodel.Cell;
  37. import org.apache.poi.ss.usermodel.CellStyle;
  38. import org.apache.poi.ss.usermodel.Footer;
  39. import org.apache.poi.ss.usermodel.Header;
  40. import org.apache.poi.ss.usermodel.Row;
  41. import org.apache.poi.ss.usermodel.Sheet;
  42. import org.apache.poi.ss.util.CellRangeAddress;
  43. import org.apache.poi.ss.util.CellReference;
  44. import org.apache.poi.util.POILogFactory;
  45. import org.apache.poi.util.POILogger;
  46. import org.apache.poi.util.Internal;
  47. import org.apache.poi.xssf.model.CommentsTable;
  48. import org.apache.poi.xssf.usermodel.helpers.ColumnHelper;
  49. import org.apache.poi.xssf.usermodel.helpers.XSSFRowShifter;
  50. import org.apache.xmlbeans.XmlException;
  51. import org.apache.xmlbeans.XmlOptions;
  52. import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelationshipId;
  53. import org.openxmlformats.schemas.spreadsheetml.x2006.main.*;
  54. /**
  55. * High level representation of a SpreadsheetML worksheet.
  56. *
  57. * <p>
  58. * Sheets are the central structures within a workbook, and are where a user does most of his spreadsheet work.
  59. * The most common type of sheet is the worksheet, which is represented as a grid of cells. Worksheet cells can
  60. * contain text, numbers, dates, and formulas. Cells can also be formatted.
  61. * </p>
  62. */
  63. public class XSSFSheet extends POIXMLDocumentPart implements Sheet {
  64. private static final POILogger logger = POILogFactory.getLogger(XSSFSheet.class);
  65. //TODO make the two variable below private!
  66. protected CTSheet sheet;
  67. protected CTWorksheet worksheet;
  68. private TreeMap<Integer, XSSFRow> rows;
  69. private List<XSSFHyperlink> hyperlinks;
  70. private ColumnHelper columnHelper;
  71. private CommentsTable sheetComments;
  72. private Map<Integer, XSSFCell> sharedFormulas;
  73. /**
  74. * Creates new XSSFSheet - called by XSSFWorkbook to create a sheet from scratch.
  75. *
  76. * @see org.apache.poi.xssf.usermodel.XSSFWorkbook#createSheet()
  77. */
  78. protected XSSFSheet() {
  79. super();
  80. onDocumentCreate();
  81. }
  82. /**
  83. * Creates an XSSFSheet representing the given package part and relationship.
  84. * Should only be called by XSSFWorkbook when reading in an exisiting file.
  85. *
  86. * @param part - The package part that holds xml data represenring this sheet.
  87. * @param rel - the relationship of the given package part in the underlying OPC package
  88. */
  89. protected XSSFSheet(PackagePart part, PackageRelationship rel) {
  90. super(part, rel);
  91. }
  92. /**
  93. * Returns the parent XSSFWorkbook
  94. *
  95. * @return the parent XSSFWorkbook
  96. */
  97. public XSSFWorkbook getWorkbook() {
  98. return (XSSFWorkbook)getParent();
  99. }
  100. /**
  101. * Initialize worksheet data when reading in an exisiting file.
  102. */
  103. @Override
  104. protected void onDocumentRead() {
  105. try {
  106. read(getPackagePart().getInputStream());
  107. } catch (IOException e){
  108. throw new POIXMLException(e);
  109. }
  110. }
  111. protected void read(InputStream is) throws IOException {
  112. try {
  113. worksheet = WorksheetDocument.Factory.parse(is).getWorksheet();
  114. } catch (XmlException e){
  115. throw new POIXMLException(e);
  116. }
  117. initRows(worksheet);
  118. columnHelper = new ColumnHelper(worksheet);
  119. for(POIXMLDocumentPart p : getRelations()){
  120. if(p instanceof CommentsTable) sheetComments = (CommentsTable)p;
  121. }
  122. // Process external hyperlinks for the sheet, if there are any
  123. initHyperlinks();
  124. }
  125. /**
  126. * Initialize worksheet data when creating a new sheet.
  127. */
  128. @Override
  129. protected void onDocumentCreate(){
  130. worksheet = newSheet();
  131. initRows(worksheet);
  132. columnHelper = new ColumnHelper(worksheet);
  133. hyperlinks = new ArrayList<XSSFHyperlink>();
  134. }
  135. private void initRows(CTWorksheet worksheet) {
  136. rows = new TreeMap<Integer, XSSFRow>();
  137. sharedFormulas = new HashMap<Integer, XSSFCell>();
  138. for (CTRow row : worksheet.getSheetData().getRowArray()) {
  139. XSSFRow r = new XSSFRow(row, this);
  140. rows.put(r.getRowNum(), r);
  141. }
  142. }
  143. /**
  144. * Read hyperlink relations, link them with CTHyperlink beans in this worksheet
  145. * and initialize the internal array of XSSFHyperlink objects
  146. */
  147. private void initHyperlinks() {
  148. hyperlinks = new ArrayList<XSSFHyperlink>();
  149. if(!worksheet.isSetHyperlinks()) return;
  150. try {
  151. PackageRelationshipCollection hyperRels =
  152. getPackagePart().getRelationshipsByType(XSSFRelation.SHEET_HYPERLINKS.getRelation());
  153. // Turn each one into a XSSFHyperlink
  154. for(CTHyperlink hyperlink : worksheet.getHyperlinks().getHyperlinkArray()) {
  155. PackageRelationship hyperRel = null;
  156. if(hyperlink.getId() != null) {
  157. hyperRel = hyperRels.getRelationshipByID(hyperlink.getId());
  158. }
  159. hyperlinks.add( new XSSFHyperlink(hyperlink, hyperRel) );
  160. }
  161. } catch (InvalidFormatException e){
  162. throw new POIXMLException(e);
  163. }
  164. }
  165. /**
  166. * Create a new CTWorksheet instance with all values set to defaults
  167. *
  168. * @return a new instance
  169. */
  170. private static CTWorksheet newSheet(){
  171. CTWorksheet worksheet = CTWorksheet.Factory.newInstance();
  172. CTSheetFormatPr ctFormat = worksheet.addNewSheetFormatPr();
  173. ctFormat.setDefaultRowHeight(15.0);
  174. CTSheetView ctView = worksheet.addNewSheetViews().addNewSheetView();
  175. ctView.setWorkbookViewId(0);
  176. worksheet.addNewDimension().setRef("A1");
  177. worksheet.addNewSheetData();
  178. CTPageMargins ctMargins = worksheet.addNewPageMargins();
  179. ctMargins.setBottom(0.75);
  180. ctMargins.setFooter(0.3);
  181. ctMargins.setHeader(0.3);
  182. ctMargins.setLeft(0.7);
  183. ctMargins.setRight(0.7);
  184. ctMargins.setTop(0.75);
  185. return worksheet;
  186. }
  187. /**
  188. * Provide access to the CTWorksheet bean holding this sheet's data
  189. *
  190. * @return the CTWorksheet bean holding this sheet's data
  191. */
  192. @Internal
  193. public CTWorksheet getCTWorksheet() {
  194. return this.worksheet;
  195. }
  196. public ColumnHelper getColumnHelper() {
  197. return columnHelper;
  198. }
  199. /**
  200. * Returns the name of this sheet
  201. *
  202. * @return the name of this sheet
  203. */
  204. public String getSheetName() {
  205. return sheet.getName();
  206. }
  207. /**
  208. * Adds a merged region of cells (hence those cells form one).
  209. *
  210. * @param cra (rowfrom/colfrom-rowto/colto) to merge
  211. * @return index of this region
  212. */
  213. public int addMergedRegion(CellRangeAddress cra) {
  214. cra.validate(SpreadsheetVersion.EXCEL2007);
  215. CTMergeCells ctMergeCells = worksheet.isSetMergeCells() ? worksheet.getMergeCells() : worksheet.addNewMergeCells();
  216. CTMergeCell ctMergeCell = ctMergeCells.addNewMergeCell();
  217. ctMergeCell.setRef(cra.formatAsString());
  218. return ctMergeCells.sizeOfMergeCellArray();
  219. }
  220. /**
  221. * Adjusts the column width to fit the contents.
  222. *
  223. * This process can be relatively slow on large sheets, so this should
  224. * normally only be called once per column, at the end of your
  225. * processing.
  226. *
  227. * @param column the column index
  228. */
  229. public void autoSizeColumn(int column) {
  230. autoSizeColumn(column, false);
  231. }
  232. /**
  233. * Adjusts the column width to fit the contents.
  234. * <p>
  235. * This process can be relatively slow on large sheets, so this should
  236. * normally only be called once per column, at the end of your
  237. * processing.
  238. * </p>
  239. * You can specify whether the content of merged cells should be considered or ignored.
  240. * Default is to ignore merged cells.
  241. *
  242. * @param column the column index
  243. * @param useMergedCells whether to use the contents of merged cells when calculating the width of the column
  244. */
  245. public void autoSizeColumn(int column, boolean useMergedCells) {
  246. double width = ColumnHelper.getColumnWidth(this, column, useMergedCells);
  247. if(width != -1){
  248. columnHelper.setColBestFit(column, true);
  249. columnHelper.setCustomWidth(column, true);
  250. columnHelper.setColWidth(column, width);
  251. }
  252. }
  253. /**
  254. * Create a new SpreadsheetML drawing. If this sheet already contains a drawing - return that.
  255. *
  256. * @return a SpreadsheetML drawing
  257. */
  258. public XSSFDrawing createDrawingPatriarch() {
  259. XSSFDrawing drawing = null;
  260. CTDrawing ctDrawing = worksheet.getDrawing();
  261. if(ctDrawing == null) {
  262. //drawingNumber = #drawings.size() + 1
  263. int drawingNumber = getPackagePart().getPackage().getPartsByContentType(XSSFRelation.DRAWINGS.getContentType()).size() + 1;
  264. drawing = (XSSFDrawing)createRelationship(XSSFRelation.DRAWINGS, XSSFFactory.getInstance(), drawingNumber);
  265. String relId = drawing.getPackageRelationship().getId();
  266. //add CT_Drawing element which indicates that this sheet contains drawing components built on the drawingML platform.
  267. //The relationship Id references the part containing the drawingML definitions.
  268. ctDrawing = worksheet.addNewDrawing();
  269. ctDrawing.setId(relId);
  270. } else {
  271. //search the referenced drawing in the list of the sheet's relations
  272. for(POIXMLDocumentPart p : getRelations()){
  273. if(p instanceof XSSFDrawing) {
  274. XSSFDrawing dr = (XSSFDrawing)p;
  275. String drId = dr.getPackageRelationship().getId();
  276. if(drId.equals(ctDrawing.getId())){
  277. drawing = dr;
  278. break;
  279. }
  280. break;
  281. }
  282. }
  283. if(drawing == null){
  284. logger.log(POILogger.ERROR, "Can't find drawing with id=" + ctDrawing.getId() + " in the list of the sheet's relationships");
  285. }
  286. }
  287. return drawing;
  288. }
  289. /**
  290. * Get VML drawing for this sheet (aka 'legacy' drawig)
  291. *
  292. * @param autoCreate if true, then a new VML drawing part is created
  293. *
  294. * @return the VML drawing of <code>null</code> if the drawing was not found and autoCreate=false
  295. */
  296. protected XSSFVMLDrawing getVMLDrawing(boolean autoCreate) {
  297. XSSFVMLDrawing drawing = null;
  298. CTLegacyDrawing ctDrawing = worksheet.getLegacyDrawing();
  299. if(ctDrawing == null) {
  300. if(autoCreate) {
  301. //drawingNumber = #drawings.size() + 1
  302. int drawingNumber = getPackagePart().getPackage().getPartsByContentType(XSSFRelation.VML_DRAWINGS.getContentType()).size() + 1;
  303. drawing = (XSSFVMLDrawing)createRelationship(XSSFRelation.VML_DRAWINGS, XSSFFactory.getInstance(), drawingNumber);
  304. String relId = drawing.getPackageRelationship().getId();
  305. //add CTLegacyDrawing element which indicates that this sheet contains drawing components built on the drawingML platform.
  306. //The relationship Id references the part containing the drawing definitions.
  307. ctDrawing = worksheet.addNewLegacyDrawing();
  308. ctDrawing.setId(relId);
  309. }
  310. } else {
  311. //search the referenced drawing in the list of the sheet's relations
  312. for(POIXMLDocumentPart p : getRelations()){
  313. if(p instanceof XSSFVMLDrawing) {
  314. XSSFVMLDrawing dr = (XSSFVMLDrawing)p;
  315. String drId = dr.getPackageRelationship().getId();
  316. if(drId.equals(ctDrawing.getId())){
  317. drawing = dr;
  318. break;
  319. }
  320. break;
  321. }
  322. }
  323. if(drawing == null){
  324. logger.log(POILogger.ERROR, "Can't find VML drawing with id=" + ctDrawing.getId() + " in the list of the sheet's relationships");
  325. }
  326. }
  327. return drawing;
  328. }
  329. /**
  330. * Creates a split (freezepane). Any existing freezepane or split pane is overwritten.
  331. * @param colSplit Horizonatal position of split.
  332. * @param rowSplit Vertical position of split.
  333. */
  334. public void createFreezePane(int colSplit, int rowSplit) {
  335. createFreezePane( colSplit, rowSplit, colSplit, rowSplit );
  336. }
  337. /**
  338. * Creates a split (freezepane). Any existing freezepane or split pane is overwritten.
  339. * @param colSplit Horizonatal position of split.
  340. * @param rowSplit Vertical position of split.
  341. * @param topRow Top row visible in bottom pane
  342. * @param leftmostColumn Left column visible in right pane.
  343. */
  344. public void createFreezePane(int colSplit, int rowSplit, int leftmostColumn, int topRow) {
  345. CTPane pane = getPane();
  346. if (colSplit > 0) pane.setXSplit(colSplit);
  347. if (rowSplit > 0) pane.setYSplit(rowSplit);
  348. pane.setState(STPaneState.FROZEN);
  349. if (rowSplit == 0) {
  350. pane.setTopLeftCell(new CellReference(0, topRow).formatAsString());
  351. pane.setActivePane(STPane.TOP_RIGHT);
  352. } else if (colSplit == 0) {
  353. pane.setTopLeftCell(new CellReference(rowSplit, 0).formatAsString());
  354. pane.setActivePane(STPane.BOTTOM_LEFT);
  355. } else {
  356. pane.setTopLeftCell(new CellReference(leftmostColumn, topRow).formatAsString());
  357. pane.setActivePane(STPane.BOTTOM_RIGHT);
  358. }
  359. CTSheetView ctView = getDefaultSheetView();
  360. ctView.setSelectionArray(null);
  361. CTSelection sel = ctView.addNewSelection();
  362. sel.setPane(pane.getActivePane());
  363. }
  364. /**
  365. * Creates a new comment for this sheet. You still
  366. * need to assign it to a cell though
  367. *
  368. * @deprecated since Nov 2009 this method is not compatible with the common SS interfaces,
  369. * use {@link org.apache.poi.xssf.usermodel.XSSFDrawing#createCellComment
  370. * (org.apache.poi.ss.usermodel.ClientAnchor)} instead
  371. */
  372. @Deprecated
  373. public XSSFComment createComment() {
  374. return createDrawingPatriarch().createCellComment(new XSSFClientAnchor());
  375. }
  376. /**
  377. * Create a new row within the sheet and return the high level representation
  378. *
  379. * @param rownum row number
  380. * @return High level {@link XSSFRow} object representing a row in the sheet
  381. * @see #removeRow(org.apache.poi.ss.usermodel.Row)
  382. */
  383. public XSSFRow createRow(int rownum) {
  384. CTRow ctRow;
  385. XSSFRow prev = rows.get(rownum);
  386. if(prev != null){
  387. ctRow = prev.getCTRow();
  388. ctRow.set(CTRow.Factory.newInstance());
  389. } else {
  390. ctRow = worksheet.getSheetData().addNewRow();
  391. }
  392. XSSFRow r = new XSSFRow(ctRow, this);
  393. r.setRowNum(rownum);
  394. rows.put(rownum, r);
  395. return r;
  396. }
  397. /**
  398. * Creates a split pane. Any existing freezepane or split pane is overwritten.
  399. * @param xSplitPos Horizonatal position of split (in 1/20th of a point).
  400. * @param ySplitPos Vertical position of split (in 1/20th of a point).
  401. * @param topRow Top row visible in bottom pane
  402. * @param leftmostColumn Left column visible in right pane.
  403. * @param activePane Active pane. One of: PANE_LOWER_RIGHT,
  404. * PANE_UPPER_RIGHT, PANE_LOWER_LEFT, PANE_UPPER_LEFT
  405. * @see org.apache.poi.ss.usermodel.Sheet#PANE_LOWER_LEFT
  406. * @see org.apache.poi.ss.usermodel.Sheet#PANE_LOWER_RIGHT
  407. * @see org.apache.poi.ss.usermodel.Sheet#PANE_UPPER_LEFT
  408. * @see org.apache.poi.ss.usermodel.Sheet#PANE_UPPER_RIGHT
  409. */
  410. public void createSplitPane(int xSplitPos, int ySplitPos, int leftmostColumn, int topRow, int activePane) {
  411. createFreezePane(xSplitPos, ySplitPos, leftmostColumn, topRow);
  412. getPane().setState(STPaneState.SPLIT);
  413. getPane().setActivePane(STPane.Enum.forInt(activePane));
  414. }
  415. public XSSFComment getCellComment(int row, int column) {
  416. if (sheetComments == null) {
  417. return null;
  418. }
  419. String ref = new CellReference(row, column).formatAsString();
  420. CTComment ctComment = sheetComments.getCTComment(ref);
  421. if(ctComment == null) return null;
  422. XSSFVMLDrawing vml = getVMLDrawing(false);
  423. return new XSSFComment(sheetComments, ctComment,
  424. vml == null ? null : vml.findCommentShape(row, column));
  425. }
  426. public XSSFHyperlink getHyperlink(int row, int column) {
  427. String ref = new CellReference(row, column).formatAsString();
  428. for(XSSFHyperlink hyperlink : hyperlinks) {
  429. if(hyperlink.getCellRef().equals(ref)) {
  430. return hyperlink;
  431. }
  432. }
  433. return null;
  434. }
  435. /**
  436. * Vertical page break information used for print layout view, page layout view, drawing print breaks
  437. * in normal view, and for printing the worksheet.
  438. *
  439. * @return column indexes of all the vertical page breaks, never <code>null</code>
  440. */
  441. public int[] getColumnBreaks() {
  442. if (!worksheet.isSetColBreaks() || worksheet.getColBreaks().sizeOfBrkArray() == 0) {
  443. return new int[0];
  444. }
  445. CTBreak[] brkArray = worksheet.getColBreaks().getBrkArray();
  446. int[] breaks = new int[brkArray.length];
  447. for (int i = 0 ; i < brkArray.length ; i++) {
  448. CTBreak brk = brkArray[i];
  449. breaks[i] = (int)brk.getId();
  450. }
  451. return breaks;
  452. }
  453. private CTPageBreak getSheetTypeColumnBreaks() {
  454. if (worksheet.getColBreaks() == null) {
  455. worksheet.setColBreaks(CTPageBreak.Factory.newInstance());
  456. }
  457. return worksheet.getColBreaks();
  458. }
  459. /**
  460. * Get the actual column width (in units of 1/256th of a character width )
  461. *
  462. * <p>
  463. * Note, the returned value is always gerater that {@link #getDefaultColumnWidth()} because the latter does not include margins.
  464. * Actual column width measured as the number of characters of the maximum digit width of the
  465. * numbers 0, 1, 2, ..., 9 as rendered in the normal style's font. There are 4 pixels of margin
  466. * padding (two on each side), plus 1 pixel padding for the gridlines.
  467. * </p>
  468. *
  469. * @param columnIndex - the column to set (0-based)
  470. * @return width - the width in units of 1/256th of a character width
  471. */
  472. public int getColumnWidth(int columnIndex) {
  473. CTCol col = columnHelper.getColumn(columnIndex, false);
  474. double width = col == null || !col.isSetWidth() ? getDefaultColumnWidth() : col.getWidth();
  475. return (int)(width*256);
  476. }
  477. /**
  478. * Get the default column width for the sheet (if the columns do not define their own width) in
  479. * characters.
  480. * <p>
  481. * Note, this value is different from {@link #getColumnWidth(int)}. The latter is always greater and includes
  482. * 4 pixels of margin padding (two on each side), plus 1 pixel padding for the gridlines.
  483. * </p>
  484. * @return column width, default value is 8
  485. */
  486. public int getDefaultColumnWidth() {
  487. CTSheetFormatPr pr = worksheet.getSheetFormatPr();
  488. return pr == null ? 8 : (int)pr.getBaseColWidth();
  489. }
  490. /**
  491. * Get the default row height for the sheet (if the rows do not define their own height) in
  492. * twips (1/20 of a point)
  493. *
  494. * @return default row height
  495. */
  496. public short getDefaultRowHeight() {
  497. return (short)(getDefaultRowHeightInPoints() * 20);
  498. }
  499. /**
  500. * Get the default row height for the sheet measued in point size (if the rows do not define their own height).
  501. *
  502. * @return default row height in points
  503. */
  504. public float getDefaultRowHeightInPoints() {
  505. CTSheetFormatPr pr = worksheet.getSheetFormatPr();
  506. return (float)(pr == null ? 0 : pr.getDefaultRowHeight());
  507. }
  508. private CTSheetFormatPr getSheetTypeSheetFormatPr() {
  509. return worksheet.isSetSheetFormatPr() ?
  510. worksheet.getSheetFormatPr() :
  511. worksheet.addNewSheetFormatPr();
  512. }
  513. /**
  514. * Returns the CellStyle that applies to the given
  515. * (0 based) column, or null if no style has been
  516. * set for that column
  517. */
  518. public CellStyle getColumnStyle(int column) {
  519. int idx = columnHelper.getColDefaultStyle(column);
  520. return getWorkbook().getCellStyleAt((short)(idx == -1 ? 0 : idx));
  521. }
  522. /**
  523. * Get whether to display the guts or not,
  524. * default value is true
  525. *
  526. * @return boolean - guts or no guts
  527. */
  528. public boolean getDisplayGuts() {
  529. CTSheetPr sheetPr = getSheetTypeSheetPr();
  530. CTOutlinePr outlinePr = sheetPr.getOutlinePr() == null ? CTOutlinePr.Factory.newInstance() : sheetPr.getOutlinePr();
  531. return outlinePr.getShowOutlineSymbols();
  532. }
  533. /**
  534. * Set whether to display the guts or not
  535. *
  536. * @param value - guts or no guts
  537. */
  538. public void setDisplayGuts(boolean value) {
  539. CTSheetPr sheetPr = getSheetTypeSheetPr();
  540. CTOutlinePr outlinePr = sheetPr.getOutlinePr() == null ? sheetPr.addNewOutlinePr() : sheetPr.getOutlinePr();
  541. outlinePr.setShowOutlineSymbols(value);
  542. }
  543. /**
  544. * Gets the flag indicating whether the window should show 0 (zero) in cells containing zero value.
  545. * When false, cells with zero value appear blank instead of showing the number zero.
  546. *
  547. * @return whether all zero values on the worksheet are displayed
  548. */
  549. public boolean isDisplayZeros(){
  550. CTSheetView view = getDefaultSheetView();
  551. return view == null ? true : view.getShowZeros();
  552. }
  553. /**
  554. * Set whether the window should show 0 (zero) in cells containing zero value.
  555. * When false, cells with zero value appear blank instead of showing the number zero.
  556. *
  557. * @param value whether to display or hide all zero values on the worksheet
  558. */
  559. public void setDisplayZeros(boolean value){
  560. CTSheetView view = getSheetTypeSheetView();
  561. view.setShowZeros(value);
  562. }
  563. /**
  564. * Gets the first row on the sheet
  565. *
  566. * @return the number of the first logical row on the sheet, zero based
  567. */
  568. public int getFirstRowNum() {
  569. return rows.size() == 0 ? 0 : rows.firstKey();
  570. }
  571. /**
  572. * Flag indicating whether the Fit to Page print option is enabled.
  573. *
  574. * @return <code>true</code>
  575. */
  576. public boolean getFitToPage() {
  577. CTSheetPr sheetPr = getSheetTypeSheetPr();
  578. CTPageSetUpPr psSetup = (sheetPr == null || !sheetPr.isSetPageSetUpPr()) ?
  579. CTPageSetUpPr.Factory.newInstance() : sheetPr.getPageSetUpPr();
  580. return psSetup.getFitToPage();
  581. }
  582. private CTSheetPr getSheetTypeSheetPr() {
  583. if (worksheet.getSheetPr() == null) {
  584. worksheet.setSheetPr(CTSheetPr.Factory.newInstance());
  585. }
  586. return worksheet.getSheetPr();
  587. }
  588. private CTHeaderFooter getSheetTypeHeaderFooter() {
  589. if (worksheet.getHeaderFooter() == null) {
  590. worksheet.setHeaderFooter(CTHeaderFooter.Factory.newInstance());
  591. }
  592. return worksheet.getHeaderFooter();
  593. }
  594. /**
  595. * Returns the default footer for the sheet,
  596. * creating one as needed.
  597. * You may also want to look at
  598. * {@link #getFirstFooter()},
  599. * {@link #getOddFooter()} and
  600. * {@link #getEvenFooter()}
  601. */
  602. public Footer getFooter() {
  603. // The default footer is an odd footer
  604. return getOddFooter();
  605. }
  606. /**
  607. * Returns the default header for the sheet,
  608. * creating one as needed.
  609. * You may also want to look at
  610. * {@link #getFirstHeader()},
  611. * {@link #getOddHeader()} and
  612. * {@link #getEvenHeader()}
  613. */
  614. public Header getHeader() {
  615. // The default header is an odd header
  616. return getOddHeader();
  617. }
  618. /**
  619. * Returns the odd footer. Used on all pages unless
  620. * other footers also present, when used on only
  621. * odd pages.
  622. */
  623. public Footer getOddFooter() {
  624. return new XSSFOddFooter(getSheetTypeHeaderFooter());
  625. }
  626. /**
  627. * Returns the even footer. Not there by default, but
  628. * when set, used on even pages.
  629. */
  630. public Footer getEvenFooter() {
  631. return new XSSFEvenFooter(getSheetTypeHeaderFooter());
  632. }
  633. /**
  634. * Returns the first page footer. Not there by
  635. * default, but when set, used on the first page.
  636. */
  637. public Footer getFirstFooter() {
  638. return new XSSFFirstFooter(getSheetTypeHeaderFooter());
  639. }
  640. /**
  641. * Returns the odd header. Used on all pages unless
  642. * other headers also present, when used on only
  643. * odd pages.
  644. */
  645. public Header getOddHeader() {
  646. return new XSSFOddHeader(getSheetTypeHeaderFooter());
  647. }
  648. /**
  649. * Returns the even header. Not there by default, but
  650. * when set, used on even pages.
  651. */
  652. public Header getEvenHeader() {
  653. return new XSSFEvenHeader(getSheetTypeHeaderFooter());
  654. }
  655. /**
  656. * Returns the first page header. Not there by
  657. * default, but when set, used on the first page.
  658. */
  659. public Header getFirstHeader() {
  660. return new XSSFFirstHeader(getSheetTypeHeaderFooter());
  661. }
  662. /**
  663. * Determine whether printed output for this sheet will be horizontally centered.
  664. */
  665. public boolean getHorizontallyCenter() {
  666. CTPrintOptions opts = worksheet.getPrintOptions();
  667. return opts != null && opts.getHorizontalCentered();
  668. }
  669. public int getLastRowNum() {
  670. return rows.size() == 0 ? 0 : rows.lastKey();
  671. }
  672. public short getLeftCol() {
  673. String cellRef = worksheet.getSheetViews().getSheetViewArray(0).getTopLeftCell();
  674. CellReference cellReference = new CellReference(cellRef);
  675. return cellReference.getCol();
  676. }
  677. /**
  678. * Gets the size of the margin in inches.
  679. *
  680. * @param margin which margin to get
  681. * @return the size of the margin
  682. * @see Sheet#LeftMargin
  683. * @see Sheet#RightMargin
  684. * @see Sheet#TopMargin
  685. * @see Sheet#BottomMargin
  686. * @see Sheet#HeaderMargin
  687. * @see Sheet#FooterMargin
  688. */
  689. public double getMargin(short margin) {
  690. if (!worksheet.isSetPageMargins()) return 0;
  691. CTPageMargins pageMargins = worksheet.getPageMargins();
  692. switch (margin) {
  693. case LeftMargin:
  694. return pageMargins.getLeft();
  695. case RightMargin:
  696. return pageMargins.getRight();
  697. case TopMargin:
  698. return pageMargins.getTop();
  699. case BottomMargin:
  700. return pageMargins.getBottom();
  701. case HeaderMargin:
  702. return pageMargins.getHeader();
  703. case FooterMargin:
  704. return pageMargins.getFooter();
  705. default :
  706. throw new IllegalArgumentException("Unknown margin constant: " + margin);
  707. }
  708. }
  709. /**
  710. * Sets the size of the margin in inches.
  711. *
  712. * @param margin which margin to get
  713. * @param size the size of the margin
  714. * @see Sheet#LeftMargin
  715. * @see Sheet#RightMargin
  716. * @see Sheet#TopMargin
  717. * @see Sheet#BottomMargin
  718. * @see Sheet#HeaderMargin
  719. * @see Sheet#FooterMargin
  720. */
  721. public void setMargin(short margin, double size) {
  722. CTPageMargins pageMargins = worksheet.isSetPageMargins() ?
  723. worksheet.getPageMargins() : worksheet.addNewPageMargins();
  724. switch (margin) {
  725. case LeftMargin:
  726. pageMargins.setLeft(size);
  727. break;
  728. case RightMargin:
  729. pageMargins.setRight(size);
  730. break;
  731. case TopMargin:
  732. pageMargins.setTop(size);
  733. break;
  734. case BottomMargin:
  735. pageMargins.setBottom(size);
  736. break;
  737. case HeaderMargin:
  738. pageMargins.setHeader(size);
  739. break;
  740. case FooterMargin:
  741. pageMargins.setFooter(size);
  742. break;
  743. default :
  744. throw new IllegalArgumentException( "Unknown margin constant: " + margin );
  745. }
  746. }
  747. /**
  748. * @return the merged region at the specified index
  749. * @throws IllegalStateException if this worksheet does not contain merged regions
  750. */
  751. public CellRangeAddress getMergedRegion(int index) {
  752. CTMergeCells ctMergeCells = worksheet.getMergeCells();
  753. if(ctMergeCells == null) throw new IllegalStateException("This worksheet does not contain merged regions");
  754. CTMergeCell ctMergeCell = ctMergeCells.getMergeCellArray(index);
  755. String ref = ctMergeCell.getRef();
  756. return CellRangeAddress.valueOf(ref);
  757. }
  758. /**
  759. * Returns the number of merged regions defined in this worksheet
  760. *
  761. * @return number of merged regions in this worksheet
  762. */
  763. public int getNumMergedRegions() {
  764. CTMergeCells ctMergeCells = worksheet.getMergeCells();
  765. return ctMergeCells == null ? 0 : ctMergeCells.sizeOfMergeCellArray();
  766. }
  767. public int getNumHyperlinks() {
  768. return hyperlinks.size();
  769. }
  770. /**
  771. * Returns the information regarding the currently configured pane (split or freeze).
  772. *
  773. * @return null if no pane configured, or the pane information.
  774. */
  775. public PaneInformation getPaneInformation() {
  776. CTPane pane = getPane();
  777. CellReference cellRef = pane.isSetTopLeftCell() ? new CellReference(pane.getTopLeftCell()) : null;
  778. return new PaneInformation((short)pane.getXSplit(), (short)pane.getYSplit(),
  779. (short)(cellRef == null ? 0 : cellRef.getRow()),(cellRef == null ? 0 : cellRef.getCol()),
  780. (byte)pane.getActivePane().intValue(), pane.getState() == STPaneState.FROZEN);
  781. }
  782. /**
  783. * Returns the number of phsyically defined rows (NOT the number of rows in the sheet)
  784. *
  785. * @return the number of phsyically defined rows
  786. */
  787. public int getPhysicalNumberOfRows() {
  788. return rows.size();
  789. }
  790. /**
  791. * Gets the print setup object.
  792. *
  793. * @return The user model for the print setup object.
  794. */
  795. public XSSFPrintSetup getPrintSetup() {
  796. return new XSSFPrintSetup(worksheet);
  797. }
  798. /**
  799. * Answer whether protection is enabled or disabled
  800. *
  801. * @return true => protection enabled; false => protection disabled
  802. */
  803. public boolean getProtect() {
  804. return worksheet.isSetSheetProtection() && sheetProtectionEnabled();
  805. }
  806. /**
  807. * Returns the logical row ( 0-based). If you ask for a row that is not
  808. * defined you get a null. This is to say row 4 represents the fifth row on a sheet.
  809. *
  810. * @param rownum row to get
  811. * @return <code>XSSFRow</code> representing the rownumber or <code>null</code> if its not defined on the sheet
  812. */
  813. public XSSFRow getRow(int rownum) {
  814. return rows.get(rownum);
  815. }
  816. /**
  817. * Horizontal page break information used for print layout view, page layout view, drawing print breaks in normal
  818. * view, and for printing the worksheet.
  819. *
  820. * @return row indexes of all the horizontal page breaks, never <code>null</code>
  821. */
  822. public int[] getRowBreaks() {
  823. if (!worksheet.isSetRowBreaks() || worksheet.getRowBreaks().sizeOfBrkArray() == 0) {
  824. return new int[0];
  825. }
  826. CTBreak[] brkArray = worksheet.getRowBreaks().getBrkArray();
  827. int[] breaks = new int[brkArray.length];
  828. for (int i = 0 ; i < brkArray.length ; i++) {
  829. CTBreak brk = brkArray[i];
  830. breaks[i] = (int)brk.getId();
  831. }
  832. return breaks;
  833. }
  834. /**
  835. * Flag indicating whether summary rows appear below detail in an outline, when applying an outline.
  836. *
  837. * <p>
  838. * When true a summary row is inserted below the detailed data being summarized and a
  839. * new outline level is established on that row.
  840. * </p>
  841. * <p>
  842. * When false a summary row is inserted above the detailed data being summarized and a new outline level
  843. * is established on that row.
  844. * </p>
  845. * @return <code>true</code> if row summaries appear below detail in the outline
  846. */
  847. public boolean getRowSumsBelow() {
  848. CTSheetPr sheetPr = worksheet.getSheetPr();
  849. CTOutlinePr outlinePr = (sheetPr != null && sheetPr.isSetOutlinePr())
  850. ? sheetPr.getOutlinePr() : null;
  851. return outlinePr == null || outlinePr.getSummaryBelow();
  852. }
  853. /**
  854. * Flag indicating whether summary rows appear below detail in an outline, when applying an outline.
  855. *
  856. * <p>
  857. * When true a summary row is inserted below the detailed data being summarized and a
  858. * new outline level is established on that row.
  859. * </p>
  860. * <p>
  861. * When false a summary row is inserted above the detailed data being summarized and a new outline level
  862. * is established on that row.
  863. * </p>
  864. * @param value <code>true</code> if row summaries appear below detail in the outline
  865. */
  866. public void setRowSumsBelow(boolean value) {
  867. ensureOutlinePr().setSummaryBelow(value);
  868. }
  869. /**
  870. * Flag indicating whether summary columns appear to the right of detail in an outline, when applying an outline.
  871. *
  872. * <p>
  873. * When true a summary column is inserted to the right of the detailed data being summarized
  874. * and a new outline level is established on that column.
  875. * </p>
  876. * <p>
  877. * When false a summary column is inserted to the left of the detailed data being
  878. * summarized and a new outline level is established on that column.
  879. * </p>
  880. * @return <code>true</code> if col summaries appear right of the detail in the outline
  881. */
  882. public boolean getRowSumsRight() {
  883. CTSheetPr sheetPr = worksheet.getSheetPr();
  884. CTOutlinePr outlinePr = (sheetPr != null && sheetPr.isSetOutlinePr())
  885. ? sheetPr.getOutlinePr() : CTOutlinePr.Factory.newInstance();
  886. return outlinePr.getSummaryRight();
  887. }
  888. /**
  889. * Flag indicating whether summary columns appear to the right of detail in an outline, when applying an outline.
  890. *
  891. * <p>
  892. * When true a summary column is inserted to the right of the detailed data being summarized
  893. * and a new outline level is established on that column.
  894. * </p>
  895. * <p>
  896. * When false a summary column is inserted to the left of the detailed data being
  897. * summarized and a new outline level is established on that column.
  898. * </p>
  899. * @param value <code>true</code> if col summaries appear right of the detail in the outline
  900. */
  901. public void setRowSumsRight(boolean value) {
  902. ensureOutlinePr().setSummaryRight(value);
  903. }
  904. /**
  905. * Ensure CTWorksheet.CTSheetPr.CTOutlinePr
  906. */
  907. private CTOutlinePr ensureOutlinePr(){
  908. CTSheetPr sheetPr = worksheet.isSetSheetPr() ? worksheet.getSheetPr() : worksheet.addNewSheetPr();
  909. return sheetPr.isSetOutlinePr() ? sheetPr.getOutlinePr() : sheetPr.addNewOutlinePr();
  910. }
  911. /**
  912. * A flag indicating whether scenarios are locked when the sheet is protected.
  913. *
  914. * @return true => protection enabled; false => protection disabled
  915. */
  916. public boolean getScenarioProtect() {
  917. return worksheet.isSetSheetProtection() && worksheet.getSheetProtection().getScenarios();
  918. }
  919. /**
  920. * The top row in the visible view when the sheet is
  921. * first viewed after opening it in a viewer
  922. *
  923. * @return integer indicating the rownum (0 based) of the top row
  924. */
  925. public short getTopRow() {
  926. String cellRef = getSheetTypeSheetView().getTopLeftCell();
  927. CellReference cellReference = new CellReference(cellRef);
  928. return (short) cellReference.getRow();
  929. }
  930. /**
  931. * Determine whether printed output for this sheet will be vertically centered.
  932. *
  933. * @return whether printed output for this sheet will be vertically centered.
  934. */
  935. public boolean getVerticallyCenter() {
  936. CTPrintOptions opts = worksheet.getPrintOptions();
  937. return opts != null && opts.getVerticalCentered();
  938. }
  939. /**
  940. * Group between (0 based) columns
  941. */
  942. public void groupColumn(int fromColumn, int toColumn) {
  943. groupColumn1Based(fromColumn+1, toColumn+1);
  944. }
  945. private void groupColumn1Based(int fromColumn, int toColumn) {
  946. CTCols ctCols=worksheet.getColsArray(0);
  947. CTCol ctCol=CTCol.Factory.newInstance();
  948. ctCol.setMin(fromColumn);
  949. ctCol.setMax(toColumn);
  950. this.columnHelper.addCleanColIntoCols(ctCols, ctCol);
  951. for(int index=fromColumn;index<=toColumn;index++){
  952. CTCol col=columnHelper.getColumn1Based(index, false);
  953. //col must exist
  954. short outlineLevel=col.getOutlineLevel();
  955. col.setOutlineLevel((short)(outlineLevel+1));
  956. index=(int)col.getMax();
  957. }
  958. worksheet.setColsArray(0,ctCols);
  959. setSheetFormatPrOutlineLevelCol();
  960. }
  961. /**
  962. * Tie a range of cell together so that they can be collapsed or expanded
  963. *
  964. * @param fromRow start row (0-based)
  965. * @param toRow end row (0-based)
  966. */
  967. public void groupRow(int fromRow, int toRow) {
  968. for (int i = fromRow; i <= toRow; i++) {
  969. XSSFRow xrow = getRow(i);
  970. if (xrow == null) {
  971. xrow = createRow(i);
  972. }
  973. CTRow ctrow = xrow.getCTRow();
  974. short outlineLevel = ctrow.getOutlineLevel();
  975. ctrow.setOutlineLevel((short) (outlineLevel + 1));
  976. }
  977. setSheetFormatPrOutlineLevelRow();
  978. }
  979. private short getMaxOutlineLevelRows(){
  980. short outlineLevel=0;
  981. for(XSSFRow xrow : rows.values()){
  982. outlineLevel=xrow.getCTRow().getOutlineLevel()>outlineLevel? xrow.getCTRow().getOutlineLevel(): outlineLevel;
  983. }
  984. return outlineLevel;
  985. }
  986. private short getMaxOutlineLevelCols(){
  987. CTCols ctCols=worksheet.getColsArray(0);
  988. CTCol[]colArray=ctCols.getColArray();
  989. short outlineLevel=0;
  990. for(CTCol col: colArray){
  991. outlineLevel=col.getOutlineLevel()>outlineLevel? col.getOutlineLevel(): outlineLevel;
  992. }
  993. return outlineLevel;
  994. }
  995. /**
  996. * Determines if there is a page break at the indicated column
  997. */
  998. public boolean isColumnBroken(int column) {
  999. int[] colBreaks = getColumnBreaks();
  1000. for (int i = 0 ; i < colBreaks.length ; i++) {
  1001. if (colBreaks[i] == column) {
  1002. return true;
  1003. }
  1004. }
  1005. return false;
  1006. }
  1007. /**
  1008. * Get the hidden state for a given column.
  1009. *
  1010. * @param columnIndex - the column to set (0-based)
  1011. * @return hidden - <code>false</code> if the column is visible
  1012. */
  1013. public boolean isColumnHidden(int columnIndex) {
  1014. CTCol col = columnHelper.getColumn(columnIndex, false);
  1015. return col != null && col.getHidden();
  1016. }
  1017. /**
  1018. * Gets the flag indicating whether this sheet should display formulas.
  1019. *
  1020. * @return <code>true</code> if this sheet should display formulas.
  1021. */
  1022. public boolean isDisplayFormulas() {
  1023. return getSheetTypeSheetView().getShowFormulas();
  1024. }
  1025. /**
  1026. * Gets the flag indicating whether this sheet displays the lines
  1027. * between rows and columns to make editing and reading easier.
  1028. *
  1029. * @return <code>true</code> if this sheet displays gridlines.
  1030. * @see #isPrintGridlines() to check if printing of gridlines is turned on or off
  1031. */
  1032. public boolean isDisplayGridlines() {
  1033. return getSheetTypeSheetView().getShowGridLines();
  1034. }
  1035. /**
  1036. * Sets the flag indicating whether this sheet should display the lines
  1037. * between rows and columns to make editing and reading easier.
  1038. * To turn printing of gridlines use {@link #setPrintGridlines(boolean)}
  1039. *
  1040. *
  1041. * @param show <code>true</code> if this sheet should display gridlines.
  1042. * @see #setPrintGridlines(boolean)
  1043. */
  1044. public void setDisplayGridlines(boolean show) {
  1045. getSheetTypeSheetView().setShowGridLines(show);
  1046. }
  1047. /**
  1048. * Gets the flag indicating whether this sheet should display row and column headings.
  1049. * <p>
  1050. * Row heading are the row numbers to the side of the sheet
  1051. * </p>
  1052. * <p>
  1053. * Column heading are the letters or numbers that appear above the columns of the sheet
  1054. * </p>
  1055. *
  1056. * @return <code>true</code> if this sheet should display row and column headings.
  1057. */
  1058. public boolean isDisplayRowColHeadings() {
  1059. return getSheetTypeSheetView().getShowRowColHeaders();
  1060. }
  1061. /**
  1062. * Sets the flag indicating whether this sheet should display row and column headings.
  1063. * <p>
  1064. * Row heading are the row numbers to the side of the sheet
  1065. * </p>
  1066. * <p>
  1067. * Column heading are the letters or numbers that appear above the columns of the sheet
  1068. * </p>
  1069. *
  1070. * @param show <code>true</code> if this sheet should display row and column headings.
  1071. */
  1072. public void setDisplayRowColHeadings(boolean show) {
  1073. getSheetTypeSheetView().setShowRowColHeaders(show);
  1074. }
  1075. /**
  1076. * Returns whether gridlines are printed.
  1077. *
  1078. * @return whether gridlines are printed
  1079. */
  1080. public boolean isPrintGridlines() {
  1081. CTPrintOptions opts = worksheet.getPrintOptions();
  1082. return opts != null && opts.getGridLines();
  1083. }
  1084. /**
  1085. * Turns on or off the printing of gridlines.
  1086. *
  1087. * @param value boolean to turn on or off the printing of gridlines
  1088. */
  1089. public void setPrintGridlines(boolean value) {
  1090. CTPrintOptions opts = worksheet.isSetPrintOptions() ?
  1091. worksheet.getPrintOptions() : worksheet.addNewPrintOptions();
  1092. opts.setGridLines(value);
  1093. }
  1094. /**
  1095. * Tests if there is a page break at the indicated row
  1096. *
  1097. * @param row index of the row to test
  1098. * @return <code>true</code> if there is a page break at the indicated row
  1099. */
  1100. public boolean isRowBroken(int row) {
  1101. int[] rowBreaks = getRowBreaks();
  1102. for (int i = 0 ; i < rowBreaks.length ; i++) {
  1103. if (rowBreaks[i] == row) {
  1104. return true;
  1105. }
  1106. }
  1107. return false;
  1108. }
  1109. /**
  1110. * Sets a page break at the indicated row
  1111. */
  1112. public void setRowBreak(int row) {
  1113. CTPageBreak pgBreak = worksheet.isSetRowBreaks() ? worksheet.getRowBreaks() : worksheet.addNewRowBreaks();
  1114. if (! isRowBroken(row)) {
  1115. CTBreak brk = pgBreak.addNewBrk();
  1116. brk.setId(row);
  1117. }
  1118. }
  1119. /**
  1120. * Removes a page break at the indicated column
  1121. */
  1122. public void removeColumnBreak(int column) {
  1123. CTBreak[] brkArray = getSheetTypeColumnBreaks().getBrkArray();
  1124. for (int i = 0 ; i < brkArray.length ; i++) {
  1125. if (brkArray[i].getId() == column) {
  1126. getSheetTypeColumnBreaks().removeBrk(i);
  1127. }
  1128. }
  1129. }
  1130. /**
  1131. * Removes a merged region of cells (hence letting them free)
  1132. *
  1133. * @param index of the region to unmerge
  1134. */
  1135. public void removeMergedRegion(int index) {
  1136. CTMergeCells ctMergeCells = worksheet.getMergeCells();
  1137. CTMergeCell[] mergeCellsArray = new CTMergeCell[ctMergeCells.sizeOfMergeCellArray() - 1];
  1138. for (int i = 0 ; i < ctMergeCells.sizeOfMergeCellArray() ; i++) {
  1139. if (i < index) {
  1140. mergeCellsArray[i] = ctMergeCells.getMergeCellArray(i);
  1141. }
  1142. else if (i > index) {
  1143. mergeCellsArray[i - 1] = ctMergeCells.getMergeCellArray(i);
  1144. }
  1145. }
  1146. ctMergeCells.setMergeCellArray(mergeCellsArray);
  1147. }
  1148. /**
  1149. * Remove a row from this sheet. All cells contained in the row are removed as well
  1150. *
  1151. * @param row the row to remove.
  1152. */
  1153. public void removeRow(Row row) {
  1154. if (row.getSheet() != this) {
  1155. throw new IllegalArgumentException("Specified row does not belong to this sheet");
  1156. }
  1157. rows.remove(row.getRowNum());
  1158. }
  1159. /**
  1160. * Removes the page break at the indicated row
  1161. */
  1162. public void removeRowBreak(int row) {
  1163. CTPageBreak pgBreak = worksheet.isSetRowBreaks() ? worksheet.getRowBreaks() : worksheet.addNewRowBreaks();
  1164. CTBreak[] brkArray = pgBreak.getBrkArray();
  1165. for (int i = 0 ; i < brkArray.length ; i++) {
  1166. if (brkArray[i].getId() == row) {
  1167. pgBreak.removeBrk(i);
  1168. }
  1169. }
  1170. }
  1171. /**
  1172. * @return an iterator of the PHYSICAL rows. Meaning the 3rd element may not
  1173. * be the third row if say for instance the second row is undefined.
  1174. * Call getRowNum() on each row if you care which one it is.
  1175. */
  1176. public Iterator<Row> rowIterator() {
  1177. return (Iterator<Row>)(Iterator<? extends Row>)rows.values().iterator();
  1178. }
  1179. /**
  1180. * Alias for {@link #rowIterator()} to
  1181. * allow foreach loops
  1182. */
  1183. public Iterator<Row> iterator() {
  1184. return rowIterator();
  1185. }
  1186. /**
  1187. * Flag indicating whether the sheet displays Automatic Page Breaks.
  1188. *
  1189. * @return <code>true</code> if the sheet displays Automatic Page Breaks.
  1190. */
  1191. public boolean getAutobreaks() {
  1192. CTSheetPr sheetPr = getSheetTypeSheetPr();
  1193. CTPageSetUpPr psSetup = (sheetPr == null || !sheetPr.isSetPageSetUpPr()) ?
  1194. CTPageSetUpPr.Factory.newInstance() : sheetPr.getPageSetUpPr();
  1195. return psSetup.getAutoPageBreaks();
  1196. }
  1197. /**
  1198. * Flag indicating whether the sheet displays Automatic Page Breaks.
  1199. *
  1200. * @param value <code>true</code> if the sheet displays Automatic Page Breaks.
  1201. */
  1202. public void setAutobreaks(boolean value) {
  1203. CTSheetPr sheetPr = getSheetTypeSheetPr();
  1204. CTPageSetUpPr psSetup = sheetPr.isSetPageSetUpPr() ? sheetPr.getPageSetUpPr() : sheetPr.addNewPageSetUpPr();
  1205. psSetup.setAutoPageBreaks(value);
  1206. }
  1207. /**
  1208. * Sets a page break at the indicated column
  1209. *
  1210. * @param column the column to break
  1211. */
  1212. public void setColumnBreak(int column) {
  1213. if (! isColumnBroken(column)) {
  1214. CTBreak brk = getSheetTypeColumnBreaks().addNewBrk();
  1215. brk.setId(column);
  1216. }
  1217. }
  1218. public void setColumnGroupCollapsed(int columnNumber, boolean collapsed) {
  1219. if (collapsed) {
  1220. collapseColumn(columnNumber);
  1221. } else {
  1222. expandColumn(columnNumber);
  1223. }
  1224. }
  1225. private void collapseColumn(int columnNumber) {
  1226. CTCols cols = worksheet.getColsArray(0);
  1227. CTCol col = columnHelper.getColumn(columnNumber, false);
  1228. int colInfoIx = columnHelper.getIndexOfColumn(cols, col);
  1229. if (colInfoIx == -1) {
  1230. return;
  1231. }
  1232. // Find the start of the group.
  1233. int groupStartColInfoIx = findStartOfColumnOutlineGroup(colInfoIx);
  1234. CTCol columnInfo = cols.getColArray(groupStartColInfoIx);
  1235. // Hide all the columns until the end of the group
  1236. int lastColMax = setGroupHidden(groupStartColInfoIx, columnInfo
  1237. .getOutlineLevel(), true);
  1238. // write collapse field
  1239. setColumn(lastColMax + 1, null, 0, null, null, Boolean.TRUE);
  1240. }
  1241. private void setColumn(int targetColumnIx, Short xfIndex, Integer style,
  1242. Integer level, Boolean hidden, Boolean collapsed) {
  1243. CTCols cols = worksheet.getColsArray(0);
  1244. CTCol ci = null;
  1245. int k = 0;
  1246. for (k = 0; k < cols.sizeOfColArray(); k++) {
  1247. CTCol tci = cols.getColArray(k);
  1248. if (tci.getMin() >= targetColumnIx
  1249. && tci.getMax() <= targetColumnIx) {
  1250. ci = tci;
  1251. break;
  1252. }