<li><link href="#Hyperlinks">Hyperlinks</link></li>
<li><link href="#Validation">Data Validation</link></li>
<li><link href="#Embedded">Embedded Objects</link></li>
+ <li><link href="#Autofilter">Autofilters</link></li>
</ul>
</section>
<section><title>Features</title>
}
</source>
</section>
+ <anchor id="Autofilter"/>
+ <p>(Since POI-3.7)</p>
+ <section><title>Autofilters</title>
+ <source>
+ Workbook wb = new HSSFWorkbook(); //or new XSSFWorkbook();
+ Sheet sheet = wb.createSheet();
+ sheet.setAutoFilter(CellRangeAddress.valueOf("C5:F200"));
+ </source>
+ </section>
</body>
</document>
</developers>
<changes>
-<!--
- <release version="3.7-beta2" date="2010-??-??">
+ <release version="3.7-beta3" date="2010-??-??">
+ <action dev="POI-DEVELOPERS" type="add">initial support for Excel autofilter</action>
</release>
--->
<release version="3.7-beta2" date="2010-08-09">
<action dev="POI-DEVELOPERS" type="add">47990 - Support for .msg attachments within a MAPIMessage .msg</action>
<action dev="POI-DEVELOPERS" type="fix">Improve handling and warnings when closing OPCPackage objects</action>
case AxisParentRecord.sid: return new AxisParentRecord(in);
case AxisRecord.sid: return new AxisRecord(in);
case AxisUsedRecord.sid: return new AxisUsedRecord(in);
+ case AutoFilterInfoRecord.sid: return new AutoFilterInfoRecord(in);
case BOFRecord.sid: return new BOFRecord(in);
case BackupRecord.sid: return new BackupRecord(in);
case BarRecord.sid: return new BarRecord(in);
case HSSFSimpleShape.OBJECT_TYPE_RECTANGLE:
shape = new SimpleFilledShape( simpleShape, shapeId );
break;
+ case HSSFSimpleShape.OBJECT_TYPE_COMBO_BOX:
+ shape = new ComboboxShape( simpleShape, shapeId );
+ break;
default:
throw new IllegalArgumentException("Do not know how to handle this type of shape");
}
--- /dev/null
+/* ====================================================================
+ 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.model;
+
+import org.apache.poi.ddf.*;
+import org.apache.poi.hssf.record.*;
+import org.apache.poi.hssf.usermodel.*;
+
+/**
+ * Represents a combobox shape.
+ *
+ * @author Yegor Kozlov
+ */
+public class ComboboxShape
+ extends AbstractShape {
+ private EscherContainerRecord spContainer;
+ private ObjRecord objRecord;
+
+ /**
+ * Creates the low evel records for a combobox.
+ *
+ * @param hssfShape The highlevel shape.
+ * @param shapeId The shape id to use for this shape.
+ */
+ ComboboxShape(HSSFSimpleShape hssfShape, int shapeId) {
+ spContainer = createSpContainer(hssfShape, shapeId);
+ objRecord = createObjRecord(hssfShape, shapeId);
+ }
+
+ /**
+ * Creates the low level OBJ record for this shape.
+ */
+ private ObjRecord createObjRecord(HSSFSimpleShape shape, int shapeId) {
+ ObjRecord obj = new ObjRecord();
+ CommonObjectDataSubRecord c = new CommonObjectDataSubRecord();
+ c.setObjectType(HSSFSimpleShape.OBJECT_TYPE_COMBO_BOX);
+ c.setObjectId(shapeId);
+ c.setLocked(true);
+ c.setPrintable(false);
+ c.setAutofill(true);
+ c.setAutoline(false);
+
+ LbsDataSubRecord l = LbsDataSubRecord.newAutoFilterInstance();
+
+ EndSubRecord e = new EndSubRecord();
+
+ obj.addSubRecord(c);
+ obj.addSubRecord(l);
+ obj.addSubRecord(e);
+
+ return obj;
+ }
+
+ /**
+ * Generates the escher shape records for this shape.
+ */
+ private EscherContainerRecord createSpContainer(HSSFSimpleShape shape, int shapeId) {
+ EscherContainerRecord spContainer = new EscherContainerRecord();
+ EscherSpRecord sp = new EscherSpRecord();
+ EscherOptRecord opt = new EscherOptRecord();
+ EscherClientDataRecord clientData = new EscherClientDataRecord();
+
+ spContainer.setRecordId(EscherContainerRecord.SP_CONTAINER);
+ spContainer.setOptions((short) 0x000F);
+ sp.setRecordId(EscherSpRecord.RECORD_ID);
+ sp.setOptions((short) ((EscherAggregate.ST_HOSTCONTROL << 4) | 0x2));
+
+ sp.setShapeId(shapeId);
+ sp.setFlags(EscherSpRecord.FLAG_HAVEANCHOR | EscherSpRecord.FLAG_HASSHAPETYPE);
+ opt.setRecordId(EscherOptRecord.RECORD_ID);
+ opt.addEscherProperty(new EscherBoolProperty(EscherProperties.PROTECTION__LOCKAGAINSTGROUPING, 17039620));
+ opt.addEscherProperty(new EscherBoolProperty(EscherProperties.TEXT__SIZE_TEXT_TO_FIT_SHAPE, 0x00080008));
+ opt.addEscherProperty(new EscherBoolProperty(EscherProperties.LINESTYLE__NOLINEDRAWDASH, 0x00080000));
+ opt.addEscherProperty(new EscherSimpleProperty(EscherProperties.GROUPSHAPE__PRINT, 0x00020000));
+
+ HSSFClientAnchor userAnchor = (HSSFClientAnchor) shape.getAnchor();
+ userAnchor.setAnchorType(1);
+ EscherRecord anchor = createAnchor(userAnchor);
+ clientData.setRecordId(EscherClientDataRecord.RECORD_ID);
+ clientData.setOptions((short) 0x0000);
+
+ spContainer.addChildRecord(sp);
+ spContainer.addChildRecord(opt);
+ spContainer.addChildRecord(anchor);
+ spContainer.addChildRecord(clientData);
+
+ return spContainer;
+ }
+
+ public EscherContainerRecord getSpContainer() {
+ return spContainer;
+ }
+
+ public ObjRecord getObjRecord() {
+ return objRecord;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+
+/* ====================================================================
+ 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.record;
+
+import org.apache.poi.util.LittleEndianOutput;
+
+/**
+ * The AutoFilterInfo record specifies the number of columns that have AutoFilter enabled
+ * and indicates the beginning of the collection of AutoFilter records.
+ *
+ * @author Yegor Kozlov
+ */
+
+public final class AutoFilterInfoRecord
+ extends StandardRecord
+{
+ public final static short sid = 0x9D;
+ /**
+ * Number of AutoFilter drop-down arrows on the sheet
+ */
+ private short _cEntries; // = 0;
+
+ public AutoFilterInfoRecord()
+ {
+ }
+
+ public AutoFilterInfoRecord(RecordInputStream in)
+ {
+ _cEntries = in.readShort();
+ }
+
+ /**
+ * set the number of AutoFilter drop-down arrows on the sheet
+ *
+ * @param num the number of AutoFilter drop-down arrows on the sheet
+ */
+
+ public void setNumEntries(short num)
+ {
+ _cEntries = num;
+ }
+
+ /**
+ * get the number of AutoFilter drop-down arrows on the sheet
+ *
+ * @return the number of AutoFilter drop-down arrows on the sheet
+ */
+
+ public short getNumEntries()
+ {
+ return _cEntries;
+ }
+
+ public String toString()
+ {
+ StringBuffer buffer = new StringBuffer();
+
+ buffer.append("[AUTOFILTERINFO]\n");
+ buffer.append(" .numEntries = ")
+ .append(_cEntries).append("\n");
+ buffer.append("[/AUTOFILTERINFO]\n");
+ return buffer.toString();
+ }
+
+ public void serialize(LittleEndianOutput out) {
+ out.writeShort(_cEntries);
+ }
+
+ protected int getDataSize() {
+ return 2;
+ }
+
+ public short getSid()
+ {
+ return sid;
+ }
+
+ @Override
+ public Object clone()
+ {
+ return cloneViaReserialise();
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/* ====================================================================
+ 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.record;
+
+import org.apache.poi.util.HexDump;
+import org.apache.poi.util.LittleEndianInput;
+import org.apache.poi.util.LittleEndianOutput;
+
+
+/**
+ * This structure appears as part of an Obj record that represents a checkbox or radio button.
+ *
+ * @author Yegor Kozlov
+ */
+public final class FtCblsSubRecord extends SubRecord {
+ public final static short sid = 0x0C;
+ private static final int ENCODED_SIZE = 20;
+
+ private byte[] reserved;
+
+ /**
+ * Construct a new <code>FtCblsSubRecord</code> and
+ * fill its data with the default values
+ */
+ public FtCblsSubRecord()
+ {
+ reserved = new byte[ENCODED_SIZE];
+ }
+
+ public FtCblsSubRecord(LittleEndianInput in, int size) {
+ if (size != ENCODED_SIZE) {
+ throw new RecordFormatException("Unexpected size (" + size + ")");
+ }
+ //just grab the raw data
+ byte[] buf = new byte[size];
+ in.readFully(buf);
+ reserved = buf;
+ }
+
+ /**
+ * Convert this record to string.
+ * Used by BiffViewer and other utilities.
+ */
+ public String toString()
+ {
+ StringBuffer buffer = new StringBuffer();
+
+ buffer.append("[FtCbls ]").append("\n");
+ buffer.append(" size = ").append(getDataSize()).append("\n");
+ buffer.append(" reserved = ").append(HexDump.toHex(reserved)).append("\n");
+ buffer.append("[/FtCbls ]").append("\n");
+ return buffer.toString();
+ }
+
+ /**
+ * Serialize the record data into the supplied array of bytes
+ *
+ * @param out the stream to serialize into
+ */
+ public void serialize(LittleEndianOutput out) {
+ out.writeShort(sid);
+ out.writeShort(reserved.length);
+ out.write(reserved);
+ }
+
+ protected int getDataSize() {
+ return reserved.length;
+ }
+
+ /**
+ * @return id of this record.
+ */
+ public short getSid()
+ {
+ return sid;
+ }
+
+ public Object clone() {
+ FtCblsSubRecord rec = new FtCblsSubRecord();
+ byte[] recdata = new byte[reserved.length];
+ System.arraycopy(reserved, 0, recdata, 0, recdata.length);
+ rec.reserved = recdata;
+ return rec;
+ }
+
+}
\ No newline at end of file
\r
}\r
\r
+ LbsDataSubRecord(){\r
+\r
+ }\r
+\r
+ /**\r
+ *\r
+ * @return a new instance of LbsDataSubRecord to construct auto-filters\r
+ * @see org.apache.poi.hssf.model.ComboboxShape#createObjRecord(org.apache.poi.hssf.usermodel.HSSFSimpleShape, int)\r
+ */\r
+ public static LbsDataSubRecord newAutoFilterInstance(){\r
+ LbsDataSubRecord lbs = new LbsDataSubRecord();\r
+ lbs._cbFContinued = 0x1FEE; //autofilters seem to alway have this magic number\r
+ lbs._iSel = 0x000;\r
+\r
+ lbs._flags = 0x0301;\r
+ lbs._dropData = new LbsDropData();\r
+ lbs._dropData._wStyle = LbsDropData.STYLE_COMBO_SIMPLE_DROPDOWN;\r
+\r
+ // the number of lines to be displayed in the dropdown\r
+ lbs._dropData._cLine = 8;\r
+ return lbs;\r
+ }\r
+\r
/**\r
* @return true as LbsDataSubRecord is always the last sub-record\r
*/\r
* This structure specifies properties of the dropdown list control\r
*/\r
public static class LbsDropData {\r
+ /**\r
+ * Combo dropdown control\r
+ */\r
+ public static int STYLE_COMBO_DROPDOWN = 0;\r
+ /**\r
+ * Combo Edit dropdown control\r
+ */\r
+ public static int STYLE_COMBO_EDIT_DROPDOWN = 1;\r
+ /**\r
+ * Simple dropdown control (just the dropdown button)\r
+ */\r
+ public static int STYLE_COMBO_SIMPLE_DROPDOWN = 2;\r
+\r
/**\r
* An unsigned integer that specifies the style of this dropdown. \r
*/\r
*/\r
private Byte _unused;\r
\r
+ public LbsDropData(){\r
+ _str = "";\r
+ _unused = 0;\r
+ }\r
+\r
public LbsDropData(LittleEndianInput in){\r
_wStyle = in.readUShort();\r
_cLine = in.readUShort();\r
}\r
}\r
\r
+ /**\r
+ * Set the style of this dropdown.\r
+ *\r
+ * Possible values:\r
+ * <p>\r
+ * 0 Combo dropdown control\r
+ * 1 Combo Edit dropdown control\r
+ * 2 Simple dropdown control (just the dropdown button)\r
+ *\r
+ */\r
+ public void setStyle(int style){\r
+ _wStyle = style;\r
+ }\r
+\r
+ /**\r
+ * Set the number of lines to be displayed in the dropdown.\r
+ */\r
+ public void setNumLines(int num){\r
+ _cLine = num;\r
+ }\r
+\r
public void serialize(LittleEndianOutput out) {\r
out.writeShort(_wStyle);\r
out.writeShort(_cLine);\r
@SuppressWarnings("unchecked")
private static final Class<? extends Record>[] recordClasses = new Class[] {
ArrayRecord.class,
- BackupRecord.class,
+ AutoFilterInfoRecord.class,
+ BackupRecord.class,
BlankRecord.class,
BOFRecord.class,
BookBoolRecord.class,
return new NoteStructureSubRecord(in, secondUShort);
case LbsDataSubRecord.sid:
return new LbsDataSubRecord(in, secondUShort, cmoOt);
+ case FtCblsSubRecord.sid:
+ return new FtCblsSubRecord(in, secondUShort);
}
return new UnknownSubRecord(in, sid, secondUShort);
}
case SORT_0090: return "SORT"; // Sorting Options
case 0x0094: return "LHRECORD"; // .WK? File Conversion Information
case STANDARDWIDTH_0099: return "STANDARDWIDTH"; //Standard Column Width
- case 0x009D: return "AUTOFILTERINFO"; // Drop-Down Arrow Count
case SCL_00A0: return "SCL"; // Window Zoom Magnification
case 0x00AE: return "SCENMAN"; // Scenario Output Data
case 0x101B:
case 0x101D:
case 0x101E:
+ case 0x101F:
case 0x1020:
case 0x1021:
case 0x1022:
--- /dev/null
+/* ====================================================================
+ 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 org.apache.poi.ss.usermodel.AutoFilter;
+
+/**
+ * Represents autofiltering for the specified worksheet.
+ *
+ * @author Yegor Kozlov
+ */
+public final class HSSFAutoFilter implements AutoFilter {
+ private HSSFSheet _sheet;
+
+ HSSFAutoFilter(HSSFSheet sheet){
+ _sheet = sheet;
+ }
+}
\ No newline at end of file
return shape;
}
+ /**
+ * YK: used to create autofilters
+ *
+ * @see org.apache.poi.hssf.usermodel.HSSFSheet#setAutoFilter(int, int, int, int)
+ */
+ HSSFSimpleShape createComboBox(HSSFAnchor anchor)
+ {
+ HSSFSimpleShape shape = new HSSFSimpleShape(null, anchor);
+ shape.setShapeType(HSSFSimpleShape.OBJECT_TYPE_COMBO_BOX);
+ shape.anchor = anchor;
+ _shapes.add(shape);
+ return shape;
+ }
+
public HSSFComment createCellComment(ClientAnchor anchor) {
return createComment((HSSFAnchor)anchor);
}
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.CellValueRecordInterface;
-import org.apache.poi.hssf.record.DVRecord;
-import org.apache.poi.hssf.record.EscherAggregate;
-import org.apache.poi.hssf.record.ExtendedFormatRecord;
-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.*;
import org.apache.poi.hssf.record.aggregates.DataValidityTable;
import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate;
import org.apache.poi.hssf.record.aggregates.WorksheetProtectionBlock;
import org.apache.poi.hssf.record.formula.FormulaShifter;
import org.apache.poi.hssf.record.formula.Ptg;
+import org.apache.poi.hssf.record.formula.Area3DPtg;
import org.apache.poi.hssf.util.PaneInformation;
import org.apache.poi.hssf.util.Region;
import org.apache.poi.ss.SpreadsheetVersion;
* @return The new patriarch.
*/
public HSSFPatriarch createDrawingPatriarch() {
- // Create the drawing group if it doesn't already exist.
- _book.createDrawingGroup();
-
- _sheet.aggregateDrawingRecords(_book.getDrawingManager(), true);
- EscherAggregate agg = (EscherAggregate) _sheet.findFirstRecordBySid(EscherAggregate.sid);
- _patriarch = new HSSFPatriarch(this, agg);
- agg.clear(); // Initially the behaviour will be to clear out any existing shapes in the sheet when
- // creating a new patriarch.
- agg.setPatriarch(_patriarch);
+ if(_patriarch == null){
+ // Create the drawing group if it doesn't already exist.
+ _book.createDrawingGroup();
+
+ _sheet.aggregateDrawingRecords(_book.getDrawingManager(), true);
+ EscherAggregate agg = (EscherAggregate) _sheet.findFirstRecordBySid(EscherAggregate.sid);
+ _patriarch = new HSSFPatriarch(this, agg);
+ agg.clear(); // Initially the behaviour will be to clear out any existing shapes in the sheet when
+ // creating a new patriarch.
+ agg.setPatriarch(_patriarch);
+ }
return _patriarch;
}
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);
+ }
+
+ // The built-in name must consist of a single Area3d Ptg.
+ Area3DPtg ptg = new Area3DPtg(range.getFirstRow(), 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, range.getFirstRow(), (short)(col+1), range.getFirstRow()+1));
+ }
+
+ return new HSSFAutoFilter(this);
+ }
+
}
// public final static short OBJECT_TYPE_SCROLL_BAR = 17;
// public final static short OBJECT_TYPE_LIST_BOX = 18;
// public final static short OBJECT_TYPE_GROUP_BOX = 19;
-// public final static short OBJECT_TYPE_COMBO_BOX = 20;
+ public final static short OBJECT_TYPE_COMBO_BOX = 20;
public final static short OBJECT_TYPE_COMMENT = 25;
// public final static short OBJECT_TYPE_MICROSOFT_OFFICE_DRAWING = 30;
--- /dev/null
+/* ====================================================================\r
+ Licensed to the Apache Software Foundation (ASF) under one or more\r
+ contributor license agreements. See the NOTICE file distributed with\r
+ this work for additional information regarding copyright ownership.\r
+ The ASF licenses this file to You under the Apache License, Version 2.0\r
+ (the "License"); you may not use this file except in compliance with\r
+ the License. You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+==================================================================== */\r
+package org.apache.poi.ss.usermodel;\r
+\r
+/**\r
+ * Represents autofiltering for the specified worksheet.\r
+ *\r
+ * <p>\r
+ * Filtering data is a quick and easy way to find and work with a subset of data in a range of cells or table.\r
+ * For example, you can filter to see only the values that you specify, filter to see the top or bottom values,\r
+ * or filter to quickly see duplicate values.\r
+ * </p>\r
+ *\r
+ * TODO YK: For now (Aug 2010) POI only supports setting a basic autofilter on a range of cells.\r
+ * In future, when we support more auto-filter functions like custom criteria, sort, etc. we will add\r
+ * corresponding methods to this interface.\r
+ */\r
+public interface AutoFilter {\r
+ /**\r
+ * Apply a custom filter\r
+ *\r
+ * <p>\r
+ * A custom AutoFilter specifies an operator and a value.\r
+ * There can be at most two customFilters specified, and in that case the parent element\r
+ * specifies whether the two conditions are joined by 'and' or 'or'. For any cells whose\r
+ * values do not meet the specified criteria, the corresponding rows shall be hidden from\r
+ * view when the filter is applied.\r
+ * </p>\r
+ *\r
+ * <p>\r
+ * Example:\r
+ * <blockquote><pre>\r
+ * AutoFilter filter = sheet.setAutoFilter(CellRangeAddress.valueOf("A1:F200"));\r
+ * filter.applyFilter(0, FilterOperator.GreaterThanOrEqual", "0.2");\r
+ * filter.applyFilter(1, FilterOperator.LessThanOrEqual"", "0.5");\r
+ * </pre></blockquote>\r
+ * </p>\r
+ *\r
+ * @param columnIndex 0-based column index\r
+ * @param operator the operator to apply\r
+ * @param criteria top or bottom value used in the filter criteria.\r
+ *\r
+ * TODO YK: think how to combine AutoFilter with with DataValidationConstraint, they are really close relatives\r
+ * void applyFilter(int columnIndex, FilterOperator operator, String criteria);\r
+ */\r
+\r
+\r
+ /**\r
+ * Apply a filter against a list of values\r
+ *\r
+ * <p>\r
+ * Example:\r
+ * <blockquote><pre>\r
+ * AutoFilter filter = sheet.setAutoFilter(CellRangeAddress.valueOf("A1:F200"));\r
+ * filter.applyFilter(0, "apache", "poi", "java", "api");\r
+ * </pre></blockquote>\r
+ * </p>\r
+ *\r
+ * @param columnIndex 0-based column index\r
+ * @param values the filter values\r
+ *\r
+ * void applyFilter(int columnIndex, String ... values);\r
+ */\r
+ \r
+}\r
* @param dataValidation The Data validation object settings
*/
public void addValidationData(DataValidation dataValidation);
+
+ /**
+ * Enable filtering for a range of cells
+ *
+ * @param range the range of cells to filter
+ */
+ AutoFilter setAutoFilter(CellRangeAddress range);
+
}
--- /dev/null
+/* ====================================================================
+ 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.xssf.usermodel;
+import org.apache.poi.ss.usermodel.AutoFilter;
+
+/**
+ * Represents autofiltering for the specified worksheet.
+ *
+ * @author Yegor Kozlov
+ */
+public final class XSSFAutoFilter implements AutoFilter {
+ private XSSFSheet _sheet;
+
+ XSSFAutoFilter(XSSFSheet sheet){
+ _sheet = sheet;
+ }
+
+}
\ No newline at end of file
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlOptions;
import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelationshipId;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBreak;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCell;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCellFormula;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCol;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCols;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComment;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCommentList;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDataValidation;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDataValidations;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDrawing;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTHeaderFooter;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTHyperlink;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTLegacyDrawing;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTMergeCell;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTMergeCells;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTOutlinePr;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPageBreak;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPageMargins;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPageSetUpPr;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPane;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPrintOptions;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRow;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSelection;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheet;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetData;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetFormatPr;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetPr;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetProtection;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetView;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheetViews;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheet;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCellFormulaType;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.STPane;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.STPaneState;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.WorksheetDocument;
+import org.openxmlformats.schemas.spreadsheetml.x2006.main.*;
/**
* High level representation of a SpreadsheetML worksheet.
dataValidations.setCount(currentCount + 1);
}
+
+ public XSSFAutoFilter setAutoFilter(CellRangeAddress range) {
+ CTAutoFilter af = worksheet.getAutoFilter();
+ if(af == null) af = worksheet.addNewAutoFilter();
+
+ CellRangeAddress norm = new CellRangeAddress(range.getFirstRow(), range.getLastRow(),
+ range.getFirstColumn(), range.getLastColumn());
+ String ref = norm.formatAsString();
+ af.setRef(ref);
+
+ return new XSSFAutoFilter(this);
+ }
}
assertEquals(3, xrow[2].getR());
}
+
+ public void testSetAutoFilter() {
+ XSSFWorkbook wb = new XSSFWorkbook();
+ XSSFSheet sheet = wb.createSheet();
+ sheet.setAutoFilter(CellRangeAddress.valueOf("A1:D100"));
+
+ assertEquals("A1:D100", sheet.getCTWorksheet().getAutoFilter().getRef());
+ }
}
--- /dev/null
+/* ====================================================================
+ 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.record;
+
+import junit.framework.TestCase;
+import org.apache.poi.ddf.EscherClientDataRecord;
+import org.apache.poi.ddf.EscherContainerRecord;
+import org.apache.poi.ddf.EscherDggRecord;
+import org.apache.poi.ddf.EscherSpRecord;
+import org.apache.poi.hssf.model.DrawingManager2;
+import org.apache.poi.util.HexDump;
+import org.apache.poi.util.HexRead;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Arrays;
+
+/**
+ * Tests the AutoFilterInfoRecord class.
+ *
+ * @author Yegor Kozlov
+ */
+public final class TestAutoFilterInfoRecord extends TestCase {
+ private byte[] data = new byte[] {
+ 0x05, 0x00
+ };
+
+ public void testRead() {
+
+ AutoFilterInfoRecord record = new AutoFilterInfoRecord(TestcaseRecordInputStream.create(AutoFilterInfoRecord.sid, data));
+
+ assertEquals(AutoFilterInfoRecord.sid, record.getSid());
+ assertEquals(data.length, record.getDataSize());
+ assertEquals(5, record.getNumEntries());
+ record.setNumEntries((short)3);
+ assertEquals(3, record.getNumEntries());
+ }
+
+ public void testWrite() {
+ AutoFilterInfoRecord record = new AutoFilterInfoRecord();
+ record.setNumEntries((short)3);
+
+ byte [] ser = record.serialize();
+ assertEquals(ser.length - 4, data.length);
+ record = new AutoFilterInfoRecord(TestcaseRecordInputStream.create(ser));
+ assertEquals(3, record.getNumEntries());
+ }
+
+ public void testClone()
+ {
+ AutoFilterInfoRecord record = new AutoFilterInfoRecord();
+ record.setNumEntries((short)3);
+ byte[] src = record.serialize();
+
+ AutoFilterInfoRecord cloned = (AutoFilterInfoRecord)record.clone();
+ assertEquals(3, record.getNumEntries());
+ byte[] cln = cloned.serialize();
+
+ assertEquals(record.getDataSize(), cloned.getDataSize());
+ assertTrue(Arrays.equals(src, cln));
+ }
+}
\ No newline at end of file
--- /dev/null
+/* ====================================================================
+ 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.record;
+
+
+import junit.framework.TestCase;
+
+import java.util.Arrays;
+
+/**
+ * Tests the serialization and deserialization of the FtCblsSubRecord
+ * class works correctly.
+ *
+ * @author Yegor Kozlov
+ */
+public final class TestFtCblsSubRecord extends TestCase {
+ private byte[] data = new byte[] {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00,
+ 0x01, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00
+ };
+
+ public void testRead() {
+
+ FtCblsSubRecord record = new FtCblsSubRecord(TestcaseRecordInputStream.create(FtCblsSubRecord.sid, data), data.length);
+
+ assertEquals(FtCblsSubRecord.sid, record.getSid());
+ assertEquals(data.length, record.getDataSize());
+ }
+
+ public void testWrite() {
+ FtCblsSubRecord record = new FtCblsSubRecord();
+ assertEquals(FtCblsSubRecord.sid, record.getSid());
+ assertEquals(data.length, record.getDataSize());
+
+ byte [] ser = record.serialize();
+ assertEquals(ser.length - 4, data.length);
+
+ }
+
+ public void testClone()
+ {
+ FtCblsSubRecord record = new FtCblsSubRecord();
+ byte[] src = record.serialize();
+
+ FtCblsSubRecord cloned = (FtCblsSubRecord)record.clone();
+ byte[] cln = cloned.serialize();
+
+ assertEquals(record.getDataSize(), cloned.getDataSize());
+ assertTrue(Arrays.equals(src, cln));
+ }
+}
\ No newline at end of file
import org.apache.poi.hssf.HSSFITestDataProvider;
import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.model.DrawingManager2;
-import org.apache.poi.hssf.record.DimensionsRecord;
-import org.apache.poi.hssf.record.GridsetRecord;
-import org.apache.poi.hssf.record.HCenterRecord;
-import org.apache.poi.hssf.record.ObjectProtectRecord;
-import org.apache.poi.hssf.record.PasswordRecord;
-import org.apache.poi.hssf.record.ProtectRecord;
-import org.apache.poi.hssf.record.Record;
-import org.apache.poi.hssf.record.SCLRecord;
-import org.apache.poi.hssf.record.ScenarioProtectRecord;
-import org.apache.poi.hssf.record.VCenterRecord;
-import org.apache.poi.hssf.record.WSBoolRecord;
-import org.apache.poi.hssf.record.WindowTwoRecord;
+import org.apache.poi.hssf.model.InternalWorkbook;
+import org.apache.poi.hssf.model.InternalSheet;
+import org.apache.poi.hssf.record.*;
+import org.apache.poi.hssf.record.formula.Ptg;
+import org.apache.poi.hssf.record.formula.Area3DPtg;
import org.apache.poi.hssf.record.aggregates.WorksheetProtectionBlock;
import org.apache.poi.hssf.usermodel.RecordInspector.RecordCollector;
import org.apache.poi.ss.usermodel.BaseTestSheet;
assertEquals(0, r6.getOutlineLevel());
}
+ public void testCreateDrawings() {
+ HSSFWorkbook workbook = new HSSFWorkbook();
+ HSSFSheet sheet = workbook.createSheet();
+ HSSFPatriarch p1 = sheet.createDrawingPatriarch();
+ HSSFPatriarch p2 = sheet.createDrawingPatriarch();
+ assertSame(p1, p2);
+ }
+
public void testGetDrawings() {
HSSFWorkbook wb1c = HSSFTestDataSamples.openSampleWorkbook("WithChart.xls");
HSSFWorkbook wb2c = HSSFTestDataSamples.openSampleWorkbook("WithTwoCharts.xls");
// 1 chart sheet -> data on 1st, chart on 2nd
assertNotNull(wb1c.getSheetAt(0).getDrawingPatriarch());
+ assertSame(wb1c.getSheetAt(0).getDrawingPatriarch(), wb1c.getSheetAt(0).getDrawingPatriarch());
assertNotNull(wb1c.getSheetAt(1).getDrawingPatriarch());
+ assertSame(wb1c.getSheetAt(1).getDrawingPatriarch(), wb1c.getSheetAt(1).getDrawingPatriarch());
assertFalse(wb1c.getSheetAt(0).getDrawingPatriarch().containsChart());
assertTrue(wb1c.getSheetAt(1).getDrawingPatriarch().containsChart());
s.setRightToLeft(true);
assertEquals(true, s.isRightToLeft());
}
+
+ public void testAutoFilter(){
+ HSSFWorkbook wb = new HSSFWorkbook();
+ HSSFSheet sh = wb.createSheet();
+ InternalWorkbook iwb = wb.getWorkbook();
+ InternalSheet ish = sh.getSheet();
+
+ assertNull( iwb.getSpecificBuiltinRecord(NameRecord.BUILTIN_FILTER_DB, 1) );
+ assertNull( ish.findFirstRecordBySid(AutoFilterInfoRecord.sid) );
+
+ CellRangeAddress range = CellRangeAddress.valueOf("A1:B10");
+ sh.setAutoFilter(range);
+
+ NameRecord name = iwb.getSpecificBuiltinRecord(NameRecord.BUILTIN_FILTER_DB, 1);
+ assertNotNull( name );
+
+ // The built-in name for auto-filter must consist of a single Area3d Ptg.
+ Ptg[] ptg = name.getNameDefinition();
+ assertEquals("The built-in name for auto-filter must consist of a single Area3d Ptg", 1, ptg.length);
+ assertTrue("The built-in name for auto-filter must consist of a single Area3d Ptg", ptg[0] instanceof Area3DPtg);
+
+ Area3DPtg aref = (Area3DPtg)ptg[0];
+ assertEquals(range.getFirstColumn(), aref.getFirstColumn());
+ assertEquals(range.getFirstRow(), aref.getFirstRow());
+ assertEquals(range.getLastColumn(), aref.getLastColumn());
+ assertEquals(range.getLastRow(), aref.getLastRow());
+
+ // verify AutoFilterInfoRecord
+ AutoFilterInfoRecord afilter = (AutoFilterInfoRecord)ish.findFirstRecordBySid(AutoFilterInfoRecord.sid);
+ assertNotNull(afilter );
+ assertEquals(2, afilter.getNumEntries()); //filter covers two columns
+
+ }
}