? CVS_REL_2_BRANCH.jpx ? CVS_REL_2_BRANCH.jpx.local ? DragosPatch.patch ? JBuilder_lib ? POI_libs.library ? Servlet.library ? bak ? classes ? jsp.war ? workbook.xls ? workbook_2.xls ? src/contrib/src/org/apache/poi/hssf/usermodel/TestDataValidationAndHideRows.java ? src/contrib/src/org/apache/poi/hssf/usermodel/TestHSSFSheet_Hide_Clone.java ? src/contrib/src/org/apache/poi/hssf/usermodel/TestOutliningGrouping.java ? src/examples/jsp/WEB-INF ? src/java/org/apache/poi/hssf/record/DVALRecord.java ? src/java/org/apache/poi/hssf/record/DVRecord.java ? src/java/org/apache/poi/hssf/util/HSSFCellRangeAddress.java ? src/java/org/apache/poi/hssf/util/HSSFDataValidation.java ? src/testcases/org/apache/poi/hssf/data/templateExcelWithAutofilter.xls Index: src/examples/jsp/HSSFExample.jsp =================================================================== RCS file: /home/cvspublic/jakarta-poi/src/examples/jsp/HSSFExample.jsp,v retrieving revision 1.1 diff -u -r1.1 HSSFExample.jsp --- src/examples/jsp/HSSFExample.jsp 26 Jan 2003 20:43:02 -0000 1.1 +++ src/examples/jsp/HSSFExample.jsp 8 Mar 2004 08:47:32 -0000 @@ -1,26 +1,23 @@ -<%@page contentType="text/html" -import="java.io.*,org.apache.poi.poifs.filesystem.POIFSFileSystem,org.apache.poi -.hssf.record.*,org.apache.poi.hssf.model.*,org.apache.poi.hssf.usermodel.*,org.a -pache.poi.hssf.util.*" %> +<%@page contentType="text/html" import="java.io.*,org.apache.poi.poifs.filesystem.POIFSFileSystem,org.apache.poi.hssf.record.*,org.apache.poi.hssf.model.*,org.apache.poi.hssf.usermodel.*,org.apache.poi.hssf.util.*" %>
@@ -336,16 +346,16 @@ */ private int getPtgSize(int index) { int count = 0; - + Iterator ptgIterator = tokens.listIterator(index); while (ptgIterator.hasNext()) { Ptg ptg = (Ptg)ptgIterator.next(); count+=ptg.getSize(); } - + return count; } - + private int getPtgSize(int start, int end) { int count = 0; int index = start; @@ -355,91 +365,91 @@ count+=ptg.getSize(); index++; } - + return count; } /** * Generates the variable function ptg for the formula. *
- * For IF Formulas, additional PTGs are added to the tokens
+ * For IF Formulas, additional PTGs are added to the tokens
* @param name
* @param numArgs
* @return Ptg a null is returned if we're in an IF formula, it needs extreme manipulation and is handled in this function
*/
private AbstractFunctionPtg getFunction(String name, byte numArgs) {
AbstractFunctionPtg retval = null;
-
+
if (name.equals("IF")) {
retval = new FuncVarPtg(AbstractFunctionPtg.ATTR_NAME, numArgs);
-
+
//simulated pop, no bounds checking because this list better be populated by function()
List argumentPointers = (List)this.functionTokens.get(0);
-
-
+
+
AttrPtg ifPtg = new AttrPtg();
ifPtg.setData((short)7); //mirroring excel output
ifPtg.setOptimizedIf(true);
-
+
if (argumentPointers.size() != 2 && argumentPointers.size() != 3) {
throw new IllegalArgumentException("["+argumentPointers.size()+"] Arguments Found - An IF formula requires 2 or 3 arguments. IF(CONDITION, TRUE_VALUE, FALSE_VALUE [OPTIONAL]");
}
-
+
//Biffview of an IF formula record indicates the attr ptg goes after the condition ptgs and are
//tracked in the argument pointers
//The beginning first argument pointer is the last ptg of the condition
int ifIndex = tokens.indexOf(argumentPointers.get(0))+1;
tokens.add(ifIndex, ifPtg);
-
+
//we now need a goto ptgAttr to skip to the end of the formula after a true condition
//the true condition is should be inserted after the last ptg in the first argument
-
+
int gotoIndex = tokens.indexOf(argumentPointers.get(1))+1;
-
+
AttrPtg goto1Ptg = new AttrPtg();
goto1Ptg.setGoto(true);
-
-
+
+
tokens.add(gotoIndex, goto1Ptg);
-
-
+
+
if (numArgs > 2) { //only add false jump if there is a false condition
-
+
//second goto to skip past the function ptg
AttrPtg goto2Ptg = new AttrPtg();
goto2Ptg.setGoto(true);
goto2Ptg.setData((short)(retval.getSize()-1));
//Page 472 of the Microsoft Excel Developer's kit states that:
//The b(or w) field specifies the number byes (or words to skip, minus 1
-
+
tokens.add(goto2Ptg); //this goes after all the arguments are defined
}
-
+
//data portion of the if ptg points to the false subexpression (Page 472 of MS Excel Developer's kit)
//count the number of bytes after the ifPtg to the False Subexpression
//doesn't specify -1 in the documentation
ifPtg.setData((short)(getPtgSize(ifIndex+1, gotoIndex)));
-
+
//count all the additional (goto) ptgs but dont count itself
int ptgCount = this.getPtgSize(gotoIndex)-goto1Ptg.getSize()+retval.getSize();
if (ptgCount > (int)Short.MAX_VALUE) {
throw new RuntimeException("Ptg Size exceeds short when being specified for a goto ptg in an if");
}
-
+
goto1Ptg.setData((short)(ptgCount-1));
-
+
} else {
-
+
retval = new FuncVarPtg(name,numArgs);
}
-
+
return retval;
}
-
+
/** get arguments to a function */
private int Arguments() {
int numArgs = 0;
if (look != ')') {
- numArgs++;
+ numArgs++;
Expression();
addArgumentPointer();
}
@@ -475,7 +485,7 @@
} else if(look == '"') {
StringLiteral();
} else {
-
+
String number = GetNum();
if (look=='.') {
Match('.');
@@ -487,8 +497,8 @@
}
}
}
-
- private void StringLiteral()
+
+ private void StringLiteral()
{
// Can't use match here 'cuz it consumes whitespace
// which we need to preserve inside the string.
@@ -524,16 +534,16 @@
tokens.add(new StringPtg(Token.toString()));
}
}
-
+
/** Recognize and Translate a Multiply */
private void Multiply(){
Match('*');
Factor();
tokens.add(new MultiplyPtg());
-
+
}
-
-
+
+
/** Recognize and Translate a Divide */
private void Divide() {
Match('/');
@@ -541,13 +551,13 @@
tokens.add(new DividePtg());
}
-
-
+
+
/** Parse and Translate a Math Term */
private void Term(){
Factor();
while (look == '*' || look == '/' || look == '^' || look == '&') {
-
+
///TODO do we need to do anything here??
if (look == '*') Multiply();
else if (look == '/') Divide();
@@ -555,42 +565,42 @@
else if (look == '&') Concat();
}
}
-
+
/** Recognize and Translate an Add */
private void Add() {
Match('+');
Term();
tokens.add(new AddPtg());
}
-
+
/** Recognize and Translate a Concatination */
private void Concat() {
Match('&');
Term();
tokens.add(new ConcatPtg());
}
-
+
/** Recognize and Translate a test for Equality */
private void Equal() {
Match('=');
Expression();
tokens.add(new EqualPtg());
}
-
+
/** Recognize and Translate a Subtract */
private void Subtract() {
Match('-');
Term();
tokens.add(new SubtractPtg());
- }
+ }
private void Power() {
Match('^');
Term();
tokens.add(new PowerPtg());
}
-
-
+
+
/** Parse and Translate an Expression */
private void Expression() {
Term();
@@ -598,21 +608,21 @@
if (look == '+' ) Add();
else if (look == '-') Subtract();
}
-
+
/*
* This isn't quite right since it would allow multiple comparison operators.
*/
-
+
if(look == '=' || look == '>' || look == '<') {
if (look == '=') Equal();
else if (look == '>') GreaterThan();
else if (look == '<') LessThan();
return;
- }
-
-
+ }
+
+
}
-
+
/** Recognize and Translate a Greater Than */
private void GreaterThan() {
Match('>');
@@ -623,7 +633,7 @@
tokens.add(new GreaterThanPtg());
}
}
-
+
/** Recognize and Translate a Less Than */
private void LessThan() {
Match('<');
@@ -636,40 +646,40 @@
tokens.add(new LessThanPtg());
}
- }
-
+ }
+
/**
* Recognize and translate Greater than or Equal
*
- */
+ */
private void GreaterEqual() {
Match('=');
Expression();
tokens.add(new GreaterEqualPtg());
- }
+ }
/**
* Recognize and translate Less than or Equal
*
- */
+ */
private void LessEqual() {
Match('=');
Expression();
tokens.add(new LessEqualPtg());
}
-
+
/**
* Recognize and not Equal
*
- */
+ */
private void NotEqual() {
Match('>');
Expression();
tokens.add(new NotEqualPtg());
- }
-
+ }
+
//{--------------------------------------------------------------}
//{ Parse and Translate an Assignment Statement }
/**
@@ -682,15 +692,15 @@
end;
**/
-
-
+
+
/** Initialize */
-
+
private void init() {
GetChar();
SkipWhite();
}
-
+
/** API call to execute the parsing of the formula
*
*/
@@ -700,27 +710,27 @@
Expression();
}
}
-
-
+
+
/*********************************
* PARSER IMPLEMENTATION ENDS HERE
* EXCEL SPECIFIC METHODS BELOW
*******************************/
-
- /** API call to retrive the array of Ptgs created as
+
+ /** API call to retrive the array of Ptgs created as
* a result of the parsing
*/
public Ptg[] getRPNPtg() {
return getRPNPtg(FORMULA_TYPE_CELL);
}
-
+
public Ptg[] getRPNPtg(int formulaType) {
Node node = createTree();
setRootLevelRVA(node, formulaType);
setParameterRVA(node,formulaType);
return (Ptg[]) tokens.toArray(new Ptg[0]);
}
-
+
private void setRootLevelRVA(Node n, int formulaType) {
//Pg 16, excelfileformat.pdf @ openoffice.org
Ptg p = (Ptg) n.getValue();
@@ -733,9 +743,9 @@
} else {
setClass(n,Ptg.CLASS_VALUE);
}
-
+
}
-
+
private void setParameterRVA(Node n, int formulaType) {
Ptg p = (Ptg) n.getValue();
if (p instanceof AbstractFunctionPtg) {
@@ -745,16 +755,16 @@
if (n.getChild(i).getValue() instanceof AbstractFunctionPtg) {
setParameterRVA(n.getChild(i),formulaType);
}
- }
+ }
} else {
for (int i =0;i
* Description: Defines a sheet within a workbook. Basically stores the sheetname @@ -29,6 +31,7 @@ * REFERENCE: PG 291 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)
* @author Andrew C. Oliver (acoliver at apache dot org) * @author Sergei Kozello (sergeikozello at mail.ru) + * @author Dragos Buleandra (dragos.buleandra@trade2b.ro) Added support for modifying sheet's visibility and type * @version 2.0-pre */ @@ -42,6 +45,27 @@ private byte field_4_compressed_unicode_flag; // not documented private String field_5_sheetname; + /** + * Dragos Buleandra + * Description : added support for modifying sheet's visibility and type + * field_2_option_flags - compund from following optioon flags : + * - ---------------------------------------------- + * | Bits Mask Contents + * - ---------------------------------------------- + * 0-1 0003 Visibility - 00 = Visible + * 01 = Hidden , but the sheet can be unhidden + * via Excel user interface + * ( Format->Sheet->Unhide... menu) + * 02 = Strong hidden , but it's not possible anymore + * to make visible such a sheet via + * Excel user interface , only via a VBA macro + * 15-8 FF00 Sheet type - 00 = Worksheet + * 02 = Chart + * 06 = VBA module + */ + private BitField _sheet_visibility = new BitField(0x0003); + private BitField _sheet_type = new BitField(0xFF00); + public BoundSheetRecord() { } @@ -133,6 +157,30 @@ } /** + * Dragos Buleandra + * set the option flag for making a sheet visible/hidden + * @param hidden + */ + public void setHidden( boolean hidden ) + { + short value = (hidden) ? (short)0x0001 : (short)0x0000 ; + this.field_2_option_flags = this._sheet_visibility.setShortValue(this.field_2_option_flags, value); + } + + /** + * Dragos Buleandra + * set the option flag for making a sheet strong hidden + * @param hidden + */ + public void setStrongHidden( boolean strong_hidden ) + { + if ( strong_hidden ) + { + this.field_2_option_flags = this._sheet_visibility.setShortValue(this.field_2_option_flags, (short)0x0002); + } + } + + /** * Set the length of the sheetname in characters * * @param len number of characters in the sheet name @@ -158,12 +206,12 @@ /** * Set the sheetname for this sheet. (this appears in the tabs at the bottom) * @param sheetname the name of the sheet - * @thows IllegalArgumentException if sheet name will cause excel to crash. + * @thows IllegalArgumentException if sheet name will cause excel to crash. */ public void setSheetname( String sheetname ) { - + if ((sheetname == null) || (sheetname.length()==0) || (sheetname.length()>31) || (sheetname.indexOf("/") > -1) Index: src/java/org/apache/poi/hssf/record/DrawingRecord.java =================================================================== RCS file: /home/cvspublic/jakarta-poi/src/java/org/apache/poi/hssf/record/Attic/DrawingRecord.java,v retrieving revision 1.1.2.2 diff -u -r1.1.2.2 DrawingRecord.java --- src/java/org/apache/poi/hssf/record/DrawingRecord.java 22 Feb 2004 11:54:47 -0000 1.1.2.2 +++ src/java/org/apache/poi/hssf/record/DrawingRecord.java 8 Mar 2004 08:47:46 -0000 @@ -109,4 +109,15 @@ this.recordData = thedata; } + /** + * @author Dragos Buleandra + * @return + */ + public Object clone() + { + DrawingRecord rec = new DrawingRecord(); + rec.recordData = recordData; + return rec; + } + } Index: src/java/org/apache/poi/hssf/record/ExternSheetRecord.java =================================================================== RCS file: /home/cvspublic/jakarta-poi/src/java/org/apache/poi/hssf/record/ExternSheetRecord.java,v retrieving revision 1.4.2.2 diff -u -r1.4.2.2 ExternSheetRecord.java --- src/java/org/apache/poi/hssf/record/ExternSheetRecord.java 22 Feb 2004 11:54:47 -0000 1.4.2.2 +++ src/java/org/apache/poi/hssf/record/ExternSheetRecord.java 8 Mar 2004 08:47:46 -0000 @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. ==================================================================== */ - + package org.apache.poi.hssf.record; @@ -27,6 +27,7 @@ * Description: A List of Inndexes to SupBook
* REFERENCE:
* @author Libin Roman (Vista Portal LDT. Developer) + * @author Dragos Buleandra (dragos.buleandra@trade2b.ro) * @version 1.0-pre */ @@ -34,11 +35,11 @@ public final static short sid = 0x17; private short field_1_number_of_REF_sturcutres; private ArrayList field_2_REF_structures; - + public ExternSheetRecord() { field_2_REF_structures = new ArrayList(); } - + /** * Constructs a Extern Sheet record and sets its fields appropriately. * @@ -46,11 +47,11 @@ * @param size the size of the data area of the record * @param data data of the record (should not contain sid/len) */ - + public ExternSheetRecord(short id, short size, byte[] data) { super(id, size, data); } - + /** * Constructs a Extern Sheet record and sets its fields appropriately. * @@ -62,7 +63,7 @@ public ExternSheetRecord(short id, short size, byte[] data, int offset) { super(id, size, data, offset); } - + /** * called by constructor, should throw runtime exception in the event of a * record passed with a differing ID. @@ -74,7 +75,7 @@ throw new RecordFormatException("NOT An ExternSheet RECORD"); } } - + /** * called by the constructor, should set class level fields. Should throw * runtime exception for bad/icomplete data. @@ -85,63 +86,71 @@ */ protected void fillFields(byte [] data, short size, int offset) { field_2_REF_structures = new ArrayList(); - + field_1_number_of_REF_sturcutres = LittleEndian.getShort(data, 0 + offset); - + int pos = 2 + offset; for (int i = 0 ; i < field_1_number_of_REF_sturcutres ; ++i) { ExternSheetSubRecord rec = new ExternSheetSubRecord((short)0, (short)6 , data , pos); - + pos += 6; - + field_2_REF_structures.add( rec); } } - - /** + + /** * sets the number of the REF structors , that is in Excel file * @param numStruct number of REF structs */ public void setNumOfREFStructures(short numStruct) { field_1_number_of_REF_sturcutres = numStruct; } - - /** + + /** * return the number of the REF structors , that is in Excel file * @return number of REF structs */ public short getNumOfREFStructures() { return field_1_number_of_REF_sturcutres; } - - /** + + /** * adds REF struct (ExternSheetSubRecord) * @param rec REF struct */ public void addREFRecord(ExternSheetSubRecord rec) { field_2_REF_structures.add(rec); } - + + /** + * @author Dragos Buleandra + */ + public void removeREFRecord() + { + field_2_REF_structures.remove(field_2_REF_structures.size()-1); + } + /** returns the number of REF Records, which is in model * @return number of REF records */ public int getNumOfREFRecords() { return field_2_REF_structures.size(); } - + /** returns the REF record (ExternSheetSubRecord) * @param elem index to place * @return REF record */ public ExternSheetSubRecord getREFRecordAt(int elem) { ExternSheetSubRecord result = ( ExternSheetSubRecord ) field_2_REF_structures.get(elem); - + return result; } - + public String toString() { StringBuffer buffer = new StringBuffer(); - + buffer.append("[EXTERNSHEET]\n"); buffer.append(" numOfRefs = ").append(getNumOfREFStructures()).append("\n"); for (int k=0; k < this.getNumOfREFRecords(); k++) { @@ -150,11 +159,11 @@ buffer.append("----refrec #").append(k).append('\n'); } buffer.append("[/EXTERNSHEET]\n"); - - + + return buffer.toString(); } - + /** * called by the class that is responsible for writing this sucker. * Subclasses should implement this so that their data is passed back in a @@ -167,24 +176,24 @@ public int serialize(int offset, byte [] data) { LittleEndian.putShort(data, 0 + offset, sid); LittleEndian.putShort(data, 2 + offset,(short)(2 + (getNumOfREFRecords() *6))); - + LittleEndian.putShort(data, 4 + offset, getNumOfREFStructures()); - + int pos = 6 ; - + for (int k = 0; k < getNumOfREFRecords(); k++) { ExternSheetSubRecord record = getREFRecordAt(k); System.arraycopy(record.serialize(), 0, data, pos + offset, 6); - + pos +=6; } return getRecordSize(); } - + public int getRecordSize() { return 4 + 2 + getNumOfREFRecords() * 6; } - + /** * return the non static version of the id for this record. */ Index: src/java/org/apache/poi/hssf/record/NameRecord.java =================================================================== RCS file: /home/cvspublic/jakarta-poi/src/java/org/apache/poi/hssf/record/NameRecord.java,v retrieving revision 1.12.2.3 diff -u -r1.12.2.3 NameRecord.java --- src/java/org/apache/poi/hssf/record/NameRecord.java 22 Feb 2004 11:54:47 -0000 1.12.2.3 +++ src/java/org/apache/poi/hssf/record/NameRecord.java 8 Mar 2004 08:47:47 -0000 @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. ==================================================================== */ - + package org.apache.poi.hssf.record; @@ -37,6 +37,7 @@ * @author Libin Roman (Vista Portal LDT. Developer) * @author Sergei Kozello (sergeikozello at mail.ru) * @author Glen Stampoultzis (glens at apache.org) + * @author Dragos Buleandra (dragos.buleandra@trade2b.ro) Added support for Autofiltering * @version 1.0-pre */ @@ -44,11 +45,11 @@ /** */ public final static short sid = 0x18; //Docs says that it is 0x218 - + /**Included for completeness sake, not implemented */ public final static byte BUILTIN_CONSOLIDATE_AREA = (byte)1; - + /**Included for completeness sake, not implemented */ public final static byte BUILTIN_AUTO_OPEN = (byte)2; @@ -64,32 +65,35 @@ /**Included for completeness sake, not implemented */ public final static byte BUILTIN_CRITERIA = (byte)5; - + public final static byte BUILTIN_PRINT_AREA = (byte)6; public final static byte BUILTIN_PRINT_TITLE = (byte)7; - + /**Included for completeness sake, not implemented */ public final static byte BUILTIN_RECORDER = (byte)8; - + /**Included for completeness sake, not implemented */ public final static byte BUILTIN_DATA_FORM = (byte)9; - + /**Included for completeness sake, not implemented */ public final static byte BUILTIN_AUTO_ACTIVATE = (byte)10; - + /**Included for completeness sake, not implemented */ public final static byte BUILTIN_AUTO_DEACTIVATE = (byte)11; - + /**Included for completeness sake, not implemented */ public final static byte BUILTIN_SHEET_TITLE = (byte)12; - + + //Dragos Buleandra + public final static byte BUILTIN_AUTOFILTER = (byte)13; + public static final short OPT_HIDDEN_NAME = (short) 0x0001; public static final short OPT_FUNCTION_NAME = (short) 0x0002; public static final short OPT_COMMAND_NAME = (short) 0x0004; @@ -98,7 +102,7 @@ public static final short OPT_BUILTIN = (short) 0x0020; public static final short OPT_BINDATA = (short) 0x1000; - + private short field_1_option_flag; private byte field_2_keyboard_shortcut; private byte field_3_length_name_text; @@ -157,23 +161,23 @@ /** * Constructor to create a built-in named region * @param builtin Built-in byte representation for the name record, use the public constants - * @param index + * @param index */ public NameRecord(byte builtin, short index) { - this(); + this(); this.field_12_builtIn_name = builtin; this.setOptionFlag((short)(this.getOptionFlag() | OPT_BUILTIN)); this.setNameTextLength((byte)1); this.setEqualsToIndexToSheet(index); //the extern sheets are set through references - + //clearing these because they are not used with builtin records this.setCustomMenuLength((byte)0); this.setDescriptionTextLength((byte)0); this.setHelpTopicLength((byte)0); this.setStatusBarLength((byte)0); - + } /** sets the option flag for the named range @@ -539,7 +543,7 @@ else { */ LittleEndian.putShort( data, 2 + offset, (short) ( 15 + getTextsLength() ) ); - + int start_of_name_definition = 19 + field_3_length_name_text; if (this.isBuiltInName()) { @@ -547,7 +551,7 @@ data [19 + offset] = this.getBuiltInName(); } else { StringUtil.putCompressedUnicode( getNameText(), data, 19 + offset ); - + } @@ -559,7 +563,7 @@ { System.arraycopy( field_13_raw_name_definition, 0, data , start_of_name_definition + offset, field_13_raw_name_definition.length ); - } + } int start_of_custom_menu_text = start_of_name_definition + field_4_length_name_definition; @@ -678,6 +682,34 @@ return result; } + /** + * @author Dragos Buleandra + * Return the Ptg token from this NameRecord's field_13_name_definition field + */ + public Ptg getRPN_Token() + { + if (field_13_name_definition == null) return null; + Ptg ptg = (Ptg) field_13_name_definition.peek(); + return ptg; + } + + /** + * @author Dragos Buleandra + * Set sheet index reference ( zero-based ) + * NOTE ! This method is implemented only for Area3D RPN token + * + * @param zeroBasedSheetNo + */ + public void setPTGTokenExternSheetIndex( short zeroBasedSheetNo ) + { + /** @todo Extend implementation for others RPN tokens */ + Ptg RPNToken = getRPN_Token(); + if (RPNToken.getClass() == Area3DPtg.class) + { + ((Area3DPtg)RPNToken).setExternSheetIndex(zeroBasedSheetNo); + } + } + /** sets the reference , the area only (range) * @param ref area reference */ @@ -739,7 +771,7 @@ field_8_length_description_text = data [11 + offset]; field_9_length_help_topic_text = data [12 + offset]; field_10_length_status_bar_text = data [13 + offset]; - + /* temp: gjs @@ -764,34 +796,34 @@ } } else { */ - + field_11_compressed_unicode_flag= data [14 + offset]; - - + + //store the name in byte form if it's a builtin name if (this.isBuiltInName()) { field_12_builtIn_name = data[ 15 + offset ]; } - + field_12_name_text = StringUtil.getFromCompressedUnicode(data, 15 + offset, LittleEndian.ubyteToInt(field_3_length_name_text)); - + int start_of_name_definition = 15 + field_3_length_name_text; field_13_name_definition = getParsedExpressionTokens(data, field_4_length_name_definition, offset, start_of_name_definition); - + int start_of_custom_menu_text = start_of_name_definition + field_4_length_name_definition; field_14_custom_menu_text = StringUtil.getFromCompressedUnicode(data, start_of_custom_menu_text + offset, LittleEndian.ubyteToInt(field_7_length_custom_menu)); - + int start_of_description_text = start_of_custom_menu_text + field_7_length_custom_menu;; field_15_description_text = StringUtil.getFromCompressedUnicode(data, start_of_description_text + offset, LittleEndian.ubyteToInt(field_8_length_description_text)); - + int start_of_help_topic_text = start_of_description_text + field_8_length_description_text; field_16_help_topic_text = StringUtil.getFromCompressedUnicode(data, start_of_help_topic_text + offset, LittleEndian.ubyteToInt(field_9_length_help_topic_text)); - + int start_of_status_bar_text = start_of_help_topic_text + field_9_length_help_topic_text; field_17_status_bar_text = StringUtil.getFromCompressedUnicode(data, start_of_status_bar_text + offset, LittleEndian.ubyteToInt(field_10_length_status_bar_text)); @@ -831,54 +863,54 @@ return this.sid; } /* - 20 00 - 00 - 01 + 20 00 + 00 + 01 1A 00 // sz = 0x1A = 26 - 00 00 - 01 00 - 00 - 00 - 00 - 00 + 00 00 + 01 00 + 00 + 00 + 00 + 00 00 // unicode flag 07 // name - + 29 17 00 3B 00 00 00 00 FF FF 00 00 02 00 3B 00 //{ 26 00 07 00 07 00 00 00 FF 00 10 // } - - - - 20 00 - 00 - 01 + + + + 20 00 + 00 + 01 0B 00 // sz = 0xB = 11 - 00 00 - 01 00 - 00 - 00 - 00 - 00 + 00 00 + 01 00 + 00 + 00 + 00 + 00 00 // unicode flag 07 // name - + 3B 00 00 07 00 07 00 00 00 FF 00 // { 11 } */ /* - 18, 00, - 1B, 00, - - 20, 00, - 00, - 01, - 0B, 00, - 00, - 00, - 00, - 00, - 00, - 07, - 3B 00 00 07 00 07 00 00 00 FF 00 ] + 18, 00, + 1B, 00, + + 20, 00, + 00, + 01, + 0B, 00, + 00, + 00, + 00, + 00, + 00, + 07, + 3B 00 00 07 00 07 00 00 00 FF 00 ] */ /** @@ -912,10 +944,10 @@ .append("\n"); buffer.append(" .Name (Unicode text) = ").append( getNameText() ) .append("\n"); - buffer.append(" .Formula data (RPN token array without size field) = ").append( HexDump.toHex( + buffer.append(" .Formula data (RPN token array without size field) = ").append( HexDump.toHex( ((field_13_raw_name_definition != null) ? field_13_raw_name_definition : new byte[0] ) ) ) .append("\n"); - + buffer.append(" .Menu text (Unicode string without length field) = ").append( field_14_custom_menu_text ) .append("\n"); buffer.append(" .Description text (Unicode string without length field) = ").append( field_15_description_text ) @@ -926,7 +958,7 @@ .append("\n"); buffer.append(org.apache.poi.util.HexDump.dump(this.field_13_raw_name_definition,0,0)); buffer.append("[/NAME]\n"); - + return buffer.toString(); } @@ -944,16 +976,27 @@ case NameRecord.BUILTIN_CONSOLIDATE_AREA : return "Consolidate_Area"; case NameRecord.BUILTIN_CRITERIA : return "Criteria"; case NameRecord.BUILTIN_DATABASE : return "Database"; - case NameRecord.BUILTIN_DATA_FORM : return "Data_Form"; + case NameRecord.BUILTIN_DATA_FORM : return "Data_Form"; case NameRecord.BUILTIN_PRINT_AREA : return "Print_Area"; case NameRecord.BUILTIN_PRINT_TITLE : return "Print_Titles"; case NameRecord.BUILTIN_RECORDER : return "Recorder"; case NameRecord.BUILTIN_SHEET_TITLE : return "Sheet_Title"; - + case NameRecord.BUILTIN_AUTOFILTER : return "Auto_Filter"; //added by Dragos Buleandra } - + return "Unknown"; } - + /** + * @author Dragos Buleandra + * @return A clone object + */ + public Object clone() + { + byte[] sdata = this.serialize(); + byte[] data = new byte[sdata.length-4]; + System.arraycopy(sdata, 4, data, 0, data.length); + NameRecord rec = new NameRecord(NameRecord.sid, (short)(data.length), data); + return rec; + } } Index: src/java/org/apache/poi/hssf/record/ObjRecord.java =================================================================== RCS file: /home/cvspublic/jakarta-poi/src/java/org/apache/poi/hssf/record/Attic/ObjRecord.java,v retrieving revision 1.1.2.2 diff -u -r1.1.2.2 ObjRecord.java --- src/java/org/apache/poi/hssf/record/ObjRecord.java 22 Feb 2004 11:54:47 -0000 1.1.2.2 +++ src/java/org/apache/poi/hssf/record/ObjRecord.java 8 Mar 2004 08:47:47 -0000 @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. ==================================================================== */ - + package org.apache.poi.hssf.record; @@ -31,6 +31,7 @@ * The obj record is used to hold various graphic objects and controls. * * @author Glen Stampoultzis (glens at apache.org) + * @author Dragos Buleandra ( dragos.buleandra@trade2b.ro ) */ public class ObjRecord extends Record @@ -96,7 +97,26 @@ { short subRecordSid = LittleEndian.getShort(data, pos); short subRecordSize = LittleEndian.getShort(data, pos + 2); - Record subRecord = SubRecord.createSubRecord(subRecordSid, subRecordSize, data, pos + 4); + //Draqos Buleandra + //here's a strange behaviour which I encountered on an Obj record + //involved in autofiltering : + //A subrecord with sid = 0x13 (List box data) has a strange length field ( huge value , + //greater than Obj record's length !?!?!?! ) which should be , theoretically , impossible + //since it's a subrecord af the Obj record , but for Excel XP ( at least ) , this isn't a problem ; + //it renders the autofilter without any problems + //So , to avoid such situations , when we encounter a record with such a greater length field, + //we'll read the rest of the Obj record as an UnknownRecord ( without EndSubRecord , of course, which + //always should be the last subrecord of an OBJ record ) + Record subRecord = null; + if ( (subRecordSize > size-4-(pos+4)) && (subRecordSid != EndSubRecord.sid) ) + { + subRecordSize = (short)(size-4-(pos+4)); + subRecord = new UnknownRecord(subRecordSid, subRecordSize, data, pos + 4); + } + else + { + subRecord = SubRecord.createSubRecord(subRecordSid, subRecordSize, data, pos + 4); + } subrecords.add(subRecord); pos += 4 + subRecordSize; } @@ -179,7 +199,14 @@ rec.subrecords = new ArrayList(); for ( Iterator iterator = subrecords.iterator(); iterator.hasNext(); ) - subrecords.add(( (Record) iterator.next() ).clone()); + { + //Dragos Buleandra - the following statement throws an java.util.ConcurrentModificationException + // because "subrecords" coleection of this Obj record is modified and iterated + // at the same time ; here we should clone this object , not modify it + // - just joking , I know that it's a rush mistaken -:) + //subrecords.add( ( (Record) iterator.next()).clone()); + rec.subrecords.add( ( (Record) iterator.next()).clone()); + } return rec; } Index: src/java/org/apache/poi/hssf/record/RecordFactory.java =================================================================== RCS file: /home/cvspublic/jakarta-poi/src/java/org/apache/poi/hssf/record/RecordFactory.java,v retrieving revision 1.16.2.3 diff -u -r1.16.2.3 RecordFactory.java --- src/java/org/apache/poi/hssf/record/RecordFactory.java 22 Feb 2004 11:54:47 -0000 1.16.2.3 +++ src/java/org/apache/poi/hssf/record/RecordFactory.java 8 Mar 2004 08:47:48 -0000 @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. ==================================================================== */ - + package org.apache.poi.hssf.record; @@ -35,6 +35,7 @@ * @author Marc Johnson (mjohnson at apache dot org) * @author Glen Stampoultzis (glens at apache.org) * @author Csaba Nagy (ncsaba at yahoo dot com) + * @author Dragos Buleandra (dragos.buleandra@trade2b.ro) * @version 1.0-pre */ @@ -57,7 +58,7 @@ PrecisionRecord.class, RefreshAllRecord.class, BookBoolRecord.class, FontRecord.class, FormatRecord.class, ExtendedFormatRecord.class, StyleRecord.class, UseSelFSRecord.class, BoundSheetRecord.class, - CountryRecord.class, SSTRecord.class, ExtSSTRecord.class, + CountryRecord.class, SupBookRecord.class, SSTRecord.class, ExtSSTRecord.class, EOFRecord.class, IndexRecord.class, CalcModeRecord.class, CalcCountRecord.class, RefModeRecord.class, IterationRecord.class, DeltaRecord.class, SaveRecalcRecord.class, PrintHeadersRecord.class, @@ -91,7 +92,7 @@ PrecisionRecord.class, RefreshAllRecord.class, BookBoolRecord.class, FontRecord.class, FormatRecord.class, ExtendedFormatRecord.class, StyleRecord.class, UseSelFSRecord.class, BoundSheetRecord.class, - CountryRecord.class, SSTRecord.class, ExtSSTRecord.class, + CountryRecord.class, SupBookRecord.class, SSTRecord.class, ExtSSTRecord.class, EOFRecord.class, IndexRecord.class, CalcModeRecord.class, CalcCountRecord.class, RefModeRecord.class, IterationRecord.class, DeltaRecord.class, SaveRecalcRecord.class, PrintHeadersRecord.class, Index: src/java/org/apache/poi/hssf/record/RowRecord.java =================================================================== RCS file: /home/cvspublic/jakarta-poi/src/java/org/apache/poi/hssf/record/RowRecord.java,v retrieving revision 1.7.2.1 diff -u -r1.7.2.1 RowRecord.java --- src/java/org/apache/poi/hssf/record/RowRecord.java 22 Feb 2004 11:54:47 -0000 1.7.2.1 +++ src/java/org/apache/poi/hssf/record/RowRecord.java 8 Mar 2004 08:47:49 -0000 @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. ==================================================================== */ - + package org.apache.poi.hssf.record; @@ -27,6 +27,7 @@ * REFERENCE: PG 379 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)
* @author Andrew C. Oliver (acoliver at apache dot org) * @author Jason Height (jheight at chariot dot net dot au) + * @author Dragos Buleandra (dragos.buleandra@trade2b.ro) * @version 2.0-pre */ @@ -36,7 +37,7 @@ { public final static short sid = 0x208; //private short field_1_row_number; - private int field_1_row_number; + private int field_1_row_number; private short field_2_first_col; private short field_3_last_col; // plus 1 private short field_4_height; @@ -302,7 +303,9 @@ public short getOptionFlags() { - return field_7_option_flags; + //Dragos Buleandra + //return field_7_option_flags; + return (short)(field_7_option_flags | (short)0x0100); } // option bitfields Index: src/java/org/apache/poi/hssf/record/WSBoolRecord.java =================================================================== RCS file: /home/cvspublic/jakarta-poi/src/java/org/apache/poi/hssf/record/WSBoolRecord.java,v retrieving revision 1.5.2.1 diff -u -r1.5.2.1 WSBoolRecord.java --- src/java/org/apache/poi/hssf/record/WSBoolRecord.java 22 Feb 2004 11:54:47 -0000 1.5.2.1 +++ src/java/org/apache/poi/hssf/record/WSBoolRecord.java 8 Mar 2004 08:47:49 -0000 @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. ==================================================================== */ - + package org.apache.poi.hssf.record; @@ -29,6 +29,8 @@ * @author Andrew C. Oliver (acoliver at apache dot org) * @author Glen Stampoultzis (gstamp@iprimus.com.au) * @author Jason Height (jheight at chariot dot net dot au) + * @author Dragos Buleandra (dragos.buleandra@trade2b.ro) Fixed bug : field_1_wsbool and field_2_wsbool were wrong + * filled/serialized ( in a reversed order ) * @version 2.0-pre */ @@ -105,10 +107,13 @@ protected void fillFields(byte [] data, short size, int offset) { - field_1_wsbool = - data[ 1 + offset ]; // backwards because theoretically this is one short field - field_2_wsbool = - data[ 0 + offset ]; // but it was easier to implement it this way to avoid confusion + //Dragos Buleandra - these 2 fields were filled in a reversed order +// field_1_wsbool = +// data[ 1 + offset ]; // backwards because theoretically this is one short field +// field_2_wsbool = +// data[ 0 + offset ]; // but it was easier to implement it this way to avoid confusion + field_1_wsbool = data[ 0 + offset ]; + field_2_wsbool = data[ 1 + offset ]; } // because the dev kit shows the masks for it as 2 byte fields // why? Why ask why? But don't drink bud dry as its a really @@ -365,8 +370,11 @@ { LittleEndian.putShort(data, 0 + offset, sid); LittleEndian.putShort(data, 2 + offset, ( short ) 0x2); - data[ 5 + offset ] = getWSBool1(); - data[ 4 + offset ] = getWSBool2(); + //Dragos Buleandra - like filled the serialization of these 2 fields was made in a reversed order +// data[ 5 + offset ] = getWSBool1(); +// data[ 4 + offset ] = getWSBool2(); + data[ 4 + offset ] = getWSBool1(); + data[ 5 + offset ] = getWSBool2(); return getRecordSize(); } Index: src/java/org/apache/poi/hssf/record/formula/IntPtg.java =================================================================== RCS file: /home/cvspublic/jakarta-poi/src/java/org/apache/poi/hssf/record/formula/IntPtg.java,v retrieving revision 1.10.2.2 diff -u -r1.10.2.2 IntPtg.java --- src/java/org/apache/poi/hssf/record/formula/IntPtg.java 22 Feb 2004 11:54:52 -0000 1.10.2.2 +++ src/java/org/apache/poi/hssf/record/formula/IntPtg.java 8 Mar 2004 08:47:49 -0000 @@ -38,11 +38,12 @@ { public final static int SIZE = 3; public final static byte sid = 0x1e; - private short field_1_value; + // private short field_1_value; + private int field_1_value; private String val; private int strlen = 0; - + private IntPtg() { //Required for clone methods } @@ -51,19 +52,20 @@ { setValue(LittleEndian.getShort(data, offset + 1)); } - - + + // IntPtg should be able to create itself, shouldnt have to call setValue public IntPtg(String formulaToken) { - setValue(Short.parseShort(formulaToken)); + //setValue(Short.parseShort(formulaToken)); + setValue( Integer.parseInt(formulaToken)); } - public void setValue(short value) + public void setValue(int value) { field_1_value = value; } - public short getValue() + public int getValue() { return field_1_value; } @@ -71,7 +73,7 @@ public void writeBytes(byte [] array, int offset) { array[ offset + 0 ] = sid; - LittleEndian.putShort(array, offset + 1, getValue()); + LittleEndian.putInt(array, offset + 1, getValue()); //.putShort(array, offset + 1, getValue()); } public int getSize() @@ -83,7 +85,7 @@ { return "" + getValue(); } - public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;} + public byte getDefaultOperandClass() {return Ptg.CLASS_VALUE;} public Object clone() { IntPtg ptg = new IntPtg(); Index: src/java/org/apache/poi/hssf/usermodel/HSSFRow.java =================================================================== RCS file: /home/cvspublic/jakarta-poi/src/java/org/apache/poi/hssf/usermodel/HSSFRow.java,v retrieving revision 1.12.2.1 diff -u -r1.12.2.1 HSSFRow.java --- src/java/org/apache/poi/hssf/usermodel/HSSFRow.java 22 Feb 2004 11:54:53 -0000 1.12.2.1 +++ src/java/org/apache/poi/hssf/usermodel/HSSFRow.java 8 Mar 2004 08:47:50 -0000 @@ -36,6 +36,7 @@ * @version 1.0-pre * @author Andrew C. Oliver (acoliver at apache dot org) * @author Glen Stampoultzis (glens at apache.org) + * @author Dragos Buleandra (dragos.buleandra@trade2b.ro) Added method for hiding rows */ public class HSSFRow @@ -345,6 +346,16 @@ row.setBadFontHeight(true); row.setHeight((short) (height * 20)); } + + /** + * @author Dragos Buleandra + * Hide a row + * @param hide True to hide the row , false otherwise + */ + public void hide( boolean hide ) + { + sheet.getRow(rowNum).setZeroHeight( hide ); + } /** * get the row's height or ff (-1) for undefined/default-height in twips (1/20th of a point) Index: src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java =================================================================== RCS file: /home/cvspublic/jakarta-poi/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java,v retrieving revision 1.21.2.6 diff -u -r1.21.2.6 HSSFSheet.java --- src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java 22 Feb 2004 11:54:53 -0000 1.21.2.6 +++ src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java 8 Mar 2004 08:47:52 -0000 @@ -28,12 +28,21 @@ import org.apache.poi.hssf.util.Region; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; +import org.apache.poi.hssf.model.FormulaParser; +import org.apache.poi.hssf.record.formula.Ptg; +import org.apache.poi.hssf.util.HSSFDataValidation; +import org.apache.poi.hssf.util.HSSFCellRangeAddress; +import org.apache.poi.hssf.record.DVALRecord; +import org.apache.poi.hssf.record.DVRecord; +import org.apache.poi.hssf.record.EOFRecord; +import org.apache.poi.hssf.record.GutsRecord; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.TreeMap; +import java.util.Stack; /** * High level representation of a worksheet. @@ -41,6 +50,8 @@ * @author Glen Stampoultzis (glens at apache.org) * @author Libin Roman (romal at vistaportal.com) * @author Shawn Laubach (slaubach at apache dot org) (Just a little) + * @author Dragos Buleandra (dragos.buleandra@trade2b.ro) Added support for grouping/outlining rows and columns + * Method for full implementation of Data validation Excel's mechanism */ public class HSSFSheet @@ -964,7 +975,7 @@ shiftMerged(startRow, endRow, n, true); sheet.shiftRowBreaks(startRow, endRow, n); - + for ( int rowNum = s; rowNum >= startRow && rowNum <= endRow && rowNum >= 0 && rowNum < 65536; rowNum += inc ) { HSSFRow row = getRow( rowNum ); @@ -1018,6 +1029,238 @@ } /** + * @author : Dragos Buleandra + * Creates a data validation object + * @param obj_validation The Data validation object settings + */ + public void addValidationData( HSSFDataValidation obj_validation ) + { + if ( obj_validation == null ) + { + return; + } + DVALRecord dvalRec = (DVALRecord)sheet.findFirstRecordBySid( DVALRecord.sid ); + int eofLoc = sheet.findFirstRecordLocBySid( EOFRecord.sid ); + if ( dvalRec == null ) + { + dvalRec = new DVALRecord(); + sheet.getRecords().add( eofLoc, dvalRec ); + } + int curr_dvRecNo = dvalRec.getDVRecNo(); + dvalRec.setDVRecNo(curr_dvRecNo+1); + + //create dv record + DVRecord dvRecord = new DVRecord(); + + //dv record's option flags + dvRecord.setDataType( obj_validation.getDataValidationType() ); + dvRecord.setErrorStyle(obj_validation.getErrorStyle()); + dvRecord.setEmptyCellAllowed(obj_validation.getEmptyCellAllowed()); + dvRecord.setSurppresDropdownArrow(obj_validation.getSurppressDropDownArrow()); + dvRecord.setShowPromptOnCellSelected(obj_validation.getShowPromptBox()); + dvRecord.setShowErrorOnInvalidValue(obj_validation.getShowErrorBox()); + dvRecord.setConditionOperator(obj_validation.getOperator()); + + //string fields + dvRecord.setStringField( DVRecord.STRING_PROMPT_TITLE,obj_validation.getPromptBoxTitle()); + dvRecord.setStringField( DVRecord.STRING_PROMPT_TEXT, obj_validation.getPromptBoxText()); + dvRecord.setStringField( DVRecord.STRING_ERROR_TITLE, obj_validation.getErrorBoxTitle()); + dvRecord.setStringField( DVRecord.STRING_ERROR_TEXT, obj_validation.getErrorBoxText()); + + //formula fields ( size and data ) + String str_formula = obj_validation.getFirstFormula(); + FormulaParser fp = new FormulaParser(str_formula+";",book); + fp.parse(); + Stack ptg_arr = new Stack(); + Ptg[] ptg = fp.getRPNPtg(); + int size = 0; + for (int k = 0; k < ptg.length; k++) + { + if ( ptg[k] instanceof org.apache.poi.hssf.record.formula.AreaPtg ) + { + //we should set ptgClass to Ptg.CLASS_REF and explicit formula string to false + ptg[k].setClass(Ptg.CLASS_REF); + obj_validation.setExplicitListFormula(false); + } + size += ptg[k].getSize(); + ptg_arr.push(ptg[k]); + } + dvRecord.setFirstFormulaRPN(ptg_arr); + dvRecord.setFirstFormulaSize((short)size); + + dvRecord.setListExplicitFormula(obj_validation.getExplicitListFormula()); + + if ( obj_validation.getSecondFormula() != null ) + { + str_formula = obj_validation.getSecondFormula(); + fp = new FormulaParser(str_formula+";",book); + fp.parse(); + ptg_arr = new Stack(); + ptg = fp.getRPNPtg(); + size = 0; + for (int k = 0; k < ptg.length; k++) + { + size += ptg[k].getSize(); + ptg_arr.push(ptg[k]); + } + dvRecord.setSecFormulaRPN(ptg_arr); + dvRecord.setSecFormulaSize((short)size); + } + + //dv records cell range field + HSSFCellRangeAddress cell_range = new HSSFCellRangeAddress(); + cell_range.addADDRStructure(obj_validation.getFirstRow(), obj_validation.getFirstColumn(), obj_validation.getLastRow(), obj_validation.getLastColumn()); + dvRecord.setCellRangeAddress(cell_range); + + //add dv record + eofLoc = sheet.findFirstRecordLocBySid( EOFRecord.sid ); + sheet.getRecords().add( eofLoc, dvRecord ); + } + + /** + * @author : Dragos Buleandra + * @param rowno The row number ( zero based ) + * @param level The outlining level ( 1<= level <=7 ) + * @param collapsed True if row should be collapsed , false otherwise + * @param rowSumBellow True if summary rows should be placed bellow detail , false otherwise + * In other words , where to place the '+' sign . + */ + public void createOutlineRow(int rowno, short level, boolean collapsed, boolean rowSumBellow ) + { + HSSFRow row = this.getRow(rowno); + + GutsRecord gutsRec = (GutsRecord)sheet.findFirstRecordBySid( GutsRecord.sid ); + + short currLevelMax = gutsRec.getRowLevelMax(); + if ( level < 0 ) level = 0; + if ( level > 7 ) level = 7; + + short level_diff = (short)(currLevelMax - level); + + if ( level_diff < (short)0 ) + { + if ( Math.abs(level_diff) > 1 ) + { + level = ( currLevelMax == 0 ) ? 1 : currLevelMax ; + } + gutsRec.setRowLevelMax( (short)(level+1) ); + } + else + { + if (level_diff == (short)0 ) + { + gutsRec.setRowLevelMax( (short)(level+1) ); + } + } + + if ( row == null ) + { + row = this.createRow( rowno ); + } + + if ( gutsRec.getLeftRowGutter() == 0) + { + gutsRec.setLeftRowGutter((short)41); + } + + WSBoolRecord wsBoolRec = (WSBoolRecord)sheet.findFirstRecordBySid( WSBoolRecord.sid ); + wsBoolRec.setRowSumsBelow(rowSumBellow); + + RowRecord undRow = row.getRowRecord(); + undRow.setOutlineLevel(level); + undRow.setBadFontHeight(false); + undRow.setColapsed(collapsed); + undRow.setZeroHeight(collapsed); + } + + /** + * @author : Dragos Buleandra + * @param rowno The row number ( zero based ) + * @param level The outlining level ( 1<= level <=7 ) + * @param collapsed True if row should be collapsed , false otherwise + */ + public void createOutlineRow(int rowno, short level, boolean collapsed ) + { + this.createOutlineRow( rowno, level, collapsed, true ); + } + + /** + * @author : Dragos Buleandra + * @param rowno The row number ( zero based ) + * @param level The outlining level ( 1<= level <=7 ) + */ + public void createOutlineRow(int rowno, short level) + { + this.createOutlineRow( rowno, level, false, true ); + } + + /** + * @author : Dragos Buleandra + * @param colno The column number ( zero based ) + * @param level The outlining level ( max. level is 7 ) + * @param collapsed True if this outline level should be collapsed , false otherwise + * @param colSumRight True if summary cols should be placed on the right of detail , false otherwise + * In other words , where to place the '+' sign . + */ + public void createOutlineColumn( short colno, short level, boolean collapsed, boolean colSumRight ) + { + GutsRecord gutsRec = (GutsRecord)sheet.findFirstRecordBySid( GutsRecord.sid ); + + short currLevelMax = gutsRec.getColLevelMax(); + if ( level < 0 ) level = 0; + if ( level > 7 ) level = 7; + + short level_diff = (short)(currLevelMax - level); + + if ( level_diff < (short)0 ) + { + if ( Math.abs(level_diff) > 1 ) + { + level = ( currLevelMax == 0 ) ? 1 : currLevelMax ; + } + gutsRec.setColLevelMax( (short)(level+1) ); + } + else + { + if (level_diff == (short)0 ) + { + gutsRec.setColLevelMax( (short)(level+1) ); + } + } + + if ( gutsRec.getTopColGutter() == 0) + { + gutsRec.setTopColGutter((short)41); + } + + WSBoolRecord wsBoolRec = (WSBoolRecord)sheet.findFirstRecordBySid( WSBoolRecord.sid ); + wsBoolRec.setRowSumsRight(colSumRight); + + this.sheet.createOutlineColumn( colno, level, collapsed ); + } + + /** + * @author : Dragos Buleandra + * @param colno The column number ( zero based ) + * @param level The outlining level ( max. level is 7 ) + * @param collapsed True if this outline level should be collapsed , false otherwise + */ + public void createOutlineColumn( short colno, short level, boolean collapsed ) + { + this.createOutlineColumn( colno, level, collapsed, true ); + } + + /** + * @author : Dragos Buleandra + * @param colno The column number ( zero based ) + * @param level The outlining level ( max. level is 7 ) + */ + public void createOutlineColumn( short colno, short level ) + { + this.createOutlineColumn( colno, level, false, true ); + } + + /** * Creates a split (freezepane). * @param colSplit Horizonatal position of split. * @param rowSplit Vertical position of split. @@ -1108,7 +1351,7 @@ public boolean isDisplayRowColHeadings() { return sheet.isDisplayRowColHeadings(); } - + /** * Sets a page break at the indicated row * @param row @@ -1126,7 +1369,7 @@ public boolean isRowBroken(int row) { return sheet.isRowBroken(row); } - + /** * Removes the page break at the indicated row * @param row @@ -1134,13 +1377,13 @@ public void removeRowBreak(int row) { sheet.removeRowBreak(row); } - + /** * Retrieves all the horizontal page breaks * @return */ public int[] getRowBreaks(){ - //we can probably cache this information, but this should be a sparsely used function + //we can probably cache this information, but this should be a sparsely used function int[] returnValue = new int[sheet.getNumRowBreaks()]; Iterator iterator = sheet.getRowBreaks(); int i = 0; @@ -1156,7 +1399,7 @@ * @return */ public short[] getColumnBreaks(){ - //we can probably cache this information, but this should be a sparsely used function + //we can probably cache this information, but this should be a sparsely used function short[] returnValue = new short[sheet.getNumColumnBreaks()]; Iterator iterator = sheet.getColumnBreaks(); int i = 0; @@ -1166,8 +1409,8 @@ } return returnValue; } - - + + /** * Sets a page break at the indicated column * @param column @@ -1185,7 +1428,7 @@ public boolean isColumnBroken(short column) { return sheet.isColumnBroken(column); } - + /** * Removes a page break at the indicated column * @param column @@ -1193,7 +1436,7 @@ public void removeColumnBreak(short column) { sheet.removeColumnBreak(column); } - + /** * Runs a bounds check for row numbers * @param row @@ -1202,7 +1445,7 @@ if (row > 65535) throw new IllegalArgumentException("Maximum row number is 65535"); if (row < 0) throw new IllegalArgumentException("Minumum row number is 0"); } - + /** * Runs a bounds check for column numbers * @param column Index: src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java =================================================================== RCS file: /home/cvspublic/jakarta-poi/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java,v retrieving revision 1.24.2.6 diff -u -r1.24.2.6 HSSFWorkbook.java --- src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java 22 Feb 2004 11:54:53 -0000 1.24.2.6 +++ src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java 8 Mar 2004 08:47:53 -0000 @@ -59,6 +59,8 @@ * @author Andrew C. Oliver (acoliver at apache dot org) * @author Glen Stampoultzis (glens at apache.org) * @author Shawn Laubach (slaubach at apache dot org) + * @author Dragos Buleandra (dragos.buleandra@trade2b.ro) Fixed bugs when cloning sheets . + * Methods for hidding ( normal hide and strong hide ) sheets * @version 2.0-pre */ @@ -160,8 +162,6 @@ EventRecordFactory factory = new EventRecordFactory(); - - List records = RecordFactory.createRecords(stream); workbook = Workbook.createWorkbook(records); @@ -239,7 +239,7 @@ /** - * set the sheet name. + * set the sheet name. * Will throw IllegalArgumentException if the name is greater than 31 chars * or contains /\?*[] * @param sheet number (0 based) @@ -328,7 +328,8 @@ /** * create an HSSFSheet from an existing sheet in the HSSFWorkbook. - * + * Modified : Dragos Buleandra -> we should also check if cloned sheet is involved in a Name record , in which case + * we should create a Name record for the new sheet also * @return HSSFSheet representing the cloned sheet. */ @@ -347,6 +348,17 @@ }else { workbook.setSheetName(sheets.size()-1,srcName.substring(0,28)+"(2)"); } + //Dragos Buleandra + NameRecord nameRecord = workbook.getNameRecordForSheet( (short)sheetNum ); + if ( nameRecord != null ) + { + short cloneSheetNo = (short)sheets.size(); + //we should create a name record for this new sheet also + NameRecord newNameRecord = (NameRecord) nameRecord.clone(); + newNameRecord.setEqualsToIndexToSheet(cloneSheetNo); + newNameRecord.setPTGTokenExternSheetIndex( (short)(cloneSheetNo-1) ); + workbook.addName(newNameRecord); + } return clonedSheet; } return null; @@ -427,6 +439,30 @@ { sheets.remove(index); workbook.removeSheet(index); + } + + /** + * @author Dragos Buleandra + * Hide/Unhide a sheet + * @param sheetnum Sheet's index + * @param hide True to hide the sheet , false to make it visible + * @param strong_hide True if the sheet should be string hidden ( can't be unhidden form Excel user interface ) + */ + public void hideSheet(int sheetnum, boolean hide, boolean strong_hide ) + { + workbook.hideSheet( sheetnum, hide, strong_hide); + } + + /** + * @author Dragos Buleandra + * Hide/Unhide a sheet + * @param sheetname Sheet's name + * @param hide True to hide the sheet , false to make it visible + * @param strong_hide True if the sheet should be string hidden ( can't be unhidden form Excel user interface ) + */ + public void hideSheet(String sheetname, boolean hide, boolean strong_hide ) + { + workbook.hideSheet( sheetname, hide, strong_hide); } /** Index: src/java/org/apache/poi/util/LittleEndian.java =================================================================== RCS file: /home/cvspublic/jakarta-poi/src/java/org/apache/poi/util/LittleEndian.java,v retrieving revision 1.12.2.2 diff -u -r1.12.2.2 LittleEndian.java --- src/java/org/apache/poi/util/LittleEndian.java 22 Feb 2004 11:50:12 -0000 1.12.2.2 +++ src/java/org/apache/poi/util/LittleEndian.java 8 Mar 2004 08:47:54 -0000 @@ -98,7 +98,7 @@ *@return The shortArray value */ public static short[] getShortArray(final byte[] data, final int offset) { - int size = (short) getNumber(data, offset, SHORT_SIZE); + int size = (int) getNumber(data, offset, SHORT_SIZE); short[] results = getSimpleShortArray(data, offset, size); return results; }