12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345 |
- /* ====================================================================
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ==================================================================== */
-
- package org.apache.poi.hssf.usermodel;
-
- import java.io.PrintWriter;
- import java.util.ArrayList;
- import java.util.Iterator;
- import java.util.List;
- import java.util.TreeMap;
-
- import org.apache.poi.ddf.EscherRecord;
- import org.apache.poi.hssf.model.DrawingManager2;
- import org.apache.poi.hssf.model.HSSFFormulaParser;
- import org.apache.poi.hssf.model.InternalSheet;
- import org.apache.poi.hssf.model.InternalWorkbook;
- import org.apache.poi.hssf.record.AutoFilterInfoRecord;
- import org.apache.poi.hssf.record.CellValueRecordInterface;
- import org.apache.poi.hssf.record.DVRecord;
- import org.apache.poi.hssf.record.DimensionsRecord;
- import org.apache.poi.hssf.record.DrawingRecord;
- import org.apache.poi.hssf.record.EscherAggregate;
- import org.apache.poi.hssf.record.ExtendedFormatRecord;
- import org.apache.poi.hssf.record.NameRecord;
- import org.apache.poi.hssf.record.NoteRecord;
- import org.apache.poi.hssf.record.Record;
- import org.apache.poi.hssf.record.RowRecord;
- import org.apache.poi.hssf.record.SCLRecord;
- import org.apache.poi.hssf.record.WSBoolRecord;
- import org.apache.poi.hssf.record.WindowTwoRecord;
- import org.apache.poi.hssf.record.aggregates.DataValidityTable;
- import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate;
- import org.apache.poi.hssf.record.aggregates.RecordAggregate.RecordVisitor;
- import org.apache.poi.hssf.record.aggregates.WorksheetProtectionBlock;
- import org.apache.poi.hssf.util.PaneInformation;
- import org.apache.poi.ss.SpreadsheetVersion;
- import org.apache.poi.ss.formula.FormulaShifter;
- import org.apache.poi.ss.formula.FormulaType;
- import org.apache.poi.ss.formula.ptg.Area3DPtg;
- import org.apache.poi.ss.formula.ptg.MemFuncPtg;
- import org.apache.poi.ss.formula.ptg.Ptg;
- import org.apache.poi.ss.formula.ptg.UnionPtg;
- import org.apache.poi.ss.usermodel.Cell;
- import org.apache.poi.ss.usermodel.CellRange;
- import org.apache.poi.ss.usermodel.CellStyle;
- import org.apache.poi.ss.usermodel.DataValidation;
- import org.apache.poi.ss.usermodel.DataValidationHelper;
- import org.apache.poi.ss.usermodel.Row;
- import org.apache.poi.ss.util.CellRangeAddress;
- import org.apache.poi.ss.util.CellRangeAddressList;
- import org.apache.poi.ss.util.CellReference;
- import org.apache.poi.ss.util.SSCellRange;
- import org.apache.poi.ss.util.SheetUtil;
- import org.apache.poi.util.Configurator;
- import org.apache.poi.util.POILogFactory;
- import org.apache.poi.util.POILogger;
-
- /**
- * High level representation of a worksheet.
- */
- public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet {
- private static final POILogger log = POILogFactory.getLogger(HSSFSheet.class);
- private static final int DEBUG = POILogger.DEBUG;
-
- /**
- * width of 1px in columns with default width in units of 1/256 of a character width
- */
- private static final float PX_DEFAULT = 32.00f;
- /**
- * width of 1px in columns with overridden width in units of 1/256 of a character width
- */
- private static final float PX_MODIFIED = 36.56f;
-
-
- /**
- * Used for compile-time optimization. This is the initial size for the collection of
- * rows. It is currently set to 20. If you generate larger sheets you may benefit
- * by setting this to a higher number and recompiling a custom edition of HSSFSheet.
- */
- public final static int INITIAL_CAPACITY = Configurator.getIntValue("HSSFSheet.RowInitialCapacity", 20);
-
- /**
- * reference to the low level {@link InternalSheet} object
- */
- private final InternalSheet _sheet;
- /**
- * stores rows by zero-based row number
- */
- private final TreeMap<Integer, HSSFRow> _rows;
- protected final InternalWorkbook _book;
- protected final HSSFWorkbook _workbook;
- private HSSFPatriarch _patriarch;
- private int _firstrow;
- private int _lastrow;
-
- /**
- * Creates new HSSFSheet - called by HSSFWorkbook to create a sheet from
- * scratch. You should not be calling this from application code (its protected anyhow).
- *
- * @param workbook - The HSSF Workbook object associated with the sheet.
- * @see org.apache.poi.hssf.usermodel.HSSFWorkbook#createSheet()
- */
- protected HSSFSheet(HSSFWorkbook workbook) {
- _sheet = InternalSheet.createSheet();
- _rows = new TreeMap<Integer, HSSFRow>();
- this._workbook = workbook;
- this._book = workbook.getWorkbook();
- }
-
- /**
- * Creates an HSSFSheet representing the given Sheet object. Should only be
- * called by HSSFWorkbook when reading in an exisiting file.
- *
- * @param workbook - The HSSF Workbook object associated with the sheet.
- * @param sheet - lowlevel Sheet object this sheet will represent
- * @see org.apache.poi.hssf.usermodel.HSSFWorkbook#createSheet()
- */
- protected HSSFSheet(HSSFWorkbook workbook, InternalSheet sheet) {
- this._sheet = sheet;
- _rows = new TreeMap<Integer, HSSFRow>();
- this._workbook = workbook;
- this._book = workbook.getWorkbook();
- setPropertiesFromSheet(sheet);
- }
-
- HSSFSheet cloneSheet(HSSFWorkbook workbook) {
- this.getDrawingPatriarch();/**Aggregate drawing records**/
- HSSFSheet sheet = new HSSFSheet(workbook, _sheet.cloneSheet());
- int pos = sheet._sheet.findFirstRecordLocBySid(DrawingRecord.sid);
- DrawingRecord dr = (DrawingRecord) sheet._sheet.findFirstRecordBySid(DrawingRecord.sid);
- if (null != dr) {
- sheet._sheet.getRecords().remove(dr);
- }
- if (getDrawingPatriarch() != null) {
- HSSFPatriarch patr = HSSFPatriarch.createPatriarch(this.getDrawingPatriarch(), sheet);
- sheet._sheet.getRecords().add(pos, patr._getBoundAggregate());
- sheet._patriarch = patr;
- }
- return sheet;
- }
-
- /**
- * check whether the data of sheet can be serialized
- */
- protected void preSerialize(){
- if (_patriarch != null){
- _patriarch.preSerialize();
- }
- }
-
- /**
- * Return the parent workbook
- *
- * @return the parent workbook
- */
- public HSSFWorkbook getWorkbook() {
- return _workbook;
- }
-
- /**
- * used internally to set the properties given a Sheet object
- */
- private void setPropertiesFromSheet(InternalSheet sheet) {
-
- RowRecord row = sheet.getNextRow();
- boolean rowRecordsAlreadyPresent = row != null;
-
- while (row != null) {
- createRowFromRecord(row);
-
- row = sheet.getNextRow();
- }
-
- Iterator<CellValueRecordInterface> iter = sheet.getCellValueIterator();
- long timestart = System.currentTimeMillis();
-
- if (log.check( POILogger.DEBUG )) {
- log.log(DEBUG, "Time at start of cell creating in HSSF sheet = ",
- Long.valueOf(timestart));
- }
- HSSFRow lastrow = null;
-
- // Add every cell to its row
- while (iter.hasNext()) {
- CellValueRecordInterface cval = iter.next();
-
- long cellstart = System.currentTimeMillis();
- HSSFRow hrow = lastrow;
-
- if (hrow == null || hrow.getRowNum() != cval.getRow()) {
- hrow = getRow(cval.getRow());
- lastrow = hrow;
- if (hrow == null) {
- // Some tools (like Perl module Spreadsheet::WriteExcel - bug 41187) skip the RowRecords
- // Excel, OpenOffice.org and GoogleDocs are all OK with this, so POI should be too.
- if (rowRecordsAlreadyPresent) {
- // if at least one row record is present, all should be present.
- throw new RuntimeException("Unexpected missing row when some rows already present");
- }
- // create the row record on the fly now.
- RowRecord rowRec = new RowRecord(cval.getRow());
- sheet.addRow(rowRec);
- hrow = createRowFromRecord(rowRec);
- }
- }
- if (log.check( POILogger.DEBUG )) {
- if (cval instanceof Record) {
- log.log( DEBUG, "record id = " + Integer.toHexString( ( (Record) cval ).getSid() ) );
- } else {
- log.log( DEBUG, "record = " + cval );
- }
- }
- hrow.createCellFromRecord( cval );
- if (log.check( POILogger.DEBUG )) {
- log.log( DEBUG, "record took ",
- Long.valueOf( System.currentTimeMillis() - cellstart ) );
- }
-
- }
- if (log.check( POILogger.DEBUG )) {
- log.log(DEBUG, "total sheet cell creation took ",
- Long.valueOf(System.currentTimeMillis() - timestart));
- }
- }
-
- /**
- * Create a new row within the sheet and return the high level representation
- *
- * @param rownum row number
- * @return High level HSSFRow object representing a row in the sheet
- * @see org.apache.poi.hssf.usermodel.HSSFRow
- * @see #removeRow(org.apache.poi.ss.usermodel.Row)
- */
- public HSSFRow createRow(int rownum) {
- HSSFRow row = new HSSFRow(_workbook, this, rownum);
- // new rows inherit default height from the sheet
- row.setHeight(getDefaultRowHeight());
- row.getRowRecord().setBadFontHeight(false);
-
- addRow(row, true);
- return row;
- }
-
- /**
- * Used internally to create a high level Row object from a low level row object.
- * USed when reading an existing file
- *
- * @param row low level record to represent as a high level Row and add to sheet
- * @return HSSFRow high level representation
- */
-
- private HSSFRow createRowFromRecord(RowRecord row) {
- HSSFRow hrow = new HSSFRow(_workbook, this, row);
-
- addRow(hrow, false);
- return hrow;
- }
-
- /**
- * Remove a row from this sheet. All cells contained in the row are removed as well
- *
- * @param row representing a row to remove.
- */
- public void removeRow(Row row) {
- HSSFRow hrow = (HSSFRow) row;
- if (row.getSheet() != this) {
- throw new IllegalArgumentException("Specified row does not belong to this sheet");
- }
- for (Cell cell : row) {
- HSSFCell xcell = (HSSFCell) cell;
- if (xcell.isPartOfArrayFormulaGroup()) {
- String msg = "Row[rownum=" + row.getRowNum() + "] contains cell(s) included in a multi-cell array formula. You cannot change part of an array.";
- xcell.notifyArrayFormulaChanging(msg);
- }
- }
-
- if (_rows.size() > 0) {
- Integer key = Integer.valueOf(row.getRowNum());
- HSSFRow removedRow = _rows.remove(key);
- if (removedRow != row) {
- //should not happen if the input argument is valid
- throw new IllegalArgumentException("Specified row does not belong to this sheet");
- }
- if (hrow.getRowNum() == getLastRowNum()) {
- _lastrow = findLastRow(_lastrow);
- }
- if (hrow.getRowNum() == getFirstRowNum()) {
- _firstrow = findFirstRow(_firstrow);
- }
- _sheet.removeRow(hrow.getRowRecord());
- }
- }
-
- /**
- * used internally to refresh the "last row" when the last row is removed.
- */
- private int findLastRow(int lastrow) {
- if (lastrow < 1) {
- return 0;
- }
- int rownum = lastrow - 1;
- HSSFRow r = getRow(rownum);
-
- while (r == null && rownum > 0) {
- r = getRow(--rownum);
- }
- if (r == null) {
- return 0;
- }
- return rownum;
- }
-
- /**
- * used internally to refresh the "first row" when the first row is removed.
- */
-
- private int findFirstRow(int firstrow) {
- int rownum = firstrow + 1;
- HSSFRow r = getRow(rownum);
-
- while (r == null && rownum <= getLastRowNum()) {
- r = getRow(++rownum);
- }
-
- if (rownum > getLastRowNum())
- return 0;
-
- return rownum;
- }
-
- /**
- * add a row to the sheet
- *
- * @param addLow whether to add the row to the low level model - false if its already there
- */
-
- private void addRow(HSSFRow row, boolean addLow) {
- _rows.put(Integer.valueOf(row.getRowNum()), row);
- if (addLow) {
- _sheet.addRow(row.getRowRecord());
- }
- boolean firstRow = _rows.size() == 1;
- if (row.getRowNum() > getLastRowNum() || firstRow) {
- _lastrow = row.getRowNum();
- }
- if (row.getRowNum() < getFirstRowNum() || firstRow) {
- _firstrow = row.getRowNum();
- }
- }
-
- /**
- * Returns the logical row (not physical) 0-based. If you ask for a row that is not
- * defined you get a null. This is to say row 4 represents the fifth row on a sheet.
- *
- * @param rowIndex row to get
- * @return HSSFRow representing the row number or null if its not defined on the sheet
- */
- public HSSFRow getRow(int rowIndex) {
- return _rows.get(Integer.valueOf(rowIndex));
- }
-
- /**
- * Returns the number of physically defined rows (NOT the number of rows in the sheet)
- */
- public int getPhysicalNumberOfRows() {
- return _rows.size();
- }
-
- /**
- * Gets the first row on the sheet
- *
- * @return the number of the first logical row on the sheet, zero based
- */
- public int getFirstRowNum() {
- return _firstrow;
- }
-
- /**
- * Gets the number last row on the sheet.
- * Owing to idiosyncrasies in the excel file
- * format, if the result of calling this method
- * is zero, you can't tell if that means there
- * are zero rows on the sheet, or one at
- * position zero. For that case, additionally
- * call {@link #getPhysicalNumberOfRows()} to
- * tell if there is a row at position zero
- * or not.
- *
- * @return the number of the last row contained in this sheet, zero based.
- */
- public int getLastRowNum() {
- return _lastrow;
- }
-
- public List<HSSFDataValidation> getDataValidations() {
- DataValidityTable dvt = _sheet.getOrCreateDataValidityTable();
- final List<HSSFDataValidation> hssfValidations = new ArrayList<HSSFDataValidation>();
- RecordVisitor visitor = new RecordVisitor() {
- private HSSFEvaluationWorkbook book = HSSFEvaluationWorkbook.create(getWorkbook());
-
- @Override
- public void visitRecord(Record r) {
- if (!(r instanceof DVRecord)) {
- return;
- }
- DVRecord dvRecord = (DVRecord) r;
- CellRangeAddressList regions = dvRecord.getCellRangeAddress().copy();
- DVConstraint constraint = DVConstraint.createDVConstraint(dvRecord, book);
- HSSFDataValidation hssfDataValidation = new HSSFDataValidation(regions, constraint);
- hssfDataValidation.setErrorStyle(dvRecord.getErrorStyle());
- hssfDataValidation.setEmptyCellAllowed(dvRecord.getEmptyCellAllowed());
- hssfDataValidation.setSuppressDropDownArrow(dvRecord.getSuppressDropdownArrow());
- hssfDataValidation.createPromptBox(dvRecord.getPromptTitle(), dvRecord.getPromptText());
- hssfDataValidation.setShowPromptBox(dvRecord.getShowPromptOnCellSelected());
- hssfDataValidation.createErrorBox(dvRecord.getErrorTitle(), dvRecord.getErrorText());
- hssfDataValidation.setShowErrorBox(dvRecord.getShowErrorOnInvalidValue());
- hssfValidations.add(hssfDataValidation);
- }
- };
- dvt.visitContainedRecords(visitor);
- return hssfValidations;
- }
-
- /**
- * Creates a data validation object
- *
- * @param dataValidation The Data validation object settings
- */
- public void addValidationData(DataValidation dataValidation) {
- if (dataValidation == null) {
- throw new IllegalArgumentException("objValidation must not be null");
- }
- HSSFDataValidation hssfDataValidation = (HSSFDataValidation) dataValidation;
- DataValidityTable dvt = _sheet.getOrCreateDataValidityTable();
-
- DVRecord dvRecord = hssfDataValidation.createDVRecord(this);
- dvt.addDataValidation(dvRecord);
- }
-
-
- /**
- * @deprecated (Sep 2008) use {@link #setColumnHidden(int, boolean)}
- */
- public void setColumnHidden(short columnIndex, boolean hidden) {
- setColumnHidden(columnIndex & 0xFFFF, hidden);
- }
-
- /**
- * @deprecated (Sep 2008) use {@link #isColumnHidden(int)}
- */
- public boolean isColumnHidden(short columnIndex) {
- return isColumnHidden(columnIndex & 0xFFFF);
- }
-
- /**
- * @deprecated (Sep 2008) use {@link #setColumnWidth(int, int)}
- */
- public void setColumnWidth(short columnIndex, short width) {
- setColumnWidth(columnIndex & 0xFFFF, width & 0xFFFF);
- }
-
- /**
- * @deprecated (Sep 2008) use {@link #getColumnWidth(int)}
- */
- public short getColumnWidth(short columnIndex) {
- return (short) getColumnWidth(columnIndex & 0xFFFF);
- }
-
- /**
- * @deprecated (Sep 2008) use {@link #setDefaultColumnWidth(int)}
- */
- public void setDefaultColumnWidth(short width) {
- setDefaultColumnWidth(width & 0xFFFF);
- }
-
- /**
- * Get the visibility state for a given column.
- *
- * @param columnIndex - the column to get (0-based)
- * @param hidden - the visiblity state of the column
- */
- public void setColumnHidden(int columnIndex, boolean hidden) {
- _sheet.setColumnHidden(columnIndex, hidden);
- }
-
- /**
- * Get the hidden state for a given column.
- *
- * @param columnIndex - the column to set (0-based)
- * @return hidden - <code>false</code> if the column is visible
- */
- public boolean isColumnHidden(int columnIndex) {
- return _sheet.isColumnHidden(columnIndex);
- }
-
- /**
- * Set the width (in units of 1/256th of a character width)
- * <p/>
- * <p>
- * The maximum column width for an individual cell is 255 characters.
- * This value represents the number of characters that can be displayed
- * in a cell that is formatted with the standard font (first font in the workbook).
- * </p>
- * <p/>
- * <p>
- * Character width is defined as the maximum digit width
- * of the numbers <code>0, 1, 2, ... 9</code> as rendered
- * using the default font (first font in the workbook).
- * <br/>
- * Unless you are using a very special font, the default character is '0' (zero),
- * this is true for Arial (default font font in HSSF) and Calibri (default font in XSSF)
- * </p>
- * <p/>
- * <p>
- * Please note, that the width set by this method includes 4 pixels of margin padding (two on each side),
- * plus 1 pixel padding for the gridlines (Section 3.3.1.12 of the OOXML spec).
- * This results is a slightly less value of visible characters than passed to this method (approx. 1/2 of a character).
- * </p>
- * <p>
- * To compute the actual number of visible characters,
- * Excel uses the following formula (Section 3.3.1.12 of the OOXML spec):
- * </p>
- * <code>
- * width = Truncate([{Number of Visible Characters} *
- * {Maximum Digit Width} + {5 pixel padding}]/{Maximum Digit Width}*256)/256
- * </code>
- * <p>Using the Calibri font as an example, the maximum digit width of 11 point font size is 7 pixels (at 96 dpi).
- * If you set a column width to be eight characters wide, e.g. <code>setColumnWidth(columnIndex, 8*256)</code>,
- * then the actual value of visible characters (the value shown in Excel) is derived from the following equation:
- * <code>
- * Truncate([numChars*7+5]/7*256)/256 = 8;
- * </code>
- * <p/>
- * which gives <code>7.29</code>.
- *
- * @param columnIndex - the column to set (0-based)
- * @param width - the width in units of 1/256th of a character width
- * @throws IllegalArgumentException if width > 255*256 (the maximum column width in Excel is 255 characters)
- */
- public void setColumnWidth(int columnIndex, int width) {
- _sheet.setColumnWidth(columnIndex, width);
- }
-
- /**
- * get the width (in units of 1/256th of a character width )
- *
- * @param columnIndex - the column to set (0-based)
- * @return width - the width in units of 1/256th of a character width
- */
- public int getColumnWidth(int columnIndex) {
- return _sheet.getColumnWidth(columnIndex);
- }
-
- public float getColumnWidthInPixels(int column){
- int cw = getColumnWidth(column);
- int def = getDefaultColumnWidth()*256;
- float px = (cw == def ? PX_DEFAULT : PX_MODIFIED);
-
- return cw/px;
- }
-
- /**
- * get the default column width for the sheet (if the columns do not define their own width) in
- * characters
- *
- * @return default column width
- */
- public int getDefaultColumnWidth() {
- return _sheet.getDefaultColumnWidth();
- }
-
- /**
- * set the default column width for the sheet (if the columns do not define their own width) in
- * characters
- *
- * @param width default column width
- */
- public void setDefaultColumnWidth(int width) {
- _sheet.setDefaultColumnWidth(width);
- }
-
-
- /**
- * get the default row height for the sheet (if the rows do not define their own height) in
- * twips (1/20 of a point)
- *
- * @return default row height
- */
- public short getDefaultRowHeight() {
- return _sheet.getDefaultRowHeight();
- }
-
- /**
- * get the default row height for the sheet (if the rows do not define their own height) in
- * points.
- *
- * @return default row height in points
- */
-
- public float getDefaultRowHeightInPoints() {
- return ((float) _sheet.getDefaultRowHeight() / 20);
- }
-
- /**
- * set the default row height for the sheet (if the rows do not define their own height) in
- * twips (1/20 of a point)
- *
- * @param height default row height
- */
-
- public void setDefaultRowHeight(short height) {
- _sheet.setDefaultRowHeight(height);
- }
-
- /**
- * set the default row height for the sheet (if the rows do not define their own height) in
- * points
- *
- * @param height default row height
- */
-
- public void setDefaultRowHeightInPoints(float height) {
- _sheet.setDefaultRowHeight((short) (height * 20));
- }
-
- /**
- * Returns the HSSFCellStyle that applies to the given
- * (0 based) column, or null if no style has been
- * set for that column
- */
- public HSSFCellStyle getColumnStyle(int column) {
- short styleIndex = _sheet.getXFIndexForColAt((short) column);
-
- if (styleIndex == 0xf) {
- // None set
- return null;
- }
-
- ExtendedFormatRecord xf = _book.getExFormatAt(styleIndex);
- return new HSSFCellStyle(styleIndex, xf, _book);
- }
-
- /**
- * get whether gridlines are printed.
- *
- * @return true if printed
- */
-
- public boolean isGridsPrinted() {
- return _sheet.isGridsPrinted();
- }
-
- /**
- * set whether gridlines printed.
- *
- * @param value false if not printed.
- */
-
- public void setGridsPrinted(boolean value) {
- _sheet.setGridsPrinted(value);
- }
-
- /**
- * @deprecated (Aug-2008) use <tt>CellRangeAddress</tt> instead of <tt>Region</tt>
- */
- public int addMergedRegion(org.apache.poi.ss.util.Region region) {
- return _sheet.addMergedRegion(region.getRowFrom(),
- region.getColumnFrom(),
- //(short) region.getRowTo(),
- region.getRowTo(),
- region.getColumnTo());
- }
-
- /**
- * adds a merged region of cells (hence those cells form one)
- *
- * @param region (rowfrom/colfrom-rowto/colto) to merge
- * @return index of this region
- */
- public int addMergedRegion(CellRangeAddress region) {
- region.validate(SpreadsheetVersion.EXCEL97);
-
- // throw IllegalStateException if the argument CellRangeAddress intersects with
- // a multi-cell array formula defined in this sheet
- validateArrayFormulas(region);
-
- return _sheet.addMergedRegion(region.getFirstRow(),
- region.getFirstColumn(),
- region.getLastRow(),
- region.getLastColumn());
- }
-
- private void validateArrayFormulas(CellRangeAddress region) {
- int firstRow = region.getFirstRow();
- int firstColumn = region.getFirstColumn();
- int lastRow = region.getLastRow();
- int lastColumn = region.getLastColumn();
- for (int rowIn = firstRow; rowIn <= lastRow; rowIn++) {
- for (int colIn = firstColumn; colIn <= lastColumn; colIn++) {
- HSSFRow row = getRow(rowIn);
- if (row == null) continue;
-
- HSSFCell cell = row.getCell(colIn);
- if (cell == null) continue;
-
- if (cell.isPartOfArrayFormulaGroup()) {
- CellRangeAddress arrayRange = cell.getArrayFormulaRange();
- if (arrayRange.getNumberOfCells() > 1 &&
- (arrayRange.isInRange(region.getFirstRow(), region.getFirstColumn()) ||
- arrayRange.isInRange(region.getFirstRow(), region.getFirstColumn()))) {
- String msg = "The range " + region.formatAsString() + " intersects with a multi-cell array formula. " +
- "You cannot merge cells of an array.";
- throw new IllegalStateException(msg);
- }
- }
- }
- }
-
- }
-
- /**
- * Control if Excel should be asked to recalculate all formulas on this sheet
- * when the workbook is opened.
- * <p/>
- * <p>
- * Calculating the formula values with {@link org.apache.poi.ss.usermodel.FormulaEvaluator} is the
- * recommended solution, but this may be used for certain cases where
- * evaluation in POI is not possible.
- * </p>
- * <p/>
- * <p>
- * It is recommended to force recalcuation of formulas on workbook level using
- * {@link org.apache.poi.ss.usermodel.Workbook#setForceFormulaRecalculation(boolean)}
- * to ensure that all cross-worksheet formuals and external dependencies are updated.
- * </p>
- *
- * @param value true if the application will perform a full recalculation of
- * this worksheet values when the workbook is opened
- * @see org.apache.poi.ss.usermodel.Workbook#setForceFormulaRecalculation(boolean)
- */
- public void setForceFormulaRecalculation(boolean value) {
- _sheet.setUncalced(value);
- }
-
- /**
- * Whether a record must be inserted or not at generation to indicate that
- * formula must be recalculated when workbook is opened.
- *
- * @return true if an uncalced record must be inserted or not at generation
- */
- public boolean getForceFormulaRecalculation() {
- return _sheet.getUncalced();
- }
-
-
- /**
- * determines whether the output is vertically centered on the page.
- *
- * @param value true to vertically center, false otherwise.
- */
-
- public void setVerticallyCenter(boolean value) {
- _sheet.getPageSettings().getVCenter().setVCenter(value);
- }
-
- /**
- * TODO: Boolean not needed, remove after next release
- *
- * @deprecated (Mar-2008) use getVerticallyCenter() instead
- */
- public boolean getVerticallyCenter(boolean value) {
- return getVerticallyCenter();
- }
-
- /**
- * Determine whether printed output for this sheet will be vertically centered.
- */
- public boolean getVerticallyCenter() {
- return _sheet.getPageSettings().getVCenter().getVCenter();
- }
-
- /**
- * determines whether the output is horizontally centered on the page.
- *
- * @param value true to horizontally center, false otherwise.
- */
-
- public void setHorizontallyCenter(boolean value) {
- _sheet.getPageSettings().getHCenter().setHCenter(value);
- }
-
- /**
- * Determine whether printed output for this sheet will be horizontally centered.
- */
-
- public boolean getHorizontallyCenter() {
-
- return _sheet.getPageSettings().getHCenter().getHCenter();
- }
-
- /**
- * Sets whether the worksheet is displayed from right to left instead of from left to right.
- *
- * @param value true for right to left, false otherwise.
- */
- public void setRightToLeft(boolean value) {
- _sheet.getWindowTwo().setArabic(value);
- }
-
- /**
- * Whether the text is displayed in right-to-left mode in the window
- *
- * @return whether the text is displayed in right-to-left mode in the window
- */
- public boolean isRightToLeft() {
- return _sheet.getWindowTwo().getArabic();
- }
-
- /**
- * removes a merged region of cells (hence letting them free)
- *
- * @param index of the region to unmerge
- */
-
- public void removeMergedRegion(int index) {
- _sheet.removeMergedRegion(index);
- }
-
- /**
- * returns the number of merged regions
- *
- * @return number of merged regions
- */
-
- public int getNumMergedRegions() {
- return _sheet.getNumMergedRegions();
- }
-
- /**
- * @deprecated (Aug-2008) use {@link HSSFSheet#getMergedRegion(int)}
- */
- public org.apache.poi.hssf.util.Region getMergedRegionAt(int index) {
- CellRangeAddress cra = getMergedRegion(index);
-
- return new org.apache.poi.hssf.util.Region(cra.getFirstRow(), (short) cra.getFirstColumn(),
- cra.getLastRow(), (short) cra.getLastColumn());
- }
-
- /**
- * @return the merged region at the specified index
- */
- public CellRangeAddress getMergedRegion(int index) {
- return _sheet.getMergedRegionAt(index);
- }
-
- /**
- * @return an iterator of the PHYSICAL rows. Meaning the 3rd element may not
- * be the third row if say for instance the second row is undefined.
- * Call getRowNum() on each row if you care which one it is.
- */
- public Iterator<Row> rowIterator() {
- @SuppressWarnings("unchecked") // can this clumsy generic syntax be improved?
- Iterator<Row> result = (Iterator<Row>) (Iterator<? extends Row>) _rows.values().iterator();
- return result;
- }
-
- /**
- * Alias for {@link #rowIterator()} to allow
- * foreach loops
- */
- public Iterator<Row> iterator() {
- return rowIterator();
- }
-
-
- /**
- * used internally in the API to get the low level Sheet record represented by this
- * Object.
- *
- * @return Sheet - low level representation of this HSSFSheet.
- */
- InternalSheet getSheet() {
- return _sheet;
- }
-
- /**
- * whether alternate expression evaluation is on
- *
- * @param b alternative expression evaluation or not
- */
- public void setAlternativeExpression(boolean b) {
- WSBoolRecord record =
- (WSBoolRecord) _sheet.findFirstRecordBySid(WSBoolRecord.sid);
-
- record.setAlternateExpression(b);
- }
-
- /**
- * whether alternative formula entry is on
- *
- * @param b alternative formulas or not
- */
- public void setAlternativeFormula(boolean b) {
- WSBoolRecord record =
- (WSBoolRecord) _sheet.findFirstRecordBySid(WSBoolRecord.sid);
-
- record.setAlternateFormula(b);
- }
-
- /**
- * show automatic page breaks or not
- *
- * @param b whether to show auto page breaks
- */
- public void setAutobreaks(boolean b) {
- WSBoolRecord record =
- (WSBoolRecord) _sheet.findFirstRecordBySid(WSBoolRecord.sid);
-
- record.setAutobreaks(b);
- }
-
- /**
- * set whether sheet is a dialog sheet or not
- *
- * @param b isDialog or not
- */
- public void setDialog(boolean b) {
- WSBoolRecord record =
- (WSBoolRecord) _sheet.findFirstRecordBySid(WSBoolRecord.sid);
-
- record.setDialog(b);
- }
-
- /**
- * set whether to display the guts or not
- *
- * @param b guts or no guts (or glory)
- */
- public void setDisplayGuts(boolean b) {
- WSBoolRecord record =
- (WSBoolRecord) _sheet.findFirstRecordBySid(WSBoolRecord.sid);
-
- record.setDisplayGuts(b);
- }
-
- /**
- * fit to page option is on
- *
- * @param b fit or not
- */
- public void setFitToPage(boolean b) {
- WSBoolRecord record =
- (WSBoolRecord) _sheet.findFirstRecordBySid(WSBoolRecord.sid);
-
- record.setFitToPage(b);
- }
-
- /**
- * set if row summaries appear below detail in the outline
- *
- * @param b below or not
- */
- public void setRowSumsBelow(boolean b) {
- WSBoolRecord record =
- (WSBoolRecord) _sheet.findFirstRecordBySid(WSBoolRecord.sid);
-
- record.setRowSumsBelow(b);
- //setAlternateExpression must be set in conjuction with setRowSumsBelow
- record.setAlternateExpression(b);
- }
-
- /**
- * set if col summaries appear right of the detail in the outline
- *
- * @param b right or not
- */
- public void setRowSumsRight(boolean b) {
- WSBoolRecord record =
- (WSBoolRecord) _sheet.findFirstRecordBySid(WSBoolRecord.sid);
-
- record.setRowSumsRight(b);
- }
-
- /**
- * whether alternate expression evaluation is on
- *
- * @return alternative expression evaluation or not
- */
- public boolean getAlternateExpression() {
- return ((WSBoolRecord) _sheet.findFirstRecordBySid(WSBoolRecord.sid))
- .getAlternateExpression();
- }
-
- /**
- * whether alternative formula entry is on
- *
- * @return alternative formulas or not
- */
- public boolean getAlternateFormula() {
- return ((WSBoolRecord) _sheet.findFirstRecordBySid(WSBoolRecord.sid))
- .getAlternateFormula();
- }
-
- /**
- * show automatic page breaks or not
- *
- * @return whether to show auto page breaks
- */
- public boolean getAutobreaks() {
- return ((WSBoolRecord) _sheet.findFirstRecordBySid(WSBoolRecord.sid))
- .getAutobreaks();
- }
-
- /**
- * get whether sheet is a dialog sheet or not
- *
- * @return isDialog or not
- */
- public boolean getDialog() {
- return ((WSBoolRecord) _sheet.findFirstRecordBySid(WSBoolRecord.sid))
- .getDialog();
- }
-
- /**
- * get whether to display the guts or not
- *
- * @return guts or no guts (or glory)
- */
- public boolean getDisplayGuts() {
- return ((WSBoolRecord) _sheet.findFirstRecordBySid(WSBoolRecord.sid))
- .getDisplayGuts();
- }
-
-
- /**
- * Gets the flag indicating whether the window should show 0 (zero) in cells containing zero value.
- * When false, cells with zero value appear blank instead of showing the number zero.
- * <p>
- * In Excel 2003 this option can be changed in the Options dialog on the View tab.
- * </p>
- *
- * @return whether all zero values on the worksheet are displayed
- */
- public boolean isDisplayZeros() {
- return _sheet.getWindowTwo().getDisplayZeros();
- }
-
- /**
- * Set whether the window should show 0 (zero) in cells containing zero value.
- * When false, cells with zero value appear blank instead of showing the number zero.
- * <p>
- * In Excel 2003 this option can be set in the Options dialog on the View tab.
- * </p>
- *
- * @param value whether to display or hide all zero values on the worksheet
- */
- public void setDisplayZeros(boolean value) {
- _sheet.getWindowTwo().setDisplayZeros(value);
- }
-
- /**
- * fit to page option is on
- *
- * @return fit or not
- */
- public boolean getFitToPage() {
- return ((WSBoolRecord) _sheet.findFirstRecordBySid(WSBoolRecord.sid))
- .getFitToPage();
- }
-
- /**
- * get if row summaries appear below detail in the outline
- *
- * @return below or not
- */
- public boolean getRowSumsBelow() {
- return ((WSBoolRecord) _sheet.findFirstRecordBySid(WSBoolRecord.sid))
- .getRowSumsBelow();
- }
-
- /**
- * get if col summaries appear right of the detail in the outline
- *
- * @return right or not
- */
- public boolean getRowSumsRight() {
- return ((WSBoolRecord) _sheet.findFirstRecordBySid(WSBoolRecord.sid))
- .getRowSumsRight();
- }
-
- /**
- * Returns whether gridlines are printed.
- *
- * @return Gridlines are printed
- */
- public boolean isPrintGridlines() {
- return getSheet().getPrintGridlines().getPrintGridlines();
- }
-
- /**
- * Turns on or off the printing of gridlines.
- *
- * @param newPrintGridlines boolean to turn on or off the printing of
- * gridlines
- */
- public void setPrintGridlines(boolean newPrintGridlines) {
- getSheet().getPrintGridlines().setPrintGridlines(newPrintGridlines);
- }
-
- /**
- * Gets the print setup object.
- *
- * @return The user model for the print setup object.
- */
- public HSSFPrintSetup getPrintSetup() {
- return new HSSFPrintSetup(_sheet.getPageSettings().getPrintSetup());
- }
-
- public HSSFHeader getHeader() {
- return new HSSFHeader(_sheet.getPageSettings());
- }
-
- public HSSFFooter getFooter() {
- return new HSSFFooter(_sheet.getPageSettings());
- }
-
- /**
- * Note - this is not the same as whether the sheet is focused (isActive)
- *
- * @return <code>true</code> if this sheet is currently selected
- */
- public boolean isSelected() {
- return getSheet().getWindowTwo().getSelected();
- }
-
- /**
- * Sets whether sheet is selected.
- *
- * @param sel Whether to select the sheet or deselect the sheet.
- */
- public void setSelected(boolean sel) {
- getSheet().getWindowTwo().setSelected(sel);
- }
-
- /**
- * @return <code>true</code> if this sheet is currently focused
- */
- public boolean isActive() {
- return getSheet().getWindowTwo().isActive();
- }
-
- /**
- * Sets whether sheet is selected.
- *
- * @param sel Whether to select the sheet or deselect the sheet.
- */
- public void setActive(boolean sel) {
- getSheet().getWindowTwo().setActive(sel);
- }
-
- /**
- * Gets the size of the margin in inches.
- *
- * @param margin which margin to get
- * @return the size of the margin
- */
- public double getMargin(short margin) {
- switch (margin) {
- case FooterMargin:
- return _sheet.getPageSettings().getPrintSetup().getFooterMargin();
- case HeaderMargin:
- return _sheet.getPageSettings().getPrintSetup().getHeaderMargin();
- default:
- return _sheet.getPageSettings().getMargin(margin);
- }
- }
-
- /**
- * Sets the size of the margin in inches.
- *
- * @param margin which margin to get
- * @param size the size of the margin
- */
- public void setMargin(short margin, double size) {
- switch (margin) {
- case FooterMargin:
- _sheet.getPageSettings().getPrintSetup().setFooterMargin(size);
- break;
- case HeaderMargin:
- _sheet.getPageSettings().getPrintSetup().setHeaderMargin(size);
- break;
- default:
- _sheet.getPageSettings().setMargin(margin, size);
- }
- }
-
- private WorksheetProtectionBlock getProtectionBlock() {
- return _sheet.getProtectionBlock();
- }
-
- /**
- * Answer whether protection is enabled or disabled
- *
- * @return true => protection enabled; false => protection disabled
- */
- public boolean getProtect() {
- return getProtectionBlock().isSheetProtected();
- }
-
- /**
- * @return hashed password
- */
- public short getPassword() {
- return (short) getProtectionBlock().getPasswordHash();
- }
-
- /**
- * Answer whether object protection is enabled or disabled
- *
- * @return true => protection enabled; false => protection disabled
- */
- public boolean getObjectProtect() {
- return getProtectionBlock().isObjectProtected();
- }
-
- /**
- * Answer whether scenario protection is enabled or disabled
- *
- * @return true => protection enabled; false => protection disabled
- */
- public boolean getScenarioProtect() {
- return getProtectionBlock().isScenarioProtected();
- }
-
- /**
- * Sets the protection enabled as well as the password
- *
- * @param password to set for protection. Pass <code>null</code> to remove protection
- */
- public void protectSheet(String password) {
- getProtectionBlock().protectSheet(password, true, true); //protect objs&scenarios(normal)
- }
-
- /**
- * Sets the zoom magnification for the sheet. The zoom is expressed as a
- * fraction. For example to express a zoom of 75% use 3 for the numerator
- * and 4 for the denominator.
- *
- * @param numerator The numerator for the zoom magnification.
- * @param denominator The denominator for the zoom magnification.
- */
- public void setZoom(int numerator, int denominator) {
- if (numerator < 1 || numerator > 65535)
- throw new IllegalArgumentException("Numerator must be greater than 0 and less than 65536");
- if (denominator < 1 || denominator > 65535)
- throw new IllegalArgumentException("Denominator must be greater than 0 and less than 65536");
-
- SCLRecord sclRecord = new SCLRecord();
- sclRecord.setNumerator((short) numerator);
- sclRecord.setDenominator((short) denominator);
- getSheet().setSCLRecord(sclRecord);
- }
-
- /**
- * The top row in the visible view when the sheet is
- * first viewed after opening it in a viewer
- *
- * @return short indicating the rownum (0 based) of the top row
- */
- public short getTopRow() {
- return _sheet.getTopRow();
- }
-
- /**
- * The left col in the visible view when the sheet is
- * first viewed after opening it in a viewer
- *
- * @return short indicating the rownum (0 based) of the top row
- */
- public short getLeftCol() {
- return _sheet.getLeftCol();
- }
-
- /**
- * Sets desktop window pane display area, when the
- * file is first opened in a viewer.
- *
- * @param toprow the top row to show in desktop window pane
- * @param leftcol the left column to show in desktop window pane
- */
- public void showInPane(int toprow, int leftcol) {
- int maxrow = SpreadsheetVersion.EXCEL97.getLastRowIndex();
- if (toprow > maxrow) throw new IllegalArgumentException("Maximum row number is " + maxrow);
-
- showInPane((short)toprow, (short)leftcol);
- }
- /**
- * Sets desktop window pane display area, when the
- * file is first opened in a viewer.
- *
- * @param toprow the top row to show in desktop window pane
- * @param leftcol the left column to show in desktop window pane
- */
- public void showInPane(short toprow, short leftcol) {
- _sheet.setTopRow(toprow);
- _sheet.setLeftCol(leftcol);
- }
-
- /**
- * Shifts the merged regions left or right depending on mode
- * <p/>
- * TODO: MODE , this is only row specific
- *
- * @param startRow
- * @param endRow
- * @param n
- * @param isRow
- */
- protected void shiftMerged(int startRow, int endRow, int n, boolean isRow) {
- List<CellRangeAddress> shiftedRegions = new ArrayList<CellRangeAddress>();
- //move merged regions completely if they fall within the new region boundaries when they are shifted
- for (int i = 0; i < getNumMergedRegions(); i++) {
- CellRangeAddress merged = getMergedRegion(i);
-
- boolean inStart = (merged.getFirstRow() >= startRow || merged.getLastRow() >= startRow);
- boolean inEnd = (merged.getFirstRow() <= endRow || merged.getLastRow() <= endRow);
-
- //don't check if it's not within the shifted area
- if (!inStart || !inEnd) {
- continue;
- }
-
- //only shift if the region outside the shifted rows is not merged too
- if (!SheetUtil.containsCell(merged, startRow - 1, 0) &&
- !SheetUtil.containsCell(merged, endRow + 1, 0)) {
- merged.setFirstRow(merged.getFirstRow() + n);
- merged.setLastRow(merged.getLastRow() + n);
- //have to remove/add it back
- shiftedRegions.add(merged);
- removeMergedRegion(i);
- i = i - 1; // we have to back up now since we removed one
- }
- }
-
- //read so it doesn't get shifted again
- Iterator<CellRangeAddress> iterator = shiftedRegions.iterator();
- while (iterator.hasNext()) {
- CellRangeAddress region = iterator.next();
-
- this.addMergedRegion(region);
- }
- }
-
- /**
- * Shifts rows between startRow and endRow n number of rows.
- * If you use a negative number, it will shift rows up.
- * Code ensures that rows don't wrap around.
- * <p/>
- * Calls shiftRows(startRow, endRow, n, false, false);
- * <p/>
- * <p/>
- * Additionally shifts merged regions that are completely defined in these
- * rows (ie. merged 2 cells on a row to be shifted).
- *
- * @param startRow the row to start shifting
- * @param endRow the row to end shifting
- * @param n the number of rows to shift
- */
- public void shiftRows(int startRow, int endRow, int n) {
- shiftRows(startRow, endRow, n, false, false);
- }
-
- /**
- * Shifts rows between startRow and endRow n number of rows.
- * If you use a negative number, it will shift rows up.
- * Code ensures that rows don't wrap around
- * <p/>
- * <p/>
- * Additionally shifts merged regions that are completely defined in these
- * rows (ie. merged 2 cells on a row to be shifted).
- * <p/>
- * TODO Might want to add bounds checking here
- *
- * @param startRow the row to start shifting
- * @param endRow the row to end shifting
- * @param n the number of rows to shift
- * @param copyRowHeight whether to copy the row height during the shift
- * @param resetOriginalRowHeight whether to set the original row's height to the default
- */
- public void shiftRows(int startRow, int endRow, int n, boolean copyRowHeight, boolean resetOriginalRowHeight) {
- shiftRows(startRow, endRow, n, copyRowHeight, resetOriginalRowHeight, true);
- }
-
- /**
- * Shifts rows between startRow and endRow n number of rows.
- * If you use a negative number, it will shift rows up.
- * Code ensures that rows don't wrap around
- * <p/>
- * <p/>
- * Additionally shifts merged regions that are completely defined in these
- * rows (ie. merged 2 cells on a row to be shifted).
- * <p/>
- * TODO Might want to add bounds checking here
- *
- * @param startRow the row to start shifting
- * @param endRow the row to end shifting
- * @param n the number of rows to shift
- * @param copyRowHeight whether to copy the row height during the shift
- * @param resetOriginalRowHeight whether to set the original row's height to the default
- * @param moveComments whether to move comments at the same time as the cells they are attached to
- */
- public void shiftRows(int startRow, int endRow, int n,
- boolean copyRowHeight, boolean resetOriginalRowHeight, boolean moveComments) {
- int s, inc;
- if (n < 0) {
- s = startRow;
- inc = 1;
- } else if (n > 0) {
- s = endRow;
- inc = -1;
- } else {
- // Nothing to do
- return;
- }
-
- NoteRecord[] noteRecs;
- if (moveComments) {
- noteRecs = _sheet.getNoteRecords();
- } else {
- noteRecs = NoteRecord.EMPTY_ARRAY;
- }
-
- shiftMerged(startRow, endRow, n, true);
- _sheet.getPageSettings().shiftRowBreaks(startRow, endRow, n);
-
- for (int rowNum = s; rowNum >= startRow && rowNum <= endRow && rowNum >= 0 && rowNum < 65536; rowNum += inc) {
- HSSFRow row = getRow(rowNum);
- // notify all cells in this row that we are going to shift them,
- // it can throw IllegalStateException if the operation is not allowed, for example,
- // if the row contains cells included in a multi-cell array formula
- if (row != null) notifyRowShifting(row);
-
- HSSFRow row2Replace = getRow(rowNum + n);
- if (row2Replace == null)
- row2Replace = createRow(rowNum + n);
-
-
- // Remove all the old cells from the row we'll
- // be writing too, before we start overwriting
- // any cells. This avoids issues with cells
- // changing type, and records not being correctly
- // overwritten
- row2Replace.removeAllCells();
-
- // If this row doesn't exist, nothing needs to
- // be done for the now empty destination row
- if (row == null) continue; // Nothing to do for this row
-
- // Fix up row heights if required
- if (copyRowHeight) {
- row2Replace.setHeight(row.getHeight());
- }
- if (resetOriginalRowHeight) {
- row.setHeight((short) 0xff);
- }
-
- // Copy each cell from the source row to
- // the destination row
- for (Iterator<Cell> cells = row.cellIterator(); cells.hasNext(); ) {
- HSSFCell cell = (HSSFCell) cells.next();
- row.removeCell(cell);
- CellValueRecordInterface cellRecord = cell.getCellValueRecord();
- cellRecord.setRow(rowNum + n);
- row2Replace.createCellFromRecord(cellRecord);
- _sheet.addValueRecord(rowNum + n, cellRecord);
-
- HSSFHyperlink link = cell.getHyperlink();
- if (link != null) {
- link.setFirstRow(link.getFirstRow() + n);
- link.setLastRow(link.getLastRow() + n);
- }
- }
- // Now zap all the cells in the source row
- row.removeAllCells();
-
- // Move comments from the source row to the
- // destination row. Note that comments can
- // exist for cells which are null
- if (moveComments) {
- // This code would get simpler if NoteRecords could be organised by HSSFRow.
- HSSFPatriarch patriarch = createDrawingPatriarch();
- for (int i = patriarch.getChildren().size() - 1; i >= 0; i--) {
- HSSFShape shape = patriarch.getChildren().get(i);
- if (!(shape instanceof HSSFComment)) {
- continue;
- }
- HSSFComment comment = (HSSFComment) shape;
- if (comment.getRow() != rowNum) {
- continue;
- }
- comment.setRow(rowNum + n);
- }
- }
- }
-
- // Re-compute the first and last rows of the sheet as needed
- if (n > 0) {
- // Rows are moving down
- if (startRow == _firstrow) {
- // Need to walk forward to find the first non-blank row
- _firstrow = Math.max(startRow + n, 0);
- for (int i = startRow + 1; i < startRow + n; i++) {
- if (getRow(i) != null) {
- _firstrow = i;
- break;
- }
- }
- }
- if (endRow + n > _lastrow) {
- _lastrow = Math.min(endRow + n, SpreadsheetVersion.EXCEL97.getLastRowIndex());
- }
- } else {
- // Rows are moving up
- if (startRow + n < _firstrow) {
- _firstrow = Math.max(startRow + n, 0);
- }
- if (endRow == _lastrow) {
- // Need to walk backward to find the last non-blank row
- _lastrow = Math.min(endRow + n, SpreadsheetVersion.EXCEL97.getLastRowIndex());
- for (int i = endRow - 1; i > endRow + n; i++) {
- if (getRow(i) != null) {
- _lastrow = i;
- break;
- }
- }
- }
- }
-
- // Update any formulas on this sheet that point to
- // rows which have been moved
- int sheetIndex = _workbook.getSheetIndex(this);
- String sheetName = _workbook.getSheetName(sheetIndex);
- short externSheetIndex = _book.checkExternSheet(sheetIndex);
- FormulaShifter shifter = FormulaShifter.createForRowShift(
- externSheetIndex, sheetName, startRow, endRow, n);
- _sheet.updateFormulasAfterCellShift(shifter, externSheetIndex);
-
- int nSheets = _workbook.getNumberOfSheets();
- for (int i = 0; i < nSheets; i++) {
- InternalSheet otherSheet = _workbook.getSheetAt(i).getSheet();
- if (otherSheet == this._sheet) {
- continue;
- }
- short otherExtSheetIx = _book.checkExternSheet(i);
- otherSheet.updateFormulasAfterCellShift(shifter, otherExtSheetIx);
- }
- _workbook.getWorkbook().updateNamesAfterCellShift(shifter);
- }
-
- protected void insertChartRecords(List<Record> records) {
- int window2Loc = _sheet.findFirstRecordLocBySid(WindowTwoRecord.sid);
- _sheet.getRecords().addAll(window2Loc, records);
- }
-
- private void notifyRowShifting(HSSFRow row) {
- String msg = "Row[rownum=" + row.getRowNum() + "] contains cell(s) included in a multi-cell array formula. " +
- "You cannot change part of an array.";
- for (Cell cell : row) {
- HSSFCell hcell = (HSSFCell) cell;
- if (hcell.isPartOfArrayFormulaGroup()) {
- hcell.notifyArrayFormulaChanging(msg);
- }
- }
- }
-
- /**
- * Creates a split (freezepane). Any existing freezepane or split pane is overwritten.
- * <p/>
- * <p>
- * If both colSplit and rowSplit are zero then the existing freeze pane is removed
- * </p>
- *
- * @param colSplit Horizonatal position of split.
- * @param rowSplit Vertical position of split.
- * @param leftmostColumn Left column visible in right pane.
- * @param topRow Top row visible in bottom pane
- */
- public void createFreezePane(int colSplit, int rowSplit, int leftmostColumn, int topRow) {
- validateColumn(colSplit);
- validateRow(rowSplit);
- if (leftmostColumn < colSplit)
- throw new IllegalArgumentException("leftmostColumn parameter must not be less than colSplit parameter");
- if (topRow < rowSplit)
- throw new IllegalArgumentException("topRow parameter must not be less than leftmostColumn parameter");
- getSheet().createFreezePane(colSplit, rowSplit, topRow, leftmostColumn);
- }
-
- /**
- * Creates a split (freezepane). Any existing freezepane or split pane is overwritten.
- * <p/>
- * <p>
- * If both colSplit and rowSplit are zero then the existing freeze pane is removed
- * </p>
- *
- * @param colSplit Horizonatal position of split.
- * @param rowSplit Vertical position of split.
- */
- public void createFreezePane(int colSplit, int rowSplit) {
- createFreezePane(colSplit, rowSplit, colSplit, rowSplit);
- }
-
- /**
- * Creates a split pane. Any existing freezepane or split pane is overwritten.
- *
- * @param xSplitPos Horizonatal position of split (in 1/20th of a point).
- * @param ySplitPos Vertical position of split (in 1/20th of a point).
- * @param topRow Top row visible in bottom pane
- * @param leftmostColumn Left column visible in right pane.
- * @param activePane Active pane. One of: PANE_LOWER_RIGHT,
- * PANE_UPPER_RIGHT, PANE_LOWER_LEFT, PANE_UPPER_LEFT
- * @see #PANE_LOWER_LEFT
- * @see #PANE_LOWER_RIGHT
- * @see #PANE_UPPER_LEFT
- * @see #PANE_UPPER_RIGHT
- */
- public void createSplitPane(int xSplitPos, int ySplitPos, int leftmostColumn, int topRow, int activePane) {
- getSheet().createSplitPane(xSplitPos, ySplitPos, topRow, leftmostColumn, activePane);
- }
-
- /**
- * Returns the information regarding the currently configured pane (split or freeze).
- *
- * @return null if no pane configured, or the pane information.
- */
- public PaneInformation getPaneInformation() {
- return getSheet().getPaneInformation();
- }
-
- /**
- * Sets whether the gridlines are shown in a viewer.
- *
- * @param show whether to show gridlines or not
- */
- public void setDisplayGridlines(boolean show) {
- _sheet.setDisplayGridlines(show);
- }
-
- /**
- * Returns if gridlines are displayed.
- *
- * @return whether gridlines are displayed
- */
- public boolean isDisplayGridlines() {
- return _sheet.isDisplayGridlines();
- }
-
- /**
- * Sets whether the formulas are shown in a viewer.
- *
- * @param show whether to show formulas or not
- */
- public void setDisplayFormulas(boolean show) {
- _sheet.setDisplayFormulas(show);
- }
-
- /**
- * Returns if formulas are displayed.
- *
- * @return whether formulas are displayed
- */
- public boolean isDisplayFormulas() {
- return _sheet.isDisplayFormulas();
- }
-
- /**
- * Sets whether the RowColHeadings are shown in a viewer.
- *
- * @param show whether to show RowColHeadings or not
- */
- public void setDisplayRowColHeadings(boolean show) {
- _sheet.setDisplayRowColHeadings(show);
- }
-
- /**
- * Returns if RowColHeadings are displayed.
- *
- * @return whether RowColHeadings are displayed
- */
- public boolean isDisplayRowColHeadings() {
- return _sheet.isDisplayRowColHeadings();
- }
-
- /**
- * Sets a page break at the indicated row
- * Breaks occur above the specified row and left of the specified column inclusive.
- * <p/>
- * For example, <code>sheet.setColumnBreak(2);</code> breaks the sheet into two parts
- * with columns A,B,C in the first and D,E,... in the second. Simuilar, <code>sheet.setRowBreak(2);</code>
- * breaks the sheet into two parts with first three rows (rownum=1...3) in the first part
- * and rows starting with rownum=4 in the second.
- *
- * @param row the row to break, inclusive
- */
- public void setRowBreak(int row) {
- validateRow(row);
- _sheet.getPageSettings().setRowBreak(row, (short) 0, (short) 255);
- }
-
- /**
- * @return <code>true</code> if there is a page break at the indicated row
- */
- public boolean isRowBroken(int row) {
- return _sheet.getPageSettings().isRowBroken(row);
- }
-
- /**
- * Removes the page break at the indicated row
- */
- public void removeRowBreak(int row) {
- _sheet.getPageSettings().removeRowBreak(row);
- }
-
- /**
- * @return row indexes of all the horizontal page breaks, never <code>null</code>
- */
- public int[] getRowBreaks() {
- //we can probably cache this information, but this should be a sparsely used function
- return _sheet.getPageSettings().getRowBreaks();
- }
-
- /**
- * @return column indexes of all the vertical page breaks, never <code>null</code>
- */
- public int[] getColumnBreaks() {
- //we can probably cache this information, but this should be a sparsely used function
- return _sheet.getPageSettings().getColumnBreaks();
- }
-
-
- /**
- * Sets a page break at the indicated column.
- * Breaks occur above the specified row and left of the specified column inclusive.
- * <p/>
- * For example, <code>sheet.setColumnBreak(2);</code> breaks the sheet into two parts
- * with columns A,B,C in the first and D,E,... in the second. Simuilar, <code>sheet.setRowBreak(2);</code>
- * breaks the sheet into two parts with first three rows (rownum=1...3) in the first part
- * and rows starting with rownum=4 in the second.
- *
- * @param column the column to break, inclusive
- */
- public void setColumnBreak(int column) {
- validateColumn((short) column);
- _sheet.getPageSettings().setColumnBreak((short) column, (short) 0, (short) SpreadsheetVersion.EXCEL97.getLastRowIndex());
- }
-
- /**
- * Determines if there is a page break at the indicated column
- *
- * @param column FIXME: Document this!
- * @return FIXME: Document this!
- */
- public boolean isColumnBroken(int column) {
- return _sheet.getPageSettings().isColumnBroken(column);
- }
-
- /**
- * Removes a page break at the indicated column
- *
- * @param column
- */
- public void removeColumnBreak(int column) {
- _sheet.getPageSettings().removeColumnBreak(column);
- }
-
- /**
- * Runs a bounds check for row numbers
- *
- * @param row
- */
- protected void validateRow(int row) {
- int maxrow = SpreadsheetVersion.EXCEL97.getLastRowIndex();
- if (row > maxrow) throw new IllegalArgumentException("Maximum row number is " + maxrow);
- if (row < 0) throw new IllegalArgumentException("Minumum row number is 0");
- }
-
- /**
- * Runs a bounds check for column numbers
- *
- * @param column
- */
- protected void validateColumn(int column) {
- int maxcol = SpreadsheetVersion.EXCEL97.getLastColumnIndex();
- if (column > maxcol) throw new IllegalArgumentException("Maximum column number is " + maxcol);
- if (column < 0) throw new IllegalArgumentException("Minimum column number is 0");
- }
-
- /**
- * Aggregates the drawing records and dumps the escher record hierarchy
- * to the standard output.
- */
- public void dumpDrawingRecords(boolean fat) {
- _sheet.aggregateDrawingRecords(_book.getDrawingManager(), false);
-
- EscherAggregate r = (EscherAggregate) getSheet().findFirstRecordBySid(EscherAggregate.sid);
- List<EscherRecord> escherRecords = r.getEscherRecords();
- PrintWriter w = new PrintWriter(System.out);
- for (Iterator<EscherRecord> iterator = escherRecords.iterator(); iterator.hasNext(); ) {
- EscherRecord escherRecord = iterator.next();
- if (fat) {
- System.out.println(escherRecord.toString());
- } else {
- escherRecord.display(w, 0);
- }
- }
- w.flush();
- }
-
- /**
- * Returns the agregate escher records for this sheet,
- * it there is one.
- */
- public EscherAggregate getDrawingEscherAggregate() {
- _book.findDrawingGroup();
-
- // If there's now no drawing manager, then there's
- // no drawing escher records on the workbook
- if (_book.getDrawingManager() == null) {
- return null;
- }
-
- int found = _sheet.aggregateDrawingRecords(
- _book.getDrawingManager(), false
- );
- if (found == -1) {
- // Workbook has drawing stuff, but this sheet doesn't
- return null;
- }
-
- // Grab our aggregate record, and wire it up
- EscherAggregate agg = (EscherAggregate) _sheet.findFirstRecordBySid(EscherAggregate.sid);
- return agg;
- }
-
- /**
- * This will hold any graphics or charts for the sheet.
- *
- * @return the top-level drawing patriarch, if there is one, else returns null
- */
- public HSSFPatriarch getDrawingPatriarch() {
- _patriarch = getPatriarch(false);
- return _patriarch;
- }
-
- /**
- * Creates the top-level drawing patriarch.
- * <p>This may then be used to add graphics or charts.</p>
- * <p>Note that this will normally have the effect of removing
- * any existing drawings on this sheet.</p>
- *
- * @return The new patriarch.
- */
- public HSSFPatriarch createDrawingPatriarch() {
- _patriarch = getPatriarch(true);
- return _patriarch;
- }
-
- private HSSFPatriarch getPatriarch(boolean createIfMissing) {
- HSSFPatriarch patriarch = null;
- if (_patriarch != null) {
- return _patriarch;
- }
- DrawingManager2 dm = _book.findDrawingGroup();
- if (null == dm) {
- if (!createIfMissing) {
- return null;
- } else {
- _book.createDrawingGroup();
- dm = _book.getDrawingManager();
- }
- }
- EscherAggregate agg = (EscherAggregate) _sheet.findFirstRecordBySid(EscherAggregate.sid);
- if (null == agg) {
- int pos = _sheet.aggregateDrawingRecords(dm, false);
- if (-1 == pos) {
- if (createIfMissing) {
- pos = _sheet.aggregateDrawingRecords(dm, true);
- agg = (EscherAggregate) _sheet.getRecords().get(pos);
- patriarch = new HSSFPatriarch(this, agg);
- patriarch.afterCreate();
- return patriarch;
- } else {
- return null;
- }
- }
- agg = (EscherAggregate) _sheet.getRecords().get(pos);
- }
- return new HSSFPatriarch(this, agg);
- }
-
- /**
- * @deprecated (Sep 2008) use {@link #setColumnGroupCollapsed(int, boolean)}
- */
- public void setColumnGroupCollapsed(short columnNumber, boolean collapsed) {
- setColumnGroupCollapsed(columnNumber & 0xFFFF, collapsed);
- }
-
- /**
- * @deprecated (Sep 2008) use {@link #groupColumn(int, int)}
- */
- public void groupColumn(short fromColumn, short toColumn) {
- groupColumn(fromColumn & 0xFFFF, toColumn & 0xFFFF);
- }
-
- /**
- * @deprecated (Sep 2008) use {@link #ungroupColumn(int, int)}
- */
- public void ungroupColumn(short fromColumn, short toColumn) {
- ungroupColumn(fromColumn & 0xFFFF, toColumn & 0xFFFF);
- }
-
- /**
- * Expands or collapses a column group.
- *
- * @param columnNumber One of the columns in the group.
- * @param collapsed true = collapse group, false = expand group.
- */
- public void setColumnGroupCollapsed(int columnNumber, boolean collapsed) {
- _sheet.setColumnGroupCollapsed(columnNumber, collapsed);
- }
-
- /**
- * Create an outline for the provided column range.
- *
- * @param fromColumn beginning of the column range.
- * @param toColumn end of the column range.
- */
- public void groupColumn(int fromColumn, int toColumn) {
- _sheet.groupColumnRange(fromColumn, toColumn, true);
- }
-
- public void ungroupColumn(int fromColumn, int toColumn) {
- _sheet.groupColumnRange(fromColumn, toColumn, false);
- }
-
- /**
- * Tie a range of cell together so that they can be collapsed or expanded
- *
- * @param fromRow start row (0-based)
- * @param toRow end row (0-based)
- */
- public void groupRow(int fromRow, int toRow) {
- _sheet.groupRowRange(fromRow, toRow, true);
- }
-
- public void ungroupRow(int fromRow, int toRow) {
- _sheet.groupRowRange(fromRow, toRow, false);
- }
-
- public void setRowGroupCollapsed(int rowIndex, boolean collapse) {
- if (collapse) {
- _sheet.getRowsAggregate().collapseRow(rowIndex);
- } else {
- _sheet.getRowsAggregate().expandRow(rowIndex);
- }
- }
-
- /**
- * Sets the default column style for a given column. POI will only apply this style to new cells added to the sheet.
- *
- * @param column the column index
- * @param style the style to set
- */
- public void setDefaultColumnStyle(int column, CellStyle style) {
- _sheet.setDefaultColumnStyle(column, ((HSSFCellStyle) style).getIndex());
- }
-
- /**
- * Adjusts the column width to fit the contents.
- * <p/>
- * This process can be relatively slow on large sheets, so this should
- * normally only be called once per column, at the end of your
- * processing.
- *
- * @param column the column index
- */
- public void autoSizeColumn(int column) {
- autoSizeColumn(column, false);
- }
-
- /**
- * Adjusts the column width to fit the contents.
- * <p/>
- * This process can be relatively slow on large sheets, so this should
- * normally only be called once per column, at the end of your
- * processing.
- * <p/>
- * You can specify whether the content of merged cells should be considered or ignored.
- * Default is to ignore merged cells.
- *
- * @param column the column index
- * @param useMergedCells whether to use the contents of merged cells when calculating the width of the column
- */
- public void autoSizeColumn(int column, boolean useMergedCells) {
- double width = SheetUtil.getColumnWidth(this, column, useMergedCells);
-
- if (width != -1) {
- width *= 256;
- int maxColumnWidth = 255 * 256; // The maximum column width for an individual cell is 255 characters
- if (width > maxColumnWidth) {
- width = maxColumnWidth;
- }
- setColumnWidth(column, (int) (width));
- }
-
- }
-
- /**
- * Returns cell comment for the specified row and column
- *
- * @return cell comment or <code>null</code> if not found
- */
- public HSSFComment getCellComment(int row, int column) {
- return findCellComment(row, column);
- }
-
- public HSSFSheetConditionalFormatting getSheetConditionalFormatting() {
- return new HSSFSheetConditionalFormatting(this);
- }
-
- /**
- * Returns the name of this sheet
- *
- * @return the name of this sheet
- */
- public String getSheetName() {
- HSSFWorkbook wb = getWorkbook();
- int idx = wb.getSheetIndex(this);
- return wb.getSheetName(idx);
- }
-
- /**
- * Also creates cells if they don't exist
- */
- private CellRange<HSSFCell> getCellRange(CellRangeAddress range) {
- int firstRow = range.getFirstRow();
- int firstColumn = range.getFirstColumn();
- int lastRow = range.getLastRow();
- int lastColumn = range.getLastColumn();
- int height = lastRow - firstRow + 1;
- int width = lastColumn - firstColumn + 1;
- List<HSSFCell> temp = new ArrayList<HSSFCell>(height * width);
- for (int rowIn = firstRow; rowIn <= lastRow; rowIn++) {
- for (int colIn = firstColumn; colIn <= lastColumn; colIn++) {
- HSSFRow row = getRow(rowIn);
- if (row == null) {
- row = createRow(rowIn);
- }
- HSSFCell cell = row.getCell(colIn);
- if (cell == null) {
- cell = row.createCell(colIn);
- }
- temp.add(cell);
- }
- }
- return SSCellRange.create(firstRow, firstColumn, height, width, temp, HSSFCell.class);
- }
-
- public CellRange<HSSFCell> setArrayFormula(String formula, CellRangeAddress range) {
- // make sure the formula parses OK first
- int sheetIndex = _workbook.getSheetIndex(this);
- Ptg[] ptgs = HSSFFormulaParser.parse(formula, _workbook, FormulaType.ARRAY, sheetIndex);
- CellRange<HSSFCell> cells = getCellRange(range);
-
- for (HSSFCell c : cells) {
- c.setCellArrayFormula(range);
- }
- HSSFCell mainArrayFormulaCell = cells.getTopLeftCell();
- FormulaRecordAggregate agg = (FormulaRecordAggregate) mainArrayFormulaCell.getCellValueRecord();
- agg.setArrayFormula(range, ptgs);
- return cells;
- }
-
-
- public CellRange<HSSFCell> removeArrayFormula(Cell cell) {
- if (cell.getSheet() != this) {
- throw new IllegalArgumentException("Specified cell does not belong to this sheet.");
- }
- CellValueRecordInterface rec = ((HSSFCell) cell).getCellValueRecord();
- if (!(rec instanceof FormulaRecordAggregate)) {
- String ref = new CellReference(cell).formatAsString();
- throw new IllegalArgumentException("Cell " + ref + " is not part of an array formula.");
- }
- FormulaRecordAggregate fra = (FormulaRecordAggregate) rec;
- CellRangeAddress range = fra.removeArrayFormula(cell.getRowIndex(), cell.getColumnIndex());
-
- CellRange<HSSFCell> result = getCellRange(range);
- // clear all cells in the range
- for (Cell c : result) {
- c.setCellType(Cell.CELL_TYPE_BLANK);
- }
- return result;
- }
-
- public DataValidationHelper getDataValidationHelper() {
- return new HSSFDataValidationHelper(this);
- }
-
- public HSSFAutoFilter setAutoFilter(CellRangeAddress range) {
- InternalWorkbook workbook = _workbook.getWorkbook();
- int sheetIndex = _workbook.getSheetIndex(this);
-
- NameRecord name = workbook.getSpecificBuiltinRecord(NameRecord.BUILTIN_FILTER_DB, sheetIndex + 1);
-
- if (name == null) {
- name = workbook.createBuiltInName(NameRecord.BUILTIN_FILTER_DB, sheetIndex + 1);
- }
-
- int firstRow = range.getFirstRow();
-
- // if row was not given when constructing the range...
- if(firstRow == -1) {
- firstRow = 0;
- }
-
- // The built-in name must consist of a single Area3d Ptg.
- Area3DPtg ptg = new Area3DPtg(firstRow, range.getLastRow(),
- range.getFirstColumn(), range.getLastColumn(),
- false, false, false, false, sheetIndex);
- name.setNameDefinition(new Ptg[]{ptg});
-
- AutoFilterInfoRecord r = new AutoFilterInfoRecord();
- // the number of columns that have AutoFilter enabled.
- int numcols = 1 + range.getLastColumn() - range.getFirstColumn();
- r.setNumEntries((short) numcols);
- int idx = _sheet.findFirstRecordLocBySid(DimensionsRecord.sid);
- _sheet.getRecords().add(idx, r);
-
- //create a combobox control for each column
- HSSFPatriarch p = createDrawingPatriarch();
- for (int col = range.getFirstColumn(); col <= range.getLastColumn(); col++) {
- p.createComboBox(new HSSFClientAnchor(0, 0, 0, 0,
- (short) col, firstRow, (short) (col + 1), firstRow + 1));
- }
-
- return new HSSFAutoFilter(this);
- }
-
- protected HSSFComment findCellComment(int row, int column) {
- HSSFPatriarch patriarch = getDrawingPatriarch();
- if (null == patriarch) {
- patriarch = createDrawingPatriarch();
- }
- return lookForComment(patriarch, row, column);
- }
-
- private HSSFComment lookForComment(HSSFShapeContainer container, int row, int column) {
- for (Object object : container.getChildren()) {
- HSSFShape shape = (HSSFShape) object;
- if (shape instanceof HSSFShapeGroup) {
- HSSFShape res = lookForComment((HSSFShapeContainer) shape, row, column);
- if (null != res) {
- return (HSSFComment) res;
- }
- continue;
- }
- if (shape instanceof HSSFComment) {
- HSSFComment comment = (HSSFComment) shape;
- if (comment.hasPosition() && comment.getColumn() == column && comment.getRow() == row) {
- return comment;
- }
- }
- }
- return null;
- }
-
-
- public CellRangeAddress getRepeatingRows() {
- return getRepeatingRowsOrColums(true);
- }
-
-
- public CellRangeAddress getRepeatingColumns() {
- return getRepeatingRowsOrColums(false);
- }
-
-
- public void setRepeatingRows(CellRangeAddress rowRangeRef) {
- CellRangeAddress columnRangeRef = getRepeatingColumns();
- setRepeatingRowsAndColumns(rowRangeRef, columnRangeRef);
- }
-
-
- public void setRepeatingColumns(CellRangeAddress columnRangeRef) {
- CellRangeAddress rowRangeRef = getRepeatingRows();
- setRepeatingRowsAndColumns(rowRangeRef, columnRangeRef);
- }
-
-
- private void setRepeatingRowsAndColumns(
- CellRangeAddress rowDef, CellRangeAddress colDef) {
- int sheetIndex = _workbook.getSheetIndex(this);
- int maxRowIndex = SpreadsheetVersion.EXCEL97.getLastRowIndex();
- int maxColIndex = SpreadsheetVersion.EXCEL97.getLastColumnIndex();
-
- int col1 = -1;
- int col2 = -1;
- int row1 = -1;
- int row2 = -1;
-
- if (rowDef != null) {
- row1 = rowDef.getFirstRow();
- row2 = rowDef.getLastRow();
- if ((row1 == -1 && row2 != -1) || (row1 > row2)
- || (row1 < 0 || row1 > maxRowIndex)
- || (row2 < 0 || row2 > maxRowIndex)) {
- throw new IllegalArgumentException("Invalid row range specification");
- }
- }
- if (colDef != null) {
- col1 = colDef.getFirstColumn();
- col2 = colDef.getLastColumn();
- if ((col1 == -1 && col2 != -1) || (col1 > col2)
- || (col1 < 0 || col1 > maxColIndex)
- || (col2 < 0 || col2 > maxColIndex)) {
- throw new IllegalArgumentException("Invalid column range specification");
- }
- }
-
- short externSheetIndex =
- _workbook.getWorkbook().checkExternSheet(sheetIndex);
-
- boolean setBoth = rowDef != null && colDef != null;
- boolean removeAll = rowDef == null && colDef == null;
-
- HSSFName name = _workbook.getBuiltInName(
- NameRecord.BUILTIN_PRINT_TITLE, sheetIndex);
- if (removeAll) {
- if (name != null) {
- _workbook.removeName(name);
- }
- return;
- }
- if (name == null) {
- name = _workbook.createBuiltInName(
- NameRecord.BUILTIN_PRINT_TITLE, sheetIndex);
- }
-
- List<Ptg> ptgList = new ArrayList<Ptg>();
- if (setBoth) {
- final int exprsSize = 2 * 11 + 1; // 2 * Area3DPtg.SIZE + UnionPtg.SIZE
- ptgList.add(new MemFuncPtg(exprsSize));
- }
- if (colDef != null) {
- Area3DPtg colArea = new Area3DPtg(0, maxRowIndex, col1, col2,
- false, false, false, false, externSheetIndex);
- ptgList.add(colArea);
- }
- if (rowDef != null) {
- Area3DPtg rowArea = new Area3DPtg(row1, row2, 0, maxColIndex,
- false, false, false, false, externSheetIndex);
- ptgList.add(rowArea);
- }
- if (setBoth) {
- ptgList.add(UnionPtg.instance);
- }
-
- Ptg[] ptgs = new Ptg[ptgList.size()];
- ptgList.toArray(ptgs);
- name.setNameDefinition(ptgs);
-
- HSSFPrintSetup printSetup = getPrintSetup();
- printSetup.setValidSettings(false);
- setActive(true);
- }
-
-
- private CellRangeAddress getRepeatingRowsOrColums(boolean rows) {
- NameRecord rec = getBuiltinNameRecord(NameRecord.BUILTIN_PRINT_TITLE);
- if (rec == null) {
- return null;
- }
-
- Ptg[] nameDefinition = rec.getNameDefinition();
- if (nameDefinition == null) {
- return null;
- }
-
- int maxRowIndex = SpreadsheetVersion.EXCEL97.getLastRowIndex();
- int maxColIndex = SpreadsheetVersion.EXCEL97.getLastColumnIndex();
-
- for (Ptg ptg : nameDefinition) {
-
- if (ptg instanceof Area3DPtg) {
- Area3DPtg areaPtg = (Area3DPtg) ptg;
-
- if (areaPtg.getFirstColumn() == 0
- && areaPtg.getLastColumn() == maxColIndex) {
- if (rows) {
- CellRangeAddress rowRange = new CellRangeAddress(
- areaPtg.getFirstRow(), areaPtg.getLastRow(), -1, -1);
- return rowRange;
- }
- } else if (areaPtg.getFirstRow() == 0
- && areaPtg.getLastRow() == maxRowIndex) {
- if (!rows) {
- CellRangeAddress columnRange = new CellRangeAddress(-1, -1,
- areaPtg.getFirstColumn(), areaPtg.getLastColumn());
- return columnRange;
- }
- }
-
- }
-
- }
-
- return null;
- }
-
-
- private NameRecord getBuiltinNameRecord(byte builtinCode) {
- int sheetIndex = _workbook.getSheetIndex(this);
- int recIndex =
- _workbook.findExistingBuiltinNameRecordIdx(sheetIndex, builtinCode);
- if (recIndex == -1) {
- return null;
- }
- return _workbook.getNameRecord(recIndex);
- }
-
-
- }
|