jexcelapi/0000750000175000017500000000000011270605572012716 5ustar drazzibdrazzibjexcelapi/docs/0000750000175000017500000000000011270605402013636 5ustar drazzibdrazzibjexcelapi/build/0000750000175000017500000000000011270605461014012 5ustar drazzibdrazzibjexcelapi/build/Yylex.java0000750000175000017500000005661711270605356016014 0ustar drazzibdrazzib/* The following code was generated by JFlex 1.4.1 on 24/10/09 14:10 */ /********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; /** * This file is generated by JLex. Do not alter the contents of this file * because changes will be overridden */ import jxl.biff.WorkbookMethods; /** * This class is a scanner generated by * JFlex 1.4.1 * on 24/10/09 14:10 from the specification file * xlformula.flex */ class Yylex { /** This character denotes the end of file */ public static final int YYEOF = -1; /** initial size of the lookahead buffer */ private static final int ZZ_BUFFERSIZE = 16384; /** lexical states */ public static final int YYSTRING = 1; public static final int YYINITIAL = 0; /** * Translates characters to character classes */ private static final String ZZ_CMAP_PACKED = "\10\0\3\25\25\0\1\25\1\24\1\21\1\26\1\10\2\0\1\22"+ "\1\5\1\6\1\41\1\37\1\4\1\40\1\7\1\33\1\34\11\2"+ "\1\3\1\0\1\44\1\43\1\42\1\36\1\0\1\16\2\1\1\30"+ "\1\14\1\15\2\1\1\31\2\1\1\17\1\35\1\27\3\1\1\12"+ "\1\20\1\11\1\13\1\32\4\1\4\0\1\23\1\0\32\1\uff85\0"; /** * Translates characters to character classes */ private static final char [] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED); /** * Translates DFA states to action switch labels. */ private static final int [] ZZ_ACTION = zzUnpackAction(); private static final String ZZ_ACTION_PACKED_0 = "\1\0\1\1\1\2\1\3\1\4\1\5\1\6\1\7"+ "\1\0\2\2\1\10\1\0\1\11\1\0\1\12\1\13"+ "\1\14\1\15\1\16\1\17\1\20\1\1\1\21\1\2"+ "\1\22\1\0\1\23\1\0\1\2\3\0\2\2\5\0"+ "\1\24\1\25\1\26\1\2\1\0\1\27\1\0\1\22"+ "\2\0\1\30\1\0\2\2\10\0\1\27\1\0\1\31"+ "\1\0\1\32\10\0\1\33\2\0\1\31\2\0\1\34"+ "\4\0\1\35\3\0\1\35\1\0\1\36\1\0"; private static int [] zzUnpackAction() { int [] result = new int[94]; int offset = 0; offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result); return result; } private static int zzUnpackAction(String packed, int offset, int [] result) { int i = 0; /* index in packed string */ int j = offset; /* index in unpacked array */ int l = packed.length(); while (i < l) { int count = packed.charAt(i++); int value = packed.charAt(i++); do result[j++] = value; while (--count > 0); } return j; } /** * Translates a state to a row index in the transition table */ private static final int [] ZZ_ROWMAP = zzUnpackRowMap(); private static final String ZZ_ROWMAP_PACKED_0 = "\0\0\0\45\0\112\0\157\0\224\0\224\0\224\0\224"+ "\0\271\0\336\0\u0103\0\224\0\u0128\0\224\0\u014d\0\224"+ "\0\224\0\224\0\224\0\u0172\0\224\0\u0197\0\u01bc\0\224"+ "\0\u01e1\0\u0206\0\u022b\0\224\0\u0250\0\u0275\0\u029a\0\u02bf"+ "\0\u02e4\0\u0309\0\u032e\0\u0353\0\u0378\0\u039d\0\u03c2\0\u03e7"+ "\0\224\0\224\0\224\0\u040c\0\u0431\0\u0456\0\u047b\0\u04a0"+ "\0\u04c5\0\u04ea\0\u02bf\0\u050f\0\u0534\0\u0559\0\u057e\0\u05a3"+ "\0\u05c8\0\u05ed\0\u0612\0\u0637\0\u065c\0\u0681\0\224\0\u06a6"+ "\0\u06cb\0\u06cb\0\u040c\0\u06f0\0\u0715\0\u073a\0\u075f\0\u0784"+ "\0\u07a9\0\u07ce\0\u07f3\0\u0818\0\u0818\0\u083d\0\u0862\0\u0887"+ "\0\u08ac\0\224\0\u08d1\0\u08f6\0\u091b\0\u0940\0\u0965\0\u098a"+ "\0\u09af\0\u09d4\0\224\0\u09f9\0\u0a1e\0\u0a1e"; private static int [] zzUnpackRowMap() { int [] result = new int[94]; int offset = 0; offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result); return result; } private static int zzUnpackRowMap(String packed, int offset, int [] result) { int i = 0; /* index in packed string */ int j = offset; /* index in unpacked array */ int l = packed.length(); while (i < l) { int high = packed.charAt(i++) << 16; result[j++] = high | packed.charAt(i++); } return j; } /** * The transition table of the DFA */ private static final int [] ZZ_TRANS = zzUnpackTrans(); private static final String ZZ_TRANS_PACKED_0 = "\1\0\1\3\1\4\1\5\1\6\1\7\1\10\1\0"+ "\1\11\1\12\3\3\1\13\3\3\1\14\1\15\2\0"+ "\1\16\1\17\4\3\1\20\1\4\1\3\1\0\1\21"+ "\1\22\1\23\1\24\1\25\1\26\21\27\1\30\23\27"+ "\1\0\1\31\1\32\1\33\1\0\1\34\2\0\1\35"+ "\10\31\2\0\1\36\1\37\2\0\4\31\1\0\1\32"+ "\1\31\11\0\1\4\4\0\1\40\24\0\1\4\56\0"+ "\1\41\7\0\10\41\6\0\4\41\2\0\1\41\10\0"+ "\1\31\1\32\1\33\1\0\1\34\2\0\1\35\1\31"+ "\1\42\6\31\2\0\1\36\1\37\2\0\4\31\1\0"+ "\1\32\1\31\10\0\1\31\1\32\1\33\1\0\1\34"+ "\2\0\1\35\5\31\1\43\2\31\2\0\1\36\1\37"+ "\2\0\4\31\1\0\1\32\1\31\7\0\22\15\1\44"+ "\22\15\12\0\1\45\14\0\1\46\1\47\1\0\1\50"+ "\55\0\1\51\43\0\1\52\1\53\1\0\21\27\1\0"+ "\23\27\1\0\1\54\1\32\1\33\1\0\1\34\2\0"+ "\1\35\10\54\2\0\1\36\1\37\2\0\4\54\1\0"+ "\1\32\1\54\10\0\1\36\1\32\1\55\5\0\10\36"+ "\2\0\1\36\3\0\4\36\1\0\1\32\1\36\10\0"+ "\1\56\6\0\1\57\10\56\6\0\4\56\2\0\1\56"+ "\11\0\1\60\31\0\1\60\11\0\2\36\6\0\10\36"+ "\2\0\1\36\3\0\4\36\1\0\2\36\10\0\1\61"+ "\6\0\1\62\10\61\6\0\4\61\2\0\1\61\11\0"+ "\1\63\31\0\1\63\11\0\1\64\1\60\1\33\4\0"+ "\1\35\10\64\6\0\4\64\1\0\1\60\1\64\10\0"+ "\1\54\1\32\1\33\1\0\1\34\2\0\1\35\2\54"+ "\1\65\5\54\2\0\1\36\1\37\2\0\4\54\1\0"+ "\1\32\1\54\10\0\1\54\1\32\1\33\1\0\1\34"+ "\2\0\1\35\6\54\1\66\1\54\2\0\1\36\1\37"+ "\2\0\4\54\1\0\1\32\1\54\33\0\1\67\34\0"+ "\1\70\43\0\1\71\2\0\1\72\57\0\1\73\31\0"+ "\1\74\27\0\1\54\1\36\2\0\1\34\3\0\10\54"+ "\2\0\1\36\1\37\2\0\4\54\1\0\1\36\1\54"+ "\10\0\1\75\6\0\1\76\10\75\6\0\4\75\2\0"+ "\1\75\10\0\1\77\7\0\10\77\6\0\4\77\2\0"+ "\1\77\10\0\1\56\7\0\10\56\6\0\4\56\2\0"+ "\1\56\11\0\1\60\1\55\30\0\1\60\11\0\1\100"+ "\1\101\5\0\1\102\10\100\6\0\4\100\1\0\1\101"+ "\1\100\10\0\1\61\7\0\10\61\6\0\4\61\2\0"+ "\1\61\11\0\1\60\1\33\4\0\1\35\23\0\1\60"+ "\11\0\1\54\1\36\2\0\1\34\3\0\3\54\1\103"+ "\4\54\2\0\1\36\1\37\2\0\4\54\1\0\1\36"+ "\1\54\10\0\1\54\1\36\2\0\1\34\3\0\7\54"+ "\1\65\2\0\1\36\1\37\2\0\4\54\1\0\1\36"+ "\1\54\10\0\1\104\6\0\1\105\10\104\6\0\4\104"+ "\2\0\1\104\24\0\1\106\46\0\1\107\15\0\1\106"+ "\44\0\1\110\41\0\1\111\31\0\1\112\26\0\1\113"+ "\1\114\5\0\1\115\10\113\6\0\4\113\1\0\1\114"+ "\1\113\10\0\1\75\7\0\10\75\6\0\4\75\2\0"+ "\1\75\11\0\1\101\5\0\1\102\23\0\1\101\12\0"+ "\1\101\31\0\1\101\11\0\1\116\1\117\1\120\4\0"+ "\1\121\10\116\6\0\4\116\1\0\1\117\1\116\10\0"+ "\1\104\7\0\10\104\6\0\4\104\2\0\1\104\33\0"+ "\1\122\37\0\1\106\41\0\1\123\63\0\1\124\24\0"+ "\1\125\33\0\1\114\5\0\1\115\23\0\1\114\12\0"+ "\1\114\31\0\1\114\12\0\1\117\1\120\4\0\1\121"+ "\23\0\1\117\12\0\1\117\1\126\30\0\1\117\11\0"+ "\1\127\6\0\1\130\10\127\6\0\4\127\2\0\1\127"+ "\11\0\1\117\31\0\1\117\46\0\1\122\42\0\1\106"+ "\24\0\1\106\31\0\1\131\6\0\1\132\10\131\6\0"+ "\4\131\2\0\1\131\10\0\1\133\7\0\10\133\6\0"+ "\4\133\2\0\1\133\10\0\1\127\7\0\10\127\6\0"+ "\4\127\2\0\1\127\10\0\1\134\1\135\5\0\1\136"+ "\10\134\6\0\4\134\1\0\1\135\1\134\10\0\1\131"+ "\7\0\10\131\6\0\4\131\2\0\1\131\11\0\1\135"+ "\5\0\1\136\23\0\1\135\12\0\1\135\31\0\1\135"+ "\10\0"; private static int [] zzUnpackTrans() { int [] result = new int[2627]; int offset = 0; offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result); return result; } private static int zzUnpackTrans(String packed, int offset, int [] result) { int i = 0; /* index in packed string */ int j = offset; /* index in unpacked array */ int l = packed.length(); while (i < l) { int count = packed.charAt(i++); int value = packed.charAt(i++); value--; do result[j++] = value; while (--count > 0); } return j; } /* error codes */ private static final int ZZ_UNKNOWN_ERROR = 0; private static final int ZZ_NO_MATCH = 1; private static final int ZZ_PUSHBACK_2BIG = 2; /* error messages for the codes above */ private static final String ZZ_ERROR_MSG[] = { "Unkown internal scanner error", "Error: could not match input", "Error: pushback value was too large" }; /** * ZZ_ATTRIBUTE[aState] contains the attributes of state aState */ private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute(); private static final String ZZ_ATTRIBUTE_PACKED_0 = "\1\0\3\1\4\11\1\0\2\1\1\11\1\0\1\11"+ "\1\0\4\11\1\1\1\11\2\1\1\11\2\1\1\0"+ "\1\11\1\0\1\1\3\0\2\1\5\0\3\11\1\1"+ "\1\0\1\1\1\0\1\1\2\0\1\1\1\0\2\1"+ "\10\0\1\11\1\0\1\1\1\0\1\1\10\0\1\1"+ "\2\0\1\1\2\0\1\11\4\0\1\1\3\0\1\11"+ "\1\0\1\1\1\0"; private static int [] zzUnpackAttribute() { int [] result = new int[94]; int offset = 0; offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result); return result; } private static int zzUnpackAttribute(String packed, int offset, int [] result) { int i = 0; /* index in packed string */ int j = offset; /* index in unpacked array */ int l = packed.length(); while (i < l) { int count = packed.charAt(i++); int value = packed.charAt(i++); do result[j++] = value; while (--count > 0); } return j; } /** the input device */ private java.io.Reader zzReader; /** the current state of the DFA */ private int zzState; /** the current lexical state */ private int zzLexicalState = YYINITIAL; /** this buffer contains the current text to be matched and is the source of the yytext() string */ private char zzBuffer[] = new char[ZZ_BUFFERSIZE]; /** the textposition at the last accepting state */ private int zzMarkedPos; /** the textposition at the last state to be included in yytext */ private int zzPushbackPos; /** the current text position in the buffer */ private int zzCurrentPos; /** startRead marks the beginning of the yytext() string in the buffer */ private int zzStartRead; /** endRead marks the last character in the buffer, that has been read from input */ private int zzEndRead; /** number of newlines encountered up to the start of the matched text */ private int yyline; /** the number of characters up to the start of the matched text */ private int yychar; /** * the number of characters from the last newline up to the start of the * matched text */ private int yycolumn; /** * zzAtBOL == true <=> the scanner is currently at the beginning of a line */ private boolean zzAtBOL = true; /** zzAtEOF == true <=> the scanner is at the EOF */ private boolean zzAtEOF; /* user code: */ int getPos() { return yychar ; } private boolean emptyString; private ExternalSheet externalSheet; private WorkbookMethods nameTable; void setExternalSheet(ExternalSheet es) { externalSheet = es; } void setNameTable(WorkbookMethods nt) { nameTable = nt; } /** * Creates a new scanner * There is also a java.io.InputStream version of this constructor. * * @param in the java.io.Reader to read input from. */ Yylex(java.io.Reader in) { this.zzReader = in; } /** * Creates a new scanner. * There is also java.io.Reader version of this constructor. * * @param in the java.io.Inputstream to read input from. */ Yylex(java.io.InputStream in) { this(new java.io.InputStreamReader(in)); } /** * Unpacks the compressed character translation table. * * @param packed the packed character translation table * @return the unpacked character translation table */ private static char [] zzUnpackCMap(String packed) { char [] map = new char[0x10000]; int i = 0; /* index in packed string */ int j = 0; /* index in unpacked array */ while (i < 100) { int count = packed.charAt(i++); char value = packed.charAt(i++); do map[j++] = value; while (--count > 0); } return map; } /** * Refills the input buffer. * * @return false, iff there was new input. * * @exception java.io.IOException if any I/O-Error occurs */ private boolean zzRefill() throws java.io.IOException { /* first: make room (if you can) */ if (zzStartRead > 0) { System.arraycopy(zzBuffer, zzStartRead, zzBuffer, 0, zzEndRead-zzStartRead); /* translate stored positions */ zzEndRead-= zzStartRead; zzCurrentPos-= zzStartRead; zzMarkedPos-= zzStartRead; zzPushbackPos-= zzStartRead; zzStartRead = 0; } /* is the buffer big enough? */ if (zzCurrentPos >= zzBuffer.length) { /* if not: blow it up */ char newBuffer[] = new char[zzCurrentPos*2]; System.arraycopy(zzBuffer, 0, newBuffer, 0, zzBuffer.length); zzBuffer = newBuffer; } /* finally: fill the buffer with new input */ int numRead = zzReader.read(zzBuffer, zzEndRead, zzBuffer.length-zzEndRead); if (numRead < 0) { return true; } else { zzEndRead+= numRead; return false; } } /** * Closes the input stream. */ public final void yyclose() throws java.io.IOException { zzAtEOF = true; /* indicate end of file */ zzEndRead = zzStartRead; /* invalidate buffer */ if (zzReader != null) zzReader.close(); } /** * Resets the scanner to read from a new input stream. * Does not close the old reader. * * All internal variables are reset, the old input stream * cannot be reused (internal buffer is discarded and lost). * Lexical state is set to ZZ_INITIAL. * * @param reader the new input stream */ public final void yyreset(java.io.Reader reader) { zzReader = reader; zzAtBOL = true; zzAtEOF = false; zzEndRead = zzStartRead = 0; zzCurrentPos = zzMarkedPos = zzPushbackPos = 0; yyline = yychar = yycolumn = 0; zzLexicalState = YYINITIAL; } /** * Returns the current lexical state. */ public final int yystate() { return zzLexicalState; } /** * Enters a new lexical state * * @param newState the new lexical state */ public final void yybegin(int newState) { zzLexicalState = newState; } /** * Returns the text matched by the current regular expression. */ public final String yytext() { return new String( zzBuffer, zzStartRead, zzMarkedPos-zzStartRead ); } /** * Returns the character at position pos from the * matched text. * * It is equivalent to yytext().charAt(pos), but faster * * @param pos the position of the character to fetch. * A value from 0 to yylength()-1. * * @return the character at position pos */ public final char yycharat(int pos) { return zzBuffer[zzStartRead+pos]; } /** * Returns the length of the matched text region. */ public final int yylength() { return zzMarkedPos-zzStartRead; } /** * Reports an error that occured while scanning. * * In a wellformed scanner (no or only correct usage of * yypushback(int) and a match-all fallback rule) this method * will only be called with things that "Can't Possibly Happen". * If this method is called, something is seriously wrong * (e.g. a JFlex bug producing a faulty scanner etc.). * * Usual syntax/scanner level error handling should be done * in error fallback rules. * * @param errorCode the code of the errormessage to display */ private void zzScanError(int errorCode) { String message; try { message = ZZ_ERROR_MSG[errorCode]; } catch (ArrayIndexOutOfBoundsException e) { message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR]; } throw new Error(message); } /** * Pushes the specified amount of characters back into the input stream. * * They will be read again by then next call of the scanning method * * @param number the number of characters to be read again. * This number must not be greater than yylength()! */ public void yypushback(int number) { if ( number > yylength() ) zzScanError(ZZ_PUSHBACK_2BIG); zzMarkedPos -= number; } /** * Resumes scanning until the next regular expression is matched, * the end of input is encountered or an I/O-Error occurs. * * @return the next token * @exception java.io.IOException if any I/O-Error occurs */ public ParseItem yylex() throws java.io.IOException, jxl.biff.formula.FormulaException { int zzInput; int zzAction; // cached fields: int zzCurrentPosL; int zzMarkedPosL; int zzEndReadL = zzEndRead; char [] zzBufferL = zzBuffer; char [] zzCMapL = ZZ_CMAP; int [] zzTransL = ZZ_TRANS; int [] zzRowMapL = ZZ_ROWMAP; int [] zzAttrL = ZZ_ATTRIBUTE; while (true) { zzMarkedPosL = zzMarkedPos; yychar+= zzMarkedPosL-zzStartRead; boolean zzR = false; for (zzCurrentPosL = zzStartRead; zzCurrentPosL < zzMarkedPosL; zzCurrentPosL++) { switch (zzBufferL[zzCurrentPosL]) { case '\u000B': case '\u000C': case '\u0085': case '\u2028': case '\u2029': yyline++; zzR = false; break; case '\r': yyline++; zzR = true; break; case '\n': if (zzR) zzR = false; else { yyline++; } break; default: zzR = false; } } if (zzR) { // peek one character ahead if it is \n (if we have counted one line too much) boolean zzPeek; if (zzMarkedPosL < zzEndReadL) zzPeek = zzBufferL[zzMarkedPosL] == '\n'; else if (zzAtEOF) zzPeek = false; else { boolean eof = zzRefill(); zzEndReadL = zzEndRead; zzMarkedPosL = zzMarkedPos; zzBufferL = zzBuffer; if (eof) zzPeek = false; else zzPeek = zzBufferL[zzMarkedPosL] == '\n'; } if (zzPeek) yyline--; } zzAction = -1; zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL; zzState = zzLexicalState; zzForAction: { while (true) { if (zzCurrentPosL < zzEndReadL) zzInput = zzBufferL[zzCurrentPosL++]; else if (zzAtEOF) { zzInput = YYEOF; break zzForAction; } else { // store back cached positions zzCurrentPos = zzCurrentPosL; zzMarkedPos = zzMarkedPosL; boolean eof = zzRefill(); // get translated positions and possibly new buffer zzCurrentPosL = zzCurrentPos; zzMarkedPosL = zzMarkedPos; zzBufferL = zzBuffer; zzEndReadL = zzEndRead; if (eof) { zzInput = YYEOF; break zzForAction; } else { zzInput = zzBufferL[zzCurrentPosL++]; } } int zzNext = zzTransL[ zzRowMapL[zzState] + zzCMapL[zzInput] ]; if (zzNext == -1) break zzForAction; zzState = zzNext; int zzAttributes = zzAttrL[zzState]; if ( (zzAttributes & 1) == 1 ) { zzAction = zzState; zzMarkedPosL = zzCurrentPosL; if ( (zzAttributes & 8) == 8 ) break zzForAction; } } } // store back cached position zzMarkedPos = zzMarkedPosL; switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) { case 12: { return new Minus() ; } case 31: break; case 7: { return new CloseParentheses() ; } case 32: break; case 3: { return new IntegerValue(yytext()) ; } case 33: break; case 24: { return new DoubleValue(yytext()) ; } case 34: break; case 29: { return new ColumnRange3d(yytext(),externalSheet) ; } case 35: break; case 4: { return new RangeSeparator(); } case 36: break; case 10: { return new Divide() ; } case 37: break; case 25: { return new CellReference3d(yytext(),externalSheet) ; } case 38: break; case 26: { return new BooleanValue(yytext()); } case 39: break; case 15: { return new Equal() ; } case 40: break; case 17: { yybegin(YYINITIAL); if (emptyString) return new StringValue(""); } case 41: break; case 8: { emptyString = true; yybegin(YYSTRING); } case 42: break; case 21: { return new NotEqual() ; } case 43: break; case 22: { return new LessEqual() ; } case 44: break; case 16: { return new LessThan() ; } case 45: break; case 5: { return new ArgumentSeparator() ; } case 46: break; case 30: { return new Area3d(yytext(),externalSheet) ; } case 47: break; case 14: { return new GreaterThan() ; } case 48: break; case 18: { return new CellReference(yytext()) ; } case 49: break; case 20: { return new GreaterEqual() ; } case 50: break; case 27: { return new Area(yytext()) ; } case 51: break; case 23: { return new ColumnRange(yytext()); } case 52: break; case 1: { emptyString = false; return new StringValue(yytext()) ; } case 53: break; case 2: { return new NameRange(yytext(), nameTable); } case 54: break; case 19: { return new StringFunction(yytext()) ; } case 55: break; case 11: { return new Plus() ; } case 56: break; case 28: { return new ErrorConstant(yytext()); } case 57: break; case 9: { } case 58: break; case 13: { return new Multiply() ; } case 59: break; case 6: { return new OpenParentheses() ; } case 60: break; default: if (zzInput == YYEOF && zzStartRead == zzCurrentPos) { zzAtEOF = true; return null; } else { zzScanError(ZZ_NO_MATCH); } } } } } jexcelapi/build/xlformula.flex0000750000175000017500000001075311207000662016704 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; /** * This file is generated by JLex. Do not alter the contents of this file * because changes will be overridden */ import jxl.biff.WorkbookMethods; %% %{ int getPos() { return yychar ; } %} %{ private boolean emptyString; %} %{ private ExternalSheet externalSheet; private WorkbookMethods nameTable; void setExternalSheet(ExternalSheet es) { externalSheet = es; } void setNameTable(WorkbookMethods nt) { nameTable = nt; } %} %yylexthrow{ jxl.biff.formula.FormulaException %yylexthrow} %line %char %unicode %type ParseItem %state YYSTRING ALPHA=[A-Za-z] DIGIT=[0-9] RANGE_SEPARATOR=":" ARGUMENT_SEPARATOR="," OPEN_PARENTHESES="(" CLOSE_PARENTHESES=")" INTEGER={DIGIT}+ FLOAT={DIGIT}+"."{DIGIT}+ NON_RELATIVE_CELL_IND="$" BOOLEAN_TRUE="TRUE" BOOLEAN_FALSE="FALSE" QUOTE="\"" STRING=[^\"]* SINGLE_QUOTE="'" CELL_REFERENCE={NON_RELATIVE_CELL_IND}?{ALPHA}{ALPHA}?{NON_RELATIVE_CELL_IND}?{INTEGER} CELL_RANGE={CELL_REFERENCE}{RANGE_SEPARATOR}{CELL_REFERENCE} NAME={ALPHA}({ALPHA}|{INTEGER}|_)* SHEET_NAME={SINGLE_QUOTE}[^\']*{SINGLE_QUOTE} COLUMN_RANGE={NON_RELATIVE_CELL_IND}?{ALPHA}{ALPHA}?{RANGE_SEPARATOR}{NON_RELATIVE_CELL_IND}?{ALPHA}{ALPHA}? CELL_RANGE_3D={CELL_REFERENCE_3D}:{CELL_REFERENCE} CELL_REFERENCE_3D={SHEET_NAME}\!{CELL_REFERENCE} CELL_REFERENCE_3D2=({ALPHA})+\!{CELL_REFERENCE} COLUMN_RANGE_3D={SHEET_NAME}\!{COLUMN_RANGE} WHITE_SPACE=[\n\ \t\b\012] START_FUNCTION={ALPHA}+{OPEN_PARENTHESES} ERROR_CONSTANT="#NULL!"|"#DIV/0!"|"#VALUE!"|"#REF!"|"#NAME?"|"#NUM!" %% "+" { return new Plus() ;} "-" { return new Minus() ; } "*" { return new Multiply() ; } "/" { return new Divide() ; } ">" { return new GreaterThan() ; } "=" { return new Equal() ; } ">=" { return new GreaterEqual() ; } "<" { return new LessThan() ; } "<>" { return new NotEqual() ; } "<=" { return new LessEqual() ; } {BOOLEAN_TRUE} {return new BooleanValue(yytext());} {BOOLEAN_FALSE} {return new BooleanValue(yytext());} {ARGUMENT_SEPARATOR} { return new ArgumentSeparator() ; } {INTEGER} { return new IntegerValue(yytext()) ; } {FLOAT} { return new DoubleValue(yytext()) ; } {START_FUNCTION} { return new StringFunction(yytext()) ; } {CELL_REFERENCE} { return new CellReference(yytext()) ; } {NAME} {return new NameRange(yytext(), nameTable); } {CELL_RANGE_3D} { return new Area3d(yytext(),externalSheet) ; } {CELL_RANGE} { return new Area(yytext()) ; } {COLUMN_RANGE} { return new ColumnRange(yytext()); } {CELL_REFERENCE_3D} {return new CellReference3d(yytext(),externalSheet) ; } {CELL_REFERENCE_3D2} {return new CellReference3d(yytext(),externalSheet) ; } {COLUMN_RANGE_3D} { return new ColumnRange3d(yytext(),externalSheet) ; } {WHITE_SPACE} {} {OPEN_PARENTHESES} { return new OpenParentheses() ;} {CLOSE_PARENTHESES} { return new CloseParentheses() ;} {RANGE_SEPARATOR} { return new RangeSeparator(); } {ERROR_CONSTANT} {return new ErrorConstant(yytext());} {QUOTE} {emptyString = true; yybegin(YYSTRING);} {STRING} {emptyString = false; return new StringValue(yytext()) ; } {QUOTE} {yybegin(YYINITIAL); if (emptyString) return new StringValue("");} jexcelapi/build/jlex/0000750000175000017500000000000011016653676014765 5ustar drazzibdrazzibjexcelapi/build/jxl.el0000750000175000017500000000130411016653674015141 0ustar drazzibdrazzib(jde-set-variables '(jde-global-classpath (quote ("h:/tmp/jexcelapi" "h:/tmp/jexcelapi/jxl.jar"))) ; '(jde-db-option-application-args (quote ("-bd" "/home/andyk/tmp/jexcelapi/formulatest.xls"))) ; '(jde-db-option-application-args (quote ("-write" "out.xls"))) '(jde-db-option-application-args (quote ("-rw" "h:/tmp/jexcelapi/spot_historie_2004.xls" "h:/tmp/jexcelapi/copy.xls"))) ; '(jde-db-option-application-args (quote ("-ps" "h:/tmp/jexcelapi/copy.xls" "Module1"))) ; '(jde-db-option-application-args (quote ("h:/tmp/jexcelapi/test11.xls"))) ; '(jde-run-application-class "CommentCopy") '(jde-run-application-class "jxl.demo.Demo") '(jde-sourcepath (quote ("." "h:/tmp/jexcelapi/src")))) jexcelapi/build/build.xml0000750000175000017500000000670611207000650015634 0ustar drazzibdrazzib jexcelapi/build/xlformula.lex0000750000175000017500000001122311016653674016546 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; /** * This file is generated by JLex. Do not alter the contents of this file * because changes will be overridden */ import jxl.biff.WorkbookMethods; %% %{ int getPos() { return yychar ; } %} %{ private boolean emptyString; %} %{ private ExternalSheet externalSheet; private WorkbookMethods nameTable; void setExternalSheet(ExternalSheet es) { externalSheet = es; } void setNameTable(WorkbookMethods nt) { nameTable = nt; } %} %yylexthrow{ jxl.biff.formula.FormulaException %yylexthrow} %line %char %unicode %type ParseItem %state YYSTRING ALPHA=[A-Za-z] DIGIT=[0-9] SYMBOL=[$!%^&*#_=+;#~@/?.,<>|:-\[\]\\] RANGE_SEPARATOR=":" ARGUMENT_SEPARATOR="," OPEN_PARENTHESES="(" CLOSE_PARENTHESES=")" INTEGER={DIGIT}+ FLOAT={DIGIT}+"."{DIGIT}+ NON_RELATIVE_CELL_IND="$" BOOLEAN_TRUE="TRUE" BOOLEAN_FALSE="FALSE" QUOTE="\"" STRING=[^{QUOTE}]* SINGLE_QUOTE="'" CELL_REFERENCE={NON_RELATIVE_CELL_IND}?{ALPHA}{ALPHA}?{NON_RELATIVE_CELL_IND}?{INTEGER} CELL_RANGE={CELL_REFERENCE}{RANGE_SEPARATOR}{CELL_REFERENCE} SHEET_NAME={SINGLE_QUOTE}[^{SINGLE_QUOTE}]*{SINGLE_QUOTE} COLUMN_RANGE={NON_RELATIVE_CELL_IND}?{ALPHA}{ALPHA}?{RANGE_SEPARATOR}{NON_RELATIVE_CELL_IND}?{ALPHA}{ALPHA}? CELL_RANGE_3D={CELL_REFERENCE_3D}:{CELL_REFERENCE} CELL_REFERENCE_3D={SHEET_NAME}!{CELL_REFERENCE} CELL_REFERENCE_3D2=({ALPHA})+!{CELL_REFERENCE} COLUMN_RANGE_3D={SHEET_NAME}!{COLUMN_RANGE} NAME={ALPHA}({ALPHA}|{INTEGER}|_)* WHITE_SPACE=[\n\ \t\b\012] START_FUNCTION={ALPHA}+{OPEN_PARENTHESES} ARG_LIST={NAME} ARG={ALPHA}{ALPHA}({ALPHA}|{INTEGER})* FUNCTION={START_FUNCTION}{ARG_LIST}?{CLOSE_PARENTHESES} ERROR_CONSTANT="#NULL!"|"#DIV/0!"|"#VALUE!"|"#REF!"|"#NAME?"|"#NUM!" %% "+" { return new Plus() ;} "-" { return new Minus() ; } "*" { return new Multiply() ; } "/" { return new Divide() ; } ">" { return new GreaterThan() ; } "=" { return new Equal() ; } ">=" { return new GreaterEqual() ; } "<" { return new LessThan() ; } "<>" { return new NotEqual() ; } "<=" { return new LessEqual() ; } {ARGUMENT_SEPARATOR} { return new ArgumentSeparator() ; } {INTEGER} { return new IntegerValue(yytext()) ; } {FLOAT} { return new DoubleValue(yytext()) ; } {CELL_REFERENCE} { return new CellReference(yytext()) ; } {CELL_RANGE_3D} { return new Area3d(yytext(),externalSheet) ; } {CELL_RANGE} { return new Area(yytext()) ; } {COLUMN_RANGE} { return new ColumnRange(yytext()); } {CELL_REFERENCE_3D} {return new CellReference3d(yytext(),externalSheet) ; } {CELL_REFERENCE_3D2} {return new CellReference3d(yytext(),externalSheet) ; } {COLUMN_RANGE_3D} { return new ColumnRange3d(yytext(),externalSheet) ; } {BOOLEAN_TRUE} {return new BooleanValue(yytext());} {BOOLEAN_FALSE} {return new BooleanValue(yytext());} {NAME} {return new NameRange(yytext(), nameTable); } {WHITE_SPACE} {} {OPEN_PARENTHESES} { return new OpenParentheses() ;} {CLOSE_PARENTHESES} { return new CloseParentheses() ;} {START_FUNCTION} { return new StringFunction(yytext()) ; } {RANGE_SEPARATOR} { return new RangeSeparator(); } {ERROR_CONSTANT} {return new ErrorConstant(yytext());} {QUOTE} {emptyString = true; yybegin(YYSTRING);} {STRING} {emptyString = false; return new StringValue(yytext()) ; } {QUOTE} {yybegin(YYINITIAL); if (emptyString) return new StringValue("");} jexcelapi/build/jxl.el.safe0000750000175000017500000000113611016653676016063 0ustar drazzibdrazzib(jde-project-file-version "1.0") (jde-set-variables '(jde-global-classpath (quote ("d:/home/jexcelapi" "d:/home/jexcelapi/jxl.jar"))) ; '(jde-jdb-key-bindings (quote (("[?]" . jde-debug-step-over) ("[?]" . jde-debug-step-into) ("[? ?]" . jde-debug-step-out) ("[? ?]" . jde-debug-cont) ("[? ?]" . jde-debug-run) ("[?]" . jde-debug-toggle-breakpoint) ("[? ?]" . jde-debug-up) ("[? ?]" . jde-debug-down)))) '(jde-build-function (quote (jde-ant-build))) ; '(jde-db-option-vm-args (quote ("arg1 arg2 arg3"))) '(jde-sourcepath (quote ("d:/home/jexcelapi" "d:/home/jexcelapi/src")))) jexcelapi/build/jxl_nt.el0000750000175000017500000000114411016653676015646 0ustar drazzibdrazzib(jde-set-variables '(jde-global-classpath (quote ("." "/home/jexcelapi/jxl.jar"))) ; '(jde-db-option-application-args (quote ("-bd" "/home/andyk/tmp/jexcelapi/formulatest.xls"))) ; '(jde-db-option-application-args (quote ("-write" "out.xls"))) ; '(jde-db-option-application-args (quote ("-rw" "/home/andyk/tmp/jexcelapi/jxlrwtest.xls" "/home/andyk/tmp/jexcelapi/copy.xls"))) ; '(jde-db-option-application-args (quote ("/home/jexcelapi/jasaSend3.xls"))) ; '(jde-run-application-class "jxl.demo.Demo") '(jde-run-application-class "Rationalize") '(jde-sourcepath (quote ("." "/home/jexcelapi/src")))) jexcelapi/build/build.properties0000750000175000017500000000135111016653676017243 0ustar drazzibdrazzib# Default, configurable properties file to allow clever open source users # to use a sophisticated logging facility of their choice (eg. log4j) # If they do this, then it is their responsibility to download the requisite # libraries # Indifferent or lazy users can use the simple logger which writes # messages to standard out without the need for all that tedious mucking # about with third party libraries # The logger name. This is a source file containing the name of the # class implementing the logger interface. At build time, this source file # will be copied to the file ../src/common/log/LoggerName.java logger=SimpleLogger # The classpath for any third party libraries needed by the extra add-ons loggerClasspath= jexcelapi/build/xlformula.lex.java0000750000175000017500000004423711016653674017501 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; /** * This file is generated by JLex. Do not alter the contents of this file * because changes will be overridden */ import jxl.biff.WorkbookMethods; class Yylex { private final int YY_BUFFER_SIZE = 512; private final int YY_F = -1; private final int YY_NO_STATE = -1; private final int YY_NOT_ACCEPT = 0; private final int YY_START = 1; private final int YY_END = 2; private final int YY_NO_ANCHOR = 4; private final int YY_BOL = 65536; private final int YY_EOF = 65537; int getPos() { return yychar ; } private boolean emptyString; private ExternalSheet externalSheet; private WorkbookMethods nameTable; void setExternalSheet(ExternalSheet es) { externalSheet = es; } void setNameTable(WorkbookMethods nt) { nameTable = nt; } private java.io.BufferedReader yy_reader; private int yy_buffer_index; private int yy_buffer_read; private int yy_buffer_start; private int yy_buffer_end; private char yy_buffer[]; private int yychar; private int yyline; private boolean yy_at_bol; private int yy_lexical_state; Yylex (java.io.Reader reader) { this (); if (null == reader) { throw (new Error("Error: Bad input stream initializer.")); } yy_reader = new java.io.BufferedReader(reader); } Yylex (java.io.InputStream instream) { this (); if (null == instream) { throw (new Error("Error: Bad input stream initializer.")); } yy_reader = new java.io.BufferedReader(new java.io.InputStreamReader(instream)); } private Yylex () { yy_buffer = new char[YY_BUFFER_SIZE]; yy_buffer_read = 0; yy_buffer_index = 0; yy_buffer_start = 0; yy_buffer_end = 0; yychar = 0; yyline = 0; yy_at_bol = true; yy_lexical_state = YYINITIAL; } private boolean yy_eof_done = false; private final int YYSTRING = 1; private final int YYINITIAL = 0; private final int yy_state_dtrans[] = { 0, 32 }; private void yybegin (int state) { yy_lexical_state = state; } private int yy_advance () throws java.io.IOException { int next_read; int i; int j; if (yy_buffer_index < yy_buffer_read) { return yy_buffer[yy_buffer_index++]; } if (0 != yy_buffer_start) { i = yy_buffer_start; j = 0; while (i < yy_buffer_read) { yy_buffer[j] = yy_buffer[i]; ++i; ++j; } yy_buffer_end = yy_buffer_end - yy_buffer_start; yy_buffer_start = 0; yy_buffer_read = j; yy_buffer_index = j; next_read = yy_reader.read(yy_buffer, yy_buffer_read, yy_buffer.length - yy_buffer_read); if (-1 == next_read) { return YY_EOF; } yy_buffer_read = yy_buffer_read + next_read; } while (yy_buffer_index >= yy_buffer_read) { if (yy_buffer_index >= yy_buffer.length) { yy_buffer = yy_double(yy_buffer); } next_read = yy_reader.read(yy_buffer, yy_buffer_read, yy_buffer.length - yy_buffer_read); if (-1 == next_read) { return YY_EOF; } yy_buffer_read = yy_buffer_read + next_read; } return yy_buffer[yy_buffer_index++]; } private void yy_move_end () { if (yy_buffer_end > yy_buffer_start && '\n' == yy_buffer[yy_buffer_end-1]) yy_buffer_end--; if (yy_buffer_end > yy_buffer_start && '\r' == yy_buffer[yy_buffer_end-1]) yy_buffer_end--; } private boolean yy_last_was_cr=false; private void yy_mark_start () { int i; for (i = yy_buffer_start; i < yy_buffer_index; ++i) { if ('\n' == yy_buffer[i] && !yy_last_was_cr) { ++yyline; } if ('\r' == yy_buffer[i]) { ++yyline; yy_last_was_cr=true; } else yy_last_was_cr=false; } yychar = yychar + yy_buffer_index - yy_buffer_start; yy_buffer_start = yy_buffer_index; } private void yy_mark_end () { yy_buffer_end = yy_buffer_index; } private void yy_to_mark () { yy_buffer_index = yy_buffer_end; yy_at_bol = (yy_buffer_end > yy_buffer_start) && ('\r' == yy_buffer[yy_buffer_end-1] || '\n' == yy_buffer[yy_buffer_end-1] || 2028/*LS*/ == yy_buffer[yy_buffer_end-1] || 2029/*PS*/ == yy_buffer[yy_buffer_end-1]); } private java.lang.String yytext () { return (new java.lang.String(yy_buffer, yy_buffer_start, yy_buffer_end - yy_buffer_start)); } private int yylength () { return yy_buffer_end - yy_buffer_start; } private char[] yy_double (char buf[]) { int i; char newbuf[]; newbuf = new char[2*buf.length]; for (i = 0; i < buf.length; ++i) { newbuf[i] = buf[i]; } return newbuf; } private final int YY_E_INTERNAL = 0; private final int YY_E_MATCH = 1; private java.lang.String yy_error_string[] = { "Error: Internal error.\n", "Error: Unmatched input.\n" }; private void yy_error (int code,boolean fatal) { java.lang.System.out.print(yy_error_string[code]); java.lang.System.out.flush(); if (fatal) { throw new Error("Fatal Error.\n"); } } private int[][] unpackFromString(int size1, int size2, String st) { int colonIndex = -1; String lengthString; int sequenceLength = 0; int sequenceInteger = 0; int commaIndex; String workString; int res[][] = new int[size1][size2]; for (int i= 0; i < size1; i++) { for (int j= 0; j < size2; j++) { if (sequenceLength != 0) { res[i][j] = sequenceInteger; sequenceLength--; continue; } commaIndex = st.indexOf(','); workString = (commaIndex==-1) ? st : st.substring(0, commaIndex); st = st.substring(commaIndex+1); colonIndex = workString.indexOf(':'); if (colonIndex == -1) { res[i][j]=Integer.parseInt(workString); continue; } lengthString = workString.substring(colonIndex+1); sequenceLength=Integer.parseInt(lengthString); workString=workString.substring(0,colonIndex); sequenceInteger=Integer.parseInt(workString); res[i][j] = sequenceInteger; sequenceLength--; } } return res; } private int yy_acpt[] = { /* 0 */ YY_NOT_ACCEPT, /* 1 */ YY_NO_ANCHOR, /* 2 */ YY_NO_ANCHOR, /* 3 */ YY_NO_ANCHOR, /* 4 */ YY_NO_ANCHOR, /* 5 */ YY_NO_ANCHOR, /* 6 */ YY_NO_ANCHOR, /* 7 */ YY_NO_ANCHOR, /* 8 */ YY_NO_ANCHOR, /* 9 */ YY_NO_ANCHOR, /* 10 */ YY_NO_ANCHOR, /* 11 */ YY_NO_ANCHOR, /* 12 */ YY_NO_ANCHOR, /* 13 */ YY_NO_ANCHOR, /* 14 */ YY_NO_ANCHOR, /* 15 */ YY_NO_ANCHOR, /* 16 */ YY_NO_ANCHOR, /* 17 */ YY_NO_ANCHOR, /* 18 */ YY_NO_ANCHOR, /* 19 */ YY_NO_ANCHOR, /* 20 */ YY_NO_ANCHOR, /* 21 */ YY_NO_ANCHOR, /* 22 */ YY_NO_ANCHOR, /* 23 */ YY_NO_ANCHOR, /* 24 */ YY_NO_ANCHOR, /* 25 */ YY_NO_ANCHOR, /* 26 */ YY_NO_ANCHOR, /* 27 */ YY_NO_ANCHOR, /* 28 */ YY_NO_ANCHOR, /* 29 */ YY_NO_ANCHOR, /* 30 */ YY_NO_ANCHOR, /* 31 */ YY_NO_ANCHOR, /* 32 */ YY_NO_ANCHOR, /* 33 */ YY_NO_ANCHOR, /* 34 */ YY_NOT_ACCEPT, /* 35 */ YY_NO_ANCHOR, /* 36 */ YY_NO_ANCHOR, /* 37 */ YY_NO_ANCHOR, /* 38 */ YY_NO_ANCHOR, /* 39 */ YY_NO_ANCHOR, /* 40 */ YY_NOT_ACCEPT, /* 41 */ YY_NO_ANCHOR, /* 42 */ YY_NOT_ACCEPT, /* 43 */ YY_NO_ANCHOR, /* 44 */ YY_NOT_ACCEPT, /* 45 */ YY_NO_ANCHOR, /* 46 */ YY_NOT_ACCEPT, /* 47 */ YY_NOT_ACCEPT, /* 48 */ YY_NOT_ACCEPT, /* 49 */ YY_NOT_ACCEPT, /* 50 */ YY_NOT_ACCEPT, /* 51 */ YY_NOT_ACCEPT, /* 52 */ YY_NOT_ACCEPT, /* 53 */ YY_NOT_ACCEPT, /* 54 */ YY_NOT_ACCEPT, /* 55 */ YY_NOT_ACCEPT, /* 56 */ YY_NOT_ACCEPT, /* 57 */ YY_NOT_ACCEPT, /* 58 */ YY_NOT_ACCEPT, /* 59 */ YY_NOT_ACCEPT, /* 60 */ YY_NOT_ACCEPT, /* 61 */ YY_NOT_ACCEPT, /* 62 */ YY_NOT_ACCEPT, /* 63 */ YY_NOT_ACCEPT, /* 64 */ YY_NOT_ACCEPT, /* 65 */ YY_NOT_ACCEPT, /* 66 */ YY_NOT_ACCEPT, /* 67 */ YY_NOT_ACCEPT, /* 68 */ YY_NOT_ACCEPT, /* 69 */ YY_NOT_ACCEPT, /* 70 */ YY_NOT_ACCEPT, /* 71 */ YY_NOT_ACCEPT, /* 72 */ YY_NOT_ACCEPT, /* 73 */ YY_NOT_ACCEPT, /* 74 */ YY_NOT_ACCEPT, /* 75 */ YY_NOT_ACCEPT, /* 76 */ YY_NOT_ACCEPT, /* 77 */ YY_NOT_ACCEPT, /* 78 */ YY_NOT_ACCEPT, /* 79 */ YY_NOT_ACCEPT, /* 80 */ YY_NOT_ACCEPT, /* 81 */ YY_NOT_ACCEPT, /* 82 */ YY_NOT_ACCEPT, /* 83 */ YY_NOT_ACCEPT, /* 84 */ YY_NOT_ACCEPT, /* 85 */ YY_NOT_ACCEPT, /* 86 */ YY_NOT_ACCEPT, /* 87 */ YY_NOT_ACCEPT, /* 88 */ YY_NOT_ACCEPT, /* 89 */ YY_NO_ANCHOR, /* 90 */ YY_NO_ANCHOR, /* 91 */ YY_NOT_ACCEPT, /* 92 */ YY_NOT_ACCEPT, /* 93 */ YY_NO_ANCHOR, /* 94 */ YY_NO_ANCHOR, /* 95 */ YY_NO_ANCHOR, /* 96 */ YY_NO_ANCHOR }; private int yy_cmap[] = unpackFromString(1,65538, "14:8,26:3,14:21,26,15,37,29,11,14:2,13,27,28,3,1,8,2,10,4,34,9:9,16,14,7,6," + "5,36,14,22,12:2,31,20,21,12:2,32,12:2,23,35,30,12:3,18,24,17,19,33,12:4,14:" + "4,25,14,12:26,14:65413,0:2")[0]; private int yy_rmap[] = unpackFromString(1,97, "0,1:5,2,1,3,1,4,5,1:8,6,1,7,8,9,10,11,12,10,1,13,14,15,1,16,17,18,1:2,19,20" + ",10,21,22,7,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43," + "44,9,45,46,47,48,49,50,51,11,52,53,54,55,56,57,58,59,60,61,62,14,63,64,65,6" + "6,67,68,69,70,71")[0]; private int yy_nxt[][] = unpackFromString(72,38, "1,2,3,4,5,6,7,8,9,10,-1,34,11,40,-1:2,12,95,11:3,96,11:3,-1,13,14,15,42,11:" + "4,10,11,-1,16,-1:44,17,-1:36,18,19,-1:40,10,44,-1:23,10,-1:12,20,-1,47,89,-" + "1:2,48,49,89:8,35,-1,21,-1:2,89:4,20,89,-1:11,20,-1:2,35,-1:3,91,35:9,-1:4," + "35:4,20,35,-1:11,22,-1:24,22,-1:15,37,-1:4,37:8,-1:5,37:4,-1,37,-1:11,24,-1" + ":24,24,-1:12,35,-1:2,41,-1:2,48,-1,41:8,35,-1,21,-1:2,41:4,35,41,-1:11,26,-" + "1:24,26,-1:12,27,-1:6,83,-1:17,27,-1:15,38,-1:4,38:8,-1:5,38:4,-1,38,-1:11," + "31,-1:24,31,-1:3,1,39:36,33,-1:12,46,-1:4,46:8,-1:5,46:4,-1,46,-1:11,35,-1:" + "2,35,-1:4,35:9,-1:4,35:6,-1:11,36,-1:6,91,-1:17,36,-1:4,39:36,-1:2,40:12,50" + ",40:24,-1:18,51,-1:11,52,53,-1,54,-1:13,35,-1:2,41,-1:2,48,-1,41:3,25,41:4," + "35,-1,21,-1:2,41:4,35,41,-1:11,35,-1:2,41,-1:2,48,-1,41:3,28,41:4,35,-1,21," + "-1:2,41:4,35,41,-1:11,36,-1,47,55,-1:3,49,55:8,-1:5,55:4,36,55,-1:11,36,-1:" + "24,36,-1:14,56,57,-1:4,57:8,-1:5,57:4,-1,57,-1:13,58,23,-1:4,23:8,-1:5,23:4" + ",-1,23,-1:17,59,-1:42,60,-1:36,61,-1:2,62,-1:47,63,-1:27,64,-1:24,36,-1,47," + "-1:4,49,-1:17,36,-1:15,57,-1:4,57:8,-1:5,57:4,-1,57,-1:11,24,-1,67,68,-1:4," + "68:8,-1:5,68:4,24,68,-1:14,23,-1:4,23:8,-1:5,23:4,-1,23,-1:13,69,70,-1:4,70" + ":8,-1:5,70:4,-1,70,-1:23,71,-1:39,92,-1:11,71,-1:37,72,-1:35,73,-1:27,74,-1" + ":26,66,-1:4,66:8,-1:5,66:4,-1,66,-1:11,26,-1,75,76,-1:4,76:8,-1:5,76:4,26,7" + "6,-1:11,24,-1,67,-1:22,24,-1:15,70,-1:4,70:8,-1:5,70:4,-1,70,-1:11,27,-1,77" + ",78,-1:3,79,78:8,-1:5,78:4,27,78,-1:17,29,-1:42,80,-1:21,81,-1:52,82,-1:27," + "26,-1,75,-1:22,26,-1:12,27,-1:24,27,-1:12,27,-1,77,-1:4,79,-1:17,27,-1:14,8" + "4,30,-1:4,30:8,-1:5,30:4,-1,30,-1:38,29,-1:35,71,-1:23,71,-1:28,85,86,-1:4," + "86:8,-1:5,86:4,-1,86,-1:14,30,-1:4,30:8,-1:5,30:4,-1,30,-1:14,86,-1:4,86:8," + "-1:5,86:4,-1,86,-1:11,31,-1,87,88,-1:4,88:8,-1:5,88:4,31,88,-1:11,31,-1,87," + "-1:22,31,-1:12,20,-1,47,41,-1:2,48,49,41:8,35,-1,21,-1:2,41:4,20,41,-1:11,3" + "5,-1:2,41,-1:2,48,-1,41:7,45,35,-1,21,-1:2,41:4,35,41,-1:13,65,66,-1:4,66:8" + ",-1:5,66:4,-1,66,-1:25,71,-1:23,20,-1,47,41,-1:2,48,49,41:2,43,41:5,35,-1,2" + "1,-1:2,41:4,20,41,-1:11,20,-1,47,41,-1:2,48,49,41:6,90,41,35,-1,21,-1:2,41:" + "4,20,41,-1:11,20,-1,47,89,-1:2,48,49,89,93,89:6,35,-1,21,-1:2,89:4,20,89,-1" + ":11,20,-1,47,89,-1:2,48,49,89:5,94,89:2,35,-1,21,-1:2,89:4,20,89,-1:2"); public ParseItem yylex () throws java.io.IOException, jxl.biff.formula.FormulaException { int yy_lookahead; int yy_anchor = YY_NO_ANCHOR; int yy_state = yy_state_dtrans[yy_lexical_state]; int yy_next_state = YY_NO_STATE; int yy_last_accept_state = YY_NO_STATE; boolean yy_initial = true; int yy_this_accept; yy_mark_start(); yy_this_accept = yy_acpt[yy_state]; if (YY_NOT_ACCEPT != yy_this_accept) { yy_last_accept_state = yy_state; yy_mark_end(); } while (true) { if (yy_initial && yy_at_bol) yy_lookahead = YY_BOL; else yy_lookahead = yy_advance(); yy_next_state = YY_F; yy_next_state = yy_nxt[yy_rmap[yy_state]][yy_cmap[yy_lookahead]]; if (YY_EOF == yy_lookahead && true == yy_initial) { return null; } if (YY_F != yy_next_state) { yy_state = yy_next_state; yy_initial = false; yy_this_accept = yy_acpt[yy_state]; if (YY_NOT_ACCEPT != yy_this_accept) { yy_last_accept_state = yy_state; yy_mark_end(); } } else { if (YY_NO_STATE == yy_last_accept_state) { throw (new Error("Lexical Error: Unmatched Input.")); } else { yy_anchor = yy_acpt[yy_last_accept_state]; if (0 != (YY_END & yy_anchor)) { yy_move_end(); } yy_to_mark(); switch (yy_last_accept_state) { case 1: case -2: break; case 2: { return new Plus() ;} case -3: break; case 3: { return new Minus() ; } case -4: break; case 4: { return new Multiply() ; } case -5: break; case 5: { return new Divide() ; } case -6: break; case 6: { return new GreaterThan() ; } case -7: break; case 7: { return new Equal() ; } case -8: break; case 8: { return new LessThan() ; } case -9: break; case 9: { return new ArgumentSeparator() ; } case -10: break; case 10: { return new IntegerValue(yytext()) ; } case -11: break; case 11: {return new NameRange(yytext(), nameTable); } case -12: break; case 12: { return new RangeSeparator(); } case -13: break; case 13: {} case -14: break; case 14: { return new OpenParentheses() ;} case -15: break; case 15: { return new CloseParentheses() ;} case -16: break; case 16: {emptyString = true; yybegin(YYSTRING);} case -17: break; case 17: { return new GreaterEqual() ; } case -18: break; case 18: { return new NotEqual() ; } case -19: break; case 19: { return new LessEqual() ; } case -20: break; case 20: { return new CellReference(yytext()) ; } case -21: break; case 21: { return new StringFunction(yytext()) ; } case -22: break; case 22: { return new DoubleValue(yytext()) ; } case -23: break; case 23: { return new ColumnRange(yytext()); } case -24: break; case 24: {return new CellReference3d(yytext(),externalSheet) ; } case -25: break; case 25: {return new BooleanValue(yytext());} case -26: break; case 26: { return new Area(yytext()) ; } case -27: break; case 27: {return new CellReference3d(yytext(),externalSheet) ; } case -28: break; case 28: {return new BooleanValue(yytext());} case -29: break; case 29: {return new ErrorConstant(yytext());} case -30: break; case 30: { return new ColumnRange3d(yytext(),externalSheet) ; } case -31: break; case 31: { return new Area3d(yytext(),externalSheet) ; } case -32: break; case 32: {emptyString = false; return new StringValue(yytext()) ; } case -33: break; case 33: {yybegin(YYINITIAL); if (emptyString) return new StringValue("");} case -34: break; case 35: {return new NameRange(yytext(), nameTable); } case -35: break; case 36: { return new CellReference(yytext()) ; } case -36: break; case 37: { return new ColumnRange(yytext()); } case -37: break; case 38: { return new ColumnRange3d(yytext(),externalSheet) ; } case -38: break; case 39: {emptyString = false; return new StringValue(yytext()) ; } case -39: break; case 41: {return new NameRange(yytext(), nameTable); } case -40: break; case 43: {return new NameRange(yytext(), nameTable); } case -41: break; case 45: {return new NameRange(yytext(), nameTable); } case -42: break; case 89: {return new NameRange(yytext(), nameTable); } case -43: break; case 90: {return new NameRange(yytext(), nameTable); } case -44: break; case 93: {return new NameRange(yytext(), nameTable); } case -45: break; case 94: {return new NameRange(yytext(), nameTable); } case -46: break; case 95: {return new NameRange(yytext(), nameTable); } case -47: break; case 96: {return new NameRange(yytext(), nameTable); } case -48: break; default: yy_error(YY_E_INTERNAL,false); case -1: } yy_initial = true; yy_state = yy_state_dtrans[yy_lexical_state]; yy_next_state = YY_NO_STATE; yy_last_accept_state = YY_NO_STATE; yy_mark_start(); yy_this_accept = yy_acpt[yy_state]; if (YY_NOT_ACCEPT != yy_this_accept) { yy_last_accept_state = yy_state; yy_mark_end(); } } } } } } jexcelapi/build/build_simple.properties0000750000175000017500000000135111016653676020614 0ustar drazzibdrazzib# Default, configurable properties file to allow clever open source users # to use a sophisticated logging facility of their choice (eg. log4j) # If they do this, then it is their responsibility to download the requisite # libraries # Indifferent or lazy users can use the simple logger which writes # messages to standard out without the need for all that tedious mucking # about with third party libraries # The logger name. This is a source file containing the name of the # class implementing the logger interface. At build time, this source file # will be copied to the file ../src/common/log/LoggerName.java logger=SimpleLogger # The classpath for any third party libraries needed by the extra add-ons loggerClasspath= jexcelapi/build/build_log4j.properties0000750000175000017500000000143411016653676020344 0ustar drazzibdrazzib# Default, configurable properties file to allow clever open source users # to use a sophisticated logging facility of their choice (eg. log4j) # If they do this, then it is their responsibility to download the requisite # libraries # Indifferent or lazy users can use the simple logger which writes # messages to standard out without the need for all that tedious mucking # about with third party libraries # The logger name. This is a source file containing the name of the # class implementing the logger interface. At build time, this source file # will be copied to the file ../src/common/log/LoggerName.java logger=Log4JLogger # The classpath for any third party libraries needed by the extra add-ons loggerClasspath=e:/apps/jakarta-log4j-1.2.8/dist/lib/log4j-1.2.8.jar jexcelapi/build/xlformula.lex.safe0000750000175000017500000000735011016653676017473 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; /** * This file is generated by JLex. Do not alter the contents of this file * because changes will be overridden */ import jxl.biff.WorkbookMethods; %% %{ int getPos() { return yychar ; } %} %{ private boolean emptyString; %} %{ private ExternalSheet externalSheet; private WorkbookMethods nameTable; void setExternalSheet(ExternalSheet es) { externalSheet = es; } void setNameTable(WorkbookMethods nt) { nameTable = nt; } %} %yylexthrow{ jxl.biff.formula.FormulaException %yylexthrow} %line %char %type ParseItem %state YYSTRING ALPHA=[A-Za-z] DIGIT=[0-9] SYMBOL=[$!%^&*#_=+;:#~@/?.,<>|-] INTEGER={DIGIT}+ FLOAT={DIGIT}+"."{DIGIT}+ NON_RELATIVE_CELL_IND="$" CELL_REFERENCE={NON_RELATIVE_CELL_IND}?{ALPHA}{ALPHA}?{NON_RELATIVE_CELL_IND}?{INTEGER} CELL_RANGE={CELL_REFERENCE}:{CELL_REFERENCE} CELL_RANGE_3D={CELL_REFERENCE_3D}:{CELL_REFERENCE} CELL_REFERENCE_3D={SINGLE_QUOTE}?({ALPHA}|{DIGIT}|{WHITE_SPACE}|{SYMBOL})+{SINGLE_QUOTE}?!{CELL_REFERENCE} | {SINGLE_QUOTE}({ALPHA}|{DIGIT}|{WHITE_SPACE}|{SYMBOL}|{OPEN_PARENTHESES}|{CLOSE_PARENTHESES})+{SINGLE_QUOTE}!{CELL_REFERENCE} NAME={ALPHA}{ALPHA}({ALPHA}|{INTEGER})* WHITE_SPACE=[\n\ \t\b\012] ARGUMENT_SEPARATOR="," OPEN_PARENTHESES="(" CLOSE_PARENTHESES=")" FUNCTION={ALPHA}+{OPEN_PARENTHESES} QUOTE="\"" STRING=[^{QUOTE}]* SINGLE_QUOTE="'" %% "+" { return new Plus() ;} "-" { return new Minus() ; } "*" { return new Multiply() ; } "/" { return new Divide() ; } ">" { return new GreaterThan() ; } "=" { return new Equal() ; } ">=" { return new GreaterEqual() ; } "<" { return new LessThan() ; } "<=" { return new LessEqual() ; } {ARGUMENT_SEPARATOR} { return new ArgumentSeparator() ; } {INTEGER} { return new IntegerValue(yytext()) ; } {FLOAT} { return new DoubleValue(yytext()) ; } {CELL_REFERENCE} { return new CellReference(yytext()) ; } {CELL_RANGE_3D} { return new Area3d(yytext(),externalSheet) ; } {CELL_RANGE} { return new Area(yytext()) ; } {CELL_REFERENCE_3D} { return new CellReference3d(yytext(),externalSheet) ; } {NAME} {return new NameRange(yytext(), nameTable); } {WHITE_SPACE} {} {OPEN_PARENTHESES} { return new OpenParentheses() ;} {CLOSE_PARENTHESES} { return new CloseParentheses() ;} {FUNCTION} { return new StringFunction(yytext()) ; } {QUOTE} {emptyString = true; yybegin(YYSTRING);} {STRING} {emptyString = false; return new StringValue(yytext()) ; } {QUOTE} {yybegin(YYINITIAL); if (emptyString) return new StringValue("");} jexcelapi/build/jxl.mf0000750000175000017500000000003511016653674015143 0ustar drazzibdrazzibMain-Class: jxl.demo.Demo jexcelapi/tutorial.html0000750000175000017500000011163211016653672015460 0ustar drazzibdrazzib Java Excel API Tutorial

Java Excel API Tutorial

Contents

Introduction
Reading a spreadsheet
Writing a spreadsheet
      Fundamentals
      Adding format information
      Formatting numbers
      Formatting dates
Copying and modifying a spreadsheet
Demo & Test programs
Frequently Asked Questions
      java.lang.OutOfMemory Exception
      Compiling
      Uploading a Spreadsheet
      Support for charts, macros and images
      Date display
      Cell formats across multiple workbooks
      Cross sheet formulas

Introduction

The information presented in this tutorial is intended as a brief overview as to how JExcelApi may be used to read and write data in Excel format. The tutorial is by no means exhaustive, and if something is not described here, it does not mean that it cannot be done. The reader is encouraged to examine the API documentation and the sample code (particularly Write.java and ReadWrite.java) in order to gain a more complete understanding of the capabilities and limitations of the software.

Reading Spreadsheets

JExcelApi can read an Excel spreadsheet from a file stored on the local filesystem or from some input stream. The first step when reading a spreadsheet from a file or input stream is to create a Workbook. The code fragment below illustrates creating a workbook from a file on the local filesystem.

import java.io.File;
import java.util.Date;
import jxl.*;

...

Workbook workbook = Workbook.getWorkbook(new File("myfile.xls"));
(NOTE: when creating a spreadsheet from a ServletInputStream you must remove the HTTP header information before creating the Workbook object.)

Once you have accessed the workbook, you can use this to access the individual sheets. These are zero indexed - the first sheet being 0, the second sheet being 1, and so on. (You can also use the API to retrieve a sheet by name).

Sheet sheet = workbook.getSheet(0);
Once you have a sheet, you can then start accessing the cells. You can retrieve the cell's contents as a string by using the convenience method getContents(). In the example code below, A1 is a text cell, B2 is numerical value and C2 is a date. The contents of these cells may be accessed as follows

Cell a1 = sheet.getCell(0,0);
Cell b2 = sheet.getCell(1,1);
Cell c2 = sheet.getCell(2,1);

String stringa1 = a1.getContents();
String stringb2 = b2.getContents();
String stringc2 = c2.getContents();

// Do stuff with the strings etc
...
The demo programs CSV.java and XML.java use the convenience method getContents() in order to output the spreadsheet contents.

However if it is required to access the cell's contents as the exact type ie. as a numerical value or as a date, then the retrieved Cell must be cast to the correct type and the appropriate methods called. The section of code below illustrates how JExcelApi may be used to retrieve a genuine java double and java.util.Date object from an Excel spreadsheet. For completeness the label is also cast to it's correct type, although in practice this makes no difference. The example also illustrates how to verify that cell is of the expected type - this can be useful when validating that the spreadsheet has cells in the correct place.

String stringa1 = null;
double numberb2 = 0;
Date datec2 = null;

Cell a1 = sheet.getCell(0,0);
Cell b2 = sheet.getCell(1,1);
Cell c2 = sheet.getCell(2,1);

if (a1.getType() == CellType.LABEL)
{
  LabelCell lc = (LabelCell) a1;
  stringa1 = lc.getString();
}

if (b2.getType() == CellType.NUMBER)
{
  NumberCell nc = (NumberCell) b2;
  numberb2 = nc.getValue();
}

if (c2.getType() == CellType.DATE)
{
  DateCell dc = (DateCell) c2;
  datec2 = dc.getDate();
}

// Do stuff with dates and doubles
...
When you have finished processing all the cells, use the close() method. This frees up any allocated memory used when reading spreadsheets and is particularly important when reading large spreadsheets.

// Finished - close the workbook and free up memory
workbook.close();


Writing Spreadsheets

Fundamentals

This section describes how to write out simple spreadsheet data without any formatting information, such as fonts or decimal places.

Similarly to reading a spreadsheet, the first step is to create a writable workbook using the factory method on the Workbook class.

import java.io.File;
import java.util.Date;
import jxl.*;
import jxl.write.*;

...

WritableWorkbook workbook = Workbook.createWorkbook(new File("output.xls"));
This creates the workbook object. The generated file will be located in the current working directory and will be called "output.xls". The API can also be used to send the workbook directly to an output stream eg. from a web server to the user's browser. If the HTTP header is set correctly, then this will launch Excel and display the generated spreadsheet.

The next stage is to create sheets for the workbook. Again, this is a factory method, which takes the name of the sheet and the position it will occupy in the workbook. The code fragment below creates a sheet called "First Sheet" at the first position.

WritableSheet sheet = workbook.createSheet("First Sheet", 0);
Now all that remains is to add the cells into the worksheet. This is simply a matter of instantiating cell objects and adding them to the sheet. The following code fragment puts a label in cell A3, and the number 3.14159 in cell D5.

Label label = new Label(0, 2, "A label record");
sheet.addCell(label);

Number number = new Number(3, 4, 3.1459);
sheet.addCell(number);
There are a couple of points to note here. Firstly, the cell's location in the sheet is specified as part of the constructor information. Once created, it is not possible to change a cell's location, although the cell's contents may be altered.

The other point to note is that the cell's location is specified as (column, row). Both are zero indexed integer values - A1 being represented by (0,0), B1 by (1,0), A2 by (0,1) and so on.

Once you have finished adding sheets and cells to the workbook, you call write() on the workbook, and then close the file. This final step generates the output file (output.xls in this case) which may be read by Excel. If you call close() without calling write() first, a completely empty file will be generated.

...
// All sheets and cells added. Now write out the workbook
workbook.write();
workbook.close();


Adding Format Information

The previous section illustrates the fundamentals of generating an Excel compatible spreadsheet using the JExcelApi. However, as it stands Excel will render the data in the default font, and will display the numbers to 3 decimal places. In order to supply formatting information to Excel, we must make use of the overloaded constructor, which takes an additional object containing the cell's formatting information (both the font and the style).

The code fragment below illustrates creating a label cell for an arial 10 point font.

// Create a cell format for Arial 10 point font
WritableFont arial10font = new WritableFont(WritableFont.ARIAL, 10);
WritableCellFormat arial10format = new WritableCellFormat (arial10font);

// Create the label, specifying content and format
Label label2 = new Label(1,0, "Arial 10 point label", arial10format);
sheet.addCell(label2);
Cell formats objects are shared, so many cells may use the same format object, eg.

Label label3 = new Label(2, 0, "Another Arial 10 point label", arial10format);
sheet.addCell(label3);
This creates another label, with the same format, in cell C1.

Because cell formats are shared, it is not possible to change the contents of a cell format object. (If this were permitted, then changing the contents of the object could have unforeseen repurcussions on the look of the rest of the workbook). In order to change the way a particular cell is displayed, the API does allow you to assign a new format to an individual cell.

The constructors for the WritableFont object have many overloads. By way of example, the code fragment below creates a label in 16 point Times, bold italic and assigns it to position D1.
// Create a cell format for Times 16, bold and italic
WritableFont times16font = new WritableFont(WritableFont.TIMES, 16, WritableFont.BOLD, true);
WritableCellFormat times16format = new WritableCellFormat (times16font);

// Create the label, specifying content and format
Label label4 = new Label(3,0, "Times 16 bold italic label", times16format);
sheet.addCell(label4);


Formatting Numbers

Number formatting information may be passed to the cell format object by a similar mechanism to that described for fonts.

A variety of predefined number formats are defined statically. These may be used to format numerical values as follows:

WritableCellFormat integerFormat = new WritableCellFormat (NumberFormats.INTEGER);
Number number2 = new Number(0, 4, 3.141519, integerFormat);
sheet.addCell(number2);

WritableCellFormat floatFormat = new WritableCellFormat (NumberFormats.FLOAT);
Number number3 = new Number(1, 4, 3.141519, floatFormat);
sheet.addCell(number3);
The above code inserts the value 3.14159 into cells A5 and B5, using the preset integer and floating points format respectively. When Excel renders these cells, A5 will display as "3" and B5 will display as "3.14", even though both cells contain the same floating point value.

It's possible for a user to define their own number formats, by passing in a number format string. The string passed in should be in the same format as that used by the java.text.DecimalFormat class. To format a number to display up to five decimal places in cell C5, the following code fragment may be used:
NumberFormat fivedps = new NumberFormat("#.#####");
WritableCellFormat fivedpsFormat = new WritableCellFormat(fivedps);
Number number4 = new Number(2, 4, 3.141519, fivedpsFormat);
sheet.addCell(number4);
It is, of course, also possible to specify font information as well eg. to display the same value in the 16 point times bold font defined earlier we can write
WritableCellFormat fivedpsFontFormat = new WritableCellFormat (times16font, fivedps);
Number number5 = new Number(3, 4, 3.141519, fivedpsFontFormat);
sheet.addCell(number5);


Formatting Dates

Dates are handled similarly to numbers, taking in a format compatible with that used by the java.text.SimpleDateFormat class. In addition, several predefined date formats are specified in the jxl.write.DateFormat class.

As a brief example, the below code fragment illustrates placing the current date and time in cell A7 using a custom format:

// Get the current date and time from the Calendar object
Date now = Calendar.getInstance().getTime();
DateFormat customDateFormat = new DateFormat ("dd MMM yyyy hh:mm:ss");
WritableCellFormat dateFormat = new WritableCellFormat (customDateFormat);
DateTime dateCell = new DateTime(0, 6, now, dateFormat);
sheet.addCell(dateCell);
As with numbers, font information may be used to display the date text by using the overloaded constructors on WritableCellFormat.

For a more extensive example of writing spreadsheets, the demonstration program Write.java should be studied. In addition to the functionality described above, this program tests out a variety of cell, formatting and font options, as well as displaying cells with different background and foreground colours, shading and boundaries.

Copying and Modifying Spreadsheets

This section describes the scenario where a spreadsheet is read in, it's contents altered in some way and the modified spreadsheet written out.

The first stage is to read in the spreadsheet in the normal way:

import java.io.File;
import java.util.Date;
import jxl.*;
import jxl.write.*;

...

Workbook workbook = Workbook.getWorkbook(new File("myfile.xls"));
This creates a readable spreadsheet. To obtain a writable version of this spreadsheet, a copy must be made, as follows:
WritableWorkbook copy = Workbook.createWorkbook(new File("output.xls"), workbook);
The API functions this way is for reasons of read efficiency (since this is the primary use of the API). In order to improve performance, data which relates to output information (eg. all the formatting information such as fonts) is not interpreted when the spreadsheet is read, since this is superfluous when interrogating the raw data values. However, if we need to modify this spreadsheet a handle to the various write interfaces is needed, which can be obtained using the copy method above. This copies the information that has already been read in as well as performing the additional processing to interpret the fields that are necessary to for writing spreadsheets. The disadvantage of this read-optimized strategy is that we have two spreadsheets held in memory rather than just one, thus doubling the memory requirements. For this reason copying and modifying large spreadsheets can be expensive in terms of processing and memory.

Once we have a writable interface to the workbook, we may retrieve and modify cells. The following code fragment illustrates how to modify the contents of a label cell located in cell B3 in sheet 2 of the workbook.
WritableSheet sheet2 = copy.getSheet(1);
WritableCell cell = sheet2.getWritableCell(1, 2);

if (cell.getType() == CellType.LABEL)
{
  Label l = (Label) cell;
  l.setString("modified cell");
}
There is no need to call the add() method on the sheet, since the cell is already present on the sheet. The contents of numerical and date cells may be modified in a similar way, by using the setValue() and setDate() methods respectively.

Although cell formats are immutable, the contents of a cell may be displayed differently by assigning a different format object to the cell. The following code fragment illustrates changing the format of numerical cell (in position C5) so that the contents will be displayed to five decimal places.
WritableSheet sheet2 = copy.getSheet(1);
WritableCell cell = sheet2.getWritableCell(2, 4);

NumberFormat fivedps = new NumberFormat("#.#####");
WritableCellFormat cellFormat = new WritableCellFormat(fivedps);
cell.setFormat(cellFormat);
Since the copy of the workbook is an ordinary writable workbook, new cells may be added to the sheet, thus:
Label label = new Label(0, 2, "New label record");
sheet2.addCell(label);

Number number = new Number(3, 4, 3.1459);
sheet2.addCell(number);
As before, once the modifications are complete, the workbook must be written out and closed.
...
// All cells modified/added. Now write out the workbook
copy.write();
copy.close();
The demo program contained in the source file ReadWrite.java may be studied as a more exhaustive example of how spreadsheets may be modified. This demo program copies the spreadsheet passed in on the command line; if the spreadsheet to be copied is the example spreadsheet, jxlrwtest.xls, located in the current directory, then certain modifications are carried out. DO NOT MODIFY THE EXAMPLE SPREADSHEET, otherwise the demo program will not work.



Demonstration and Test Programs

JExcelApi comes with a raft of demonstration and test programs contained in the package jxl.demo. These may be accessed from the command line as follows

java -jar jxl.jar -csv spreadsheet.xls
Reads spreadsheet.xls and writes out the corresponding csv data to the standard output. The -csv option is the default and may omitted
java -jar jxl.jar -xml spreadsheet.xls
Reads spreadsheet.xls and writes out the corresponding cell data to the standard output as XML.
java -jar jxl.jar -xml -format spreadsheet.xls
As above, but includes formatting information (font, number formats etc) in the generated XML
java -jar jxl.jar -formulas spreadsheet.xls
Reads spreadsheet.xls and displays all the formulas contained in that sheet.
java -jar jxl.jar -write test.xls
Generates a sample test spreadsheet called test.xls
java -jar jxl.jar -rw in.xls out.xls
Reads in.xls, copies it and generates a file called out.xls. If the spreadsheet passed in is a special sample spreadsheet called jxlrwtest.xls, then this demo will modify specific cells in the copy, out.xls.

Frequently Asked Questions

java.lang.OutOfMemory Exception

By default a JVM places an upper limit on the amount of memory available to the current process in order to prevent runaway processes gobbling system resources and making the machine grind to a halt. When reading or writing large spreadsheets, the JVM may require more memory than has been allocated to the JVM by default - this normally manifests itself as a java.lang.OutOfMemory exception.

For command line processes, you can allocate more memory to the JVM using the -Xms and -Xmx options eg. to allocate an initial heap allocation of 10 mB, with 100 mB as the upper bound you can use

java -Xms10m -Xmx100m -classpath jxl.jar spreadsheet.xls
In order to allocate more memory in this manner to servlets/JSPs, consult the help documentation for the Web Application Server.

Compiling

The distribution of JExcelApi comes with a build.xml file. This may be used by the build tool, ant, in order to build the software. If ant is not already installed on your machine, it may obtained here.

To build API using ant simply change to the subdirectory called build, from the command line, type

ant
This will detect any source files which have recent changes, compile them and create the jar file in the parent directory.

The build.xml specifies a number of targets. To totally rebuild the whole application, including the javadoc documentation, then obtain a command line prompt within the build directory and type
ant jxlall
As an alternative to using ant, JExcelApi may be built using the standard java tools. From the command line in the build subdirectory issue the following sequence of commands (modifying file separators and classpath separators as required for the target operating system):
javac -d out -classpath out:../src ../src/jxl/demo/*.java
jar cmf jxl.mf ../jxl.jar -C out common jxl

Uploading spreadsheets via the browser

Below is some indicative code which may be used for uploading spreadsheets from a client browser to servlet.

In the HTML page which is displayed to the user requesting the upload, declare a form of multipart form data:

<form action="/test/upload" method="post" enctype="multipart/form-data">
  <input size="70" type="file" name="spreadsheet" />
  <br /><br /><br />
  <input type="submit" value="Upload File" />
</form>
The servlet which processes this code should access the input stream directly. Because of the encoding method, it is not possible to use the request.getParameter() methods.

Accessing the input stream directly means that the HTTP information is present. The first thing to do is strip off this redundant information before passing the input stream directly to the API, thus:
protected void doPost(HttpServletRequest request, HttpServletResponse response)
   throws IOException, ServletException
{
   try
   {
     ServletInputStream is = request.getInputStream();
     byte[] junk = new byte[1024];
     int bytesRead = 0;

     // the first four lines are request junk
     bytesRead = is.readLine(junk, 0, junk.length);
     bytesRead = is.readLine(junk, 0, junk.length);
     bytesRead = is.readLine(junk, 0, junk.length);
     bytesRead = is.readLine(junk, 0, junk.length);

     Workbook workbook = Workbook.getWorkbook(is);


     // Do stuff with the workbook
     ...
   }
   catch (JXLException e)
   {
    ...
   }
}

Support for charts, macros and images

JExcelApi has limited support for charts: when copying a spreadsheet containing a chart, the chart is written out to the generated spreadsheet (as long as the sheet containing the chart contains other data as well as the chart).

All macro and information is ignored. Consequently when copying and writing out the macros that were in the original will not be present in the generated version.

All image information is preserved when copying spreadsheets. When adding an image to a spreadsheet only images in PNG format are supported

Date display

When displaying dates, the java.util package automatically adjusts for the local timezone. This can cause problems when displaying dates within an application, as the dates look as if they are exactly one day previous to that which is stored in the Excel spreadsheet, although this is not in fact the case.

Excel stores dates as a numerical value, and the conversion process for transforming this into a java.util.Date consists of converting the Excel number into a UTC value and then using the UTC number to create the java Date. Say the number in Excel represents 20 August 2003, then the UTC equivalent of this number is used to create a java.util.Date object.

The problem occurs if you are operating in a timezone other than GMT. As soon as you try and perform any user IO on that java Date object (eg. System.out.print(date)) the JVM will perform timezone adjustment calculations. If you are located in EST zone (which is GMT - 5 hours) java will subtract 5 hours from the date - so the Date object instead of being 00:00 20/08/2003 becomes 19:00 19/08/2003. Because java recognizes you only want a date and not a date time, it truncates the hours/minutes/seconds and presents 19/08/2003 - so it appears that the day is one day less than was stored in Excel, whereas it is really only a few hours (the timezone offset) less. Needless to say, this is a very annoying feature.

The easiest way to work around this (and the method used internally by the getContents() method of a jxl.DateCell) is to force the timezone of the date format as follows:

TimeZone gmtZone = TimeZone.getTimeZone("GMT");
SimpleDateFormat format = new SimpleDateFormat("dd MMM yyyy");
format.setTimeZone(gmtZone);

DateCell dateCell = ....
String dateString = format.format(dateCell.getDate());

Cell Formats Across Multiple Workbooks

Sometimes a single process may generate multiple workbooks. When doing this is it tempting to create the various cell formats once (eg. as member data or as static constants) and apply them to cells in both workbooks. This works fine for the first workbook, but for subsequent workbooks this can cause unexpected cell formatting. The reason for this is that when a format is first added to a workbook, JExcelApi assigns an internal cross-reference number to that cell, and all other cells which share this format simply store the cross reference number. However, when you add the same cell format to a different workbook, JExcelApi recognizes that the format has been added to a workbook, and simply refers to the format by the index number, rather than by initializing it properly. When Excel then tries to read this workbook, it sees an index number, but is unable to read the cell format (or reads a different one) as the cell can be formatted in an unpredictable manner.

The long and the short of it is that if it is necessary to re-use formats across multiple workbooks, then the WritableCellFormat objects must be re-created and initialised along with the each Workbook instance, and NOT re-used from a previous workbook.

Cross Sheet Formulas

JExcelApi supports formulas across sheets. However, please make sure all the sheets have been added to the workbook (even if they are blank) before attempting to create cross sheet formulas. This is because if you create a cross sheet formula referencing a sheet and then subsequently and or remove sheets from the workbook, the sheet reference in the formula when it was parsed won't necessarily reference the correct sheet, and could even cause Excel to crash

Back to JExcelApi home jexcelapi/workbook.dtd0000750000175000017500000000044711016653672015262 0ustar drazzibdrazzib jexcelapi/resources/0000750000175000017500000000000011206777770014741 5ustar drazzibdrazzibjexcelapi/resources/merchantadventurers.png0000750000175000017500000020373011016653676021540 0ustar drazzibdrazzibPNG  IHDRJiYsRGBgAMA a cHRMz&u0`:pQ< pHYs 4)$yIDATx^XT"-ݝ =tݝtw 3{sϽf!s^ /?kco߾A^.>dpٿ1G T}p=@4}cC{>1;C7|_s߿Quo̿ہo_T]g:}4?a 7/>\k} _򾿿 cOA>=|{b} "_[(L{T)5E>) ?bG!>J!_cO A6=B|pw# T?Sc2e)|w=s%-X[ւwr,|Q^=k;q}./  W E+>V*{#VND|ͤlոlըtհdd͈t͘\ͤBR̈́r͸rrZ3R7R7Z7V7^?0mi7Nt[@ imƸmʴY۴y *{7sV'O.lN-XY\<ol;@ӈA݋NgP[rY][>O_[Ew~j5P%bՐ(*((*(k+kkn\M||k5Z*Eiw3ﮃr m'?(yD>\=FT|^TlbggDPn|ufׇӃgώ}"^]D#L(CFb+|B1BCcoQ#$a!!AahEC !#W;"U9$ UOTTUF&jfefd&FUkÚcغ F #\e·NL z_$~ Z_..[YA`:h!# I+P5VBwֿJ2( ePՕ=_[NJKR tke!P_ϿO*%HFHA(IOjQ7 }z덎o7O%w"0mtm\8B!$IОP@EPPk8KAO_`)`4"\:0$ }@6IvBtP~LvPt3Q1\|Űbňr՘rr|ll4\7V?ԩҬ&#4d22jٵFA=~,jPٝF0kxfBA$YBB `t1H1=w1obbIF`>H{@kK}b=b"]Ɬ@-/ɭ6Z_[^Z_C N[?tz $ll]۸: 6 G %fϯ08J9ˆJxKF !.- Y$`T;ZN&^Clj5$kj TU}Ь֌N;SUVRӪi6)ڳFn$Ȱ}l [A#fO \@hw=y[ֳջh ]X XDԯ^FڵC`PE_7WPnFk9`!TI`(Z+V"W>!W?&W?Y5w"1Wěo ;A١I[6'6Oo0q8 e0(z.L%K>C(F a> F 1h(dŠT[7ҕ*?Hir) jyE5 u S25`ԫkk4k4jfjA@P#hG$)J2i5iF5B 1Zp׶HhО޳81 _!*ZۋP#0tsz440h䂇;;VTA`T=0CZo|֗$pg'nSN|~ 0:7`7}~|=X !~\zffOZ#09gz|Ƭ{ QQ !B"kza=ȷwշo]$@!B.^#a5"+DJLV}g5*X TVnv5ʻw-*|D!!H` H# P+"82D/_NlBHD1E䞡 0EХɝS@s "pgC A`@ ޲A rjl0L 0BIk$Q1)Q9$A:V W[rFQw]yMkXQ32ԀQU`|ء kDl}v5bL k!)"VթS[nc=8)ފQS>#!v{ {OjarMGD++%P4.S9&S=9llÄ"Y5COŭ1JX}ZDdpbnfHAIXmWh=۸ǺuӪ؆Iq1aqICYy!`ȼըPS=<`BS!!3g}/!Bs %0?_ 8 BRE`rC1HWףW⮯ڡH0=^A#j$B#ug⡽3!zcRrSėQ!!3C`(h :"Wk'^vCHBs 0EF6 غ2 :qkjM BA@0R0^/AChb)=Pf'pg@0$P9wP`$U=)SBJDrգrcuc H&~zW]D611%(.&1ϥe3ݪ7*o[[g~Diаu!̨uƸu֤m:#?=ŝܠ迬1D)A$ R%Z{ Fh7eP0" ˫@kV!Hмl/!DB@(qG0zJ*hQ5@mo 4/;17D#JH aҥ1&kSHB)x|+: ȿF8,a!ATUU#B#ȵr%Z1,V9"Q9 lkk@rR`}k0Lʂ6.>*+;9 *1 #6=3#}/lӴVnǪe)aIi`d:c5F筡]VyS AT?V=,x]#/%j@AW( _r 1B"E_YEwe-8uԋ%\_!#[M= ʼ{{oȊ)Bb(%GH+Aϐz#"$S%" H(u_tI>3CPχվK)6EOLn0 MT(:PQz J0 ~ "€MՈHXh\AUd̈`(ԎԌBP? !i޲c1,2FfnvN&x7gh﬜Čē7ZX7Эy nQlϩ9Qæ)| 85`B0:d[(ZD=)D^mi-@ 0EYQj pa,wаQd(Dֱ׈ $#Jfd{F(*e@Sg1.C6@U{$F=%^vЇu#J4H F0DGAH $]޸9C7K~<€ T" /(L*GBHz  rxٚ1ժ!p:`݌+TLy VzA>9iQɡyɮŹy 9g;n={jVƴyĴe4n F_g전HJyQе_g+.BՔ 0S/!JV@B⡋-e!$$82FP DnRnnF2=!`x5BUO7 ~FyQb%%T) Q EIP"R"B*3DzI`.n^C F`(Ǎk&Iݚݸ3u~ֳm `oPt(MQr$L!ItT|D|r1I YKL vz0RA J3heHf M3q|k* ,jFCcSNLkR!K/-¬*׻0;4>:)*&t{A5?whn4kh V'P#K0IU5TT("h#Pk:""&4B"kQ Q `z~wvګPC{Iُ GF˟n?#(Fhs[M`j5DHHX]#P.o xe$Fw-_|K .@A%S1![9 Wq1T&tXQ%S; @0"o" (Lͪ5́;Sjͨvy5L6~{(hD&.,ȿ,qpQSSqq rEXf'䦸yf&fU5wsW ۖ=fsbFN]KN] ud{,@}DTHoF!$A?bF(&G3n{{Hu 5rs?1" b\ud/{W7_m6h~0"JlZ =ZiD3s$HA1BS;צ?^AubtcH5M:pta?{0$H] : XDn$__3FCgF 7ek6)hُݙ߁:jnO/ ͝y1B@RU)U#j8DGqF`zAlx7\ӌffSǰfxENHBW0-3LFKB,=,|||CNIhԽcЩspVHHu.z֝Ϭ#>{v,x.\{{&zfNt𡌅\$C^ya1Ra}lMXI#^!ABʌcW㯬$^[tk7 ˼Eʺ})\. )Dk,+~"-3V1 !s ψ @Կ#QDEڑLlP!ݱa5BkJօP%چz hvsf&{7nL͓/?^^z6d 2X$*UIc|@]!CT7J0E  SGUa!#- :#-%Uy88QvVUZJ@Æ`dfbegebjmajafaV]_WٗsvLS7nF]̻w/vA\es=7 UM;.6ΐ]$bggPj\ϻNx׻=){*h܅ЖnWԽJE4lE#|[*Ks R+[͹wu! CVP(vh=uQ0B:b4\)}V24(ChÕ\aL=[:5`fY㳵кآTY"t0@ E맇HCݾ)Ԭ!*B4$hЗ%#ߛ'ݝ[@~:ӛWvǨOOSTG88WW|͜VfNfW;]?4iM54,k6B4KKUW5;>~>U@R9-5Ram$ٸGU6=[sf^ϣg!F:'!t!ny :7DM{_vwmtyշg!BٌW< {e-bE8$JX3m5wuYY].OF]zP@Iw(^ ֈQXCzJ#"σ޷'׿@!`u`u`$BHzΣQ ΀!0EAHԣ pg@Ѕݍg>ݘA ` =Xxhq 쫩_LaSSDj 3*PjWnPZiFaInYva~Z`ȐN 2'oYЫ5h\yzR+ /į".r!CE`9 44U l.v֪M] iSR|DAiaiK{K'yvm@ϤS2ֳ޷=Š>b@A+>{ T>ar{u7T{E?[/OXOFPgjTĵk]E5.e\\ A, ٝ D1E0tRdPn@H;Lj!iþhz 5B pg$#.eiQ?2JdD@Su RُM(Ais[S0"?^|p 'G3k+V>a4G4gԛԛ&ԛǐYe%Y0B-MF mks.M/M1GEx`ڏ>FG0Јt6Tvqv!yYhk` t5UTčpxw[ܝt|L<ZMhgnInՉΌSο~}v̽{ҷo吾>RyšK*T"z'2;uܘ%p"jB2bڢBX%MSU8[UsW Fn߸rA 8:.fsA$bHFvS>@byjdjоD,`DӱlCHz?C %BBy`hC)%9=ٽw/  ][ >t~;F-G\^%\ȼw]JEFA[WZAlb媢'.\xŶkw.O }1!Q!ïh(<~}Le Abh4 5<'S`1?oHsEi@BA36=yE%"'6N)6olߜݹ5}g0Σ'OV(xldE9ĝĭ$ݖ .kk1`^ʪȢeӤI x JeZ%Ev=围;xOi>#+,r ME`' eIc |<6zf68>ldbldofgn`glil&dhSW^zJ۩g&{3;G =OFԻٷsq5FpRTrհ+rj8+EyM91EM%}5ecEy#Mfִ[1zJoܺpޫa C7P'Hs(FO $~o,Ԩ"lw lxsv(4\f@WnA`NFS(F6on!$ >ţz zJ~חWkm-OȯHd :gNCz B,V :;#Zz}j8<}k4y N4ڄniӎ Ƕ¶N Q|r8(*&+xXVۉ`ikfgcbogbbifj!'%&/nghjjlbojblghgmodldbsr7 vK-H/m)?U{v}C!3qqV#/] G\$_X-IIkRSSR*Ԕ Uͱ6pOU3o6wz]yg..?=bhVB4oAtKv[ v9viJ."FS_)%ax~tB"4~y IA'uD}Z~ ӥg@ϋ T`ޮzD7{~h&d޾mٰyѼfh 3zkfֵ?9xv -5ׁC<`dabg?bde376Z[h8!I[CVSYDOZ ~f.v^&.&v6VjN&6a0_RZ[{L{o3<=&*ReR͘ޅRJ&J*rjrjZ68GmmP/u9}]]zW`%JVѤ (w2 0#`WP(#DH$v9C~G+HI H(AAݨ0Hh˵d:m @ ̏`=гm!:M+63>lإ2 3jjO\myޱ} ^1JtL,i81T|4\44R8%9 ..zZ;s@{+#]5iji+8:ᱚʒX% ceF^?(JMvzU` 2 ).Ki*>}³Wd^8wu%o,!@XRWAHJR]BLYJBM^co`Diz;5&6Ԗ՞8W{Ueb` CH]F` #B2$ " =GAC0?D&Ѡ :?LY"|h|e֯N4M3 U"46[`I/VȈ5ZI@ oQ9DA =ndc xӠuaG)nInIQ%'"??KAqXaActiE-u>6r|tt;kc-k%^ge3ū8;k*ɋezFNV:`'@#O+W3m'S W53Ѱr0 ss׏ NqHOK͌J/ʪ=uޥ]|*BA#hE$VZR]^VKIP[JGLMA%xuV}qr}MqɞK/+nS!!m"xQZl 6$^/"BFafQ 2 KM_A;EaU+T2ĩ!!PQH@@m0t 0@g@ߋ`u,t/+6Twv)N .O(Nv̎OrMLΊ-*ho<&2AnQ.!AzfZfIfe~eA^`7{).^~F_X{3 /."en,MqjNfXKm }s}gSCgs#*05Tl-T aYLYru|}B{~ARYuiSUfQ9-k\~k/) $NIV_M(&wTi_{A_wo3WxgX3B?fd0.j4Fy{ڴG"dd+¶Ğ2vy 5"kh#D9}h( ݚ5%PF`[#"hڻu"=iaLhk$ tGPxya:MBXjVMm{YCnmJMJcj[b_xbDTN^ns7! CS?-'eA~47AnbRxCnks+s-m U9) 0ᱲ: c=Gsc^Kb&[-w4(%*#.963+5޿*/*5^R/b`iSձQQՓUёUPIe4)v+n=[gњ},;*Ԉ0MDB`, }OОڍ(5F$0;!G2Aag2h!.F$"eF!ɪs$pLLO=^(Yۊ5k1<2BBWyF`uOUW~cV]N}AmQ=>f$df&hb٩iSsC\ 1E3۷fv`|0b6=о@BEV6(=Bx'} $!#mׂMVm=}I Y^n!v NiI^Ei~u)^-y(z Kn/o_|$5#j#tP#QddEHMjN}@?XR(;I$TMG2hvG h~ 7v 0B*FQ#HZ>@#$iNv)szβs)S3a';5ʢ#&Ds^OGHOK#)ʷ:?85=Ҵ()۩8$?ɼ~f|I3>MEs^08(Q.2xmc=%1te, &6 gk]#=,B}\l a`m(kCs qRPccᖓPQPA,%_jݣgܸMK/WaPDEFp# !sgoN B> Ǭ~Q&iDJg:59(UFPʌ;њ5JϞ;/H/׉/W_ _C"% oFvF= T㤍^.`NA; 0ٟ%tlg:OQ׬ۙ9Â8zF~VzrrKVQ ʏ(.I*"T:h0a9Ds '#`Hg}i%pO7w{gi1hkȨsFF9JI(h˫YXaMU5T$qUF:Jzfj:zX{s3`"w;SJTC-8S{ ,T5}L}}lm=$`਀@7[;m9yc"|L’JX9m%i-Uy}շ \}ݺGcO^=_{\||A=#4@EnQHZ{M&)$@5ikbsk=J$Mol\wm03v`Nςs}SdY̼('"] M:rTGiYeiihH "4'8FYdZH9w0'9dekb-/2!֘k rp>fZ*"j:zsC[smpX9=mE tJޖxU,H+Gt4t4uqt  35ebRDR)QWV8[x|Eߥݷ=VXj,S+2J krba5A+Z`Cգch`{tJՔ*05RL8 !0uhP5B һ yp  "$0KSw>oGđuWs<AL)B:k:Șs7l4/z8"zqf>t0"+=R|깉MEuAii1lTaz:#q9`l$c.m''H(/ ggwO(L pЖQWWZ17R1)a!627Ҁ$e7>  $!xPwst3RV咂i e9IY_S]{O?x2rbۛoHM9j+bZ?1Dä֩!G` )C,젡Í'@HLDCh(@hR4CBZid m7ׇ7VG&vm(y\Ns0n %ѽyz Y[F] bpK߬uB'=3=/ -qp' 7>&j&!6.40J<'`xiB͵?TDH1Jqk(DceYSJrM9YuXGؕy%%8yk*+K)JT&cDPI+&.S+*W{=O lLjLԅE8zm Dx$ĽjBW6զ7UrsogΟ|=jbǛhF4a:ٟ^4e !FesuwVq":ΐzaAF`P 46wB6r)^oF@ķk @-vxj͇O~zwh{g؍3z`pգͯU} g-ؔ99A  ^AuE-4Ԭ촴t1L00x鄕:tP(-<`В2UWecd1V+Hpi+&g+K*JG{F@SW^A \Fr8 =eiNQ~z[h#+#Bn%&S*Zj;S̒y[{XY3CyK} s1_]m]}B55%ĤD][j*#ʣ *Z:o\}Ӂ_uzЧ]H~5J)ǥ5F}O͠>V#hi?F2ӈ"houvHhc iAHPF*ה$k[d4M3|~gݏn x4q,x$<,,/{=`@sA̔VؾSab`SCEOHu7A*#4G9>Gs܇a)J9ZKp2lWM0UӒgOH'`expr\,>6M>F l3ҩ +II KsrɊi)HA)zPWgggFQ!NHGPJްsQu9 fzMX v&1PJ\.;C}#EĨ Ea Eɉqŭg:O\t΃K/_y?{yf ZN!R9?tmahwIadW{WTDQSDeF?!hF^I&mo6'sgkpOI^x蛅!y]] [=xv.w__OlfSZ 14|tjҢ‚L YЂX[=}9^QaCG88$ؘyte UM4TMj4`2ƩA`ao% bjwFt2 q^'CpjP?pu^[wPgod`f{vխ'wf&zY%'5V7TeV6Ԟ:vNk#k/Y"Mo.@d1 "82]Pe؃;v{hdw~!1B۱wЦB R^ܞI>%/4+tf 3$OW]?x ^基tYטˋA(ʱQ f.)[77L$\ i{ gN(qVYceMu+ j6#aaGx6jaftЉ)Kq3iKeGj);cӣ]UDC 3S*Hq0s2Or61WQ8ʺA*N 12pqa jXHO]-93=8HK6> ! Bp;u^NfN\#^`c kxX-5Sİڒܜ({F6UTdf%eVut]x«+sW&V.m^$7px~уݞY!Ggu RzC+/!h`4FD!c!D@\^z?AژZ_ŕ[W^yIuc{Q%-X5S-UMyI `ka5$Ep*С HKi8D x7}qM,Lt,]\ ; +; tmL!>!~p?BiNtCyFIN|nztZJDRrtjVZJ^nγ^6|u?qa 1EݘE`,Ѓ!DBP]z1RKhn˾;ZL" 8B^Ʒ6,)H021S2VU7bd(#5kBBזm F\C&&Y,-Tʚ26:*y~PC|ڵwC}_%wobJOߙ xu1*K9PJܭ;wMY:~gc6cG9b;"UdfR$A t` lH<:D%x̘9N1!/+)`n(*)+ʡ+,{USUTTSF y)^*6iQ^%B" l2,\8.3]a~q#BtG!~'}0%0?JbaWVp98YLLt` :(î$t}X:DǺƺQ:YZXZ{dfVWEj+cCKrBK c㢽b| Krc"<||#}S_;ܟ]? k{Mm׽20Kd0d W$0B^H`0G l')!1ʠ=1G엓4QA] -1Q>j@cD( ~ x7qbx-Ґ!")uNI!IV67S[gOm!MG{7+WīKA-!hW, =Sa .v@QX]AY[aZQZh#Cv!"jio`jnledeje3PЂ@?;7(`ZFD8ŹBl2x{<%UID}Q^pa_i^PUqXiAPnGa_uEdeiD~vPr,MqMNOK (mm񧋳Ѝ73H=^xhy1|e gTA 5 5T6y}Gz~c1B}Chەf? 9&H9C@{Ok?9h}uj_&[xaecom=v5Lݩ仓 w@ɷa}"t98f5>)91I&Zv.j:6 qCRŬ$ ݒYiv^(3;{Qaa wp?5'0304eX ]M_+xXw vDnX]JXE^15!i \CoٞaN:N?70tA| de;rHF 6}0D&T jv>v޶AvQ. 11.!xՆ@ttqqur2wt2vq6HI+!҈غ<$ʲP OQ١iY)!1aA^~! go]9ޕϖQ!"2{͝פD(FoWȯ {K\#" y ֣$8sE` ? 5y :P~u2dmmO?ȟO-_{5z N_z3~ƭ+ifS$ߙN=y{*tYI<08$Mc*~QUMzf[skM5f⯸+7?( ~Jr ڢi`VA[3PARFKFRE05A_5//.=ĵ>/$3T.?lK|?.523$n0&)cj$g ivw7L#+5T%[jq2ceea:?W~<:=ixm7<ڃ{/@=&B{sdߝ)3[xg"ܘs;H'N =~jCu%I~ ?qVx"'!cC@*N~L}R2347V=zނ^,=# ѣ",G< cas-˼ 9GL:۫-6[%/κ6& 4Mr@T5n":FZu pRrڸ¸֬hw"1cxai!(HK' Paf֐s 2ױ15p5uwvP"b|]pFFffșa>q>yae%U9gWjMnMlJk)Ϗ yw`_tBL\JRJnVyS]ӗ߽鉱ѝ/ϗ(UGd Y_A}R0 B=lN1H|AO;_>_Va ,-]\z9=pλCc}}o޿5sƀ;罹tS`)RŜ 9 _({c b[n8JyaFfuiYcbN1!{44qY@hڰh˳FYO\&IF B LX0qV8_d/{hoxX_@{2o?[BڒBbc5EyC\~Z~{T00=sZ=N@[|m#/4Dxmr4Pa;l"G<W f!W=ƥ",#b Y*VP|mX CGG+w;8*<5#5$?$,0,ק :9Up.4/&%!4:/"?$7*2<`Lm>s̉־/"~R/V^6@BH. azglc( h5BBCl4NXk4Pi_WWgwv>~dtӱgcu=ѹYM}\8qV`rnRisJy[hF9,FQ&:GSqq HKJY"Rx-mq Ow #|t,GNf RL" <"LtbGh!⥥;rym\u`s"=90E&չ*Ӕ=l]$NRHHE j(Jmr783CinsJKa1c=CPU@vzZ C92bR`deb%*YXxU$š: E(Dٚ ;HX{8S #8χ@rJ--/..m* =^ZRQQTVPV[ZVSicm}ɾwMN5q6h0JMJpP_F1BA@ HϟF> -|XZy3;`pxUS)4=; nsJz^mQ8.y\x 7eO/U~Qii%ܲ3w{ CPX`mCZFZ魭mܧ —_.qz{}t}it}evks>x{{fssǕ_gamiէO;|w ן<~zkn l?Y-{RdrӥgO*ε>)C ÐԴ T$eDE$eaHOGII^1dEX8iGa.@Ul %%{o Faۇ;Be.Yb褟o+*=Q\^][2 NFFL_D'R&Va]}h8'coFrf DEie85}.ԼT]++5V>I$0H@EJENLK3aՔ 7/w#NOEّYa%qMq@UKqhWmuiPÄfRBHX_vNZt\{d\D~I^yMiAUahjTVCIϽ}4$eHb mP2 & i˧ůQCs@K?3;-"4IZt>^iH|???lMwÇ/'GWW/{zǃk`*T&V"<_U\:wݪSt>=-7=+$Ueyqn^ j 0mhkn)!&+#,//%~l55$ 03_ -5̾Qeiiyrevgeuz#I* /7&ǹ$zHI*Dd$%dLp8'ߔEY̔YFr :?oOwX.XJ^h<Әeța_k&a 'jSf8 xX<&()Y:yAoijS 0cWSQP쟟Kpv'O'TU$$$''Gǧg$Ex{4UTV6%gdUsg`j~ޫ?}&(Aԩ19ԯ-4RW~+PxYu67׾~X[~2:tٳI"qluixqqDZ>l|umq#SHZ,y4_|Je@a`Bíjf.Gcj՗et y1qIs H e8;' .ޙޘ$֟lꧭ坍I_?b/ʟV>}\7 4 lZ.1Fv.# <|6x3&zv#" @1#\LBbLVEDDETY^LPZCj/h=rMpUIv:Koqf*&9>!24$6$ hlT_^(q"Rn9^slѕuyu՗LِT񬐌p_0K{@hWoRBD_?mx;`iamzˁ_{~8DƯBugۿn0 Z.u]i{bR;#4wcfF"C4Й)J3NXy([3b5e8$4R Uq>h <"NC/rЁrpt~|IZErUvugU[+:9#>E$գ("JJPޔbҒ?UvxUJ:LJwe:|>D[0 ';-qW g~JXpZ|8'0;jmxVe?=nm 5u"ͥ(jW1u#xy+Qz2 CEy$ٸ`CuqE-9Ut0rҔ]G\T`r|HLw\gfz@uyT{cؓM]MQgSN5Ԥ֔&fA204ۙ` aXxNNRMMASKYs{Y}[YusYlzoX`LZju{;MN~J;  T`+f HH48?8;E,L,,m7Wg m"ءvo[ LwKmϦLx|n*r2p2@Jb8liA~C]=Kcs^zV >| al5,#+6@ !DM{8j = DؠwTa I fs)s$;GvBiq[V]^Wmv2%/'0Mk" )(@{_AERU'ٻlIhSf+ =yq A#Ԅ\mEXDDk ݪH40v:</3nN.™'w!J4Аfc4TURw2ķYa5,4=-yd%常عŘX8$5 pZP4wu JNI NI -h= f-Lk:<ٜT^gsDOfVL]}~cKaQYjɚڪL`{߼YYȿOf߾l3$@S% 2b ϟ~ӿ~ov~__0'>\X8|ԋs/ omxFsI3p:(Apt: VVx?#GG+qL^V0_DE 8$LϢ-%'y9|pB :PѠ$ QaYӂ]R`d8owS0rN$V[Y $-i9]9@geq 4 $1m9Q+qI6r+0+i#AIpNiteq䃋I..?i7W7<}wo]}tֹb<8EECUSMlzx8ٙ@]N2AWEUJ\B\RlҜ2\br|jb jzPXx'N6wDnjI8ݒՔVQ )aUU頚֎¢Ј̔ŒҖ3/'F7Cl.~&@p(׵յ۫7gWkons?xO}!Z@w0鑵=qoWO?Ҳafs;<0PJP1ëDxBf_kԋsa%>~a 3C eE%E L1r #ŜlLC2TpO'Ct59tcʩ䲂ؐ@))94'70<.2ĄTob _'BTfZÇs[qqf4Tuv{ejc 6yϿ|DIi?}7! <Us[kKӣKqg>SgA?_#%՟Wңbgc8L'--K vF7am` A~Xt34Ԇy4]i)^d ԃ= (`ok#!zjH12[bdikbdg&c#/Kl* 'eGx+˘(+)Cj'kYkC<ь@|yi8M1%9LJXh;}q:FY6(W%&AW( Aql{?7 "ܼ8Ubm++$`jqjAUG̖`Em^VPW:(lX'Ըp-u1=2Oj(T[^14z|LՄ{y;fw*ol̬Llnmnʃ;@7pSsZq֗ -} -Dg&nWmy/_!Ǐ|?7=Kǜ{xaxˠ#ӳ/ۯʍTf<|XZddeexs3YSf;t_]$.-# `#'-).,_RNȗ rm9!ϕ^j ֹޑ7^wEu9U!PʪJCD'L2ՔoN=ٚ|=\WZGKJKC* AG/:~>)!.0-=.19&-,-&=2*%&]-O^۷_}!/v@wCd]g>察@|o~Ϥ/k\=zjhv|4?>r}|dؙx9ѝ ][2pɌXӾkcuU7΅s7%qJ .)-/&SUObΈlmjoNko<5$FKrB`jR <@5Y7eg&f$$%ظ8G&&_[HQjB 'lG}c[_6P_?Sړ7'cOgW-nޙX5Ze `)mZzV um17[UVXΊ=f:,$G0tN Y򿏝e52Ur *qEMs"\-e2c 6qv)xGo+ucUQ!MI!)6irgyR z3- &*_AuNH@]{aZRcFT<3"c%NcEރʼ$9BM*Da4NZZWey0?`OY^^>'+49Y47$${T$PuxrE΄;w:_\~/ҍu1vnt$9,ՏK~3\_?cW[~l[On^OIPANHWN V9ָͿ(|v%77H"=M}v!م|?+%2a+4,Ą8[qqJ=?8z>Nޙ)YNyj̦rA% nen,< Hҕ}x:/JbNjr"坭 {WD <|Ƙ4륷MC⼴>au䦗:{]=phkݵ a6#eiKmmmY%E!I5q9K- g7hf';R\S^VXQм uAzv^zRzBNQȫ?/?_Я_+S^=wW/9t5hutb\qu%Vqx-1V΃pt>aFX> w fPF"3x6'cA\<ˆQבs25ǩ|]m h&{8`c=S@JI4Q^v~q֍p(K Ju,Q8>fD_ -uq)a8͎gS͂tԗxڗq;\w VP7+?<ofnL㵣ppIm'KQrnUF&CRS*?l1/Ͻt>71:;/!LEWhw=k8AcEX}E}-1#@RcWWR-֒|%CbUjh/=5܇k޶7O~s/$ڍ>ݜ~4i[p"8XU +(BVKVƗ`V]sxSIMeq64FGEF%FLoF~ L`l6 H巯aB1BHq8;8v}Wz?L yt\ELMSoyߗۿ}/kgק7z.u'gƟ=yk`*cR=mԥ0.xa*CaMQ8PPQMA5P%B['F ,Pdn[( J^AJAΦN.0)[1^fGz; =,u8YhHP:?(LmT'XN8X^P!qfrf0h`۽]LdD1lon佺Qg_̊0Ή=w!LSSOQak nr6b|wNkH [YBD&Ҝ.'>SИx'.X[Co9 i~VU߾N~}ᮆO~o'go5=깳Ue1v&P^Q <̅f&Dw4UT57oHOG="#\=%?PYHȷOIىX*Jj,7,uU$`u,ߛr~fiQ穞Boy^zVl!loL( r~x|4#\VKKQ0=#͌XhHƼdD*B{iVnxzeyNɩڬ͹ ? t0YJ3,y~:/Oč١NVgG?vvor /Nu.h*-LOqst  vr5#Դ_oo۷?}ş}6܇n<<=anndgS\Jk=0pC Q F0'PQk˳ ׾\89e*<z&IzvFx!T򰶰ipa´Ϋ -p ap#T`*f mfN(#A:VB@C#HʈA.~접ݻ /K}``AZ{de;#4dTUt=\dd @XezFI/OvJIaa-y"VCD}eb/hcR윰,$ݹT*a]WM0i/KpyxEأ Uae QAyi!fgk._ț?̗W`;*O?٘|e]5ow80ZUNug7 ^i|u?O'kK(K].s5m,U4I )I.K٦` go?{`е}׍_VH;־ N=y;`k{:[ ˳[+FF^ _=Wrl++ pB8C0Q &F $e `k`퍍-S=[x7hdzXL{J\д`r6 vw412R8T#!\C ??J7-=%= ~\!0NVd/'PenN.:oS٧yk*e~P͡ϦTzH3)rj\l&ffNў&VYzSVjla&%:mV&$X&CTlCܺ20{ B0F_pR8Lt䥆[xӒ0?[5p&-/TILEQ'Kcnۚ^>Xy >F??̼Q\z^_թGr'^k'OU~` .O2ź`/o/ [W榀Dπd,{Xck_ G_ w{wޮΎq5(@?)teΑ"GtŤcMM]ee}}, Ǝ&xee+--x 1CC $銋j jJK0u1M tL]I s5Y?k *b`b*&.! 8{ȳJ2 W! U6ڒ~O;x()eȱ9;4R \ԴE`[.Zjpȉ,1EfTo3}nkL=%&2 J:b&W"'6 ~s` 6jcn&4EϮWvՄlMgږtT;Mn愝zf+yщS;K↓ BJ um-YzÎs;[ Vigy]y.**yiM|8o򄈳YڊX $EwKJbpX OLBrpDX{`-#Gm#WmwTPXɌKl#+ Va<ʤͮ J&gҸ,Nk ")Hb"pSBC2ɪ=,FJHBG;H⦦g= J\)I(汸 9h8}29*G>uwCg$#EvBD\m3ci5 G/yN \a QlUZyrߎ&F) uPt[Q;?#9@GOE0k`V|47J ac,4Q (k9iӢ_eǤx5'(%4fJ]/> |Яz!1X^\V J-:?I>سX H0-"Am{OUطS`dvTV47м2|*~xa0mL_{k{Jߣٸ5͇oDrsc~D[} -onPW|[c^;?-ie=;hoxYKgQqG{ UWTW` j*Cs&S̤3Tr^c ۭPC RuYvD`Hd > Y$jB GORA6`,qBRH`$1Ґ$[&p H A+CȮ`DAX$=Cp8u(Q"}<G"As\cߟUB"I܏^'_>1OQO{őbi`l;TiJ?>U|\gCb'}xRKqBV_vfCݕ  z7.;3jἱ޹4lD7:jGG ]]xb"sWn__gi.mMu7Gxzcٙm=~ x͝]\>ᅧ?gNݳs!omu|ZBt뮫b W˹seM\272ٻLի4y#bd4z 4X,cj[kJn[iڥ)5bnf:0;#5 -n_;ieRlb^HfrdFz6L@6;4Zr :$¬S'1$%IqP(5eB,l(fp+Z(ڢ|Qa;AtC _4>nS!jиiq:UɐzTcSbb2J<ݍnOޝPpŹIE/;~#;VMOxř: eխ. - /Ơw{{|pɛWD%>yuB Z/?Z+9 ~kgmq <>H{P 7Z1qBԥY55q8TwmmHq}Sô2rBP to,S6X﵈W/Of@Β>{BTc;~ ?)8 F>wg3"Mi{1gڊ\m -~:oa|裧O)x~`uyKj22j|OX[58{wbzDZ9?<871 : ָL9"S<bJ.MX S[lP[N9 nu"  I crֱ(a6(Y\9-3_;^t-H(,c 3^KZFM?vAʅisUrUƪ IE:Ѐ 4:'UE]Rk+)ż/[*~x4_7ttk/QO|XϬ ypDԫԓ>?kӥ?whܜǾ|}|{rw-u+o]Rn?ʮYG&GQ]ڜ*#mvʩdPO1/bQ1텹B3HJ,6'dAd|D'i69%"EU%ޓrȀR)ԃsYIQwGaO'-HFöWaIfB. HB*"D ~VJk/3RPC20^d|IZSAP+3Jk @R> IϮw+[}XIu-2d}~ڤ[aڙ'ROf}u3oLˋ:a݁On쎹C$Oό{ͤjPeژ ֆJonZ?ҍUO?~_~N=Ch[3z[׆/55:oT}|&ǖ!5PZUP10硥* *Kgƛ>΅/ODZY}rq||DG- hR>:cH|z`+v%Lv.9?pP5ү?JHTo͎HE$O5bNk^cdoo\H`aNQF|ppe Gsi\B+02aMFOLeSԌCGrDRI) )6 |)Cyt*4Gz䀎d$ᰍ5-\W0֊ rF! JD ^o7BQqd|FM}:tv1$ r#gZ߽96l&EbӋ+=f‰=nۗ{R៿3bcs Gt1aIK?<躺Rg#o?;=oo,֕:- }l怍Wߟ/S@5~b -ʇ&LOW(@>١w/|zkĕ7w{><m޿'tq,Ig|X}|q~l}P/%R΂y{-g_=ۮ+F]]󛸧\ۙ4wom*gOε׉g?yknK ֚ ɿ(b ?%/x{YKɐӠf@m >w>Ce}mV7Ѳpu@P3GZ7':nnL4Lusk;o\ۯ޸ x!(WRLxrH1~S4;<PKF*9yhЂTdJ "Qn?xw?DkeQZREl>Z֣T6bt*D"[˽Vz:^df$K^{ɯV)ڜ.x5} KR{?r}|^dkJwּf>pmI/?=`Ǜ3?zx}!TH;|'hQeqkp Щ K 2M] ,o]߀"Q .@^C3.> @Ըd0'y9Dx} SC}GEff"megy\bTf؉v(FDFPٲ0h UCg5!& }Oஐ8P3E2:;c%KdPg[B:<״f%Hb /+UtMAƈTM-|xvkd_?=;tuU=kL%FYF|l5XW_/zbvo?=;3UMN VcFt8cV*T ̓3r >}9xBv}e۟?52߿ޭ{qlZptk &(LWqy u/}fyJ2TEgjJ[FbKj}B%L<% l>5T7,$&A5C!7dY$e8J?$HϥŧГXLF 7Cȫs28L&?9)FaIDTKuzdlx&`WFmQvUm57-'}No>+'{X)1OjW0 Cǰh@ͤ܌©ײN;V6qR:,7")%G[d$# E"*ʊhrNK'KM_z}ٺ9swPy{R'~l.%b;:-{CݵVLB reرNos`WW?ym56^m.+Sm%(/7-tVO6UY=;ٳs?~bhc[mk{磤yss[O.֊B_ v?y/A^Nfp*`hkhjB̧p$,H$)[ $IRXHJ"`9"ٍN 5y\%sO{Kx́das$At):>XtaYE,:RSr㱺ŴHqr)aAZJN 96o~VRrCL2Qi&KIRZC Ir3rI4;c]YS A%fwW|;{(=_8%|.v,cE,/E7QXC=I:}x=`0(d큍BLO/ , ];,<<3P=7Ss>~cz>އZ|N|TEI~w{iّOeȖa~ww M7M7}ݙg\վ`MP#%\D#zvv[[VaT{no>MPW3]:{<؞. VGmWYJ5[WX4\B֛PVQaDV$2*RQ(yJXE%grh,)O hF_mj#XANڃaS@@F b4LXPIGx t:'D&8&|˜#=ʅ$7OvBލWpSWAlccĘ0t-ء|.MAυ =H"m s!#H'y2B8/fAIƒҡ(ềqTlOi d( 9{-HS xK-!Z5F߮ 3P򱫩av#齃 iww[r4Mmkj5^垶O㠀ɤahK?uk_npH#ۓu $]= OKbנ><7@ĭ&09BXlL 10zfepn&m!ĒI~UAA HS+**DsGR!;ݼ1TεE8*@p/o]ɻn,32JRVaT'Wsz|yUWSZe]>UuiD(AE/-@ d .[c ?egEq8=&1T ;"i. E' s #t$iPE!D4W+B[ >u(R(d{_âY^{4w#a-NsX 5y|x^X='I|qL(RYK^;]/7ckxɘhQ2V"Hy`Ea[<6waovk}5(oi1يv%}Z5W"`JnJcVWꨪoi6r -6P-h>B C"F$ us(Ի{̨,T: BHܥECQzX yjDsbOBoBTg)z#5wz,wsy U u]5npq]{w^[zv}2:R[/Zh6]aTT ^W_uK9;~nډtiVH*BlH<@O@A@C!JFARJV`hE~ Xu*)d<1.H *̡(LJ[z- H|z?3եOlak_zvh;W~o<.ݟs7τp7w'/ ^]Xk>;5U5];VV@G[ |F!Bn<%1gPVlwWƂuWW!:!a(q4xmJX=!&"‰dJL:=:<=:J;@9#Hx#:| |lya,CnZ8 GOy"_b5j )gJ{e/D9vHN7?>q2ʩ6ilsnkn SuFkV! jšzX?;5lzd a&DXZ 2܄tb|F1kk_=+{Bt2z*y* `1@D"HY !A H]ұ KA Ѓb0ߑh/,$|qKs З_M߻YphKPGe8D>?xgbå!_ߊYM, : Hk[woLOu :AW B\}ʍSHWj%0R骱p&U##P= l4EjN FNRr)q餘4$Ʃ, ID*x"t*=.cAL^CS`aP†5Ik0$F|W!Л`$$kGG Ht4P oXJ#3(*zJ!&@}fF.I5r4^#äM ">=ن`T٠ h(krnU^}9xa#VzugFl;6G0W2;JS T{kM6\뼺|eikz?xp32= ~HtpHPgkMY{]E_C]C=|A`O͕@I4-E $QNgcYԨTx&T;'!%J:He \Q"CpQaot M@ҋ$,?4NT^$\NxȇQIqPαc $ < p! c4,WPy4DTI. 0RR9j:O(,^Z8;7'B*Unf}ԨZTԲxI$VjfVt<'ֺ"@nID&@OWnсr7A$B =pW-ݕ'|Bwg|k-_[FW9baE;-]^n2|sw&B^qm>N睍7V le-Tۼ s δWxSNh V֖\6u_(ZUe ₶=u7lMDfpsB=gyi~:Ln):r:S@`Io?A O" {"HH"`9z=rF{qB$̃PCJݷ?ATǎ{l6k•Fppb16"/{ T|PłE$'=F2"aD6;)O)2RDp o))tH q(g%d"+b&)qYt%2:J'1j7 N Yī40,tx /-3Sk}6~}{࣋]v?Znzh^1 gCX.^5]kx=Zh|ʰv ѵRXQbTJ XECSؐdSui$NJXqٔ)@9>I1a$%1N$ C5|YTyey% WܿȲ_dߑqHn(<I' xE CGGASR_;+,xNŁaq $" 'Ngl^x^ Cx#!GN2̄,Nr0T&7) zL<&sDx,&$X &eC䟖 'L%FcG[Zx N)D\!;Wa`Ʃ@ ~υKC\9 .|//v{7jo?^kŴS>'m嫓՟\zZ(X~~o~&Tla'o{JowqhsA6Pq*̓Vj֔{:ZBQ'Ѝ傉KOҰ HbdVB.5:-Ner =C6/ CKxd98%ȓȇt&SF^ ` LN:*€6.]sp{[N sg5խ;ewk޻00/p 2/wߙozvVVSnYD12iP7{:Z/P ZQӈtR92DvUc\QMM֛6)EhսƦs.vTVfӈ|褜±xYTdT0p-EMa\[hꮫniaLOH!wRwٱUgG*nt___ =<1RϪwgW1VEZě%:6E3_chseu/ot,>S9XedPAf=K3h/3q 6A'~r;ʦB%$K͠ggIDy"=&X/lE $ER%)~QCHVhpNurd0pGxGw-Խqr:T:^_ÇW܋E]K-E\-zKl `whUF cRPB>Et#8legR`dt*#3A;>(x0#BSÓH7O Oz"ۈEH-rixH900zp(@MNgNLOCYO(5zll/ <± 2d?@]fYr4:Z| )koiشԢ/Wd2g sP WR3'e O x {Y o4i2ax᫷wBp[?ܜxk5pt͇;o;*Mz?}uoL~s`1xogR<; :h("oC2h}#lHaS$r\Vbg`kug;X^Uqm>TBu3$J@aA`L@eNdrrOt;M#][C!%tCȤff[6A^-Itu JF\Y^`S( u]n<42[l-[@;g&Pnvc-?}ž4'z})g?vݖGKmŗ&[v'!w{S}aPE ޾3꿻Վ *&6%Y0SҨ)K(0W` ) $ ytzbN8e19ID!J);!'Wv>PKڰo(].+>ǵ?P, )Ha%dtqfNd-oF 8$+!()A;([U*5 ?ic#80xme1-Uqպ,v2rpEe~GPJ@\ nQ'tJ2.VGW3ȅhB\ .3d7XZO#%j,%ZAH MΕFHjNYO] ܜ>lysFWG~ƿ'g/ׯ.}FT6z:=7~z TU[#许j֘B;禛1^nPA$s"DMA({Y,5 i2IT"Nrh9ήmMI/޿0 # O/a0EjTy8FFS$!e~dN bqZlA51#h7{ zZ|JT7| g~: e QI%Z Jk^uΥ„8hVzlMXw1LȞ[%~O Ud4N9Ә bP :Y btm:Ee >%EzU[m!-4hpt _{w1[^ﭿ6tuvwLoڥ獙Џ~O6<'[m϶:vgd{g;~x񟿼o?ӿN?:۴9PT/ δ꫐^kVWG9* 84Ըd-K)!HaF,:`DJ́LJ)9uF(A,FžogϑjxPD֌8gz^c.f'ԨcXkPLFMJ8swV'6Ƕ&FYxEvaB]JED4NU^9V5Y<^kWF;mY|E`I_ "aB$ A-INL*X<;6 лkK1!P:\ ᱉MąBE1,ٚj8F1-Bu,bsKK}XLXb;!4q,=3[Ϯ|if'm_xkt:Wן]l/k/1:b I jFRfe_%5.ע !i,!dЈXI&Kga""-RFVr.|I(#ݞW`E,LS>L%o{yg91;~nG#Go9+8u} UGoZ)ɇZjZzB ! L~l+D8NF/`0:B?SiJt,Oa!n0 FZ'{fdBc'ObScޝ \_^_3A!/mɐVh5VWg:O5]^ 2uUCUSS 4\qCNǠ5m%Z*{ͥP+*n |r|Έf?|V,I9F>c8PvcU6_ӕi;ܛ=hK}^ߝл;oo~}gT?'"VA ø̪rY|ȧ*\w ӰPT+%e ȦA)ps-j2 rVVBF{2r|:Ϣ 94e r."r{jڷro-moX>HJzy? q _@pBM8zQPEPlƩ$hZcP=BKt8)3Lܖ[ÝCmK}P%=|8#&:A,ց#F ,n +GR^TGdgҸy,g}5.- Z<52NX[,$9iSq4~ ,VσUۓ:ʱZ5=-OAЬ[2_-AO A LnhZgz>f?nb[m_=]?O.|xݶw6}6dgWO6kom~p>o>49 k@ vVtmmz(X=-*9bHVҔJݓH_pݷ*~_zZޗDӷn) { {9q9lX9o a; `:M>qz2{v\*;!m*6?5"$*솖ƪˢ;} Yǔl-?mƅGg[  PF!|4^>U>BT-~tOHPE)謘XH!dfƅ 2;!H,im-ޚhhnUR#>u~t?.)90ZS,5ϵ՗jXe9T{+?l~?{.#x:p/ oޜ2ow/u~t;g&FCE-^QCmpMz=Ce=ζ"Trr?1TTZ֕QJMV\2縡wkZ l82J-Ueκʦ@m]d^ueg).pP )cz>ݰnLYyګaZ#IWaȦюE7HQ;q0L|2\x4ڠJ$Sqz%K!DH:H?% qJJe&9z}ej{mlwl):p--jtJx+CZ/j0%1LWb&qu*;*bp;|N4BABȼ6tuj˰4 *\-͐?afk`7﮶ܜ OvQ\)bf,Ty^zj76j..ج|tŚ޻jKε\<ݪ?^R_^hmx=`U|rX/t$̘9&PI9T)ɧR0 j"#UrehÁ4V=.uR:ʁ_C}/e}a~- ط&ëL9 ~^O˯y>Ur{]Wp48(Cg'8ߡ:L20Wf+IFQk#kED,$&|"J&W[t`|3/NTtgyd~xi w8&C՚&h4X_?-TYABlr8Tr)THRrO&ZDvo[v^֯%;dԴ+K]v@]뭝 U!:[S\ V!Ƣ֢ʱf@]Hz+5cB|5R4T0Rlk'zönhzv\7?iXlO8gFƆ,^MOg^{A5,5՚R#)u " #vZم&^&69e%2,dI*(K(؂|&OIeAh'26µ{2G>qNb)@( n⇱/$a~ʌaPkR^} cŒJ»_})~aW`_N )ƽCXIײ71b)v1pWG˯o^\nz—.OUODL"0S-5@dZj3;,Ze i]5XPV>R_]z4eμ2DQ]ר~Mk0z veKǵV䯕WWI|^qU%˭U명5>Q],WVK}^FR_+S>NwE5Щ)\+;^{vfyµ6]raͷ6,6h yR߾p'ߡZ;*J c ƚD0BC Gӎ->x îRHD=}/C۷Ҏ{K8JҡIG=+r13OGJ>yPÄGr&+Y!P؛ydhT@uϋ -*޾)7;yܨd=TwVjh5xA`hrC5UW'.^hzzffىZT#͕ ZT`!51 RrlFLTZQZ_fWRnWFRZ)S#" -٤!BFǧ+8jnaBȯ(W*\.!s9%nӡZĞ2]u/6 PRd j!uSKk,貶Y::,= L%HVk+W^nv9tZ㣻n7?N-o7~3jÝKկ_iG޼|x;;ϵ^ ]o| qn7;ӾGBF'dB ``VnFz-5+$KKo~c/I>qMe&3rqeӸ !=G&xDRtW2jVH\vIC_eWI!hEH;~tWߺV΍[޾Bj9 Ͳ'jon=خ~۰'䵡Xeăʭh׸h-aǂL(V{ y\%#;xj쑔Lr2-ٹt UJ:i2 BYSV].IiV[4 ~MO̫TVJV#{]8炷.4~ޅZNOhm<ᖒZ05WZ|Z(\T kjX aƂ^PTa8c+s N zz:J{ܰ^;^&U0 inUꥍ AbhT6Qİ <=:4;Y^-ՎOwu77BֺruIY"wnUIig,llm7ۆF GƋgfWgWwu,xv՛W*޹YmykG=Wz5CC1iyŵX0_Z]p,ZWΖx;;;gkk=݅=6wx3WURMeU-!+@<1♛,ooyxwv7ʶK7:.].xɳ[~Z]ߵ+7oݪ}֕؝uW/߼Vݚ߯~vś'o`oݬ{YΤbyJƼU.umoi#?x{oov͝=u5؈oǙYt,lhfhـNsuUZoAqiv55HvI3W47:f-,pnnA a^qZU#tJv[V-Յڀ+jjavY#s؅.,blt({JVh>Y0ijմ);4my--v`Cב71獏T Բmzpzxadf⺴\=\ܶͭ6L+g[uƎkihf:=oON[''Ls3y"`rB0o hڵZEMR0 Fol  ʼP}~Wytpjpnpihe>?k^,.iWW ssQTmmɺ`^N&ի%╅uߺ\F㻾G7*߼{rިj:^?xwakĵ1Zrnڷ6R6A҂Z>.kGBE{-{*j<DhԀ{~te {+熫ۊ:,#epwM{e=mMFAJ?x 7+LQlRSlq,}!`+yl'tW\>JJ`JaqsV^B*U*J$2~mwE.DhS i.BP_Q];f),*iw+G㺑Q62Q(FƔc~tZ767.[VlsM9]yg V7εu cdT?7W<86: VE^X |*ea 5:*:[îvcGs~Ntz}yƩ fvڸZh6>m}pm:GXtNvfMJe-βJu֪g@u.d>#zuuIbW &5J9}lna1 82 kV Dfu_}rdntqtybi|v3?T67\9^Tm C>][#hǵp3Y _5S5_Q+t};jMmh5jO\^b8%>^O B QSÒJ+-VT*u*\+jjuIj7wz̝]CGO֫nkSv (ںD}!rxB3>Y,_-ڧMCj|oX1:],7laiSm\1oX3ډAРfxH٩k;]=^}[G~GE ׶v]Wڮ 5):6cFMw mvN8+ Ks岕ELԸevha։Ԉyf̲X^uvjctuֽ♚K+;w.xw< Y &-5g}lwgׇN,:Y\W6JW]>svƽf_,aI \ظnp(Uݩ9gSEn Gm#᱂)+~)ȸqnщʹĔc`:2lG"-*])15mͪN}{K~gn>_uۛm!}wkAV}钝y|չ5|bͳݫSu=jW$4@SbR:6#ӸP 0M1D|&V.}k{{;&?!Cwp\`wڥՙPxL|z =3K+6{'m@GRʓL&BtZZum-6mwm2aFZVwXN'r 3dM4ܘM qq6Ќ& \@ B^yJTQL7kjEu~I}@KqkÆP^S#։aǯ_5Z;ȷ:{p9})dEs%S^P_`)ܢ\mk7&Ș8[tml{7jfeu3euu{lm-VPcdVܐdh)h׷7Y{<%}vG8|TTnMe&BKevT I!AE__fly% .!%a! RG# TH+E #\#G*I DD,-OT X UL54n-n/τgCw/6F7ϵ®n7s Z?m^\Y vx*9ȎiSLi#AOQIsDmQGP+rUrT2D)8!(1@'&e$d DIlj2f2iTR<)41pJe:4aų0.'NKfXD+f&pe8^H)gC>?U&h(9O\RY)CݹVΧzTbyYlqU2rUrBJUaZf#գZԲzRotEI)L\Q)+vPs۸Ev!Q$8r]ZuKYі:UNu+X2Ay*!C/X2V2nNBH(4 'tv43@vrڱIɇDq>k-Ufa*6:zc{N*i vFJ{Z](-RZ@X"i73.;tfjLpq:73G!& ĜXG#'1,Z&+9\ F z$05yZjfVUy$(K)Uy4]3_T 2>rH<&\|^ohK=.}Y.7|VK-,XEEGfl Ea1I:Q)YjMbY((D$ oaIDAT |Kp||V#x,8t ;jj,j1Mz ȃ7NbQB&Idf%)gLdHRK=V^G}ώ9yp sp걽)G^y{DM?^Eö$p7)1"<*NBe<+K%HtR5;%1TZ6)39='9#+%-'9%헸q1cO?}ǒK9q$ O!at%ceVVb,qwE} y&  |(bALLM)ѥBJR9_q ylǒdZl5"PRIL mpIb(T.tWh*%(&43"C"fR%el>eyX̦pOCMiaVBZWW3yK|;{s??x0IBR 5=}iY l#2XTH"2r)P0l O%NU"CIab35F˥rv6!3-'=17#}:>d\ډhjT)ǏOc,5%x'%E13Oɩvp lE h.n|F 9=aBZФE0V\w& 7lU(zϜŊ2-"5(PKFO' )Č(BV<o'{CM7A/U#Ѫx P⨕\&/PT*\·BϗLњ bQ2%U ZNc nIAʒAET_C@I &H flEx-A!rdplZx.mf%!Th3FUؐ0T`;̝e $N2"&or&"0& OASLFI0ED?gQa-`Da$&.Dh'!A1~h?|RW"HJrXI1:x8XDRjvs"HBaa€1I,%>'577-Ka :QJ(B6: ^n%9Hʌ9{ HbfƱb陱ĴXRfb6&㑁'}&xjN-7H8,4lܳ/H ;r [&a<7BJS)Z*)IdQ$GH=v:=0#=tFrlnfO!F",$JHpH<MS8jr"LU,}>ۨ[prqZ&`di\r:IDC2.qM1neQv`\Rا.d%q$:f)J%XmIENDB`jexcelapi/resources/functions_fr.properties0000750000175000017500000001202311016653676021554 0ustar drazzibdrazzib# The function names in French abs=ABS absref=REFABS acos=ACOS acosh=ACOSH address=ADRESSE and=ET areas=ZONES argument=ARGUMENT asc=ASC asin=ASIN asinh=ASINH atan=ATAN atan2=ATAN2 atanh=ATANH avedev=ECART.MOYEN average=MOYENNE betadist=LOI.BETA betainv=BETA.INVERSE binomdist=LOI.BINOMIALE call=FONCTION.APPELANTE caller=CELLULE.APPELANTE cancel=KEY TOUCHE.ARRET ceiling=PLAFOND cell=CELLULE char=CAR chidist=LOI.KHIDEUX chiinv=KHIDEUX.INVERSE chitest=TEST.KHIDEUX choose=CHOISIR clean=EPURAGE code=CODE column=COLONNE columns=COLONNES combin=COMBIN concatenate=CONCATENER confidence=INTERVALLE.CONFIANCE correl=COEFFICIENT.CORRELATION cos=COS cosh=COSH count=NB counta=NBVAL countblank=NB.VIDE countif=NB.SI covar=COVARIANCE create=OBJECT CREER.OBJET critbinom=CRITERE.LOI.BINOMIALE custom=REPEAT REPETER.PERSONNALISE date=DATE datedif=DATEDIF datestring=DATESTRING datevalue=DATEVAL daverage=BDMOYENNE day=JOUR days360=JOURS360 db=DB dbcs=DBCS dcount=BDNB dcounta=BDNBVAL ddb=DDB degrees=DEGRES deref=DEREF devsq=SOMME.CARRES.ECARTS dget=BDLIRE directory=REPERTOIRE dmax=BDMAX dmin=BDMIN documents=DOCUMENTS dollar=FRANC dproduct=BDPRODUIT dstdev=BDECARTYPE dstdevp=BDECARTYPEP dsum=BDSOMME dvar=BDVAR dvarp=BDVARP echo=ECRAN error=ERREUR evaluate=EVALUER even=PAIR exact=EXACT exec=LANCER execute=EXEC exp=EXP expondist=LOI.EXPONENTIELLE fact=FACT fclose=F.FERMER fdist=LOI.F files=FICHIERS find=TROUVE findb=FINDB finv=INVERSE.LOI.F fisher=FISHER fisherinv=FISHER.INVERSE fixed=CTXT floor=PLANCHER fopen=F.OUVRIR forecast=PREVISION formula=CONVERT CONVERSION.FORMULE fpos=F.POSITION fread=F.LIRE freadln=F.LIRE.LIGNE frequency=FREQUENCE fsize=F.DIMENSION ftest=TEST.F fv=VC fwrite=F.ECRIRE fwriteln=F.ECRIRE.LIGNE gammadist=LOI.GAMMA gammainv=LOI.GAMMA.INVERSE gammaln=LNGAMMA geomean=MOYENNE.GEOMETRIQUE goto=ATTEINDRE group=GROUPER growth=CROISSANCE halt=ARRETER harmean=MOYENNE.HARMONIQUE help=AIDE hlookup=RECHERCHEH hour=HEURE hypgeomdist=LOI.HYPERGEOMETRIQUE if=SI index=INDEX indirect=INDIRECT info=INFO initiate=ACCEDER input=ENTRER int=ENT intercept=ORDONNEE.ORIGINE ipmt=INTPER irr=TRI isblank=ESTVIDE iserr=ESTERR iserror=ESTERREUR islogical=ESTLOGIQUE isna=ESTNA isnontext=ESTNONTEXTE isnumber=ESTNUM ispmt=ISPMT isref=ESTREF istext=ESTTEXTE kurt=KURTOSIS large=GRANDE.VALEUR last=ERROR DERNIERE.ERREUR left=GAUCHE leftb=LEFTB len=NBCAR lenb=LENB linest=DROITEREG links=LIAISONS ln=LN log=LOG log10=LOG10 logest=LOGREG loginv=LOI.LOGNORMALE.INVERSE lognormdist=LOI.LOGNORMALE lookup=RECHERCHE lower=MINUSCULE match=EQUIV max=MAX mdeterm=DETERMAT median=MEDIANE mid=STXT midb=MIDB min=MIN minute=MINUTE minverse=INVERSEMAT mirr=TRIM mmult=PRODUITMAT mod=MOD mode=MODE month=MOIS movie=COMMAND COMMANDE.ANIMATION n=N na=NA names=NOMS negbinomdist=LOI.BINOMIALE.NEG normdist=LOI.NORMALE norminv=LOI.NORMALE.INVERSE normsdist=LOI.NORMALE.STANDARD normsinv=LOI.NORMALE.STANDARD.INVERSE not=NON note=COMMENTAIRES now=MAINTENANT nper=NPM npv=VAN numberstring=NUMBERSTRING odd=IMPAIR offset=DECALER open=DIALOG OUVRIR.DIALOGUE options=LISTS.GET LIRE.LISTES.PERSONNELLES or=OU pause=PAUSE pearson=PEARSON percentile=CENTILE percentrank=RANG.POURCENTAGE permut=PERMUTATION pi=PI pmt=VPM poisson=LOI.POISSON poke=POINT power=PUISSANCE ppmt=PRINCPER press=TOOL ENFONCER.OUTIL prob=PROBABILITE product=PRODUIT proper=NOMPROPRE pv=VA quartile=QUARTILE radians=RADIANS rand=ALEA rank=RANG rate=TAUX reftext=TEXTEREF register=REGISTRE register=ID REGISTRE.NUMERO relref=REFREL replace=REMPLACER replaceb=REPLACEB rept=REPT request=REQUETE reset=TOOLBAR RETABLIR.BARRE.OUTILS restart=RECOMMENCER result=RESULTAT resume=REPRISE right=DROITE rightb=RIGHTB roman=ROMAIN round=ARRONDI rounddown=ARRONDI.INF roundup=ARRONDI.SUP row=LIGNE rows=LIGNES rsq=COEFFICIENT.DETERMINATION search=CHERCHE searchb=SEARCHB second=SECONDE selection=SELECTION series=SERIE sign=SIGNE sin=SIN sinh=SINH skew=COEFFICIENT.ASYMETRIE sln=AMORLIN slope=PENTE small=PETITE.VALEUR sqrt=RACINE standardize=CENTREE.REDUITE stdev=ECARTYPE stdeva=ECARTYPEA stdevp=ECARTYPEP stdevpa=ECARTYPEPA step=PAS.A.PAS steyx=ERREUR.TYPE.XY substitute=SUBSTITUE subtotal=SOUS.TOTAL sum=SOMME sumif=SOMME.SI sumproduct=SOMMEPROD sumsq=SOMME.CARRES sumx2my2=SOMME.X2MY2 sumx2py2=SOMME.X2PY2 sumxmy2=SOMME.XMY2 syd=SYD t=T tan=TAN tanh=TANH tdist=LOI.STUDENT terminate=TERMINER text=TEXTE textref=REFTEXTE time=TEMPS timevalue=TEMPSVAL tinv=LOI.STUDENT.INVERSE today=AUJOURDHUI transpose=TRANSPOSE trend=TENDANCE trim=SUPPRESPACE trimmean=MOYENNE.REDUITE trunc=TRONQUE ttest=TEST.STUDENT type=TYPE unregister=SUPPRIMER.REGISTRE upper=MAJUSCULE usdollar=USDOLLAR value=CNUM var=VAR vara=VARA varp=VAR.P varp=VAR.PA vdb=VDB vlookup=RECHERCHEV volatile=VOLATILE weekday=JOURSEM weibull=LOI.WEIBULL window=TITLE TITRE.FENETRE windows=FENETRES year=ANNEE ztest=TEST.Z false=FAUX true=VRAI jexcelapi/resources/functions.properties0000750000175000017500000001021111016653676021062 0ustar drazzibdrazzib# The default names (the English) for all function names in java abs=ABS absref=ABSREF acos=ACOS acosh=ACOSH address=ADDRESS and=AND areas=AREAS argument=ARGUMENT asc=ASC asin=ASIN asinh=ASINH atan=ATAN atan2=ATAN2 atanh=ATANH avedev=AVEDEV average=AVERAGE averagea=AVERAGEA betadist=BETADIST betainv=BETAINV binomdist=BINOMDIST call=CALL caller=CALLER ceiling=CEILING cell=CELL char=CHAR chidist=CHIDIST chiinv=CHIINV chitest=CHITEST choose=CHOOSE clean=CLEAN code=CODE column=COLUMN columns=COLUMNS combin=COMBIN concatenate=CONCATENATE confidence=CONFIDENCE correl=CORREL cos=COS cosh=COSH count=COUNT counta=COUNTA countblank=COUNTBLANK countif=COUNTIF covar=COVAR critbinom=CRITBINOM date=DATE datedif=DATEDIF datestring=DATESTRING datevalue=DATEVALUE daverage=DAVERAGE day=DAY days360=DAYS360 db=DB dbcs=DBCS dcount=DCOUNT dcounta=DCOUNTA ddb=DDB degrees=DEGREES deref=DEREF devsq=DEVSQ dget=DGET directory=DIRECTORY dmax=DMAX dmin=DMIN documents=DOCUMENTS dollar=DOLLAR dproduct=DPRODUCT dstdev=DSTDEV dstdevp=DSTDEVP dsum=DSUM dvar=DVAR dvarp=DVARP echo=ECHO error=ERROR evaluate=EVALUATE even=EVEN exact=EXACT exec=EXEC execute=EXECUTE exp=EXP expondist=EXPONDIST fact=FACT fclose=FCLOSE fdist=FDIST files=FILES find=FIND findb=FINDB finv=FINV fisher=FISHER fisherinv=FISHERINV fixed=FIXED floor=FLOOR fopen=FOPEN forecast=FORECAST fpos=FPOS fread=FREAD freadln=FREADLN frequency=FREQUENCY fsize=FSIZE ftest=FTEST fv=FV fwrite=FWRITE fwriteln=FWRITELN gammadist=GAMMADIST gammainv=GAMMAINV gammaln=GAMMALN geomean=GEOMEAN goto=GOTO group=GROUP growth=GROWTH halt=HALT harmean=HARMEAN help=HELP hlookup=HLOOKUP hour=HOUR hyperlink=HYPERLINK hypgeomdist=HYPGEOMDIST if=IF index=INDEX indirect=INDIRECT info=INFO initiate=INITIATE input=INPUT int=INT intercept=INTERCEPT ipmt=IPMT irr=IRR isblank=ISBLANK iserr=ISERR iserror=ISERROR islogical=ISLOGICAL isna=ISNA isnontext=ISNONTEXT isnumber=ISNUMBER ispmt=ISPMT isref=ISREF istext=ISTEXT kurt=KURT large=LARGE left=LEFT leftb=LEFTB len=LEN lenb=LENB linest=LINEST links=LINKS ln=LN log=LOG log10=LOG10 logest=LOGEST loginv=LOGINV lognormdist=LOGNORMDIST lookup=LOOKUP lower=LOWER match=MATCH max=MAX maxa=MAXA mdeterm=MDETERM median=MEDIAN mid=MID midb=MIDB min=MIN mina=MINA minute=MINUTE minverse=MINVERSE mirr=MIRR mmult=MMULT mod=MOD mode=MODE month=MONTH n=N na=NA names=NAMES negbinomdist=NEGBINOMDIST normdist=NORMDIST norminv=NORMINV normsdist=NORMSDIST normsinv=NORMSINV not=NOT note=NOTE now=NOW nper=NPER npv=NPV numberstring=NUMBERSTRING odd=ODD offset=OFFSET or=OR pause=PAUSE pearson=PEARSON percentile=PERCENTILE percentrank=PERCENTRANK permut=PERMUT pi=PI pmt=PMT poisson=POISSON poke=POKE power=POWER ppmt=PPMT prob=PROB product=PRODUCT proper=PROPER pv=PV quartile=QUARTILE radians=RADIANS rand=RAND rank=RANK rate=RATE reftext=REFTEXT register=REGISTER relref=RELREF replace=REPLACE replaceb=REPLACEB rept=REPT request=REQUEST restart=RESTART result=RESULT resume=RESUME right=RIGHT rightb=RIGHTB roman=ROMAN round=ROUND rounddown=ROUNDDOWN roundup=ROUNDUP row=ROW rows=ROWS rsq=RSQ search=SEARCH searchb=SEARCHB second=SECOND selection=SELECTION series=SERIES sign=SIGN sin=SIN sinh=SINH skew=SKEW sln=SLN slope=SLOPE small=SMALL sqrt=SQRT standardize=STANDARDIZE stdev=STDEV stdeva=STDDEVA stdevp=STDEVP stdevpa=STDDEVPA step=STEP steyx=STEYX substitute=SUBSTITUTE subtotal=SUBTOTAL sum=SUM sumif=SUMIF sumproduct=SUMPRODUCT sumsq=SUMSQ sumx2my2=SUMX2MY2 sumx2py2=SUMX2PY2 sumxmy2=SUMXMY2 syd=SYD t=T tan=TAN tanh=TANH tdist=TDIST terminate=TERMINATE text=TEXT textref=TEXTREF time=TIME timevalue=TIMEVALUE tinv=TINV today=TODAY transpose=TRANSPOSE trend=TREND trim=TRIM trimmean=TRIMMEAN trunc=TRUNC ttest=TTEST type=TYPE unregister=UNREGISTER upper=UPPER usdollar=USDOLLAR value=VALUE var=VAR vara=VARA varp=VARP varpa=VARPA vdb=VDB vlookup=VLOOKUP volatile=VOLATILE weekday=WEEKDAY weibull=WEIBULL windows=WINDOWS year=YEAR ztest=ZTEST false=FALSE true=TRUE jexcelapi/resources/wealdanddownland.png0000750000175000017500000051570411016653676020771 0ustar drazzibdrazzibPNG  IHDRsRGBgAMA a cHRMz&u0`:pQ< pHYs&?yIDATx^dٶ z2WV%s3:33cS0s$sfQs> gYh뿢?OJW:qdRNm==֘cu[go~#?!;tXvw/; #ݯoqGAɎ<(;xww;7_xΝ:}.\8wտ_;v… gϞOȑ#8x'Od{_Vz=_o_8yO>x ȋ ysĩ'O~~wq[o;s􉃇d ēH1Ͽ_~_O㍉K"2Q=k;rwyoC<<xw !k/~?8xP99ya5GLx3gȎc9_9*}2=A}ԩSw7o">O^Ss_qg؉?&krI$$ᅉ7?>ρ]i0q6ykS'>g^҇wXx_y"~_~xF,^$_{w|9~;t7~g I8E|#[+Wxyw7?o:}ٳg8JxrNg~W|+?ǿ /1oG|?.~ÿÿC8_2߀ [']]͋ @|ų69M0y,_yR|ǖK9HWrYq2T8gOwoۿ{>+!ܹsH{?p;gov7pi?7~/;}-O3_./_ɷN9}Xv\&;!;zVve˲C@GفCCe|PjNq/qz[}[ JGu"{c/޼&kzcDUaw$r񚻸^S1vԮ؀Wч4řْfCXz ]p˰mtG4it>ikz4*D CʭlZcjAUtaYp|>c0h8l =9W3jq(M4֧w[>'~>;|⣵>xMˏ9/vrC3`ѻ ēę;O+w[vlzici7=kjk>X~"[?`ÕmV '>tGߟ{{g^ܽw]<5lsc`MXct6t+ aGlI%7F5¥G{u#=aKԭv,#c1s`7K 9FxoylPjW CR)]&V(bC&1ƽZ-10@0h˥n::ʙsnwT\*\'hkVW8"vEtǘܫhGGm:d :?bz1_o,1-;ݞϗ 2vSƕ5#~ W%B5lE3I+f>slK7Mc.SokF5#1FA51+#AR0RpV('mli/ e10Lye'ﳧ݆cg}8h0m;[䣗;wJnhyq&܉r0Sx)++L*u%'Cu&s#q$\l9HI'uEFmo\KٺvݱwL)1wT;bv%{cf_c'GH? x*޺vP'N_<ȶkЮ4u]zWkX@OA -\uf/8\]][{S;+;؛Sdo\!A9"q[bptz+m'.:t h}uXٍ>٭~)nʮtߖ.~3мi2xk\sČ7p3X_Nr{FVGlA=4u FUZץu*U;^oXXK]9u׷e2k{ u:UJmVCo)ҁP)Go"2/NJ*9֓هw?@tGg0]$?7wx4N{V|j`:ً;ٵ{E|imv#p^ni y_~Wo#Z9(ǟ}N=.s{㫏 /*Oiҽg#jԺz)QBC W1dui:Ǥ, -ڧčΌo <ܡ yZg3Un7mf 9JO|,!gVsmH9  Z_~7ksGd xП^cȡr̪~`0jb0G,1sj"8h 9qrJ:֩>rVi?`>hy蛲7%-q#qԕZy:9z>q86 v.ȮtzǎkݗLcĬmc+tbn-/rK|K!XvyrVgH }XpJEbkLե\Ak36[g*O}ָy #V-W3xJN@m8b )H+%jY6?֠D9_ޅV@>=$@ÿ/` W?ƀ3n|7R e`-~4$Vk^zQqnvNfݗ5O, ΐk`59۳/Di)[I>ˣT႑ 4 􇟐64f;#6\Zbw0XOnM!=?N=0'7dJniIpGlr(@*EbDlխXt  ‘](3Mi0Ӏr68ا2.OA< 8[f ԰uA٧W%y|_8vwIp!?h~ݼp9ug<ƞt7'1nOoXoniݧW Twd:v9Tk7n(8HRY N_㥐 j'K<Џskኔތj}6̓|#K\]9pkjĪ:a{h_dG^vl=|étn`p t\Ϗ=kp 7{G@[ g:#Ĉ3"wΰ҂ΐ ^c<./n f{[o3Ѵ(MzW5w{S=t&pF: WzeWzo94^Ԍ7q p&;rA&;}Pvȁ3'N_={|r]/ܖ%C-~g׻e7{=1zm ݒNQIB91M,,KI1ىg#ӾX6.*YgV;mWu_54I?rSm;}svpPY♳BPb2l1U{,\^ A~B>Ɇ 8wWջwr22=yOw^}!/( ?W䟽|?|GdڂzC6 `-0 @C:H][[i5D:Y^M;OKs(/AmY]W($ g57{j04+1HV v_N@`v' sX~B$&:(B5s˄F)z5C2rfڄqtz2aP܃aۀ3)6RIg4x5w(=[U"@F p ߠ* +$ Ya) %9"H: ^s29 PZ8fA)LݔmMbh LF&s16ȝ&|r7t~ypb7%XvjX(-D  W50ͅ ^l va[f>2࿂C1OL;}BЌ};RpȄUt\xCjPAk9#=jJ߱Jʟ3fj«凉fKZ(Zr:$D!@j3 %4ìlNesBnKcVVYvstas5jGЀ0pC ̈́]GcVX6 Ʌ'kc:G/Kw:7IQNYJv[vMvI$p9x]}b}#NzRύNMېWuvC.z“k QQRTHωZ&[dC>ͱ>Ftr݋LV &K| 17/3F,Prr!a\ qG&li&k~aƯQ]nDan48p2P8Cu6R}\$]`. ‚@_Wi sJ1.@B+|ly F\iUthSȸܜ$Yëw>:!2$W58΄-[CSj>,zS7d''0 # Iґ{ ) /sJBuI@!=8 cG0_qI)Wh 6v`\ v@6 ]%'Ց2VS61E'lz_EUrP7^(*ԙO&]I; 3c#zbΙ| 8#5x*eMDppЀ=4d؃t=51&@mEkMiy{XӉTݾys{>=r{Ti sCL9slr`u=hVu޸%;{KR1n1jƛ%L\:pCGq+᱀ʜ7zUg76xpv0ɻmhxj^ZOmCt:T՞Tob[ܝWz45*ױeda5o5($ hfFr}|yg#):O~`7  e؊n-:ѵimb |s:vO'ƧPt5^YX[z6r!!r0iIfē}u[hـ5$l3,PlRb#qr6'$'ǦʲZ|^j\BPlpghO*"QZ K#MVѢKb0ωYk}'?qC ^$(ϺRq&p ,jzsy1j5L*I5qn1F G. DNi,#HN:eWs{h} F ,@y!0!WzziI 9sgc-(9M$? W1*51n")wdq>UZGp˫ShAܫDn7=Nɚ5׭;º7Z;Xr^$mCCN& 7Q B0L7vk0ƨH\"^qG6ӑpvڗbHIHdܨB3Ap<+EtB#iKxJYCI;Iil3o f xI55DL\H\Nhh8A [IqjȨ .Bp!@ H -"o)?-" (0r'l]:?oO0mg-^vKГD Ԉ?H\\2}h*HT";|{^іA6o]?ֵ#g9~Ls]׮ƴA;}TߨM'DGa[q%DN̈́AmǑш\ՌI H-""*pc/쁃sA FM*2Oጅӄa .lAtl'J_i_I b B{7̰@jX1f0h#vV{e9C+5I >dyW?֮:r9Ԍ߼yB˥m]hiGț{B3ZɋcߔPMP e'Wvf3AKFMZ)[}G5tBm^m14ŻŕiD/j'Fj&qTaVB Z6'\v4A[ CLPv*޼9QF@!0'" ϩ;km<`ه/>^~_l|?ɏw]UK_חkA$EH*x:YXLq5|F84Α$B?~%z; =7u`--V<9̞oqbң>{ NLn+D#p8Jyy+S1`;Vw%К !X>|P'QδڙE ̸}R{tX61MnY)3<}1>>5NkԨhW30f f OBӘ-9kJax@c[fUjpHu(t8Y qݮ v4`+1-A03orZ ݉:fv+2 <.c*nxNE&ڕƊAKPo7‛kKa n!T/I+cPndF5Nʪ0xLdG>>uo_5<ߨΟz ަ5d+ۢec_I7Vr! rĨ'=˪PNwJk ̡Q Q%ZFgBmq9\r$Vv1xHP[٢Cf> ᜏ?#&O6q/m*bRJq#q[빣`UD$ WScD!DW| !&  o{51gt #!uېkh{D?Lc![ahp2H-uݜ8FAl,TX֟,.#7yF8t\*8(;D xOdpq]qbDZ7ozVokȀ#1ܗ6s`މ1S\6xp(/OgYxc4Ruo8~ѣ|.W@ n|&i%gq֝*ۃ)?gc$~q[ѩCk)@BrbzSH!LmФ<2DzY+h@hx~"]X\ 4g&S^+,=]~2l/7j|yÝw|uwީ-Uz#I~ nhURq;exf>1>sM*x*$גم ނd#٘HFI^HFw#;7rGްc"bښ-}8lZ/@'I8L^Q&3z )S3aΤȰ"Բļ13S+A#_f DN0v' dbУ!0ý=AΈf5;UM|dj82Eryl=VT}T,7hJ~5//H=0Vv@a.*C0) ɽp'#|Ōl?IKR"e]8aT:_ShzF:!м{TѫMJ@},>iOV";\3)QT pq6؛փk#Ot%5ͫȈ3-Z>[|:-؍a u CcvcS]dIS4MaW2'ٲ n?w @SC9uNh#ÚaMgX7P# 59m9lsP^9n]^KyzI䍣x's V6?jQ >5^ʺj\nY8n /?pSN^K7_}ѩgI`Uˠ6qW/%n{x3rX[Ko+t̕,?'~]-MoTx4`AT Txs.&W,&-c 4GĈ'7[K^apm6t /|~o>%11e@;˛2O2E(ȣ`f., - /l>+ܙw$M+0./j~b!+Ab«G`#(bکA 5t>QXJpz1GPy-r>jIo(SmQCLޏbw1N}ϫ;Fۘ٥w%hC)*҄\  1{?lS /sp fN-b27)-$n & P_[Atn .KE b1ٛge8tRy'tĸMz([kna\j3;‚71N53{ʊ9VۯFhc]$d 铧ϟ>suww4E7IE:o&ωe@W:[#ee+,,WVNXI\}939.M!0+%IsK7MPVF@9ۉ]ܦIf#0nni7&01]7Y_<ϟ}˧_ї죟ƃxML2N_FY0?Ev8@*5E+r!] L `c$\& BvF‹UROs[ϡU}m=͏ē2`F!AG'ࣘa VV6fbUa><6K`Hψ`-WO;Urp7z(BBAqOr 6#hˍZT:pp< MLŬtk Nc62*.U69AjJn?=>}dw I\B(Pր'ܜO9 Nv/y9 KXÜ;8vKtÁsu&GI'E5AaӒ$Xq>A2A1?:` H7}; Bf~aoZDx1z~m/cD`sUzRM<[2n)=rG{z}ݕ­82@uZ-$8#7'+y1y/fS/u)[9pE @ fDU`6I5J T%5ca'Xg?vG?~ݻ,=kqI&tpLaʍ ))2u)HOef' KbL52VE]&ev  wadD|s  hBa F8jxשFcXɮT-beSԮԁKu(ep㳔;Dq1>bQuu i!!(ݒ`ҤIE.k<]PthHJ:0( NNbTrwû v#(kn0HB{MV-iCzF*# i F0? ;̴-R's{ u[0Me-W{;ΌpꍁA/6[f\ʙ0we m4shL g,8!lkkٙ$"O-߫VV2Q̑,dyLAm613=?^r+t_MREtstdqk^RuH:Tu'l_hZ$TUZ#B1,øa`oCS1&@` W)Lcc710j{U݃c1j)jW EYbH꡴6j D lمCãvDwT٪JSNrRmWG}>y(T"-^%s E E'UwU)k]]hB_~}YŃG/:z𑳇n._ fA.ʺ?;kc!&ԮdY١aÛ0coɠh臎l6z1ٱ7x0!pL޺);}Evd)ocpBMqLaH CX(ZWDu156]Z*6V2sqЖĤ9D֊z,URs Ma֒,VO٢iP)1G\ $d# Ls"/?YyE~Q">Fj,)R7L1; йD3T7TěHv>Ff ~7Ekk>jFY>u(-j7p&rWJIqe!oB AJzef &1`1Q9b1mi*T7,F 7Ҕ:(3 Wڎ֬9AA nW! Wv ?Ƨ ;ڗbY»k1p(,P#B57i3q&{a Ds@xq%g|(.&\w$sF=`=c d完l"M͗+|`79O͇+ќ&ιz}m4?G+1z6gpL.<(BB 2FPH@gv ЀׯH5CC2J, 4k&#Inippdlt#&e1d|Y˔g#)'˂%,;eK|y:r ٭IgQqPf J^ 5 }ͤT\k@>db>?>9^WywMrl* ~OT=*2&/{}E2aH1R AË%QaHU<˴{?"L6V)1esAyPR%_zR' 48'p @ Cmc@t!/7QI* 1Kv4[2#aC> ۨ!yעUnEM]GzNw<3t&U )ڣ--x7T<ܒ w zr{E?b9pͨ]0"@`gs'_>sAfrK7 ,y G%(@N sZ8]tNM. #\A+kaz4](qzJ f*Kwˋ$ s7ħ$_YMAQZdq 3}{Pi!cm.ڰ2x TAp0j13;[kΧ~ iI~4)9U*ڨ^Gf)M '0"kW vx΍&p0&I* 3 IĵJq]@F@Ƨ {^@t[kA ĵQ_g]2h{F3ݦlڕc **B%|-/aTxGO\: sPQ^^qMYLzS'S7% BEI!)s;@we-_1'[^fG wPy,*/ \cߨd\wX'ŃMEm^zx|CCXBI}C4=QTXȳ}G!3K[7>λklt#M9\V;͘xT M7Qwx"'D :s#K€\d9 p yTRa`/Pz1Hc*" Ӭ>ph[54n(Θ\5\ Mp-\vl;<(!R D[6A.æ7zD!Sܤ92~EWP{[AUQndCNsr¡7.eU܊[͈3:hq%&m.G#K8A+^#cQ{+ R:_2cBWRwPĘd\D%B!W|ӗAqC/3\LMdext*N<& /z5$9 @w:DR*~O/x("*; $j{)q9X99S0{ާȥVwh>Bdd GTB8j+fzJd#1>J[ >c4dzu.KZD8D4ykMF(bX@^TحT🊐:s TI-C)CռRG 8FȻ`A'O8`'(+C Fh( C$ 4ƐXcf}@k |QLmdjX[~-EjUn t7o |k2&5N4Ce@Xx\M:)(7@C)lY@L|Eނ{0<>eN DνlWfcR:?݋ɲ0jE8,pqF3'Vi7Zl|o5 bz0b).L29Ɂcba˻EWNFȘ`.y6# GMb DwCKfb1JZ65stl6m@sC!2W:{Z P+𭑯3VXM##!Ҧ׋I!+J>u<5@')ۧqK\OX֢h*j)b/eLA <#l4!e W"sk%R:P9킉S<1!A_:fv^wt#:.ܒX6EF0scy¡Sg?%;z㇎Cnfْ@<.(Ͽ72J.Mi($+AUnB89[G2LU ̆ '*9NJ*aL  SStd!r;cFTˆq'LT2bB1viՏuK* %HnD45n?чD4 h9E)37" P 3 nMIiұTtj ማ9hǕ0 LAMxb0m. >=/(LBkU(Td/-^x#Xz;Y|E)VjiKdC{` #ǁ-4Y i+5J=H4 ZDij'0l`mNKcJ U9GaɗZ4xӍPFE#B'! p ^`,nN<"En\X\9py~PmeSplX>ΌM> TպTBnB<=\q2Z4rO'I;_+[k3y> |QNA#2OC7ʣPu5 P9i&ps&;&Y4lA` g vx1> | 7ɾx“pl!Z>&i) 'zo@sI-N@6 pv(@9C8 <&wPTi A3[0nNhZi_,kܲ&V2Z;8{Yv Q7"m ?1kke1L_lh,ҍf¼$6VW{΂4a$*ۢQLU0D',&HxF)6ts[(*r+9{8 `ܢo03$ c\ă(BVW g SĸxJ̽Bm7K"g#ttS if2}0k)䆱ܢzPM$a 0Ʊp)5orI 蟇.{S>W3ެȺ(8ۇ+KBRRLU-cNf LC6 ,[6NspDɍPxi1oORl@BG)Ћ&9a6̢-c@Jrg41]=2:kQ{>OM?\JnaΝB# |CKd[;, + O`"H^[!MঔkB>1Gf8C`FE&&4fB+DnD1;{(5i9pO}Y"Jb6( XQB7ofP#j/fQvs\nn9L%O ,\?\0.-ܧɐe]hRQc1ޘdܒ/ꏤda4k.pxl7coF)5mtZ(ف!7.ˮ~r74o/hcr Dm.G>n4qZ Dś֮qR. NД &De Ŗ`7u$2Mxi7x2MC7na)GD5,a1 #e)A3`sZqK$a=L~It?eT/Ӟ"(R☚ ]`-=.H#H݂"hْ Q h6f .JVi$Y&nʕʅ2$0S^o8^aJ bvH˩hH9IxtAaٌYeѣNHGg,R$9#:t:fXf.Z|#;%O}ubqwjr!/c?] IJĄ7̘"DT9{qp(I0'`4kZR[Y\ .B 80MpYX2%RMn`NJ)Gc 3q秝j\X0|%iy%7֨%Fǂij_[Ɠr&'= #B -V#}gw XѢh1 R cܢ 8ws;oY҂$ĸAm4nX aqw@jTNi@,bx4u@>nNj0Q3#7rD̓nt;~(7N<$n[2Ih WE)U,v p`1-p`q0?xnàoHWr֊yF-}VU7J>ji?n~PPle8ĮWd^',@NGQ h8B5";ߘظW^gLLxPY59YtulrMj)o/\`&7wY$NX6 F0 pY  M~2 r怗ldՐ}<C4kR'M4! 8fƺ,J^z]N(GZq,j´YVSs\"G]B@nŠ3o[۠6$^4oLY!5NXr&x~FՄ XcBAMYN``+lLD>t@?MGc1!\pAumf$zE7D,F|}&0rSPoP4t-ź;+[B!{@3̏;`BL#s>pKE [z+ t mBgZ v  @&q7hps &NkBCA'.PN.IKCl!vcH4z=E[j_sWtm'QT+LΔ5HHVY3v#t6L7rʕv/j i- p_u.V" Fqn1[(K" n3"M b$ͤR1D`h+rx!qbA\[*MDnDj | ?uO5J@q֋Xvu'NSarkہ15d47¯f*w8$o8p dܢ%ݼ䞬hzT28@'&'s8D9:Mee@mi ֯if}@6P΀]0n^lH=j vsp+[ 0t/ n)vmL(obJdaBK)ZwCe.ASdg8 H=sM%#-|ɸk60M`EeNb$b'ڎszϱr~"u7.$. 4]]ښ -M]?Nkç9sK7[SI$}F榜RˤT01+HYD&i)QBVp+frģG}!̗kµ,me+[o/8:mBfR2CyuXY@/$6OJYn&4BENifOR1cvh(-P&*JlZ[!mVcǩg2R~4RϤgrikfz{vKf-fAiwv7 d7݄D..-bWKfpry xQ!fF<"jϓ%ʙjt4"3Aƅ#;wXOCd%sYS9|gF12B7%N=Efˆwd|?wT B`-*MԈ"#'t . )_qbnJ :Sߠ09F f6[؍$Xs2;bpoa%qZ W?Ȭ>)k*,xerӤ+7$Kv:@;3cJtx6^˛ 9Ujf80Z\=u!zus0}!#޸}N_ Rc51=YZFdRK- PYZ#MG/F5!i鋙--Ԕ̊_?Z@C%9lVYēSb@+JWEjn~/>_ZIRG`NGJ4fi7v_N>TP>Z"6!8"ׂV#my%Źb .J + 8d7y펰qG(lz@Z>ѧt_/֟L7APg/ й.5]"1뎅X)Ksj=HJK~x(xdž8TI=D€";BQA#mYM#]Ztzrna A`, : ъU_=vUw _{Fϵot߾ur]-Aznvci:l@ ]KOJUEm^]]mqYG:Bth~Mv溔$cI@s˝w_A2l~.m=g!vݜiD;CWE[~6Ա)ug̖q ?ܼj-rEĢ9j~v'awI8(}6׽oTŏ0bCGYb޵~݁Q^Yq H$Bys5YpI+6'lVԡq9'5{6فZy2Q{"0m&Zt̚B;"\Tc` GX6cZ6DUDJZZ+_#r0^v#{qYc%!u1ܜ5_XN]Q/ eT [|~[;L$9G ΘƞW>\]{ovTxf39XkHAxڂn Ym~&?y=E]2pϪ͢8;%%ֵIBo$02Q~Tdr4` 9{1uK%7Zntk7[]=;nt+[(nC ;``{ ӍCd,|s,~cg=s7 .{sʋg.w6v Vw&RjꖿoL?Sp؊R.\){bfugBpm 5NύN.)!EcnQ3>#V32<-xNH;iD4<  INZ}\9)V1%pf DKfQb. U Ff.SH% rX4@9tUZ5kӕ4͠gqsM?iet`9BR}{zSG$Va̴wMr]aɴ~֭]W:9Gnfw|Г$YNvη zGu[ k= ~k\ܠJܭz:E=[غ;M^l^~7B'UH7}b  ,ce&?R ;;kYdvKmXEɰߞ=h86"G ĵ#Wz  HԃJCop5y: hRt5^9 ᅂM.v(T4McTe!ܜK )b .PDHPpv-u3o6ډ2sf0hغ'lY5=S_8c2B lDpS=há!4 1 põ TBu k!Bi*M/|L) 6hy aiRD?XXznF%DKF]Yޛ#~V#/u㌛aܤO雋'HK*ݰ*[ll^6 v=jݴT:4i(R&3V{ՁQO?g}>ŋ}duޝݽRVG*A@WX($͔Bؽ L,]F_L7G3@ A…B ɖ @# VwpIi ͌Q`SLMspE*7n  p_mM[ 0n-9yQ--:ڗZ.ܺ}h?rnۢ7t=nч!נϵI`MkR˦ò6V񎱣ConuJ_ܪa9^`H=w^yH7wc7࠙С[I"e#٫HlzG'ǢS WK>l:4?HeM؁nawE>q{c78rCW{zqQ\0=CdEcl'T`5!qe@}WLcD)1~p8)h!:bI5E4Ɵ@!c/ԣ/݂0BXC5 bø >ԅڠ\!I6-JK)4zSM7Kt$*ǁKюU#Nb A%PG#HKU)r%C]y?J[_?]fGj~Snǎ<Ƭ͆d3_"6rEb\_~l{{"oy`ܽwn6V+ӎCn3{]~.ab@܎v4Lط5EG Fu@p@ E50A̋k5b7DX7\X: [gwlě3 Xs6[rͭ&vv; *u7򂅜DCːj)7"|s]\"d I<}kWF`&ޏ_?ٝO|Σ|ׯW_f;wkkdɌ{Q[2(j*2}Z"6qDiĥҲϯh:#5*ŪW6lȦ/!&`ws@yP`rёs7>ww^L=Oo<,g5䒾Z60nlX1ga?*}٭ /IJb$T$tFldLnj!o1[Tz/=/\qͣo _ R PI]qZ-fxeu(RA +_mQ}^,=qMjY`NCD*aI3D*$P[>vﻶINR. zk{7 }N-7>7}埒J$=eýtdFP}J9tT7@aڀx$~V)'9"L!Q!MLYmde[OJ?<~tᓵ{3cYjDMѸDU X3 p;l4v'*Fx- Ǭg"CMj;[7$IQN;o.m}*S,PWxxQW" F-٤lˍ7 ?_lqÙē\xVH0]ݨ[z5YzQ*<+D<*wӉwgO&  Y.3[&?O_~hwamXGAMcEB%b39O(nюT'j7 اۀxm9п",tϳ28X]308oZ6lۖןŻ΅;_-s6DbMyf6ykhb7DߤHT y "].Y$ W07]^WPіwtĐZU^`zE"ourmmYѯR &:bM6@:B+ &)}[-\J7yǵ.O+!ֳYGV ݩ2Q}CӒQrAInZxH7/>*$'] =bnc_7R 3"xsTJNW UF%;dM6` َ Zwe,6&zMҟF\2WP0C oWBF;o{{o{9IOޏ;IiI.65IH* f(R[ѕ5G̑{g,#ce "ҧ!7zn*  zD)dxVl?!%+*Etz\v <)}UK^"5h"1QUXn)]Бvj~t:_~sS ,Z_ jܴEәCR,J*if}gM S'B_Xqh|nh,BX In"^l [jgeTk4˱lz!ьRnk+Z)Qf#sI4N\%__m|y. >E*hSg*6œN &w4ns">t `bˏRrpeSaD,X-U=x:h榐*z$]HTfrvެWGgs寖|}gk?YYxyoޟ|\zqeϳٷ kjLO7{UH?lUL߭VNOޯG3SW4m}xdg|__۫C W : ;L&Rfkh.s&9 qk#y)lhzK58+羵Ǯg޽CٷطNwޏ>u.>o?O|Gksa72^lX F r6Rh цn2+1I)f Jp?t&4Φ# ᜏ9hs8#9,>kAR` ,+Gni"Rrά/fW[Wۺ[iu xX gsʐ>`5Yqw6=$'sX70qS  `ݯT1$a';)VdȒfVHuH d-Y&x&- Ȕ~&t;c qqu@6p.rDSǣۆ!k=H%/{'ܾţ'lmN-w&_\(/ej<.(+1mlb*_}QEzU+KDL啪=NȈ%2%RI(ApGyC~#;6|}`!pq+|@*bd:I8߸!;w>[N=5zt?0f.g SNt&O25t2(J|2`{s/w'w2˓鬻6rڝf4Zͨqz+Te 1a%_3g{ĽrlǵڋW^[y<a̽ݵt&[|61ٻv`hޚ>+jnE5&!uh&yH# I9 %9&ʊbPK,;nƽ24Yٳ=l , s&PWn†Mꑲ=.5Ⱥun(j^h$97ϸ8K#'eBKļ)\VWt zkHKQ Rحni)&½xEA<.%ڔJ́:`1V.ƼTP a%.[׺/ae+<X! ThQS~0 _{?A <]892#EUSΑL)(à9I.Ek[R w Hf7ٲKM\j[ KP3~˛韸_Mׇ)[9v@!H ڿgQ Nő=,_:akP{syukemoc ~{4U/MMx8Nl+-9k̙fʘ+o<]rW3K8JN-=n..DIQ&0h4Ln@n K&W֣:6;ۧ:Oߖ[*M+j/[k[b/먲| *0,ҕXc<ll|2gB$68qJɗ땷7kn7ۙ~wf}inmqvuafy1ߨLWJrŔrN,frBa׌XTfʩ3GX"CaS╄k=jc mܮ u9.^%RO7I_>.pY-|ɷOCxpgwF"OLZ+Ɲg/ןxݗm߫H_z:4oa]A:!m{#7^1~f4.\ެҡk[cf8>K8Lg_:SEd^)}UvM(emq Z<#Xp\Xiu@QWTKB^kmy0+ %U}S-qn^߳78:gﻉڮO+8 Iz|"8֐ȆRLsx²tJrQY&6Xv3WO7c WI884p9ûmY9"#7bԭFm@j?yyWDpSB Rw#]"@|$fGPj<'7n?S.ZNbƠ6-4THv ^}"MaN[)JKjy"h Qsd ^F.wc/# a!ZGPe !uwd!20DO[37kswZ n{ q/Tji1ǯ|^}bу"W7v +㵙pSs*jqjP$YP趄bOad҇=1hͺ.!vݧh_)22[g(K_9|-MLY8]QLg*/ $HQZ;r%'FlQolW],V|997fG3õ?X(K3tKA*YF2d`ϏL%U_dqH|#3rg<_S8[;3;gV֠t-9O'?^]/?lgvv d#01C{Nbi~YaQO^~UۏEo&6D3!1jTFEBSZ]`]ֻfdf<-t24MNW?v>SzJƤ >???(?ր/g|49g3fk?kd~M˥Ea`:wN T>/3w+ǍFmo p?X~/qg>z;?]OSC_|1iY!$Ji'D=YAfDz%dB&n81T&YAli 5Ԋ0/'zĂzj<؋+ʔ(Kښ.;e{PppT\%+ R6r|@*\$hC'M}q>p],}h٢ q$G># wɻPXC ^W R38:3%9bl34@$ث(FAyQ @%9R@P"uJՁ`@%9 .=o06k8P6B0n;k, ܂qwB{)tҝSXWEO|p.T{xtqH]]?٪~ѳw,=ެY*rpkgZ˩{k3?O4h%2@H=FX^Y-ӄ糙jpb*+`) +0XyOwbɸ<;ǩgYumo|־ۉڂwv5xQaqqa*3,/ =5Sh&F?~j4&],.o3zx>3[{8֖s5? ޒ* 4eRB9FH`pøptLfʙ,yK{{bN^{8Ӏq#/6^~?'6jX̅zIPc>^[oN#'ݮ{[vgl1Om\̹eV.SwId~%?=ѝşopoᝍWO6|ݵ;kKt)soc僝^<|[;3yvwsiXۘE4ߛ}Jya8_&cHj>?xөX br(TwL+mlgw[3z/r7=L=KܢZj|w9Iܽxdŝ|˭w7;[]Z[Oݟ?ze>B: n⠶tt\l3BĉMs5Fg2,ݩzBA.m&תH%,>XgO;?_>],$]%LѸ10FҖ`Xö.Fa.-\+}*~)MiΛ&tKT`7=̖;?;V_,lQͨ]{HnD]gs[jqSTB`z 4@n)go_FJ, >ZrmAx7Ԥgr?eL(b]}큛#0n@v`QАt&DjD8Cиq(j*0կGl@*"3Kǡ`" Fy2wPd-?ttK+[j1(!TB4Dwy,ѧԖu@$ ? AqxaB3g}=C^:¬=J^_;R o9gsP1j?_6EnfJwM*׍[_v\% j%Qq\2;XiX_}W:e('E_خ<~} +_:hT$oѭ1M¬X,6řt·J<lW1v⁙rׂ.1b*mNDṽjәR2Q`s噽rva;/^nn&FeRVZ)Nr˅\&HF\z}0WJl͕.hk& ;sRu>9S(RHH.|ŷ'[z54,U ɝ{;ŹBd}'=z_m~2gϧ=)lmg76ӛ[;U~t'[mxx~Jw?lwo7>O-qw勭OjH%rr!I 8\ p3F'!+4?n 8N78zQeYQqr;Oɻ09[,w6?s/{zIC٩RI0ި7n*\:STENR,ɈZ>L) .ÔAS.6zDy  ![YmOcљ&&FF`^ri3X"pLLk3,,HeH% ,[n!RC>/fs#V T aET4C"e]x]7;7;hQ>ҕMT#q@*&/nnpe` _#j39y"ч^LrRzKIQ즏 T7pB"6iP #! 8cQ#:Lל&%`>%QH7Q[$JfYy .E?ݺ/ jPCm?=/s8M3 |NyEA\W=ۚKRі.yȡ2o2XvckٰZbmv45]*UʋF6dk|)P,WrqLdn~Rc?ee3Y]y:7{Z!LX\xH-Ubb|YL/L$pM³Lmbf*(j܌sUN?ytg|{ϟ|Žl {hەMNixPo-_L2*LxQMַBr*WwFrckjV3Qil];ՠ6WerTq0OUFchqWIaItfnhb!(-+CZqиaw0zF͞-VTjpঠfU" sDm "H;DK8-ɕ!?13 JqӚ ۇh28h<՟Be X _W@9Zj hBf [̤X߽c"FW' B$qKfę~ +Fm )C#ekE{: ˦^v}lwy}tAijh?ܒTyՅB}VgC(Jmu:?[N6 b|^O<\~^dF_Hʹ彇wiukP !LpûITGQf jw(eJ 20Yk}Dw›ٚޱ$6ʯI}[Wz:b*"f'VO=x\}Z}P_Yxx&ZƝBBDL/SX=+R4G=4Icpb&XȮ+l*وSw3k٩xXJhf \(of2k|8Ncu[*ݕD15Yx{{ ooͿ\x}g~;?ß|˿ɏ_g__~G˟|/?_?}p +\Kœ|>zo擏~'?o?_G/Z?->_`{{8]_ܛ*l >$\mTg T,/zO'Kj-^oTwK;3F~> pV2 og'^e`7$z۩o'ߔK!lzjOT,?-忨{R+<|\"ƴfUýkw|'^~Շ^<}<ƭз|i )yH6R lQN0\%70MNy6vH'ƣγ J"QVsCt_͗ D:Fqrj$19иJHN\mmĜ(q@!ܖA ; _qJGbwwJh#QHwۃچ^kU\mQtU)tSӋ"BtB"[ )7zCim9M߁kòc' 6u[;!7OR  b)2 %E/vՂtv4-%t|nAwK+L6_?Mj{ەVB˥KmWuv"Z$}# u3ڛ1:D{FJ|y%3CӺ` .=GOڕJX_YY_^kfsb:2QHkt"*\`<ԘYٚ}ыgxMo|G+d! -HZ1VM`xbPЭ{E:NFl']h#٠E6l YY/s;ʀ❓g Pl+Ylap`ɖE,[nIIxR挥;'OzQ_v콛}{gnc|ZΧf1{!=%}.[N׳qxͳS+ݙN5l>Jùlӻ{wp^~~叿'^/~W?>{Wˏ^>_Ag~lkTW??ꓟ~W=/<}||!G_={'߼xJ|~O~o~w?k_课??_m3bm텵B28])Wx5!rJ\XTIҙt*gn)GR~j>ϡ<` 舩ʸĔ<&6}mJ &h9Zֱ,8瘃t}"aC8vw}]$Z@Fm.KsR;[+q2᱈D[ma-jh(3t9%7A>y76!~1c1R.݀b۷ t)2i!?.E&_EAX$YnX`Ze77E&pۄx)c·Y #-eB5[:3?ګ?^'.F|rgwT$B#I:] LnUH00;=HaЙQ¸%dnbŽ+8"\TSSQB9 ~I3JR@4>BɊ&M:vY.۳^=kc_vr! Ϥ•p`*b"d "hh'3^m;?_|/?ϿlW_/ `ŏ~B?f_~g_~>_zw/o>P βO|}?}O~^޽ǀ5߾xyǟru6< Aqzキ)gz}wbQomro$Nĉc;cEE$|>/5I@\z=s@׬w=y>>^xƍW/Ξ<ٍ+m^޸go6ڈvFf!!׳t'>EmsNRVb5hVI]ww۸*0`̆<{. EqmZN+gyՈN"#BF>LOasA?r#6s֝eҶaLWkzU]|2,^iq$wybScnc y̚L6 mzܚUUCIҽ\d-"a^m ˓r%m{pR32Z4`  jۘt]F%jߚ+or⬕RKOސ|5&c)!"0 fBq)ѣ .ʦ 2 2iJKb{LمmOҨ*5;5-'۸w^1U(;-͊ )FA.0dȀ( *y;Ep Ht$ѣH#x}X_sKn. ;>C-tp$@0ARϸY u+E#Zn*S]WD7no5n5{tɫy C;5I+{*!ɴ}yu+9%-'2:lo˶ {^c7EP u|`_qbf^1.GvNxjtckkba VSlM 6Hw]K-X׺΃-w~W]#&\xC?I!fƶǨm([<,#)MH)/,R#F@< KPfΣ{0zKyiR7v:w{I!wHdp.o Z#=i:<gG+,{ԦHqـK+S󱻋}7GgWgo-X_ܕ/ݾOW_>ʫ7\܍[mܾxz~uqJz)[pd櫗_]2?Ż͕Kk pq_xKWdǹ6Po}?r|έ]u~oQV..^ܘ[aqce+]\|浥>֥s,6ɧӻvҩ M<!?jrP$~g7p[ FN=FKgr6A_0`2y46k=~ezL:}ah73)6'qMynKw9\yg9nTQ@[:UFBV0%$܉ш(No|&\t_X U^u3Sf48CpCAm@ڰop\4TgUr*E4.6;riN[ҐiJHW43,{\ck G'hW PlhF>Ex@InjdƑG$a5qt~ӝxbETaE|&8q[#>:0M9*ȇ<澗r?/5Ϊ6.:q().䬢\g3 *2+!!X i"Kx}X npYqDDkJ< `$(,);u|ƢCVs˒ ɽlR)Fĵ[i;?SD#dfT(mMT볪N/QdTp~fTZٙ \>E*5=90w/\g! 5Ă+woFM~k<{c8Ȣ֯\|O^NYiqm \:¹5(__>wt[KW|+ׯq|.~}ٹ+goo#wqn+Jk^/*` 9}^٪R; dvyN7dkQAgd7QHPKj ,74<`q p"VVHL;U;L{Ȋ:r :d`spHƒy4n9)O/]/FwBĕe*kV9SwŴ>1\H`iocfL7h(=u\ix6Y/o׶uNCs|*jP2&M>A콵$ G~1ز4`F5QiOmR*  |IJH"8"Λ"teN+3m+U]a.kEsO!' jWTjriTq(p_p+x3f?a,etVW6T4SEeu%5c*>"Rf8WQQ* 2EUÀo[J~@E<ȴPylK J/&v{5Ȇ0mDɐ ) (!Ds͇l8QGA^!Y5N<}; >fЮrf¸jMn;Cn)5iDDp82~AN{ `nөΔ.h^NKxtb.kMC<8Ś' j* ӏkA˫K˽Wۘ^ wcqչϮNxa(o/Xpň}:h9?ڕׯ{+6>y^Wl>y_}B~εܷ\ tϭ\] &# 67}}~͹[-/>~7_Z_S3&Y\1@qD7o:{ꝵ5cVdҕw6XS΅W&G_|իW'&@`oq5&\cQy8rEHJ&=x-JH%!;9H5w ۣFÄsmn\}>efgm.uT4H=8AXz؜ X ]B~׺:o2LtZZٯ:;Br*WMVa"[7k{]C}O Av-):ՍmڶJ8(U*S5qqφčJd SGeG&:TF nŚM(#r0"Y5R|#PÉ@1ɱҹ1*Ama5RwZq%LHר)FZMMg bXOw@Oؽ)S+Ԥ|6I'YL8A)ۙIaZ'ѷM]żoo';%=ZTeTY=´TX~kC P$9I'ĸAp6)%-(ÀDa!s3  f ?q|Kί.K)oJ%q]8[uJ{j+џn?nOl1'NT*wcAmWr*-:Y.KMM>.el Sl.έ//-K;f|w˿/7^?{O?+>.]vh]^}G̩sv]~%«zȹg\UhN4sOaa8ޑ]XK[w*4Ȋ*diTXq菧͝P,p:*Qo&aɫ[OrW3{TS#^l`}jp8;л>^]:?<^ =5aeryrҍ+剻4s~q7 |߼|ʹ 6E9I@#㒻yndRwmĨk@SW'/^gla痗X@Ձ!/Ov W S2/:`>9n~g,b)Nf@ӷoJ-]f`6irr0:,Z_c۩5:FC8.]n<' Cll^_hb =̵96'r\qlݦxe,A7u#&}RB Ynm>2>_|ynB)Zp )ahBFF<͏M٨D-AF[nҦJHd H%:o)Rƕ%)< S6kvzmBMi6'gejX/woO޸D޾o~mrlael"V,ޜ]dC(W@g?i/]=╕뫓S=n5 MMaKs1x7>2Uha3(ۉUǚj #LMQyȱti[;)Ԃ])QKTp]Jn&-ph&Rޘ`Kt@ ڠZ7z^U[@ЪYVmql8]*yILp2WSc 58IX#,(futjHQ VSUۉӓ AAIV嵙s?qǚCVj9nGt<Nj Kf);A xFOpspg-@p[KJ뤆ª4q'U(އuG3PhJ \/yxNwVsN{xD:!HS3V7wu)r%s s|gPC,e@pLq#e%>jerخD"XA֫ԴЊI`@+,5>;?| 'w}sai ktg"ʫ+/ګ/ɓe2 @v*Ov>ɬGF1tCϐ%;U20cM^ J$ oSx= L7*˫3^g;4vZeШFC4QcVF }z7n_yεKkZ?wuyhķ2>,Ηفn\eq|[K㣗FG/..9蟌o 10dG{])}112_z$ly$'帰=?uO^{gzsKCΎ`tvptgkd:g.SHunYvnUv5ȻFXwI2]p\mu<p o6^ˍnȆ˼0JAN-G]MkeǦݭ +|W呫*ṳ9zK}~2 ,n)f4ڝn/j:!kV#́ްiPh[l߬mbcT:ҵuNjHF:Srk1ഢ4kZ^M . 61&Is-ӤS-W)z;'Z2ri7Әͧg3-a[$T]k1HWe(<)X?j;KesŚx1\oCwx "=|$K^ *Ǵ nMfICBǵyCu4I>n3ů.J n C,.Npۚ"J4Ԙ% "BJ/Id7 |,mHʡ}N:v((=8PHA` F iN;@zC41X?RPU}|ӑirsʨ8䑝N?ZtQ*޽{2psh.(|euynbLʹ5wnh8 ^!S\[>yמ}ni0K+sn}-mêpjwϐk;XU=+KݖF6ɓ12>R4b|Cҷv5XdQi=ґZpۑV#v_h,l'_qقCuZ- ٫uNGtXȗo^>4:6>1y~f"IӕэQXgǐ bzc0#d9el_ uoz+NϊϿ햚A胧2 25n^E(6!y.@h3RbGG.u41ݜ25tqy^ A[ha!qmfҢS^nj6C @3߼QylcIZ_t38n5ru/EQm_xo\{/\2GJWcryީ)z4 M3 jGt51W$`wzZ65 SErs55vJg<_B%G|{7>|\*u6BW@(sl:t|+w03Ncm[%pc{T}?:>T5W|ǁ<XnJvoo]b2<Xsl4z8u[lQtQZZ҆D`'xMfU\-C.~B~pѷ n ɘeF0~s  >|@¾#J+>tʂSŵÀ`ԼC9*њ仡jܕb9d:^G'qsg?3eO{|_®9'9?Aܰf0:^(2W._UpP@jg!W y k1ls7W.][<71k+/]}ncrւּ΂Ҩ2y97<}n̺ڣ Uu{̔&'X,;#+'țmLԆt߀8;L.IXߜL*?Y@ Db!=}hvYuJ19hwjcVo9ZFGX\<7b)7 0q{sb@AIZ-Ϛ^QJ %V_m {;L FÖ́sѐxUؓòE\;r\B&Ms}^ܐn 3gFxn9,_ &?+3#Vh",5 8Wx//Q)B}f-^;1b õ;X657jt.?s]ht>i:]@~kŸanQylA)bvMQoܺ6hr5uFceE4T 6 .Ŝ$;f8:*q-):,Mb-Ģ9K钧oMX:2 kd;kdAU1,7(,V`) 0 s*֢ĝy/|?"^F 8)|2%w i5x 1-&'@EǍI4NKBc5>/d+`NjL{8e}'䖟#{0$WZ,'Z'9lH"mmM&,%G9|FF05NgN<ΐɓODj Q$#np\Y 9-[LPn-ęI1^Z>ϕ[K7#צW'7'Z_Yr⺻ (͊j}, -uwu:yJyٓi9ʗ̓ǙjXg4h -([r]e, :q .cLHo7z=n/sIeL:2j4=Q7V%6 f&O ǗhxȘ ȣt|LĂVG6LJ%bI76 DjoVqCh"Q!Ύnxl" tS5ʉhyp#뤼5\[^e%/`D *A>vб3Od)LUr(2X._ܕl>Y;R= R+=ipf;dyFvKdB²(=Uj}7ЉQ;r"'Dm~ ^Av ho,nTp~wzVcM/tm`ҍX3L eb_Aa8:F-Ѷvr`y8C+P[(-}dUp|wBˎc7 N=a2Fkw7TXه66>`ܮze_ֆaH%lΆ70 F Dḟ}?39jUCV٫fK9TƝQvSһ&D IQv[ eZ- !VK 3'Pܱf0 6:Nl&kh FFf3ޞmOZVPKZ:q|7,OB=KţU7J6G!hq-,Hu|+a0Bt$p_ dg$l$0n⹉#'3>H%g1Rj<75OVTv[J)RfA+VR޻ׯ-]^;NRpza}ѨVfV,ۖFHw,I3d e@-M Na%܄YNe>W~r C&.,ߝW;CU5gJ+mƈ :nUdk Ut-(ZhW@ra|mjPlfX`?1ehJ NyܤA!]Yar~inV( ->Bcύ_XxGނ"`[`X(Am`~@%^ @)m]`\{7p1nqzߚq  B!f0nJHE]\߮y#-A6kZuqp;vROHi[$pmZ%fޠ5[c*jWF`hRUw=n5g7c4hlhnP1Em74DM:)hh"TZcFX?RqWוbJz6-9tJK"šA`"&/mE-بrGmOmkP :ѰlnwTj+n[q P: CP8pQ¼7 ]EHJ?~}FHhkJٟąf"%3DI$S%?,{lSvH,ݗL/'CpB v `ܜ fgsވ*@sd7J&ܬH "ŐJ zq":snv3w7瞽pvqfnwJ[F=ؐK?xvKys穂]gS)K)*[-B'ؐO"fp p"$I{xJ,%Yϓ2 wW'GUfRG.j1t̵7-ڗ)jK9ķ篌^ D= Anj22;e H$3)?f .q@}!;%[x)>v Ԗl)$?Bq¼/d+'R#?8l/xM< XM#B4 f43'ϩث"\`[L.pǀ6 .w^PpX6 jqepGcT( 7FvUZy{eWiB= ߨBQFLBEx$ .pT/rbOf|IF!j밹aFAz`=-"aٙd[^J+^2NIgIhdӚ4 طle[1E*k)@bL(6'-:΃<`*;\$=w}~@O ;#N  $2 Yshy#!{l>xo @f\Pդί?N +ts[\ݦjR'*Q oa* `֖P1i'i3a{d.ȆS($hjVpTVbj,l$B!B+Pd3hXpp4d|sAaD 0ehkx,a2A'{ N\Oe-eKd0LD沟N}2 sJ]duuD|#4װn1U'Z9٨OQ%} y"sɃ)=P)LI3 )a &"p/Ɂ`ZPiX9iD G\{XpY'|b fm>fx5?mmr27hC&lo:pRg1Lz\+fwf,슧vgJۑT';U#;^-ٟ,ەYV}\ T&}K^dGȲv$mOxLδǒE1?=ǯR"KaZΊ]♮UHGiY+h4V ʅ `Xja*%3ޢC~Mѱ9:)%90nqx`JCh QK3pNƦxk[# KEw\=*젲^+"6W`2(L5U!M\&^%4 N-eWmyTrRO!FE!@J(BZ퉭6ׂ<ԍ*5}]R纱EniWNiWHhhjUh[YSv;Vk8$ {؍8N-J0bneߒ6.ߔR'WW%H[z[4ݵPQgw)tT3Ѧa4ӦH x:R:P*hdȤ4=qh4Rv+GMktL1?Y—nRAѱMۡ?G^a'L{85B#>D[8>ĕn|8-ޜD(M# yՙ؛Y|5\w3hVò űM[ܡ+sH:GBD1qI9r4˘062ՄKDp\ f3T>7amY hm{Z 'V&2怜R95J ){J&-{ $`gf</mNNG9$kN pˠ3BzS;ZwJ$FNٮwr |LS67Vx<b<8ptq'ݚ <@0ڙ_8wdlKA򮖝jd)EҸakwί}*rwV坹6sIX[q(1фm&glOٞ/9UɎ`GxAFg4OEOkO'ԵcIyÂc\n+^zA@@j0 z#3AtAB}:- 7.J7P+ [vl@6-;= %.[͏_B KVe4`1~8" 0 ΂ԂbCAa!zU/=JV'o[ވV_B{3YU 4mhMTQaAds#`"ūq>8+J\"Âc٠KHmKяj*snA GEYgS;S5*s&x-"E C))iYRrx38}Љ~Bvτaz?<^A;=< v9fVG{;yT CckWujRb~@ 쾿&Έ-qKkd!^@y6v@K%MsC7tK$NR>6d ^bd pc,?')]B҉8v $dCfNffH06-Am̂7|hd[̢SM:ũփ:RJvdJ 'OdU?:K)y>^ٜRAj4@0q ?5 $N0apm~z0x p[:\zUaCAm{2칕+KӫC12H\xͪAsT@5X/>VJ);J\!K;TWHw<]taSwgGH3:ڎ撼C'ONLxTʶ8$[!} 8"YvʃζAu٨qP 鮝QL+:y 6k1 uD:d/K*x __/`k GNwa-$ͳ_Dn)n;a v6/ظ@ !:neشe6-/_]ݤCRXA;g!,GEtNJ[o͐_?6~y0;sˀ琶K4 @ڊ*6@9o{/|H]N;Cx _|[(zAgQoԛp (-|F/#lԽ 3kST`8?ӂqJ'İo&$:]Xi]2C_J;eCZa7[i6 \4̗>Ri$yB߯5+ݹ+/.Yq@U q{nٙ|T" 8p|>Lm7MנG墐P`sB \ Su Ia#(wZ -K;vڐ*Zm*?QU`{dG#=&|\p?7?G9 kf@eB!d 1Z+]68EF mvb I#n$7?"uB`U&gpŰS}UYAI hlBSݾFlИ؊DF=^$%m-6g6o j<7 uznhAgрt!$p_?(|,]/Gk,{^sE^nf{[uxw|?Gs"3ieLLϪLH)9dQ]-EJX J'} h^cgGm i!*Scq{Lr{g\!V Aou>;5{;,gUP$|-fJz$b+RDQg ۪L1&4lwo<t[$j #}5-: %)4v{bi p台Y~d͙;kȵStF;ZyU(,qn {,'_HĔ3|_R]wsQ~\ b;;+k 2KӉNʗbq n!s1%Umm4L /qA%ko]mwoi{)uG!)DAM}ajڷ@j4݈fwцsd ! G.=*vc: %4OPldHg 6=9-67i*[e`=Rx6[% ᑹe(mgӐbpQ@]T{nm}cdH5$W!Fd⦔†Za;yJġǟ>E[v  ?0,*a"rD0 tql2F9v#CvM5i۷?y&sswO^_й %C~SOT79mfGѦOն/o|ᱼy:Ah (vH" -^Ţ3F?.O0JCvyeJvONFmw$engmGerpǚkwZrBauDgD{V_}-Hݾ=3^,d`7h' D$.v?pgRK%b -؜^8v d,@p=dϽ+7@: 6~4lAkٱqMX f-[^aF*p=EQv+w.3o3Xo6 㛓8W8rERµrCL܄Lp ęEϤ b1ܢ1'>gw#sS/t< gz:yGM]}aMmn|쬀i|f8ڹ ))/e/@$k0@Q&M>;#[˨%LdEvF[ z)QYSޞ.w0Z&3C)BX1#uqh "DE6oN +w|sK%7fs^F¸-ث$7Hn 8{cC3"{kY)|y p3]7Sڨ%`c)oHр-?_u8i:̨ZF}J.i  ueZJq0 8A ebY_ďٜ}-żBCL`^c2p$v]q__sa C]aVNG̲";lTVkl;,&Cyi& d(iYLEqiAS6ˍCQe2(vA;Դ<;~4kNаG?r|YVTVqګ,7O(G[[" @¸_>BpµvS]*x1`)!Е:nΡبɯ؜wa"~(Nv^'bkݜ[FDވ@mk4nAELq|µ:A.'y<@I08jFrqj{8UꮂΪRESht8YpeÌqzRn\ΤS>ׯ8X\`qsK/=WF+0k!d@0x3%.JtBCJ*8'l5y3RGjѭW”!W 0'vNnAX@P[:-"&Q H u9 AjC|up{L9L-ɯɖχ}*]* ſ$g IdoaóDt1UjvgD M8Ѹ+ardIa@1fSPU"| B$a{}v$B*vA!8җH)^%YU[V4s}#2MQlk\xbu xmYKΘޕV׹u{a'Y޶GQgSF x`'9rx߲Y;[wiY5O1aҼXte4Ostwz^wZtN¾ .I%nx m-kLJf6 ѦnRx=# 疆΍<`W[Ġ N"vMWWKUe!4 yNc5I-PmZL;Sv40Yf+G^Lӭ*K*r>)e'sG,"=_VS5`lzn[W5a֝#7ϡkۡCfh5ǭ(Q&fDI0CH*#8n"b+!q^ܑ\r((FQ"5p>`_ 9/>xkeaag)qQaWND""4c滝摠ϭbJ([tvҮV{VM*ekPՁ6cM9ء6s~ue7VHNTm :>o]%pD.oAyUVJ.2>h4F^sE%-.v5Ba$ HG¨ٚ' 5yajtF_9 pK \&56Cn[G: p^5pC7e99ŵi) 'DwoA$52e88j3F'HflZ.MŚ]`9 :/ikÙ99 WyP!drbz~"#ZOuy-v{wa󞂦gjvqD'2*j{"agJUO(u8ꃙU{ϔ?;!̜U-|F~g\D3X0k#0΀57}[P,S~pxeo}nhmvJ:]^>^XoP*iTYe^ȕS5 Eש:`M-Wl{ixc1z_#a^]39]Xt)⼙4-hGB΄LYiN΂ʱVPa1XKraa)<ǀuvPm`7f|C~L4Uû wTޏ\|p'`[1#u.M!^#gqG(H7mxx`,+a79݌pcřXO*b. i}^{Т4BK{CCaN[yIIjRFYZnabFSyqcYQ{M"U坕u9iSiK*,u6vؔȆtSZ&Erw4[:ꖰU5 {DY O%_kl-'fK8."O2v~zk= 5ћbjqZ.//6EI[[^Gs.e-ߔP[$܂t%@mkLa)Tn67\kw3_]x\ʢ׋ÀadOpǕ,ĶB{!}Y\l$G@pp[`X~eR1&9LLƁ.s F=uA6ӊغL(MHWŴI'3,XZwcf#'N$*>]rIspEI{4݅OVu`d=B{$ewJI'?qE; 1TG 8hAh hVn!p|\q!~` >OvioMXHlz023Y\ݘ Yֶs"&uG=vZiXl:tv_ljKa*USi&֊AghjA*!/`@mqc>RYPQu hgAs$"iɗ44 3 EPgkT;4sy|`cF'UE` j7%IM+pKS0À[$FʼnyaUY”誇zǻ1ab5\7JE[NͶ/M39iTqVJnlesARz>+!7>70)Y^ݠk.*LO+n(\Î;˪U]u*UiPQml@2RkmP[ 8ꄳXϤuKGUPy7RDа24{qed 5B?")% PzEPK9¾ET*bpzt:p*7F/>J 7X'fz;̾ņ4jG!*i9(f$L!aS,ÊȨ~ Am[7 1!RlQ>z?:HSBGp6Yr70 s*[0鱸ALN8Z).lC`#*pp9Sr Or^(Hul&#:IUSiec 4dļ#bMve2^z#''NH?^t0fc6jLaNNVkFUשƽg*wS5{eEΪއ pfJ[?R号mH)≐S>^#,88[LnH7Xʅ5ۛ8/N&:ˆѨsufhz(pM٢~[˜g#Ur[}6KaQkBNO7೺ N9j֐rȢZ.ܨ-S)JwU)a01v)dtwj5cΖ!"\ף8!u:Yը%RPl иY8P75&. b/P=;"R%Z{,D;On~4Am^ y :"'MS-]ꦚ֊"֦4|*yGYIArr]qC!y%k %][77 +wc97,'MtïqNAmc[ޱmK7C5_^Joے pnT~(}$2%<.{#ana .&]ngv}%̻)Dq#q-d2wcd34E ݼ7 S`|Sqaînib~w|TaƒHwdRDn3O͸NaJj ~tr%t: fi,6[$?A2IJɮ=8I M+6ELgȷpq h&X*2%BKODp+/dWAXl? oN Ȗ!St8(y RFև]N:` Nv,z5r`7Ukb[m=>?lvg`dm-n M21eV)M]&M+I!=Scyù2i 5ѶAEC_{%#ZU)*oeX= n"I S7GX6}"]Ji5p]"jiL[1㶀# ъMI{[Po*y@|~.>t0Ij~7 ,BKx!P%b[h`ʑkߢi(m˪;ܑej*kU,RAE@!(B[#l<1<nAmIkfL z;0+ L%n~` 9܂yUKu.!/$rZXTX)53Eq5&RsN1}fT!8DW*G Q$%'p4h#H% ŵ('ܹG#YU?]f SI/_zEPMP8.ORϩ{*1iLLH_]%;q:;7!SUxS?Ӈ7)pE趐Eh .2a0FZʀ5XWͱ^?R ` d Amp+" [-EoѪ'ėqgA"Տb!H%[B$aw?FPz^Irh7[ΆbCK@KkLhG&v֙-Knǀ 5rrr@i<ΐm@1l4 ڧ zKj2 /l*JX}0nUhʮPxuM6D]OcAb/L"8跄 e#E&$E<7? ")atb{yHrrrs9%&8՘ˇ s?"쎆ZCiǡ,nj#ǥu|Fn!HĹ8F a{d9<ap 4r`7=:;J  pو7hzp?LBׁuqWPn|S)@LM+ J E%VK-#Hi!gJN$aZة?}2Ču2 ŴHTYQTRSGwLI{segPF&YSё B`\Ȳgq}Vqp*[̾: DL.%kZ$À-l$#dyUDNwLLm--M7.L}:Cg@ش<33X-5ddtn氫fGc.`p{}ʡ2bCUpm$`2#S~O83{҈& u nx,eWfîO)+O[  >UGX=d՝W S7 '%iңt_STUq #&N>)'=Jѻ^v#!6j }>W Y۰濫80\3(eK iO$fx"$Ѱ95 y{uDv8pLv86T1BdlHI>61{ϩG?wF2=+#dǂzAX("bꍀx|.ѭC |% +J_( zgGۼ,(h|TmqK6OΏU+jR 18 Z9(&ЏgR*m&=aFuCUeeut/k2dRIZT饏ra \YqS FU4+CTb(OS^;:wp:{gJǸfAwg=.C"+yEl<SWi1_E.q_Up,x} ųg>rK  Ba~XFaO{inb,s/M ew.{5SNJS9I.!+#en0nZ]:}nòӰa3\HłS.N`X#8YKYJNSǎ+2U>"/(w`4ٺ]nrL _ ,ksfGSsSjs UrYLCIME-NL;gȶ3zyzURb0kASKBquI.??~o~{?퍋,Nş7ß'_m߯',!mNWtGܹ/}&1jn R@GMX]fꭴWˠ3)(ġbQ͇B 9H%Z/QC<F3;fP+$D(DT2CAǽI+ 7}Ȇв)ٰ!;W~4'RO'3ݛ\Zj9O?z'qsuC?Y y GbePLTgKg[cͤrX .OM\=yW^/v{LBm2?nfʒ3egeyO֕%[z:hqʆm{q&0Bt: \3(}#7jq\?R,}O8 jw&/[.myR%:PhW<0):6$^1I[KC\n/z6Bemƨѫ]6ͺEyжrea 'sd׻ڜ%ܴҌb2&%v) 8m8-_`Hsօecrfi$vvһ1oph*<ΉH !OfEN ~j9hvaֳݱBSls{Gr[uy ;H&tFYE [-*aNɲv՗'j:BaZ塘W^6~vzЛ!1ނ.,2}bz牶nY01To[7qb,`Q xS!|4[6}֤)5KצMya11}߼xŋCS7| 1O>egi^κMv5Zu{q|v *ʘ/7]GvAUj+WU[b29%܊HKK?ҝg־;?޷|?^(2udk 39Rx ۟>띟'hVyAN>3:5F?)"UXi2Zǯ`>(>AM') g2Ȧ,y fzCsQC]H 87[ݘ[~@ݫ/,MQ̻QO! $찑6kNץ7mOW4jI,3 '6|೘u9<vKjlK*m |ln1Au-"%" n߁!j}t!-JvgxbteUK5"Z䉝92 04Zf VEUsީ3 /vzKn߹<{K7ο<3E6}a8m_W=NUy;55sif5MNfux>{"??=NoS_}Sk̵ {GuS&^x߸/KXn|~~;??}[o߻?[Ե˛J%WSVhe+MFqsBPo?x7<'URKqF q hేhBx:q I<$u)zˆ~O4Mr y2L{ x]Q-+j4rf/T`; ޑUxZfc{MBT<~Exld"s8D\Xoݧ5@6t{1Yu =D ,̅+@tB5uJv0 zfXlz-:kXɐb V dkC/r x׽Ӛ]p_Dl+2ΏMK2^]F< a:sLsqsJs= >7swfpcjtϠUܱ2:wx\g?Oί}_\\ݘXkW;O/珿§zgU{?{`;{K/?wͷ~[}*[UkᄂcIc'j,ݥҝ%m ڪks~[9O|o<<<12o~{~濼t~"zZ4ŅhO˥hJJ+1`rǪ9ꂃ6 6=Roh 2)5KF'(x[ѸW6ƽnU_pj f奀}3F#F,^^\sZwkV]mkadžp_qXnxwCKۘ]$>PJn}_v^1}W_y׾z/}Y5;1~Oڧ-muO_/_Λo~o5Pkw__wߑnӸ3p;jڋ:޹֮@vTIѶ̲ ́{`o|Fםk/Ȧ>|޻w{9O?ՋۛsCJU\,W-:ܣ]V*6±o}pR>2S?!8I`l]BiMgTߴx+\tC,9u`?mN.:%'V<蒙)WCjxA74Pi)eϤ"6!1ϛ{&t< `@ĘR\i3[¾Ss^@:;LnZjv8 k wrޓ9bq Dpj>b}<4LIΆ4G6'{{|kcO= F@߹W?d~ ,7j$H N-ץc[;NqEh/"SPҬoZ{QE0EW>w{c Vk6֛jsO=tԉEǏUļN$'sJgNw_v˯|w;6/>W߸ykw>/Ο?‹y.{}_|ßݟ?Ox+ҽoݟѸʦbJSOa;c@C5S^c;( ?zK+#sg~w~е~;~j?O~/?yGo@a%:1= FtK9Q徍Kѥ Ԃnr^+jzQ?bZ\.o/>7pvҥE٫sx(n5r>>LM&zeŏ_]2Q#ٺYjhAE + :vFu8=}*ƵRk;aJk3HfA1 'XbAzɇJ;pChZj("OB*F0sbGR;]y3s$a?!Xw)GMfC ܀; . aRSxdѧ$N~) &{+7jhq!+7h? ]8pø6~y1-Ѱk/JyS2NAQ\H݀./13!'t)/_^V骪VVTrecR;Jobuu ΆζTC&YyHwAВZeHq0I;X[HQm Yc ӄ=m2sgJZ#,9r:5DE^{/Mth#:INqJ''*hÑ!+Fb`CYzT2 @|RJhgh9sG[4V=Ϋ ;и?oݴMYfb~zyni\skbsA}=F3;ƖŒϼk7m^`q6;/ /xO}s_y/}>+˗{̡{g?y?>*7 Λ?w?>_k+m_zjӪKj5-Vx1z;ҪXFwK_s=S޻w}?c[?y_~?{{ο>_E7"N.]o^tί: `Һbqsk1` pM9ם 4ttsŝزE%Khւ_ -7RDաIR4 E-z(Z9P.@\ TCrH:ڥLf[^͑X9OO:w"i9iZvva#q,eD܇oprMľN:q0āS'c_vx) 㢱sa·N3SuQnk/sg =ySYt+sRm_X:rUyY쬯w6T99Ζ4gkTEc%M6?ֲ-Q\#oͱ2j[ZӮϔo+vWYݣvJC%#eR3TyJCq [h22  [f$"0)͒VB0`(niF80趃7b""pSO 5[6ߌ+180qmtv{gǧoLlc NM2F1e ig<\[냮svɛeAxmwQW2[N۽-ю5lR‡4ZE_uzí䫠n.wuKr3X5g])4+mߢKj$5!zWo 򲋲8Vԗ֔dD0I`F;@v49pbӧ䌌3gNL&(*Ӑܓ)N}'Nq,}$>'v<({tlce۟>s]O{޵O?c۟ضm#<.l>ӏNz='l e|8 1Ѐ+ 2zLj:8lC6 >jtx'']X DǬpϜ7D wߡ0nDm2 |ķNM^>j4cXkjԷv9^:n|Nf/].WB;}צx{ڕozOŁ7^}_ysg/v~~fW~$w)WW/BcS/+O\͛/W~n_|o?ϿُޞԸ#Ϯ]'ݻG?yNLJͿo|ppzgr%0tX/csyd3g͚cz^*LÀ% {lEOT@k`NoYh-b_hûYbpp6$ý z`?>:3'}lGXH.Ms#Z22mOȶ?)ծ}>Oq$y7}a P#ݮ;SH~BH0ϜW[LD%bz,H2+ML,0i;=5}qeF1TϮgx.54:>Ͼ18mաPKa#P{q#/ԙ̔jlQHvL,QAiV,DGq +e;ʃʚEuoGEcO{93y7yb3ÐGfvHSw1LL !"M[Lcؚ#rNE% )K82lTH`!Td9DQAx6=ǥ@#G<7Ds{6paNzju;p'vcxh/JE೜vKN՚G vZn\Xpm}uyjdC[=b0nj]/ rK m?[ԧ ~/n?gC%oC{oq%{?q>\0n0 H??|L|Ą'{{yӷv{?>xm>G~7; nX6 dְo>Gzw~\Phf{|;l -z73x9Ȳoj[g=kퟹ0/\u= ^5L(r L((

n~GA?>?}щĬynsd|bxa|f}hzmphxd5"gÃشrb*K@ԺyfJ-pׅ#b}cyor9jȞwN9gc36ฑˡy<'i#F'&4`6T: *'X|LTnAhR- ')PSfR{JŔYp<ܜÄ |>UN1 UVvWvիYꌊ&eU>dI!l ~Ozb]yTx< {6X~Hno@j:Amvs~{#fNJֽXzpߟB3DpnAE(qVx(qfz# U·v͜Eb^wMiVK|~>y❱ɅO+_ꯝ:5tƭB GQWwm}ZY^L8e|GZv;u'uc֊rCmګ7kݾI'cVݶHɨN[7k1)%q-Dr_FnP @Ek<~{A.Ձ nX8¾9 -C.;=np\xLl7V 0]W)6TZ+ Y)4[eJ6?.Y7;1PAmIqiܰ8mP‚bT"^sYt敛?+W/"gJ>}ï3̧~b p}kz6]B^uM{{Xɏ?x=R,7^aK_^Q;l0}v9;qd~G_w]''.j? ?}O:jtMGt6rr(kWk[zO )odLfO}n?`7.+zmb!W|ίxĪQy!jlZ_X3.z"= XS ~HزyrU#2`g0Li-&e1 Ɨ<8]OɀȰ#MLP*yl̂vcozk(@5<} Qz_oPZM@OjOVjer*RWtc{dO=~TI~cN??a7;?HNQ&?q0am$N3=C)I ; 8[zRni&zH=DFկ؜|iT$_qJ.:tNaG{Gb1W?b:,mDzI;g0:=]_>__o|KVFz2ڭbjRUߕШ;W6(}rwqY2Bk+} uѰ5gJY? vwT׭G۫8m6+Eݗ#08H 6웵yMɆ$B6vDȉPK8] 4,x#+l QP^^"j t6q78w4Zj8+sTEٞ:mY~g^:٫ yi3,e駕ɞ>EgQ _6H}ѥa7ҍZN0WBa߷BQDߢ\45+7~[/>/گ`#ݯ{7o}߽pc"&i_dLsuhd:  QKoMTL|ek^YqF;cQnͲ~@ժiLN|dHlqفGyXi<؉Ga4$O?-;J3iK ;0>À[w;%g"J(B`kaghgli`iocig[P4R}(xdnM9'8&QBs\Nu.զyW9Xf!$̧;34 nJwFr7@bs$n$P$ց(F{' qCk Օ30'WA}fVwuyIپa4֯~/0I۟߃X_|}uW{!-;-4威rJyi\'?mG86>~ y]?={d"/^H\C#KkJ776 )OZap0DŸ`EN^iJjP.Oa ı4ۮ귔y =rQMVjtn|WM[$j@R$q+Zȫ {4}Aw2/IccGNj41ɍͦz;0]m \s=rB;˪aVdd O/LWI ɰJ2})Oag#"J'=әd?Ihol[<'oM[ge[vMxv762< 2iȧhHaFh&pKm܍ l[Qܥdc8uܯAQ׶p51wu 8x[9i*GJ*U,tL̝R(֠lM 9S_+{QȋYT>&x(k7%VD$GU NATdFXp75` -6]YX4ֵ4\76Ї?q q#dn±ťC>NxZ峯'O J%ĉF}ǟLvws+G=ztpic:}?ʣR}У >_<鋟G8 n, 7o^xqeivr`p@,V#̭*7?Ix3--IaEڧeTױ"b+?7" k,0br4L"\5 l6}kL <){A5k۽o]5TT MtMj٘Y`=K9/ŤU$#Lܹ)JY覾 $1K[)T97U}q\?wT2Z30sz MЅ?P*.ycD}f|UB`GfdGj3=&=.b0#i,'5%F& lLNJHuǵSc{SbP%.v/kLHxU%Nrd]Mu--]}]CCAVw6 9|sxfxҡ#Vhizkh W~?Gh1n_E'}ão{~y|zk`c~U[TVic%عfY3 nPzsc4ayB4:_+ tL<uUG\cX^P+yAܲ@NiPPwaܡd2b?8 FUq 6:I)!Ȳ,qPx,ĽQ<4&H cDňPH@0Gm 7bnfrC mUg #=}zZƺ n]Ss󤸂1 ~=1.b砦gvKC=MxRi<ڞtOؚ$ n5m ۹tiR?mS*|q.v s2c ܍"jSՒ"o] G[nFmJ$’QձuaAU m OLNnOOg4$YX:uF&g r$==#ccC#'GpcRT<{ҡWuL?{rqf]xp֓_~E?J~O~V* NJz+k嗶K`S$7}T7:CRf#I*ȲִJdǚڦۻCda66IF :i^Ƭ8t/zjz #{jI&t.#L;GR G҆%k0#8X ߤ|YWLkdy: ,PCA}8%&\& dap^ii~^!YIaQaII07__bP o9wgٱ=2cmt,4X뺨 1P۷ a@}B 6piEUD$Suhƺ&VFFFf&ffVNP nP6D7pD174251rvٻ[aqb2A lkb>:CB+)nXep1/723{tX(Oˠ'֧FrX]Y̴Ҕibdi:5ǃT8L!qj|!-Xͨ/Y쨄|łqUGYSWEK_Mht =:supɕCG{G^fdC3O?O|-c{̹oܺHeuDVżf Lu 3KQ]ξ:=3٘ₕ5d!u}VEᕾYn{\luM q 3Ч({(5Mb&8f{2FFJ7(F Ahw K㟋bǯwXh :@Ġc<N`dž34%aw!wM-Բx^R<u7/B qw4Aܧ/9|G&*,SW3agX#2Muvm4x1xcN#ʛAn]?۵~KCwh%Q3ibڶq!;? N$6'6cw­XY1aTъ47QB,+_!D1#E@żPnL7>C?0PÕ[.5wW66/O[\8yp:Y7rֶtѵM6=7;?kL4F[[Уcw/\>r` 7VW4HP\JGZN~ }C3-+;,Fߊ,4vʵ򐹇K(!_tQV Lg9zV}{]}a> -= L}M\4t5u0'u8e Xta}^ҘRޒV՞YADZ59hKlO7cy+<{ǯ:?AIc@ -=eSMH>JYі&$67X@PdYSΟ^*Kk ^K7 oG~0:OmnLyֶ}Y*&P6=| *U2^?F/1#m_U3wЀe뾷{02Qܠi(kf ${YX%PT(B7qPp7HW#lKX$x%n)1 N/%.!)9&ՆnxYs,9fK} *ge$x8E{zyy{CqE'DDSSR2t:.6|WG?>/>~.$%xLf-QA =)򵱍;AE 4gp+$&ڥmlm3-|=]"j[㌍>-=:C#WU$=%}(L= M}|1AxXBc750*[S[Sdtq 1^@(mNŖ6'pFF_t=E}u9Uf<=@Hv-xe8#XPhmB NWttl`#fETL%7񸁀Ȳ>p͟g[=t_ձ{ĭeX㊶V[j}i/bfKH߭{%?m% nO`oDwi*iJډ#qU(% N(wRI)'Mj|V&LODŽs^l4OdOs};we݈q3mukΦfZŻ;C|#`Pc"bi* .tm qܭPK dy8$ZW]iAzf5$J)@AuO1-ALefRTplv 9{ J}4=*+jX(n+SC(n; O8` 2<<"8(ЗbOVT`@dk0Apa8Q)u)Fmy3˭!L5׃yQWڃRN3VLl<>Kk\tSW޿~} 0#P_}/E<?oOW˿ O<ߡ/N_W..L'᧳&IMOU[35MtM6+Rpprpppss6Ě9R-Í]t-u͙~6=xhhQ۔l7 7Zjk1ݽw*;VS.}j!Ǝ{  5yղR~tiiࡕfIY6ӻ87wܾxhJ⤏TvV]E%q+!$j1%MTBQJA`:% ,z_3* (S `SŖ/;ag(;NˮÊBŵп *r# o-9v~aTEsJ,ɪ`}w n>(3F.`;U}/Y6t~emN[t}[/[5S qoW*Jqad%qwD|p7iTCű^p I2Qp7X qE&6:LbSsvYy.yPy3gU9Ømkg-! d9d\,Aܱx))PTwwYF< w[uBR$ORfBNmss ?Xh]^Ir\U2bcHVo3W%٩(gf`蚏gX@@oWPOx!CgPdg$g$"C-q_CDC;#8 F1*,l\&栫\ZXKc!B?٣O>~c!J^.ΪU!PdwWbhj{YFxًg)sV6J6uΰutLu 0r٪_7^ 'UMSZ"5[w7^Ppfw- ;Mx#Wv0WQ \<45sȑǏ#ab8rZR¡3Skk>{W\p×OZY TqyPI]LyC,/#])ui8ڪ;3ZRJa`g׳P5YZArJ#7 ]pٮPD̀I/uA@am 3q=^0g[yx$O' 8"p+6-,9tV͈O*wwCz-sPN"q?K0q<ڠotH!1IEG@pz nwMO/7_/##?)(  ,NN 7gwNֆa$N1LXqG#y:*Bĸdj ǸETq,^N+seO<_RdLn(&VV}vƠXw'c%j 7e{ֵp8;wg U}=\ip?w(NF>b0I u'ZZ:#0#C5L^[9K߽wPqs;O:^Kfճ'O"|9յ'O^# m 53k\ m2UVyq?{_=εo=#gڦEܯ?O?>|GرcP NSG6ZWޙPZ[ۜZҞ\KO{ZEQSN֊>ԆzFfQ66V!fF"O5 pB]TlMLlt 8܌,۬,oS%”HblK(9X>w_ aL[AN F4qsy^߰joR_ *I EdijLd t)mvs2Vݲ7|u^+&d^Q\%rr{*'Z9Z ?s ? Bs8q{dx on`2vJNRUTHM_ƴ>GWVA܏>{RNFF&&z&{\_x5F{6mwڧw43/HMvGo=ˇ>¨&?#Çרe(=)%ķ,q4#uF{H[ Iss^1XЅuB xzĽ>s%q3c/Ge|y +JrX2,)UN,rK y&{ ~ ޡ{hYd"yܐH MV$p2[KhA R$/ׄjᓀ &8TE.&f75^?!& ؤ䢂I"IAK )#YQe+p8\XζVt;ymy VGLc)wfZdx~^aAnv)&fbo;˖080xKۡ._{L.fHJPā]2~e08s]>M잨+鑁Nv)LXO۽nFƚ&VjQ6Y_]V8Q$^/W${ W@`j3Mj10):X1SC,4GYJWq:Nn:ljj75ٸMK/d=F_crR~C]=xwݹz{?| Z~Cx)7YDhwc` F(sݦZonOKzq2o[EU<4b'ݿv ]1ҭ# 6T6vdӧAܵe myHIkLi;6Ľ޷G-?3n65Fi6r\1ˆbub r1 ]0!yq'Z95zYy:Rh+ 3>-D Ra@q×Y×@<&(9<:RH4}55vں{Mj*]m:P^{p7(G,*%iѸ`TCL,qgfg*T-ښ5r@q#j _ Ϸg*s͍r"CJ%|?KHi?G |o, r3+,{7kjjJBV)Fv攐t};c1˔ʎ=+M @k/>~ӗ?~wpM?`pBP܉^5\~UDQKtI[&>i=nA'&]@[^o & ({:zz>XqooE6STu+-am#WYCqcPe#4Am7`m.]065v!'nnHlnҟ*@[֕" &QZ%hP6@zwM$­&ڸHV*vE((n(rIRQyOzR~v17S_9loKLKrgx:@,?[ Mw6N|g@@1.F:耵Md^RO31_K|WxK˱H "HIlh3r1Ɂ a!i>PU ݝʮgr֡j~^U65baNCYKQ_A$H4'=# 𝡲AEQvD@}#V (3L7ZhK2;ȞBcM w(nhmm82!Gj*rlUM d7:n2PܰJ"\QΚV4pemH /xװJHSl2̀ = }牑HbdLPoeMge}xn@[kGzT{hG|{}v62XzSң.^VS~~e[i5=8ޛ_i Ch/,IHKwaEz{=ur ッ&V {wuI^]K2\U+q[¾NO,֛^[ف ScS\\Y:]__};*9yƉ:^Xb"y sQѝ&7 sֆӝqDn OQ$RjsCiX[MmۿE^9IkB8%n`A5i HJ0!lF(YIlq2%R 0#{[&Ltw{TSyiI1c/ (545yZJe>6/K*K ~n/6#ifomھJHo7A*+킰d0 ;bkc'}í<͍+9A+P SUszj37Lp ǴX Pj>kD/aҺ+z|jdJy`cgM&*tK%ƻx+.jv [۶֖7vعmf+GDd7T,F|r {wgSE_~헏?G!薏/&gECS7ԷAJmBI)r]W޶#mu5QĘ'՛G#x7F>?+r̐i XXW4[Ujwq KjP4?։iMWN52SG~7_|ɖT[w؜yf"!8.lqK"*q\^) #4!n,]'7y*B,qMtqS1M27a& 2@?'X D&d%88 MW-^F; plO@Ӡcw ( q~$5Pd}8$;;=&OT4k>$-d qQu:,F"̤ UcaT;9l t }uT4 4jm`Ks0Dkų C16678-$g<) vIxFjdY;`-L !CK=>܃ }7~|O?@z?yrpOdQP"ɵ?_ǿGA7{O~Z!4W_{LWuK7=A !'AhpD|*Z5|*HFß^OWt I^%IQ+&O_{E!Jⱐxz|"\#vE'Ufw7HQ?۴8:P^[,e}>য়}>Ww?9qq9P]}tt|xh#ދK1q ^WH+OLLLONeLJݾ?? f@%K׿;00/yr| oܽ鑘 lbͫowtQtZ)1ӯw?X<\7_{8~?di (,L>vAY, nx.#%MQhP< q3oHu\u)DuaOk5F* C{7&Ju8@ Zhq[ =MҖ*nI)lN).۬j}ݾwW=sJ% Ȋn^McW>1Z+ϐ6UЊZP(|%8ڢ%-aP74z{gCw[d5mݚ6ֵ[%M^EZ^ٵaޔ[%w(`m0Ӊ ZG +c'u7D㔌{TQ(Q Úd(bp(IV  --ȫYifoַշ򚱚Wnݯ5SXwW+)i$F/I餗K1(p19 <[=)źն^b#v(t0Ǣӑi\$٩9ux j2Q zKʋ2-mI eh4.*r4/wL(Yjd&k{:"mc\ʹ z>Q[iZY1p+蛈af#5Ucf4 sƌfeUyV+!(.8ԘyLFP^Dzy`Dm(IJKOV7~iW6oQVQEKDّőz4hÏ|T_|޽~;'ٽLݸI*kzeR 5tww66ttv70rh ;F(fDʮҤP|?_~!(n2qc;p4R~ţ'K 9I݃/>'х~!FkalZ{H#Ͼǟ|͇|w?~pO>y՗`O"Y3]ݐ H0N(קt,Xւ&$BX&  #qM$&hcB&&y ajڞԚnZU'/H Oe{2iGzu']I% 4J+e7%XT~qv)F+I_#nenP6 N_{Ƈf: QMjI[!%eK[Ԃ`I$q7q,+Ұ[z0t+&FT/kYmBV ѫ?R }I)2LQN$ 6'MftC)P951dN 4$GyʹilU "߫-# -j:JZ*[TT:Z:9yX'Y,bohBٜhƳ7HN&b{C.E1Ln\Š԰M@!uwqQ?{Xoy%\  ~p&c]u$tbwzp1zv*qnu;?12#w|&'.*3a&K3Q ͠Rbcר"KNN  q{afccmjmina 1߯nfe߿_~u]f6DP]n#%UEŜJ~v]#W˄O~z!{y_W}ڍ.BIwXmMD*p%U eí|Q:,'dJFǻF&kdRvן|_e MLaL`|?}(OHˊIu*x >~yx"Σk/,)$`_}  ϾzcT>zW?|챳lfTWkQg*-k ڽ",$RQjAfDw,o6%靖q*q$Q 0N^2ERS"W6'Ͼ>ۊv:IŊ IR&|KSR)OYAU^_!hwK}ڱX[s˫l}-me-*wS\l"h [k@'8_ycY:K[-2IZX T_x?Łf-Bv6ANփ u~RR,+TS]"@_ozJ}jh ?=0+=+:<%?;&"'>&324)8 4Po2O`gglhj'/H=hgjgmngO߿F]-zr9iԜH*K˿*ogIa ?s~_<CH./HP]((a6*kť~|v^(`KKCtwt4V b9)v2M~/U"i|0=ZeTzI)(o{珝GRs' O{||G! 9f?~xg-+e'% Ndi ĥ)$,Q MQLjl%5=3'6>(,m˛b*cJD B%^֌5 ⢢',6Y:ݸKx.Y @hMtkG9%$is {=OXB[¯ b@Ɩwd"Ih%oGӛY (٢A{7ܰkܤl&%D_ʄ&ckHYA zH'!O I_ڡMI ykm|pSa+r L v61PUmfFiN=J{}y|NAN!5;;?;/'3=H"oK˂fq5Boq^_(&fct7S##FZZ3ccn.nxZmxؘ]]89`-:0LСJ_>8LIyן^}O?/Ml‚i%EŠ",,Mk *yEb߻}/_-_O_G~ ¼^j7#SRK9a͏d !ܢǏ_Di(hmḧ0^;W_|ï$ qJБs-"^p;1X/z뚁fv|jEÓx7?ɓj(G_\ˌNOQ4mkml?yW^9}c^/(0liٵn:j٥k׏^rUL:~.z+{*{˻z:J;:d֢qCAPSǫTTWk3 и> @)8`h?;;yqC>RR`S\DoBG_h\^q?Kϒ\^iü`vI (XPqs8U _q #$猩fBw4-FWd@ SDs5?Be#_-ؽ˟ݰU&d ƕ%)`mHiRNN@0OVdiO& CY?lrh'@pOD)< BrW_*+qA++#]u ٻgJzjt)DVUT7&ZQlRb#c9I4NJz5Iu񎴡d㫇eUy1 zVIsPTOΊꪓXό_')" zMYb MM@7-*.-&>& $JI r1ԇGR!]"07 Tkü]]0)GWHڔbi=mF**vzz{*+5f;| JfgNx{p2gkmmi?Wm_cZbUɆ{dRށ֊֚Ɗڒ|ύǏeo ~9;;4'[=CL3:t6O8xY^U$d094yWX2htOIҳJ]ә9-¢ ۧ?s㷮zԙG.^8};/y"3VA5 wLd&)+ǁ$"Ap"QD`b} ],ϊsXP\4T0311V7 67.., c]|aQsS{g tVBX!9ɋv1[bGGtWD9ɬ,7#3싌@~>NQ~naGJ G#u]\3 ".8@BOĘbe`fjSgK <kkCO{7L637SmuLkGCq;8S(z ]mHp٧(氭Uq4vP<6{[Cu?A*yס#B!IeaQ^-d5VV ! Gow=4;:nh:+03Ǔٱ  \@yof~@aITY}/OPY%h%$w>zƛ*7|G_|+*N~z'6ɖ\9CM/F1}" dY&,\{.~._:C7n^=εwo]{;/p};7."^cN>s|uby@p@`_u_wEOgYwGiC+%m^YVVRZ\RT^VVZR\\`S\\oz'Nz&H׈O"%hGE~D |N6v #F-jOh.]L&i$(Dn4kAψF"}[5 RP5{Eݺ/+m.۩'Ly߭S^9^: =E?VWbve&y8Bޙh&O!k0LXPQ).* ->%c= e/l"DDqW%f].fy:ZٚyziS\44um`Z::P% 3"6)5-}MkO^xhKKPXL@ D|V\$*"CI[/?>*qDؘz8a𣩮w8a.:)oۭgTw&y }\*;legkbY-+n))xfz:k*):.bof};uhPޮPKG MUUAPܾvvNy{"]$js-|5Xo,+r8<Tj?_󦽻믾 >Mt5ЍJM'|O"܅ѧ/J*gfyd1x,oͱ̳Kc!Ѐ<W).JU5ײ3\*D\y{'Ko;wU0:61Y.bA&#?$1ƅ7/^u;߾}Ɲ7^ɽ?z/wkgn\:qѫ,l[,)utCKkKjdU8Et~.k'UP Fv D0:8US'jv5Z*5C: &0]A7MPS?Id ֆFメqFg}F &꿼SE%e Gp2-6L!9"I$0!I|$dv1+-!][ޠN: d&vtLCJ] )"MxӡOSgyLq^~1_&nϐ<TNv2zNXogW/'w{'W[{ 7;exE7u;zvxhNψѲh? ^_^^>q\LuvviYE2hEiIРO7 `ePMp_k/ C]5KzfPK[UC|5{Kk ;ڊ ;woQSW wB=•+W)~};tTߣ[vjk޹?Ck[6l|^GMg/XBUps]6zlт66<%* ϰD޻vWY(v򒕎egD|T/7;_m߶-6A&! ԴD->96<:, EoX_Ż}'p-R^)7:+߉]. %.ckgF˷HZgmELș.Ie[1lXY 5"?,2?8J gFD%82FF MNd)@1-8'ͪEV5uU=@ogC_Wcw0ѧ7N]][ZkKVq CȪlbK]5}Q\^=ֶL_TDJJ3+sh@ii PR@yEsQV\#qLR+Dl6&F+*)Z } $\E\.zԅK%U8--) x>C"**"JJ =@H)TUpR 22#T|'hmp }K75zoZ6خ Nq42ݢa?`M|ٞ e6a^I ) |8Ī&It:ORSM#[d|tܭ1d&EM *4 $"ŸN& -Y, `pXܜ4X\ȦWٵ^LXDdph b GZY Afhp{H'hyC34N.A9sjeeY(!!A,&;FaqY/ٸ/a1I0q_΄_Ts.~v&NZZp5s4t'L16>v{>per3._h_iMZ,Ռvcb ZiڣS\[_[iؚ*Yk)L1٥!^6N&3MsWs/s$Q^>ȑRL터|q0RrY, 23Kxgi'$$&# ZWE F$ ;<04*$  +1:ݺqΝyȩ*IIV.7<β>"6#ό^`Xft}&.gƱN-r #+ʌjT2K33$ V1@_EUe`upmhCxSdKTk|_߽8, .Z쁥Q`y~ ;;9+&NbO,̀W\8z܉SΜ|Q q.?5{o߼tpgxp;>|Pܼ`!ݷ/]{ҕ[W^p쉵K߽uɃW~3<./iIiInJnʬkaMܹuCgNY=ptmWVsrbta葞g;3yBdDX1tvZ-碴:%D $q\!i̇"w9pۡ`;A֊u Ϣq ?/1ISO4opPk|blynfuzjifznhH 7<#>;x˗n>uKKsEb)) Qqǀki2Ug 3?k;K̅Հ2F2<03@87fe޺?unoiz{RW]Z;v1){'.\RWۻHc-[M4U(kwnV퍔vEZ4kJQL.HH;~~`m7a[> PV"&ųۛL0AyyLcGy؅ru+G0@`k`?0<1:3ud~.Z90 :>7љqp4ppa.M]?p" b\< ^kQD7 dzt<ѕŅO_n^Ob=5ֳ<~ęf!7wG}Ƶc {&~Wٯ ?}|ܩ7<c+SF&[YU%5! -ݬl3DcS+k˧NL<>qFo\_ GMܚz#W.]8{Ʌf:6ysqsq W_^:{qggN>~zjncjet~hzxflazu~7 SM cu&kǫ*,;6vlةg&>vɓgL??{ˋ|pwݸ+OO^0wя?pw;w/x{|@䫥o cWm;$F'GsP#m=ۼa`eKگo~Vޫt/@ċJ7qL  'lEh-B'md %)L2@H G,B8s xAq1 u=-mSdxP(::ڟ<~uyڡ0ѣ!cb3 ɉ[7=z ntܸzđJN$c;t[@gXx;.VfvKSq4$ɓ;o}tZ殭,ƿɅ+Y\ σUlٷK_umQ,cʖmj_3jdkxa!;D, V&6KĠ`l6lmX%8"D|tqc̍ ԗ>~玩nA+)Sa)_eholDhj"Fɠ'DbsG>r'N9qr际U7- `) l <5[%Ι<' q2cܸ9y,Tjk흝o쁙ٙ904{heaɣ SǗfVp ?àʟem5ᑁ=PBGhn,5!rXY15}pLb'̭._[90XW(ZYxݛסʡͯ_>E<aBڅ .Û9~xz[n/.7Wp J]"OꘊVϐTTb#CO?:8>o<\\qq­ۗn߽rݫ޻o٭?y+=Yw;xe߻wn}m{{ݿ㣏n}靇⃛N^20X\X[U%Y\s?Xc\uzxƈӷTޯ_whlxkEEϺigR.Xtۀqچj/loy JB hBܘgvYC"!nm2Rh?SIWtŔwbrHT(XXQC&5|poL'7HNȧƄXdc4BNag&ʲYI)iASUECuE}]U[{rpڱϜ;{+׮Ox ^#h⑒0w {z>338'%&Ţ; !ԥCz/{'Ϟkhiw6 "BrT=g'_3<fkc wGx~|ha)Q[M uܝ~rDx<`]{T[XKypwTݾ@czM\>[),5iZ[d9*1@#? 7)_D7* !+ؙ }-եL,6#55؉#ﺤ_S.lhjm5O]=uMJ"Q =2XAR6 lpCIeَ,u*I`X'liy\#O[P- *(mM4ղ@%3-]MC&g&GG:ǧVזCʡ@1Ji D&1)J4n3Pmg2=tBs*;P)noM3, 8<00(n;UOkG%#@C> k hH_$#>,YW>e@?A* Y M5v7vU6qU,aI&Oaɮښ{tU-3X |INV^2-+VZs"= -4T ܣi% &w9حA ~ -_ձzqΆz,˓oM&|0M" np4Fu_+b@&` L&C8:!8Xn;. FHoZthrdpbx1zNZvjV*J!N6I>a ǖ׎?yً7ot$l'W=xdmi 0?{ܙDVMMMqϜ~:##C`_7dhhleikjT~k6o}-CU}jpl Oɉh3[AKRiYit,\=Aܬ,P9tw 5am1eF[}Wo!Ң\? 9 x񧟰~od^PSnjvr?rFC5-GXR,}(Rs/  Ԕ_82",⵴t"dx~l^bo|>zDPf>;73;=35:|L,-O/.MgƦg1Só(>[_5`=374=;81ӆ{NYchj+jV7ޢ2SR*&B*)D߉_1hVY!k\dgK&GodoRODSf~o确şm_ҵou߁7lxU6EMT~MZvhng{߾?tGm$jFJB&- %M5 eO`mh:-nAv~'TT(s273ֵ@tk1FJ`Gvx`C<:pʉ/Y[=8{h7qŬ,ccC6;7 {D$;%,[k[;3388Bq}-Z&*ۥ eoO_=E!^nvnVV{ hmRW}Mu+U^ tiޯUMe&zNk{k#G[@8#=.9j%V9}񋫫"/~k'a^3s+֠X07`OGjgX_tD0G{sS#;޲4c#ܝ4T4Քwm}W^ؽ-Cm{Tx #mcz2VRnod˧-&C-ɓ ڑGaBnfL"'EBD'rl @$0+m`AƦmnFzە̔ u*P޵:XO4Jh[ ij1Tu7V+^Vnf&Zmegkj$K*K+NLH 3䶵:$$zӣ2,3c8ll4ln?0312p\8=}M-ee|^Wϣ2r8aLgŚ纳^ j&M<VDnr%2azey/$BilymzSGlhx؞PS<bivуGHZ?8 %ྚLQ wqwzvaǗ&&,,ΌMLLLMO-,,,C $ť`aqzh{dwtlnGwTZ-҆\@V|4$R/-\]:t鵵SKKVqh#//K>r 5 # H9eF<}C|~n(jL88]_G]i]7j޶Yi65=vWuRbJyEN ##}]btF2y4F^gqTIDEj.Atiafjhcms&t"igLIl 67ئG4ܷ[ᖼ7 e'GYIİ̄Ќہ6݂tQgr!S2"p0Q\71ag{,]M%\C8kVf.Nf~ޖ>V 0ߘĸPHuFf"}ͤ' 5'/ҾWPU$l[[9xxiymC ra[˝ŃGF@ܳ"#CÂ}#c#qoG C -Ue5[xu)ܹ}֍/l44LJ!~)Mee2.;!,,Pv WZ)*Ij$^{MEcL)䃻 y)\^^̬ȸ@| e͕̎*n hJUvm.`cA[-0D-$\G|/\&+m5G=#S/Ko[+;d[9bShA^,ˤd'Ga6wy0'O/(:87wСkkHe[RiBD(OIJZ[3VWƑÀR܂nI[w!nd eѐr 7J>0j?5̀'ħ&di8qp=q䢐NIrB $? F`V4OOtM+V!oqPGZ[V? B;PDȾ)~5=<͗owl ֖h?oٓDi"OG ҝ’,S)d8w OJ Ivf905p4&Ӝ _41;:޾&v-rpEt.>|TttbҔ#w"G\1v;׶+Ӥ_h͈H&=qȗ'._̮k[: I֡6>.cʪ`|iY4$W/M% ˓pi46_C8HbѤe ع1X 71l8qʃ#nt ׆_9*&cI+5׭6yZ7`zrW Ck ޢa?ʆwmxu7@6lQ}㡵qSp A4?po' gK]ml5uXDKP}~ŶG 0SU4 P hs,b"=b<1 q>XGEIQ rAwmԨJ h+%Bia~gMIg]E_k@y`i;ӳSS3,wZ2CҢ=}qD(JNMj|y{k:q.mUU{7Im;?,1,C31mꃆ)pa} P*̫([B%dӓL)믨-˶6f1,ГaiE_oӐP@cؘ/<ڜ*%)" d1'EIe%FGۃ "|lmmÓsspL3r}M6`nDojXARvN$A=q irWbԀ$Jq#ktܒD$;OVrYP(7Ԧw00'Y<6ʥI>+>rziv|~z`z%S!q7ÀBn UKg~iٓ(KD Wbfd 1BsKvN+@_/,|NjodppG>>j%MHʪRsq4ER n'ϭa{"z4- Y%idHOcYg; W`s%ޅehJXfwQؘqS-(*S $Eu k!(nH~.J 6 nz=R0Ke#Qۗ[ԐR_ڤ_ެM:EpEnI7u] wߡ-u9e& [r F%u?`$頵AIHtzxYM |l 4PFP_mQ[eOԁg+mw{OG#=X%0f@5e0N#$D@M'%LJ =HB*}ǀᏃ 92b\^Sdt uԍt7MMNCMNLOONMMH; O'GG;QlTe FP5`ᒬcáQTbﬣeo%bq"}qg'&fbd2d ЅbajeDA*ru+J+j u Ybmyz/6e4W*D|VjS @Xkn|sJMl>{v6G#OK>S-5KMG]3w{J՜ i.{Cev]yV$S&HRKD=uc<$\e ZDAՅU8V)jOpwc;jFZpC%wC$f0}"Vazщe&ַgT4PAi,K2ٖT XZrkH?;?[=DO46!*67>^69Q4?xhi Lj B59 ^G NaKKNc#>V @"!x"rݞE8d|=TWAȡ֖fnvRVP`uhExovlHMr@XF[$E'8dnF[ax 'G4zbEK*%^qItX.TCpuJQIȠ'&$fƗB:[H2D-kz9z7JGZ-!*IMX1G`Vϒ56Lpst1 XMnqpQc"*uڤG`ދvo`H}fMO X%G~T53Qܠoq1?:rT.yH@z)P=:;Uw twrB"aedATclw)1ީqrMd#PS(e,nHKR]^~&0f:Beŕ"4Nk*B{ wbj~|}f> #C#FG #(izzG OL *ɹT`DhoPZX`4LB` dFGI&-/M3= X fff-dɖdIe$333\\]] ==C=&MB6&}oRT延s+m{?skh:ޤtK4PJ:!ή@ X$03Թ8޽4Ɯ;1֌[? kPItؠX76}6Ӗr2+d5C8\bI2S##PKc*DiDžJZ/̶ZJ"*Z"LT)2l&ם)/6/6/N5̌O ׏[4^g2=?-mgy/$Z BHK|7OL9>[e03и\^A@)n(6\L4@0w[]1q }QG%z*&3I}gī̠ܹ5{cwE7ό@'f<~]&JmuܻL;> Q[@ar.^߼9ƽ=BMK ¬ =dKnu#PeSې8p0Hޔ.nE5 r sq%sp|Gt6k[]%7oy58P31^ekT`pwgvֵ (a{=[F7t9|_?2gwp0y<@Ҧ"it"ɴdjq>JyT%* d,S]&X_RfR1V phETz2kӄ05$tqg@/I4qz>@pe *?WRz mifSmѮDnkAc{N< ML本2Qc yX5Dh7fJ}3YW5 B B#sL@RW6{8~#GћRnXNW@+ٓ3[:rV8 N05֞ G p/qdMLKDf?X|\(OD6 =(јNF_qFf&'" IKgۧ۠ȵh AgAj9\QBIg<^p5@ġ @L1hĕśW7BM=k@6|s[PGZo޽yΕk egWf lhkSSS3SýVLjSUD_ZfU8JJmV9 Fۤ7puLڤпFGҤڜMJ\%0qm]DohKm,7/-5BCUtrO56`;GGkY'(U)KK/b9WQN VYWWHQV<7ReQ8̀MG(v7e%kbS[;KG]=nIl_??Xx/I]TnM)4,ݹk/Y}cyOvxtM+wn0བྷo?;wg{F&J g'lQLm悺 %ӖE1چ4*R*XPE;&\m|2?_OsQ׺X\r)J~zۃ|cs4(;Ȉ o,[cׯRDJraaKƳ}RGNOeTc$g_ceKhz~ MT9+daX*UΒSNԒrit`k U0䎺Ly]&ܜl7jÔH~^$[zZU b~`-)RzAk?jk>;OnH5uFڣg"}&;(à&Qޣ1D5;\pL̓CdžjQQ{uTU.Gnf$!IL#%WSՏ1nPP껋{Ky @adwѓY%vKkfuRj`RkDumDH}YL Iwj1)$g8 N}*p| /G<_prǝ/?0<<4$$[\',)/Z_J NKϧ2vu,}ݮVa@p CR(!pgxysgsv~dmSӣ Sk f_yvb\qu>,^Y{{KkƮ%=6ͫ+ݫ^6ʭowO>3ow\SM.Omi+z7EY&Y!ˬRT"8іp]&d0TU"N 6{ =vFT[mvyݮuQ[{3Yr3`YX4 B{ʱM/qbKڢwUE&Dr%.AkL>h,:]aQe46RgdT=.ڪ^\6S(nR^#AsW>Y&T-lZf׌4-v,OO:{| əEIܚ 1zmyeoټy{ctT3~m m~-5*n.Z+6־\: G7/Hlo&ioXC9'C26IHn_ykwt=X2 Ypm\ٽ5340Rne0l~wzO謜޹ڃzo ōۯ\߿~[[w6o7Ztr><#gܺ#OʛɻhNj/쟐v 7*cak\Taޢ8ْhFښBSFf5ؼ Һچ=7i )S  fp%'ַFv&ݠu_߽9w `bH !1-T3& C*=NoOB=\,F(Ia u4ᮆ$%`QW%i/P(:; T(B ͗lT(jCj1 |, Y"DһbiK^wkRBKoS_)H }2s=2ocnf, ?b p):2T7Qe\aXn<<8@ /^Y 56J',\ɈҏkEsY(fp5jYjfokKyEE7^޼6?7n vgzgM,jZ@nF%QH;q^#!RLY0doJcO+ޡ%;7nlQ0=قͳDŽUH7\=>o\[,vl.M׶1 K:=噝񎍸;L]sc GP0n#%I~-gBѡFIC#:k) &ZݻwGEӮMgТ1m^lw֧Kv`{D*ؐLc=,Br5T%u.Μgy@xD%x&Ni΢*ܭ :-no\:T2RDE47s}^.;dX[EoǾqlrB65f& cÚ^D&d֝kiJgz@17+뙆WAm d=|螒>&}HCUDӠq@B4=}laH@p|iLCAj/`$˴ qn0nqeźcEڣ#DPUu(SzU!g?=UJҥOAMd%8o{wW+w_}w]4|k371g&z9. BQi:Bp.t %7IڝHۈ$k$d߸rN4,hsN48[^X]BKOկǟ`]gж2V?k5Nڦ蜠ORp^p~?;.j cO! @Lޮ3Ѥi[&+GnZU:BCGF UhAS2꫿4ƢW)Ylm79vF[;C3.5nAE\Ec S-VFdUQJl>.[m :h[C\h C Vy_g!jKŴ`wd*ڮOa5\ߒIޏL (2'Ll 2:ݱ֎ܱ @B@I/ [c|%O@4Ԃm!oE ғ ub?WZԖP"O' ~?\; JN0*`f-$h獼/eoN:"8?2ˎբϝY+kՏ.P;AKfks>}Kxswߺzu{ej59{{teHзS0F: }qAg: /R[ݿh7|<`{}歫^ GWFƷi'F3nXZ'nߟ6nmOMLJ =VIko@goƗx(<#Զ0sX7F\(hj=U35E 8GΉZ^{{Y`ҲV&yvfl-[,L^ޝ섕l;͕Li"^GeG?4aq3p XwM:Zk6̭9'pE B|`bH~gwArY:CJ{ɗƵO_j S#y|nJ]h, 4wEz;#} }E#Y=Ы(pPXW=d6#yeVlVa,'3:M7ui5Fk WrYc ܼ]Mޢ OCoIbL1 hFC.@‚ne>^;']o(=p׷LNЩxZpg) q2m4H2HwRجe!Ux5ڔ $t!DڨK4{چ>;v`xCmͫ4GavGڗlu,b*ћTcwړ{%|unpZ:P`m;IDdzjsY8'5 `2>PjvshCQK`E|ּPW>2G`Z0F&ĿAoI h14Ѻ(mc!P{QTb+'`bs,raڙ`-vC1 dTsL{Ѭ<Ҹ2?=3>L==ZFol߽vx€ػo};+W6 F(ġ1aAgZ߽2Uܾ{.d>l |o^S"37MA^!pO/PNB}uni\;_NgE<8lYJhF=597'L -DajO!" 7JG *(!Qs$%oMvLnMܜj[a썕Ήẉ0-X;f ?B8#vo"=p,=:p+T.BR.٬TU+UnO͔ogwƇ-rxz8W7'YQµ52R5Us# {x&v<[!!3Ib<2\z6j viʋNWjz}wuܵKf+7Vg;Gl6%^ uېnH_7SO16bdlaq'p[Zvi?D ZZo\"66kSmlImjMLqIk S\ :GXmL5*Av^E-Z\i>Ayޞ!6cju\<.N 4t{#f8.2ijd٫֤%lp,C.XT}ɊEGtgQdw39oMN j P )A6;Q>2W. `<*1]9#&U]3Ҏi `=ImS%oey;Z@p!y%%Yk keXǠ1@k`Vnz k̢k *wӤ+qh\-U#7TfDY6mLe"׮AN{ (CEJLoVA__?_;%9 ]e@*m6{Bx $P{agfeu@GNokvgsǙSGU"%S+۽#N\%tԫhRo G8{zZk|n [mu&J#NBB#` oM䜄-}m}jǢ<;WM]>?Hp_]Zd0P.9P &HJd8uܝotjk n$~@Pr0Nd}k|rC\A&%c/W}7|w^nxӭmUT/Z9%2g+$ t`7toE\e~et7![ڇh_OBWuX2kElPdU]1yf U#젊dGa 97z Hց Ԯ^"4\Bxt9Zbȵ©Xft} $oƺbx{ބJ6 UKsAҪ˄prTUy^ϱ/5o{yEdnwKWԼhGQ1!tǝ^1f%:ZTqIϩ%i:ɋB䝼/HFȴb^qN_1}m\BNB&o =b_3? : *S |lDmZ^V$ RgoYֿ"\SP]T,Ȼe]s*N<ɇ/cAܽ UtΊ:fʉ2xcX;Y73U5]^Kza=66܊zplgGMef7e#^G^Uf%I0):?+_y%,SGܹ`rԽ(`eBWO$_7_Wo?IϹI -ML07(g)2{:[ۼ]m_x-r=2pՑjuU֪6=n,Zw 9ljW5eJ{m)m1O.QP>:ԌQ54q֛yd$Fedd&Qc5x+߸e1Vm]3#sWVwV8 LMtMʹuA9A6 sQfy@SB&d4΂˭թ w]Q8WcnhWOR^Q-2zz1HTB$lm*U2RO_*VL.!h KN>}BKqMI V3P G'i EzʫB$h0. l`KEUYBW65Y]sQ[{QWw Ȯ֟)T;d3ں3 L }Rh i> 3@'!cJ>{ڐ"<8y 0wcrGw5wwoPmɳXklI$ UTH% FCSffUTО0=eĜ!Aݝ5D{[fhnhVP<%84t2Y".l$p;lHEj߫r,] =\qYx7*eeC{ L;CQX(Rr$eTEF\DHVJM6ĸSYgS3?+>d-ItYy^]0'jG֓v%hliO\y\o2M ٩P9ԶLl1c+ӡܜٮR7i~zx(- +G4ݦW5뺑 } 1=2kcr2%3WLņ_+n07zυyt{ ^)A IK:kUŠAp˜ZYevoI 1ZӜt:xqw{{seG.G%O~Lž0F;jbJ~_|ߦ--zoY_3܃K_:wvn|{%q*+C@Fiw.Gpœ-ml 3=ulKyGk \j(9K mtr3Ā#-ZC^#.Sg"cUAQ;8=E#񡞙řI! ꙘONOLԷu=M2T?LQ`7IƛloNЀqlTo.Rheʂ rL5 1l33]SsHweMNP@%^I*I,d(mm6y5>9јZ^~T|f wi/JMBNIC-5tI*C4#M@ n 3 MŚ*`Z=IWNѬnl'$,0pm(E[('aI")b״9q+g. vgz5v9 {]^<09̩ J4&}S 1ѣwTa'C(;'ΘZO:iC W["[:; ZYSsM\- A!C)U#辂7%]/^5%pLQ݃S YbuI!oi̦kbEBIN |,EUgH:~>%/4I*C⪘2ybiuJ(VGMTiLPE+R8:u(X2a"i4[P0_HhOn :NOR _'7jiĹq=2xG[`*{hM<24Iό{dnt[_ȢʬTE R)=0CȁKZf@'.,4|e#D`LQo~|*B$*S(d_n|HUo~oBWlR}"Y0SmSQx֕Ef. 74('dRK _Rఋ&i!龺=s*bkx`7΁@wl٠ ikkrVd7[mU\ ./Uge'D&]PUgDt9ֺȼK}\!Vb;*p+-ٛϪKU .iAEC ;8~Oq=j|d&G*xoOl*+M8GE$e֪3ӅnU,fEWe6U:,ڷW XPg!׶k, - s*O~ܼ w7m5ZkOsbrӏ(dua0pܝfƦbN vvw|ChmEzMk]B%Hl!|Fj }*hfN`{f S=3c!NƯ//X=x>DžťA!8':}>{@]@MsGN)NΎ,)JRZ֭l {G4cj,b UTs].s.}?1Wh,mn/.j_dEiqbSvVN:LzWm:ՕKpmm)FCO 9UzUigqd# L`4$K 4(*5iRsҍHFF0kP&HL/4>|S/dH~ZQ74d0ӫC8409M1_N7IZm";6Wjdt'X&; #jĮ֝( ,{"9n/ u€p@͛vS Ód'#Z(A?<y6& *ŝEO;$6i*DC/ 7P-adlIʐ%(y>&):Rp:lBȔcM^p82dTʙ9IeUYE c |04$l,"G|LFT鸤vǙZmom/<x ޣ&A*Y۱ \8(PG~yd 1?2!\Ey`})SV%*m#NQEA DUi*/RjIRn5}m#0N*T"h&K#ܹyu^^G?aTz}j15u>/~'͏NzW{h\wkʠlΦՁݛ 7.fGw_)]=}rqٰ,{wˬRBkSk]~Dm.hlAa"sUaQ811L4b:oo:K1 ?G֮6!e\ƍu}kdn$6%2y(yԳYͦ\Tr ~w"zx[ kiP4߾jBcU/BZz6u{fmv_6jv \~AmHw0H tn3j:y4*R"H ljaG+ S*FX^nv8 X0cFT$͖$ Es +/`(:"-eHXX`iĞmmq沌t^>AWI '*{owa0]/QI->=Yw7ww F~7u"0Wے`=9.U˃˥hŅ>KζK_lȴ/>s2ɳa/J=pB G23󓂣G9U%P!9L82&7[#GhK<13(ຢ\]+p߾505!&jM\̻hӏCMIڒdPSVU{J8yQ6% ѸA+IhXG9ڀ;g?jБgj²}ZgNϿO÷>=8PԆ,hr")p&S k^,C"SߙԜZ.B[R)&&wbŽ5.ׯ+x/s}܊̬dX:3Zy#0xϿ/w_۟z띍[w'gW:V79o\;H+#;kfz|-=nKMpڧ4-~kcKZhceʳTa l/,>\Tr]skq ޘ:o%~H{UK<?[ ;;ϓa[WޓK܍;"![~qQT* 3EH{_x1r&</݂o~շ2L#6r-^%?nyow)vl(15{P^_gnnrwmRLzɼ.*&ͥ- %*3W{L@wgoXw_}y v?=Ft\q}@fYq/nzgW=햭kx '^RW:6X\5^eS!uV:|]OgUDŽm}fv}: ݑpm ,SHtV4t)"6o4_:|oTq2L0hjfM$H%ڴo \۽U?1S=JPӕznȁx6a.O 3ETZkҳ7G#:C紵{8`Z1B!" &!/7̽c "øsnPXWjWj3^ \7p9K| S%XTyDV(Ǹp-D6옍Zkk$[1\9|YFs4Ҋ>A=ݼ^&aip7;)[JT,ֱKkrbE4+5&[oc(Aki66F=a'N2d)VJd@Ųzh$MeCByhvdQ C:ChNTO:O`w15kꃫkKLhKRm Uآl̉4Q!9YT5buVVIQUi5ɼf($bO~!&XBቤGBEUS*Yu9!I]) Ybu"p n6$1e~d<' b71x gʊwjRj454 UMΨ۝QT^e9U)fàlS!h s}qicbFr.#C9Apw 9{sc?oh53W:l'ƺ$Vdu'ۻjz*ۼwHd㻷{QB39^rzp<{^r=}Rʔ?;r[Z*\NGJЀcy[7&W#Css!KkI&zztmqe?\3[0M. a< ae&lwƽVqפ}TW{g{ӳ_q9{l-jנ Ht#8LH&tOcUnpzKJVS E'Kah7& >>'olP:wpm}ǛL'AGLmjb*Xkn.2ΡR 󭍗նՆcJiS}(K9`D1= y´\$@BA$?[,B0V&E B_B 1k܂0@?kgnҪc$'JX*$xqe GKdQ2y$ne IkoA93uK.]CR- ֡6{_68.Zܡ<= #b7(yO&Bg !x+p4HΌmN:D'*?$fYk*/Nɝ,ofW<d)>H%rC%M؝P%/ĵi~ZZ@mO umRc,'ǻ%i 66]26"kۓΌ19z7<۾ݮM:a̭N{BK},8CQه"2_bKtŚeCBp^WyIeѲ\]Y{MNg5:*-)[#vlx-;Oq:YdMǬHnTYY(;E0D/a?Ǖ$HU"d,dg'E$›/ܼxo}ˠ3׶wo.vv5/0+_}Y ^~+WVhA)^+038:ڊAwx]) &V<ӎVr6+['(,9#5R*--9U4zoOs@!$(B(MabdvjD# %%ȳR0}뚽FYhvAU춋-Ή֑^\s׶Ju-CFե47T|K.+@wMۇզBo%@6 `j ,1fc?1YkTpffX#$9#ߍ0t#* K}brኢ+ylQlp գK6#LҟOetX-LeCP'y 4zU]/uWʏ/g8ՄOTure}nrgd?DL,+ G (>],>sś$ڷb`:"x-PH9G~/?IJ?I^tdRuh<ȌOU/xSy34* ǫ!W`rgIG[@.uaJkyU&ܹLCQJާ4ǙkzWצ/w Jۋ\4!I´IND{<}('v67/J`ʥۮbK$+xs'/;r*yZbƩKQ/F$d'?Rx}s3. Crzث `ON/Dk:@QtN*ԩ[ 8:6 ֙-U71i璙\dJ-b|*Du4kVë6o:&SW\ض1}5A(E-ѿ/q)ÊЇo!{P9]wMk]{?OAP9*e.뇋Lv&`j3%y1,ô\&OT]Y~w޻}}w4_}+6E̝{[>e 27o߾[/=x&0j#"QBӛΩ GRkKp#FR[\whFUk@GT-#;zՌu 4eaHX\nq_DHbNk`1Ք IqCl6=. ȜIE MﭤEkP8i#$WnOi][>mZ$=f/t-0DhRHTrszj3D#cD;enzlb3_ $H"|~ջ0Sv60S4 f#tW4t&̋)ZGh' ~M| dsCô*s:W8w7Gė hRPCkvy 5?rDB٧#t%߬Н̖W(W>DŽ߼?4vBK&o,Wyǹy۹dltxTNbA W{o{HJ9X٪[ZZω s2w^]{2˟`-؆]b|dpgv#?vݳYR].˦ٻ,}M ʕd;Z[ [.?+wNމK%ya ՈyvWSc/+do]{|#ܾkW}7_{c+H"?\z}ֽũ9_@m" m)?=VPnQMPq@Ul XEU(ŴO`p4#L f,÷\*FIT(jLgFYZٚ&=Y6>D <ZQ ጎE)}3YO,1g{>׆'0(9T[ ^õz5UJCC6[=jm)ڬE/ p64k67d(]҈6ޚ6ܺ۳bJ̕)0_7:X,ح4_&hyc+o!~mMem[K'T`e,3\&+y&^h ӬмdY+kk#>Z|FK {&bIhiH9wM MWU Npa"ۘaHVӛƍGti*֥)5RYpLcי" h>=DuX`ּ KM1Ɔ.=8\,?/=^r<)PV*c,૨I뢨&JH+T-1әt'/#o~~-&Spu(m b}DAչң/zNw^3,o5=fri\QJr)Z=wrp7tN:{ʧ9 P7t2p2)k;z55?5:6p{c _:|L1?IBS9RJOgsG)Ѯ{@s<_yN4}JhE3DP ppl EkAfӘqCڠZ-23@ȆpRG?O|i`U23T77Ee(BԎ0{{jmkru ZdA qpeyXyQ(̊jjj꼢hHssn{GI*0)vٽiå޵%?>.7R>rܻdT8<^(mɧKbKi沯:4~M7i W[ExBOk4]*:Y^}RICraC0Ho 7iG >fr248:|L$1+I( \f`78nЗ8jRp FS,[q ZjwAuymW&#'+%{ѱf*hBP h h1I{qf&VB@ }MP<IM%th&ASM dPi ԷR„0<]ŮN%j hQK86C 5g`3lIx #8nV΀9gc.G!t{@6@vm:au _/_c@3v`[ǧmb-Z7ω6TO1jUhnʬQBl NVp_Ԏ&nFIgW(;Z|;ݥ'k, 4b)/p{2xtTB%}M.H/mwU)_~P3B'դ94hȗ<@egQ|XtFW Q*948 Wsvc[yY Gn&\xYO`(\8O}SMoR-6jŒܴ\H( QK"2 crBND24lt>`4 "38^̑ 8lMP)|8ـn4|"!rP %Be`~\ap [`܃G ?.<FsX"*Ǚ&߂EAډ-Mf{d1nE8+Db>4'shŇQichiE\iV 5ւZ[BᲨrߘ_A?tlݸpes 5oμҭ'7:g_tHaŜyG+U/V? AKf-/PCX{:cHѐm:S'6*h {{mSH|-:' X0{a5uO֢qڳ;W'H-C]ӥ}sLJ),5 xyc_ T{{ #eyŠevQAbO9(Vh@? #8 S 6O`E`0@@j UDZqb D;I=[9 N!ЫS(2H =JB>e@_ȕbܡ(*ySQldz3~ sxn@+&Fn0-@Z=UJSl\RbUBX}]'Rez0-sfu}@`g 0(ߟX|R>0=W3JO%Ix.ޑkT181= =CnI2D3w)V+bO>xk~KWf_ 5U:+9ܧSK^L*|.⃘IF?g$rH{ARUs&_RR's(WP,Q,=YDKPlaI]@9W+U?y31P1P0GoHL >yz_VvDZPy).3%KT^U(N~*lBәǙT<,t C1 bj-4& n,/plTe=u+)GmG#k#3)#mpn <"x +-^@ubM?m쟕N7N&yeͦMT՜k @65(:aN+-l0fb2i |.=ޒ[K /S4O>iPuektm[}5FQJ9;be+pkJ_rayfWdCߝ'MT'A2`xpj$GH}!@Nr 2R*\@<`9k&bl` BM_5":S3{'s&Fe7>VJڎ0KʺU(~X&>h.sE+ k]!Tj9Yv0>lK)|ȭ\BSRt¨ N@NbXx=r /+yeyq:E@Xt}pK+2R.HŚ !y8_" \7CIh  n1E #_pӸ:ZG NJ}#;'J-m0Rmǯz {Zn&t=Gе-gK/j@i lzn?jH<9" DNɬ|uƸZ[r)HT$]סRdXr ZP: K)ΡIs_J}6 dq#uet&,J}G RCQ@<}ehDFy Sm f)-:1"pCQlBT ; ߄J|2>@l'OrIW$')*3G5x٦Ԥ>θhi6α;|df|&\桬ֱX[[8jc܊N۽qox|{ ;(8zX8ۣ9B,/{#D TsdjTK֖DOONCo.j2H-;@R,4"jǼPo6)L pϖOWiZBK+D "I|)75x\2p{` (A.^##(1h5!H$’~! Iv Ϟ N~:!y y012-0G"[~$N ZpSrq<.Y.c oHJ3RW(UCdJ-ޟ+>^uC$''P @+13J.&䜤jbmr,Sq)67BDڧA]l[ё'̌]N}):IԘC2ԅ#h2LM.~8I(')eX3Zssh]Gt}w'#C^{։#'sļϧx 5;FM ΂Ǜ$Uu<cݽko(d/H<">26=%$%5BJ ʣO$S}6Ǥ}Qτe~ 8ff.[е9y‘^BRH]dd ^s$ClbH ȕ U<#-bߘms:{N3~t!-0m#qI[\h. Ge@ԊTn&K{*zc+\ oL2_]r`YSqg:ĦT5W٤ɩP9>|caɕ͉ٮŞݫT ,2=&SټނO zѰ2uRᄴÕ8w Cs2@ ;>%CT4 Kz%NXo޷VQllZh&K0ӸTz&ŕ*#EUQ1I%ŢԤȂ䬓иD/$!!xȔN,}!!Ѱ鄒geF԰i$ٌ€]܉< vsY00P_mc@v!jق]q D~tC1?rxzx >8Ms'2Tv; ~d>dJL e3eYY{Nf?t_y0~bY0gQ fuwtKuriNY0|[,/4v+$cLǨjmEz='2 ]iZclQzHdhڐKɵLMs4dӵju(R3JOdQmJ=iU/s-~R/=1(q@!!iUx0@7+"7+?/~*S8!J{Ґ5 zHqO}[y0ZN 4e L(7(k,( MJ;#k)&O:{m>6 :!|?f@8AQG-`{@]l^: Bf(T{dPHq甤dcaOev{ ;O1@)a TTJɧكM.|aT 7/17+t !8F 6:\l Zt]EJTŐ#}gG͓ G ։hUBS|.>Gf|2>daIO>͙WT~E֨6$eVŔk.`a#LN[|HE`3ka4 CPFXsVI 1/zyx !ppwVAn»Qr$eXlԂr*)i9)]Ĺ爤sea)Je 2cvFq0lX|ޱa5xRc*k.}Xs&d%'(?t2[ Й.u5WPUey#!.=u =-y\N*FpOjzf eȊmh=)UϬvhIWߣ1;q|խ~;wo^~wCP}cfۛgm F=HK+̛%hHqSLKтuetR7zztݍ\'̺n6yr $'* ʎΫ QGE`aȞ0j/>D;䏲.rp—%İK.z>ZU-T <{dHt)p0/YD ?refk3J.|ې 9wRz# Y3xhlv5~3 ph@Vc"*P ׇrk|h84jc|4/rz|hlnY' %z2=absv;p= pnPv((9Dk$)<=]K0 O BaU,щ#V# )MXHvtLбp̖R[겇)pYPl9#G&/4篡*x`V#L=mN!(A9 O>@\y`Z|ZɁx#Pg۟\"Gn%U0?O4#ac+ )ЉU5im$ R 4,ФgC?T"<:c+|j\G@Xj\͝56F7 /] NFqET`j{Y ^clsqnϑ APZW'bD~g#$PDpgl*BRc!)$$t9#FU)zD*v?IO /P lkx,,|(~X%t:xSfqKtBWb(N3<^*w!LalY;jIu]M#yF ;Ƴ-C( L=g|niKv$q䞚D su9@=0EX;j[g˽Ů\@VPN3$Ɋl$3Er|U=Yu.^mۦ7,%F 9*CLt)S(u:!z5]=VqShb53۸qk׾~[߾_G_կ_wޟß?z?Gگ~ ?K|[^YitŅ ijX/k/ַRXCG:z'atMg&pGk-noHk@yPLb;J86ƀ}FK 8h_ ѥ72Srfs'7%VDʈ"\ѹ̒SE' 3q#$GtgFN-:,ל0_,c=Q콀,tb) p 6E`Ds,'z;]61KKXPr{hR@$! 7 2k#Wzc}ݛQ+ڸ3i^y3-Mˠ38,Kvȥ BQRJe/IuG>Q ;ēA~] 2QPRۢ@FH() DǸqAODe<,I$~g%G]Dt: y ,L)bU>Ow':x>GvqUޞT4!7gu[oq tnvXS(\: eYxAT nT)AQ’;3V$'ay촊m܁\զy(&?t$H L9+u]RX l, @^KPKx-7 ljrN€o>rj&%HYy >/R՝7ag*Gņcm7S9H\_~F}!M0$9zbj:#!K>Dat@䶏1a(F2E`0Q8ѼA*Ӝ==CºϾ|?O?xG_+ޗ/gwŷ_}['޼smjs{lq{ustswŝPu5]&g5&A.cn'/+ۛꈷSіj()#N5Jŝhpbqܪ4xCdͯ^F LMC`葯 3eq{LfTc 8@Dg9tTf5جސw@)B>e*6di2+^ :z)T'cҏ" q|}:xdiq\%BOQ!K0`  9c'q &:C4tz&4uaR;0 -y?iMCzzRSԭfd!G /j;1"+Lχ'="$'??)4G`Ň%Gt!a÷_54KhG1!m9ZPi4X ݃o zgE} %mT KkqJyi`7\[0d/ʑ/9b/rOE|s퀋H`&7X,%|bIа1ysG༳O7z.6̯x8.ox7_o~w}?~?N~__ѷo|k_x㽷^~՛oܽ͝ybU愸qoɭݑ^beW XVnu]ߚ_ cw{l6moln,.glu(bΖd cV>\6 )J~љO|y"cw=t&I㩨O*.HCf‹| G j޼<}si[n9:F0UCi6>pgci!`Ȓg'C*e!hY||X,]UBV|mG(O=N{i8H|(IEGU~*O,|"&'Hq>PK57Pp9[a=Lh.@ap(s^>Gli uxu_W-a֦Q`frN|SY݋] e=K5 "0P~H}{G >:/؍ A'i9 )_h+m)Ɖ;~~d46aON97we3o/} [|?G}w_W?_?W/g?O~_{gݺ976[?7_\Y[=~V^{u׷o_ڽp+WWZ}Vm6M'W\3 WZVwۇV,XiB oD>/WA_kko^[׾gz{woޜbb6WJ*!i4VxH,$ʨ*F +UDJI

^c`k,9$0:z%&AmwʕR\a3V_Ҧz5›(bX,JS(' "j!O ON1YO3bot)) dAKۤGImh#-̋E I*Mf(B@ARR|! /( |sX0FdS}9XLsϝ :䡐 $+ ‚t^0?s#(NpCY<~7ӈ#Fy:/M_H'. e9~s/z/@3k9NPP8A,W~g:l3mLxخi8?V,"^;͛ HzHh1X G{ /*^*V!f~X9o:nT{=[a5]ᎁXGW$[ MhWoL}Ot]gp㘪ጾ墩-0^6.5d1;s{IQ~+\ý#:lP0gx񴊸KdT?+ZQH/ݣE/)/rh#Mv_1\(΅࠙\F]!G.E>}$Ix3Gΐ1PoȩL=?Op#}>ǂcF%_E{ew1-$3%8c{A<]9V.L|2 6V*.9=lpY-4D)L~,ry<$$Kaߘrx41_7J;:jѿv211,6/wrS?P1𓥎Gj'=^ ORC0 "&dC-k ;iL(к iOB'%L"5Yq)#cڵtjK*2 4AbX>!Vj p(!CPPu/<Ry$t`EW d5r,9΂|` `>7/Ζ@MyprСKA姎E<4{,$륗.U$8< 첄9)Ty ^/8 d(М(p5Z$-pjh7n9R?#|& N.~4xYRxqVJs?М{q@(rD07."6XS E@Ϝ3U/TOh\gծSj Zxrvqq*m`EB`[d\vH;h\t{#G[;g3}Si%@,VuK:f*|rQ2% edji$lЙ oΑIKĵBbfٸU~չ"~c޻7oo}'?}?~W?o~;7~~ï_?~o}w^}{ݿ~+znto׮v/o.mo .]X756=U9N*mlv|nb>u9Ce~8^Վmj'wT3Us7#-U5#DZMx욱o]>rUٽZIs׶Ul ڞK޹n`W76&m-zudEVO5bML;WǃhI`~`7 M:G[ ]YXbi1&kJSJpH%f_~j_M֙~Kֆ<]tr'2oT_N>D%l +0D  z 1R[{ϊK +LUDȄ鳹X!?t=$,\vIS7h=IDD={a!:p"u]B:GisOb*v/ x jwgea}tdes\u4Qb7S:[lnsx) QO$cHrI"TZ9]g@'8 $':)*)#,zbm0;HP96Z~`O}7{r4NPQJ#B|C)eGSˏ xzA:H"nJ i~3c"sΔ-],RKL)<ڕ_K(:U$WVNH(8{/}JÝz>*kiyQ9Qa9Sj8YR;"dZ3t%*|2q$#V-!i#m9A!s'z+dE1/͡RuE8"Xc?QG0Gt\;Cle2/N)r^,9.s4}(}sXh$'s/,ĶLy?3e 1w3&e kzkC1,X}0?Nko;9ᚈiM-f/wv#Mqɭ3bemsҷXȩOn-^n49&sDmֶL7δ&Y}%ccsmᳯ}3|ݷwo~bo~?/~W+!~?կ~_ko~fkw-\9sm|זn{~֭ɍkFWkcGǚrdEN": ,HeckM ڱ-TCkt7o[FפȪ^ 1\9"X."[(L^򭏴ܜp+P8}entg~hq7;^uO(7L鎖4ƚY)/(Ĉ ps12G{6aJriI^O Got)%0N"˴M;Dj+G&9C$&\<!(mR`O;?&ti@S iOx=|>y&"A#RIb@v6-Gs2c◿/>?yW;7_yu7vo^ݝru2o _9t͝ΕkJVFojexn]W1xhf80+f*څ-)͇-`Cyv$|OBo@3 ^krOu8;G{;zWnm \w5:Og$9*fu{',nJXG kI0,,U\clNQr/<{8($~_d!/)*SHvm;M8W"9Rt˾[pwO+l`c 1C{ P<;]fʭ8Bl^J}PсltRjx2UTx٨ >vl  "S'1CȂ~uI8L$K/Y}t_3ʚ6c\NI@N2]!lʮ9Gb 36W5YӰԆbcxM+zӍsvX.B/2DBa<@?$T,^zDZ…ٶ)y 'nlsw^ TWAWzȆe(0F۫}}TMxn(x2LSv9@j/z!py#*P\Rᘼl/ IE2||0n>,n e>sDLPtdvAʯKAQJj8e.,3b6<\ѧ15L驠 NɝdYVTN!MC{h+:ٌפA͖ٯ_엿>/1;~;oʗK/>XopzvnS<}wkgZ7I?A UskuF=%UhLDŽ t +ʾ%y|2n>kz? g??utg=tF0h/ uh畹W}֗ؽqcl}?6^GÕm&[@Dή+`M]J_a`fCc`jIb_  780bL;± P',[xHSb~Ds`HRy7NƢ#B[JNt%: ^M)J\~"$}Ic^M88P!2 I8AOjiZ0*p'D MҙZRt{.@B6m`.=?az-u. pնx|dٝV|)ɅJCak;xd ݈_!G弐\rPV O-=gw;ZT"8@v|Q*cECKa 6Ԇɀ*j*ՇJ;IN~8nr'a7:ݱiF),QaHsEUBaDɢaEZ"h0$M 뺩4 LqDp~`7r]81hDnjlIoNɜⶉRpa`>gG۟ؓSDwƮμF~3s~JIw}Mcgޝ7_x33{lwv'7?7毾@Y^?F~o79_ַ{o>xp͕Յk7Fnt/t,,wm^_L.7ή,l-tHL\_c|UCLi'uӛ-iؚ8f~j0m|8ߜLlc 50 vȉed^WoT 1V9Z2}U+p4v5Gx' {KWl̿vmwwٯ}ۯo\ZRtu墁#kG(]mLjƉA1N`aS`h rA𫢮~fOQpp<{v:1s1Z?ү2е!`7䡜#@$HdV^*]=bzΑrI07qj2q 3i.Q:S@e((rr#\B/Jҋ{oEܼdJNg,#jBɓД~AؒI1I`2@h d[23Qޮq-M¢*=cs<(C"/#u/XpF!cT>S 0_^O4n>1[4fM`EѬ^vpB\ل;W6{ߑ`4dC99q>0 y$nc`h|>$=5 ]x1l5?nHCˊKh8?bs-G/A7G,ni/ X,ܝ.$n6&i__AQs;$n0n $R KwPq)Ձ4&F as}n%S -H%"ᚂYH,]GqWUݰ嘣I}"#qo;ʏFUj(N4ۋu0b.iڠb8"H[>`Ӵs\ F=:_~ *>O@LUm1J+̣^y:N3ȌlS{aUn-uvԜ<np>rڍ/M?7v'_zv ?ߌzǫ^>x훷F^6|POh{OOvWh(i5̌׷樍k*Cf}Kv;KoZԶW4PͱTU5MBi ӥK/Dclz{BCG+;9d*ę.CѦG@pݵ:R˹4G -v]w7tH5h%#57uʝj*p2njdÊ% }aT?_:3znzF%)- &Pm4W".Ue)7']Pc vcJC)8G_ۊY D6>2C2=i !!5艐\\ȅ ( Zf-hBx<+&*+<ڬ);B?>Aі h8wD#F!˜48"Vˆ`E@a@Ŝ3mP/dTgؖk vsEY!nrf2iG~ܺ=@}l+/FuElfjZ)4t(0'ۂ?lrn0L:86? r /3.X>F w) >&=v)$?~ K~B.)]j˜~ex{ѶHOQ$Sv!͞$YaN-.Tvė?hb #̓1idC.#F&rd%M_ L+> PbyYQW!|Ⱥc9GppYeYYJ QLz⯷޾{/=}| 7G~:;}}mTVkd7 &G}Cl]WZmVrW12 :LߍCFz [:󌶬zsΔ"g;~BmU%U$h#u& hvq)-ZȁR#յxe\eK:ʑ^"4|C*uJ=I+4p d:]Z[Wg.uz,DcIENDB`jexcelapi/resources/functions_nl.properties0000750000175000017500000001074711206777770021574 0ustar drazzibdrazzib# The default names in Dutch abs=ABS absref=ABSOLUTE.VERWIJZING acos=BOOGCOS acosh=BOOGCOSH address=ADRES and=EN areas=BEREIKEN argument=ARGUMENT asc=ASC asin=BOOGSIN asinh=BOOGSINH atan=BOOGTAN atan2=BOOGTAN2 atanh=BOOGTANH avedev=GEMIDDELDE.DEVIATIE average=GEMIDDELDE averagea=GEMIDDELDEA betadist=BETA.VERD betainv=BETA.INV binomdist=BINOMIALE.VERD call=ROEPEN caller=ROEPER ceiling=AFRONDEN.BOVEN cell=CELL char=TEKEN chidist=CHI.KWADRAAT chiinv=CHI.KWADRAAT.INV chitest=CHI.TOETS choose=KIEZEN clean=WISSEN.CONTROL code=CODE column=KOLOM columns=KOLOMMEN combin=COMBINATIES concatenate=TEKST.SAMENVOEGEN confidence=BETROUWBAARHEID correl=CORRELATIE cos=COS cosh=COSH count=AANTAL counta=AANTAL.ARG countblank=AANTAL.LEGE.CELLEN countif=AANTAL.ALS covar=COVARIANTIE critbinom=CRIT.BINOM date=DATUM datedif=DATUMVERSCHIL datestring=DATUMNOTATIE datevalue=DATUMWAARDE daverage=DBGEMIDDELDE day=DAG days360=DAGEN360 db=DB dbcs=DBCS dcount=DBAANTAL dcounta=DBAANTALC ddb=DDB degrees=GRADEN deref=WAARDE.VERWIJZING devsq=DEV.KWAD dget=DBLEZEN directory=DIRECTORY dmax=DBMAX dmin=DBMIN documents=DOCUMENTEN dollar=GULDEN dproduct=DBPRODUCT dstdev=DBSTDEV dstdevp=DBSTDEVP dsum=DBSOM dvar=DBVAR dvarp=DBVARP echo=ECHO error=TYPEFOUT evaluate=EVALUEREN even=EVEN exact=GELIJK exec=BESTAND.STARTEN execute=BESTAND.UITVOEREN exp=EXP expondist=EXPON.VERD fact=FACULTEIT fclose=BSLUITEN fdist=F.VERDELING files=BESTANDEN find=VIND.ALLES findb=VIND.ALLES.B finv=F.INVERSE fisher=FISHER fisherinv=FISHER.INV fixed=VAST floor=AFRONDEN.BENEDEN fopen=BOPENEN forecast=VOORSPELLEN fpos=BPOS fread=BLEZEN freadln=REGEL.BLEZEN frequency=INTERVAL fsize=BGROOTTE ftest=F.TOETS fv=TW fwrite=BSCHRIJVEN fwriteln=REGEL.BSCHRIJVEN gammadist=GAMMA.VERD gammainv=GAMMA.INV gammaln=GAMMA.LN geomean=MEETK.GEM goto=GA.NAAR group=GROEPEREN growth=GROEI halt=STOPPEN harmean=HARM.GEM help=HULP hlookup=HORIZ.ZOEKEN hour=UUR hyperlink=HYPERLINK hypgeomdist=HYPERGEO.VERD if=ALS index=INDEX indirect=INDIRECT info=INFO initiate=KANAAL.OPENEN input=INVOER int=INTEGER intercept= ipmt=BET irr=IR isblank=ISLEEG iserr=ISFOUT2 iserror=ISFOUT islogical=ISLOGISCH isna=ISNB isnontext=ISGEENTEKST isnumber=ISGETAL ispmt=ISBET isref=ISVERWIJZING istext=ISTEKST kurt=KURTOSIS large=GROOTSTE left=LINKS leftb=LINKSB len=LENGTE lenb=LENGTEB linest=LIJNSCH links=KOPPELINGEN ln=LN log=LOG log10=LOG10 logest=LOGSCH loginv=LOG.NORM.INV lognormdist=LOG.NORM.VERD lookup=ZOEKEN lower=KLEINE.LETTERS match=VERGELIJKEN max=MAX maxa=MAXA mdeterm=DETERMINANTMAT median=MEDIAAN mid=DEEL midb=DEELB min=MIN mina=MINA minute=MINUUT minverse=INVERSEMAT mirr=GIR mmult=PRODUCTMAT mod=REST mode=MODUS month=MAAND n=N na=NB names=NAMEN negbinomdist=NEG.BINOM.VERD networkdays=NETTO.WERKDAGEN normdist=NORM.VERD norminv=NORM.INV normsdist=STAND.NORM.VERD normsinv=STAND.NORM.INV not=NIET note=NOTITIE now=NU nper=NPER npv=NHW numberstring=GETALNOTATIE odd=ONEVEN offset=VERSCHUIVING or=OF pause=PAUZE pearson=PEARSON percentile=PERCENTIEL percentrank=PERCENT.RANG permut=PERMUTATIES pi=PI pmt=IBET poisson=POISSON poke=INZETTEN power=MACHT ppmt=PBET prob=KANS product=PRODUCT proper=BEGINLETTERS pv=HW quartile=KWARTIEL radians=RADIALEN rand=ASELECT rank=RANG rate=RENTE reftext=VERWIJZING.TEKST register=REGISTER relref=RELATIEVE.VERWIJZING replace=VERVANGEN replaceb=VERVANGENB rept=HERHALING request=VERZOEKEN restart=OPNIEUW.STARTEN result=RESULTAAT resume=HERVATTEN right=RECHTS rightb=RECHTSB roman=ROMEINS round=AFRONDEN rounddown=AFRONDEN.NAAR.BENEDEN roundup=AFRONDEN.NAAR.BOVEN row=RIJ rows=RIJEN rsq=R.KWADRAAT search=VIND.SPEC searchb=VIND.SPEC.B second=SECONDE selection=SELECTIE series=REEKS sign=POS.NEG sin=SIN sinh=SINH skew=SCHEEFHEID sln=LIN.AFSCHR slope=RICHTING small=KLEINSTE sqrt=WORTEL standardize=NORMALISEREN stdev=STDEV stdeva=STDEVA stdevp=STDEVP stdevpa=STDEVPA step=STAP steyx=STAND.FOUT.YX substitute=SUBSTITUEREN subtotal=SUBTOTAAL sum=SOM sumif=SOM.ALS sumproduct=SOMPRODUCT sumsq=KWADRATENSOM sumx2my2=SOM.X2MINY2 sumx2py2=SOM.X2PLUSY2 sumxmy2=SOM.XMINY.2 syd=SYD t=T tan=TAN tanh=TANH tdist=T.VERD terminate=KANAAL.SLUITEN text=TEKST textref=TEKST.VERWIJZING time=TIJD timevalue=TIJDWAARDE tinv=T.INV today=VANDAAG transpose=TRANSPONEREN trend=TREND trim=SPATIES.WISSEN trimmean=GETRIMD.GEM trunc=GEHEEL ttest=T.TOETS type=TYPE unregister=REGISTRATIE.OPHEFFEN upper=HOOFDLETTERS usdollar=USDOLLAR value=WAARDE var=VAR vara=VARA varp=VARP varpa=VARPA vdb=VDB vlookup=VERT.ZOEKEN volatile=ALTIJD.HERBEREKENEN weekday=WEEKDAG weibull=WEIBULL windows=VENSTERS year=JAAR ztest=Z.TOETS false=ONWAAR true=WAAR jexcelapi/resources/functions_es.properties0000750000175000017500000001336511016653676021566 0ustar drazzibdrazzib# The function names in Spanish abs=ABS absref=REFABS acos=ACOS acosh=ACOSH address=DIRECCION and=Y areas=AREAS argument=ARGUMENTO asc=ASC asin=ASENO asinh=ASENOH atan=ATAN atan2=ATAN2 atanh=ATANH avedev=DESVPROM average=PROMEDIO betadist=DISTR.BETA betainv=DISTR.BETA.INV binomdist=DISTR.BINOM call=LLAMAR caller=LLAMADOR ceiling=MULTIPLO.SUPERIOR cell=CELDA char=CARACTER chidist=DISTR.CHI chiinv=PRUEBA.CHI.INV chitest=PRUEBA.CHI choose=ELEGIR clean=LIMPIAR code=CODIGO column=COLUMNA columns=COLUMNAS combin=COMBINAT concatenate=CONCATENAR confidence=INTERVALO.CONFIANZA correl=COEF.DE.CORREL cos=COS cosh=COSH count=CONTAR counta=CONTARA countblank=CONTAR.BLANCO countif=CONTAR.SI covar=COVAR create=OBJECT CREAR.OBJETO critbinom=BINOM.CRIT date=FECHA datedif=SIFECHA datestring=CADENA.FECHA datevalue=FECHANUMERO daverage=BDPROMEDIO day=DIA days360=DIAS360 db=DB dbcs=DBCS dcount=BDCONTAR dcounta=BDCONTARA ddb=DDB degrees=GRADOS deref=VALREF devsq=DESVIA2 dget=BDEXTRAER directory=DIRECTORIO dmax=BDMAX dmin=BDMIN documents=DOCUMENTOS dollar=MONEDA dproduct=BDPRODUCTO dstdev=BDDESVEST dstdevp=BDDESVESTP dsum=BDSUMA dvar=BDVAR dvarp=BDVARP echo=ECHO error=ERROR evaluate=EVALUAR even=REDONDEA.PAR exact=IGUAL exec=EJEC execute=EJECUTA exp=EXP expondist=DISTR.EXP fact=FACT fclose=CERRARA fdist=DISTR.F files=ARCHIVOS find=ENCONTRAR findb=ENCONTRARB finv=DISTR.F.INV fisher=FISHER fisherinv=PRUEBA.FISHER.INV fixed=DECIMAL floor=MULTIPLO.INFERIOR fopen=ABRIRA forecast=PRONOSTICO formula=CONVERT FORMULA.CONVERTIR fpos=POSICIONA fread=LEERA freadln=LEERALN frequency=FRECUENCIA fsize=TAMAOA ftest=PRUEBA.F fv=VF fwrite=ESCRIBIRA fwriteln=ESCRIBIRALN gammadist=DISTR.GAMMA gammainv=DISTR.GAMMA.INV gammaln=GAMMA.LN geomean=MEDIA.GEOM get=BAR INDICAR.BARRA get=CELL INDICAR.CELDA get=CHART.ITEM INDICAR.ELEMENTO.GRAFICO get=DEF INDICAR.DEF get=DOCUMENT INDICAR.DOCUMENTO get=FORMULA INDICAR.FORMULA get=LINK.INFO INDICAR.INFO.VINCULO get=MOVIE GET.MOVIE get=NAME INDICAR.NOMBRE get=NOTE INDICAR.NOTAS get=OBJECT INDICAR.OBJETO get=PIVOT.FIELD INDICAR.CAMPO.TABLA.DI get=PIVOT.ITEM INDICAR.ELEMENTO.TABLA.DI get=PIVOT.TABLE INDICAR.TABLA.DINAMICA get=TOOL INDICAR.HERRAMIENTA get=TOOLBAR INDICAR.BARRA.HERRAMIENTAS get=WINDOW INDICAR.VENTANA get=WORKBOOK INDICAR.LIBRO get=WORKSPACE INDICAR.AREA.DE.TRABAJO goto=IR.A group=AGRUPAR growth=CRECIMIENTO halt=DETENER harmean=MEDIA.ARMO help=AYUDA hlookup=BUSCARH hour=HORA hypgeomdist=DISTR.HIPERGEOM if=SI index=INDICE indirect=INDIRECTO info=INFO initiate=INICIAR input=INTRODUCIR int=ENTERO intercept=INTERSECCION ipmt=PAGOINT irr=TIR isblank=ESBLANCO iserr=ESERR iserror=ESERROR islogical=ESLOGICO isna=ESNOD isnontext=ESNOTEXTO isnumber=ESNUMERO ispmt=INT.PAGO.DIR isref=ESREF istext=ESTEXTO kurt=CURTOSIS large=K.ESIMO.MAYOR left=IZQUIERDA leftb=IZQUIERDAB len=LARGO lenb=LARGOB linest=ESTIMACION.LINEAL links=VINCULOS ln=LN log=LOG log10=LOG10 logest=ESTIMACION.LOGARITMICA loginv=DISTR.LOG.INV lognormdist=DISTR.LOG.NORM lookup=BUSCAR lower=MINUSC match=COINCIDIR max=MAX mdeterm=MDETERM median=MEDIANA mid=EXTRAE midb=EXTRAE min=MIN minute=MINUTO minverse=MINVERSA mirr=TIRM mmult=MMULT mod=RESIDUO mode=MODA month=MES movie=COMMAND MOVIE.COMMAND n=N na=NOD names=NOMBRES negbinomdist=NEGBINOMDIST normdist=DISTR.NORM norminv=DISTR.NORM.INV normsdist=DISTR.NORM.ESTAND normsinv=DISTR.NORM.ESTAND.INV not=NO note=NOTA now=AHORA nper=NPER npv=VNA numberstring=CADENA.NUMERO odd=REDONDEA.IMPAR offset=DESREF open=DIALOG ABRIR.ARCHIVO options=LISTS.GET OPCIONES.INDICAR.LISTAS or=O pause=PAUSA pearson=PEARSON percentile=PERCENTIL percentrank=RANGO.PERCENTIL permut=PERMUTACIONES pi=PI pivot=ADD.DATA TABLA.DI.ADICIONAR.DATOS pmt=PAGO poisson=POISSON poke=TRANSFERIR power=POTENCIA ppmt=PAGOPRIN press=TOOL PRESIONAR.HERRAMIENTA prob=PROBABILIDAD product=PRODUCTO proper=NOMPROPIO pv=VA quartile=CUARTIL radians=RADIANES rand=ALEATORIO rank=JERARQUIA rate=TASA reftext=REFTEXTO register=REGISTRAR register=ID ID.REGISTRO relref=REFREL rename=COMMAND CAMBIAR.NOMBRE.COMANDO replace=REEMPLAZAR replaceb=REEMPLAZARB rept=REPETIR request=SOLICITAR reset=TOOLBAR RESTABLECER.BARRA restart=REINICIAR result=RESULTADO resume=REANUDAR right=DERECHA rightb=DERECHAB roman=NUMERO.ROMANO round=REDONDEAR rounddown=REDONDEAR.MENOS roundup=REDONDEAR.MAS row=FILA rows=FILAS rsq=COEFICIENTE.R2 save=DIALOG GUARDAR.ARCHIVO save=TOOLBAR GUARDAR.BARRA.HERRAMIENTAS scenario=GET ESCENARIO.INDICAR search=HALLAR searchb=HALLARB second=SEGUNDO selection=SELECCION series=SERIES set=NAME ESTABLECER.NOMBRE set=VALUE ESTABLECER.VALOR show=BAR MOSTRAR.BARRA sign=SIGNO sin=SENO sinh=SENOH skew=COEFICIENTE.ASIMETRIA sln=SLN slope=PENDIENTE small=K.ESIMO.MENOR sqrt=RAIZ standardize=NORMALIZACION stdev=DESVEST stdeva=DESVESTA stdevp=DESVESTP stdevpa=DESVESTPA step=PASO.A.PASO steyx=ERROR.TIPICO.XY substitute=SUSTITUIR subtotal=SUBTOTALES sum=SUMA sumif=SUMAR.SI sumproduct=SUMAPRODUCTO sumsq=SUMA.CUADRADOS sumx2my2=SUMAX2MENOSY2 sumx2py2=SUMAX2MASY2 sumxmy2=SUMAXMENOSY2 syd=SYD t=T tan=TAN tanh=TANH tdist=DISTR.T terminate=TERMINAR text=TEXTO textref=TEXTOREF time=NSHORA timevalue=HORANUMERO tinv=DISTR.T.INV today=HOY transpose=TRANSPONER trend=TENDENCIA trim=ESPACIOS trimmean=MEDIA.ACOTADA trunc=TRUNCAR ttest=PRUEBA.T type=TIPO unregister=DESREGISTRAR upper=MAYUSC usdollar=USDOLLAR value=VALOR var=VAR vara=VARA varp=VARP varpa=VARPA vdb=DVS vlookup=BUSCARV volatile=VOLATIL weekday=DIASEM weibull=DIST.WEIBULL window=TITLE VENTANA.TITULO windows=VENTANAS year=AO ztest=PRUEBA.Z false=FALSO true=VERDADERO jexcelapi/resources/log4j.xml0000750000175000017500000000146611016653676016511 0ustar drazzibdrazzib jexcelapi/resources/Thumbs.db0000750000175000017500000001600011016653676016507 0ustar drazzibdrazzibࡱ>   Root EntryЅ 1dCatalogp XJFIF``C     C   ``" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?Ϗ-=06t}Bʵ2V|NL|KpC@L?L`Ҿ!47?x:}W^Ѿ<\O,l&Eqy2P[?1] ߏROk]X燗UCbXk Wq4=Dʥ71bswM?73G%i%k]9F+q?ƾ1/ޥnç=RƩ)4Ny1;"ua݂p}+C8%Ǐ3&d]R9aR*[/[{}O6hdvItEAp#7-nᴷ]Rd@0DP*wŸ {y4V1j+9 ^}JOs;Kkry$_ke]̕^Tt<+zAb+ bOn _2+fJhSQuWo^<\!Sz]鮖soϪxv:εp`#earK*3m Y{/_]F떷It#@q'm:׿~9xQI0 4;W2nNު Q߯dS9;ovϣ4K}quAb]~%$I'9qOzE4 z5JU*8lQ=:M/FrB?,m,mކ3D9~Y׺n+eOS`0;Ś%;A@v~`mv̍ݜdgk曏e7?]i-Ӊ{bcQ1Q>VOi3jҜU#4_͵Z-q@yެ |* wO&kMψy!kKQn|0\sLפi?%x'N0c}+rvn݇i\~Ws\WǢFO$?2?}R'G7g.|wyk}q6cMH

i4{kIS g>`?',[hkjzSo]+3bE;J8USPԢ'BQL(qJ ٿsŨQNMB(^V29-qҺ-'eh5/ 3I$Imfc3XO4I?7rRo^+<9Mykrtۛ27 X6N޿J>2j{1s5ͅd9mͤNOs_/k_HUSFx6}cm KK5d,`20S w8y72 rUaU:msɫ{f}0+Zt^0HjǙ_?)8ޜ?¿$Y}}<|7ޏ2ygBϚhMV=W x9N7d8w3` '5jڭυS{!E/h7) oYrdPF1؃_q2'%k^.05/^<4+VVm񵴏=>^$8^'vx%&1M<)?峓d⾃9o~IRQ*_į%MkvY5ku8_*¯;~8xL>!xھ-k3Sr:)G#"EX}xx#8$}FrkAk~2M6^k{gP+ݜ/NO5)E(:q]ϱ<ʭޗ~{w>QU}֍\|2[4EqK6-7;??|ʬmJe1#.ڍ~#vwc˫ZjGs&AEI"وarwgO??]yPNsiIM4<=j>/2mƍo go gxFև̛yq<[B}?<[B}>z.?kC~G_MѼ?ٞ->ٞ->S=O?kC~G_MѼ?ٞ->ٞ->S=O??#/&ikg. gW~1/o9]:Yn[~$*s2 0X׌ ۄII6j׭AQj~?3```&{A42CD7B6-E9B9-4D02-B7A6-288B71AD28BA}jexcelapi/resources/functions_de.properties0000750000175000017500000001203211016653676021535 0ustar drazzibdrazzib# The function names in German abs=ABS absref=ABSPOS acos=ARCCOS acosh=ARCCOSHYP address=ADRESSE and=UND app=TITLE ANW.TITEL areas=BEREICHE argument=ARGUMENT asc=ASC asin=ARCSIN asinh=ARCSINHYP atan=ARCTAN atan2=ARCTAN2 atanh=ARCTANHYP avedev=MITTELABW average=MITTELWERT betadist=BETAVERT betainv=BETAINV binomdist=BINOMVERT call=AUFRUFEN caller=URSPRUNG ceiling=OBERGRENZE cell=ZELLE char=ZEICHEN chidist=CHIVERT chiinv=CHIINV chitest=CHITEST choose=WAHL clean=SUBERN code=CODE column=SPALTE columns=SPALTEN combin=KOMBINATIONEN concatenate=VERKETTEN confidence=KONFIDENZ correl=KORREL cos=COS cosh=COSHYP count=ANZAHL counta=ANZAHL2 countblank=ANZAHLLEEREZELLEN countif=ZHLENWENN covar=KOVAR create=OBJECT OBJEKT.ERSTELLEN critbinom=KRITBINOM date=DATUM datedif=DATEDIF datestring=DATESTRING datevalue=DATWERT daverage=DBMITTELWERT day=TAG days360=TAGE360 db=GDA2 dbcs=DBCS dcount=DBANZAHL dcounta=DBANZAHL2 ddb=GDA degrees=GRAD deref=POSWERT devsq=SUMQUADABW dget=DBAUSZUG dialog=BOX DIALOGFELD directory=VERZEICHNIS dmax=DBMAX dmin=DBMIN documents=DOKUMENTE dollar=DM dproduct=DBPRODUKT dstdev=DBSTDABW dstdevp=DBSTDABWN dsum=DBSUMME dvar=DBVARIANZ dvarp=DBVARIANZEN echo=ECHO error=FEHLER evaluate=AUSWERTEN even=GERADE exact=IDENTISCH exec=AUSF execute=AUSFHREN exp=EXP expondist=EXPONVERT fact=FAKULTT fclose=DSCHLIESSEN fdist=FVERT files=DATEIEN find=FINDEN findb=FINDENB finv=FINV fisher=FISHER fisherinv=FISHERINV fixed=FEST floor=UNTERGRENZE fopen=DFFNEN forecast=SCHTZER formula=CONVERT FORMEL.UMWANDELN fpos=DPOS fread=DLESEN freadln=DLESEN.ZEILE frequency=HUFIGKEIT fsize=DGRSSE ftest=FTEST fv=ZW fwrite=DSCHREIBEN fwriteln=DSCHREIBEN.ZEILE gammadist=GAMMAVERT gammainv=GAMMAINV gammaln=GAMMALN geomean=GEOMITTEL goto=GEHEZU group=GRUPPIEREN growth=VARIATION halt=STOP harmean=HARMITTEL help=HILFE hlookup=WVERWEIS hour=STUNDE hypgeomdist=HYPGEOMVERT if=WENN index=INDEX indirect=INDIREKT info=INFO initiate=KANAL.FFNEN input=EINGABE int=GANZZAHL intercept=ACHSENABSCHNITT ipmt=ZINSZ irr=IKV isblank=ISTLEER iserr=ISTFEHL iserror=ISTFEHLER islogical=ISTLOG isna=ISTNV isnontext=ISTKTEXT isnumber=ISTZAHL ispmt=ISPMT isref=ISTBEZUG istext=ISTTEXT kurt=KURT large=KGRSSTE left=LINKS leftb=LINKSB len=LNGE lenb=LENB linest=RGP links=VERKNPFTE.DATEIEN ln=LN log=LOG log10=LOG10 logest=RKP loginv=LOGINV lognormdist=LOGNORMVERT lookup=VERWEIS lower=KLEIN match=VERGLEICH max=MAX mdeterm=MDET median=MEDIAN mid=TEIL midb=TEILB min=MIN minute=MINUTE minverse=MINV mirr=QIKV mmult=MMULT mod=REST mode=MODALWERT month=MONAT movie=COMMAND SEQUENZ.BEFEHL n=N na=NV names=NAMEN negbinomdist=NEGBINOMVERT normdist=NORMVERT norminv=NORMINV normsdist=STANDNORMVERT normsinv=STANDNORMINV not=NICHT note=NOTIZ now=JETZT nper=ZZR npv=NBW numberstring=NUMBERSTRING odd=UNGERADE offset=BEREICH.VERSCHIEBEN open=DIALOG DATEI.FFNEN options=LISTS.GET OPTIONEN.LISTEN.ZUORDNEN or=ODER pause=PAUSE pearson=PEARSON percentile=QUANTIL percentrank=QUANTILSRANG permut=VARIATIONEN pi=PI pivot=ADD.DATA PIVOT.DATEN.HINZUFGEN pmt=RMZ poisson=POISSON poke=SENDEN power=POTENZ ppmt=KAPZ press=TOOL SYMBOL.DRCKEN prob=WAHRSCHBEREICH product=PRODUKT proper=GROSS2 pv=BW quartile=QUARTILE radians=RADIANT rand=ZUFALLSZAHL rank=RANG rate=ZINS reftext=POSTEXT register=REGISTER register=ID REGISTER.KENNUMMER relref=RELPOS replace=ERSETZEN replaceb=ERSETZENB rept=WIEDERHOLEN request=ABFRAGEN reset=TOOLBAR SYMBOLLEISTE.ZURCKSETZEN restart=NEUSTART result=ERGEBNIS resume=WEITER.AUSFHREN right=RECHTS rightb=RECHTSB roman=RMISCH round=RUNDEN rounddown=ABRUNDEN roundup=AUFRUNDEN row=ZEILE rows=ZEILEN rsq=BESTIMMTHEITSMASS save=DIALOG DATEI.SPEICHERN.UNTER save=TOOLBAR SYMBOLLEISTE.SPEICHERN scenario=GET SZENARIO.INFO search=SUCHEN searchb=SUCHENB second=SEKUNDE selection=AUSWAHL series=DATENREIHE set=NAME NAMEN.ZUWEISEN set=VALUE WERT.FESTLEGEN show=BAR MENLEISTE.ZEIGEN sign=VORZEICHEN sin=SIN sinh=SINHYP skew=SCHIEFE sln=LIA slope=STEIGUNG small=KKLEINSTE spelling=CHECK RECHTSCHREIBUNG.BERPRFEN sqrt=WURZEL standardize=STANDARDISIERUNG stdev=STABW stdeva=STABWA stdevp=STABWN stdevpa=STABWNA step=EINZELSCHRITT steyx=STFEHLERYX substitute=WECHSELN subtotal=TEILERGEBNIS sum=SUMME sumif=SUMMEWENN sumproduct=SUMMENPRODUKT sumsq=QUADRATESUMME sumx2my2=SUMMEX2MY2 sumx2py2=SUMMEX2PY2 sumxmy2=SUMMEXMY2 syd=DIA t=T tan=TAN tanh=TANHYP tdist=TVERT terminate=KANAL.SCHLIESSEN text=TEXT text=BOX TEXTFELD textref=TEXTPOS time=ZEIT timevalue=ZEITWERT tinv=TINV today=HEUTE transpose=MTRANS trend=TREND trim=GLTTEN trimmean=GESTUTZTMITTEL trunc=KRZEN ttest=TTEST type=TYP unregister=KREGISTER upper=GROSS usdollar=USDOLLAR value=WERT var=VARIANZ vara=VARIANZA varp=VARIANZEN varpa=VARIANZENA vdb=VDB vlookup=SVERWEIS volatile=IMMER.BERECHNEN weekday=WOCHENTAG weibull=WEIBULL windows=FENSTER year=JAHR ztest=GTEST false=FALSCH true=WAHR jexcelapi/resources/functions_da.properties0000750000175000017500000000146311016653676021537 0ustar drazzibdrazzib# The default names in Danish abs=ABS acos=ARCCOS acosh=ARCCOSH address=ADRESSE and=OG areas=OMRDER asin=ARCSIN asinh=ARCSINH atan=ARCTAN atan2=ARCTAN2 atanh=ARCTANH average=MIDDEL averagea=AVERAGEA betadist=BETAFORDELING betainv=BETAINV binomdist=BINOMIALFORDELING ceiling=AFRUND.LOFT cell=CELLE char=TEGN chidist=CHIFORDELING chiinv=CHIINV chitest=CHITEST choose=VLG clean=RENS code=KODE column=KOLONNE columns=KOLONNER concatenate=SAMMENKDNING confidence=KONFIDENSINTERVAL cos=COS cosh=COSH count=TL countblank=ANTAL.BLANKE countif=TL.HVIS covar=KOVARIANS critbinom=KRITBINOM date=DATO datevalue=DATOVRDI day=DAG days360=DAGE360 db=DB degrees=GRADER dmax=DMAKS dmin=DMIN documents=DOCUMENTS false=FALSK if=HVIS not=IKKE or=ELLER sum=SUM true=SAND year=R jexcelapi/resources/littlemoretonhall.png0000750000175000017500000031420711016653676021220 0ustar drazzibdrazzibPNG  IHDR|sRGBgAMA a cHRMz&u0`:pQ< pHYs+yIDATx^|W>m`afĉ)fffAfX,YdfffpRvxvwfwgwwTI;;W_Ɏss}'0|[n}?Wҷ߼Mz.b𽟳ލ?~opcg&0ƛnZ5zͿܹs7-[p?{㿭`|Co=>I>go~ _i'_~| /?c7Ưg◆7a7o?w'10|;*q"\qϬO~G?WM1oC ?) Cc@OLN+̢Qe|psp+`=' ~q6Z1o-+*+IbL|1&gCT0?#qd&زjTZ5WqÊʦmâB7#T r팦nY0i5/V4,t3G:V&ga̔0DC4C4BF?W7wcm4!YJ$GFobv/C px +buh:tuq2 J`Vl/aw>n2Z2% o֑]ԖUJ)hhͰ&Xzn#r9ŭE'>ߚDJilz?^{ oF aݗu4UЄt `#g3%c,0iՌH;YްeU] QOB^Q"ю*US2ݴH=WNF2̥ t }c9|' 3 ߎ1Cq1p/Kʀ~p#)Fؒoq|L̐nܡq:Y>l/1\!:_Q˺  |ZayTC~ ܬf€`\)Me 0 5<ۿ{I#.Rr^N@w쑷P^&7(_z1\_qݣ7t8 b\*,LqxJţc Wu8LV/kĺ)e݂qEU3/N 1xqjS ʇcW_ #;Ko7(z( Ż aR}0@ ]8hxcaj FaA 7pie)r$Na%"D`eWSj)y$c Po@)/fz#@o:x n ހu=q_.j*l*.n4JJm-7Z),coًo/_wXɝ+ 1=Atf'R#0 J%"qLFifdsʺExwfBR9 z@i0l-ʉ /'IF7xwL4oK7š`d#ߚ_;5a7aLAK˕ UÀlx_LƘ-Ā/헩T)i@6$#bb (=||Qi' ܿ wz#יmF OO/@/l\޲H);uo;'P^\66;'@ ; ׀uw>IsU3@EpEՄf L:D~X=(*ܱVP={Qi7@HA:~L =) xIق|D.w8Pę+rb~_AرD4GIp*{\(^J?䏲yce܉qg#*O1zfBOQ4U1]A'S:ɒMUId.5"TcxX1 /7OoVpÜnÖ TpbET '[W-E鍱#%܄#7PsL D[OL"1 z@ʇaČ5~JƔ24'G .LՏNuu.O- 5M66O4εv4/U7׶tO7O7M54T5L`V*GkkS"B ;"]3VSj+f7yͥvf L jͧ1z1 37NH=̇vH~eM"=[2+M疍啎'$w, "7d` Y>a<]<%9|,U'$@'Jp%4 ҢcPH.o@ " [p7$N F5NGX_0WF\F9XT Rs\$>\ JB(s}yì6s5zr# X7@F'%B#@17W?^}UZ`VIo>k4YO Qʟ\! fR"'aQ"OXu3$L||P<[(˗٢I` 8b\G:#_7sw'ԁf _%9q/ ,xY2\;O6ÑNeQ4o<410ppDa md5Iޝwpg-T)}"@Lk\]^'Gbgiȣ掙u-:iC%<(}O+k_zz&F{sSR+@(IZI$+j-pa4B4w: )o-ط| EzJ  )uj ӘT7Q^7U*A}<ϑM! SB {{ oy\jMs#* i p-Cb0|faV+^eo"NcZ45cap(3P^~l@VW c:`Izj|s0A"F p;,!P@ pǐ @0R'3/FL?^z>br.eu1%=|A7ɟcof4>]P `ЅL˕%PkFAs9 Vtj\)al[>3[X3+S̔!rڀp'|[f1ēaŠi% .LI+&qCT7N{t- =x60wd{xoYc۲D1 [9Ă&Oc(O65 nX?F4LqIe |2>SF ] (ǘxM^1 TGu ulb=@28g@@<#*1 o.s#i)> =i+ ijFtucrAdowG ĚD,sZ8j#~v;^B:I} Kk-?lvܓ.}/{=7endA K*>۳ Jxx>*8J#WtFi~8$;(3Y\V"HrZQ"Qu XB(\u﮷ zH950?Qo9:zCJ20( FgŲTݚDvz+_}ϟxW/}z(ŕ3hu%P߀xF܃kg`D؇ʪI$!fmTj}>B_"1ޅ~ ,#|Հr}gbmf~mv,t,4Oc T%T|{t}jƕȠzӏ/k'+G+}b+DJ LA ڿOA|0G '@1nb; 60ʓkaK_kO?W?_yʖuI~!7~ H.wu K5Q+ͤR",~v(C]F+"PT]O ^K_wĪvٷn$ s# #@ E~N0 7t>lnǫ+O={~O>ڳˏ>_< 8ꑪ-H߾dF/ Ixnu@_U脏7ݠ|Kc]T 9t +kf^ffVW-XZ}^o*F:"멿B_hpQ=Ñ/AGR[7=T9ﮟEX"gC'RP67 S kO<{O?'?u'kO^ꯏxS 4w5%ܡ^x)YYxW #S=|lLS3="" ^VSyiq!^q4JTfWRLPj|X%fr8\rLU^5K{Ū9S#T1c)J=3ѫAD $ 5c^u_SZ+9b3A? lݟ?b &L„(N1^⦼fayA2W۹19l~O^[P7jRA [/3L%,ЦM#Y#$+n°L3}Q 23Ys1f(_wo[Xy5j~/w/Q 8C4ėY9nU\=w5r-KhVYLF^ZJoJwzw|D%9&?38'CggItjq*$SiuU uB.tK<|Z`K ZO[1^V\ҘӜ GpNR@vJVLq/4u]㎢vVY7j4TϷv>2; |g/`_zϿƧ.T5Nk+[p^4ΣX= ă9c7o"; cKRL΍  W1(FĿI,Js ij;: ->kuvsH# ׍+G\/2p'`1ax`#Ai o0`]ψĽD`!1~}CcO^F c,|6fb3_NKOCT2ǒ.jk_169I7k$ҎmćD$YYBIIJą&GEFF秥f2qԘ -[!a E NUT+SIY"[1K.U/8Ϩ% zAY%jMZ9,W uzNef@ױpa;qp)uesocxurG/מxg㗶byҋ5x٪,)WJ5@%& 2a9z~/ +;l@fOu̟x17!Dc&N¤ N5/B(~щ1q]-ۮ_1#BbabDXF\KaIilF^n\HpwO@QrJqZrrT`q6YdTkjDVZ]X@K9z^K^W. "uX+gEUs"n@G U ǀN+_0S:_6S5:SK^>d٧g“y'O!t -S0E$KfRoØF&mN-3D >glrK[8xmLsJKZ{`m} 32-!kUepbp qįAF@$PN!;?z pw}L={9wl] #!IܐrMPpȇluwvqsE%JBQ+LK+̄$&&gFQ#bsE9fV]Ф5ר55 3(SUϊ*4 TŴ@Xz"*Ղ}9]R5 V%n&~}0mZj[no]}22|z'sa S:8286:|xEr}Lm ^^7Ě1p-|B` TD@@0Xoy3&^&7.oJߐ(E4r0qB0Àk04Ljơkֽ;n^ O[>CF 8cihok_7 Fw(h~}J}~gc3'v No[nYn}]Q7<ֵNڇ>^$G:ݤ64 S qQ/?o'j~$.$E@adgOH !FRS#S³)q9qI1^% )1DAiV59?#0;TNi*$u m}Ӛ%ejU]X_ @6Op֗/̻s8nB*qC"dEsh{mV<[ӱqsףy$.yyxxz}0'eՈhߢ 10b@ygV?Y\|ꈉ3pfH(6/ZǤ sҪ/&VHٶt{wsXThsPVrBnzDBw~9MAr47/S+$EYѩ~Y䠼FVB9όpMqe$aI$ć8aAO-J LWkլ΁euŲ兴᩸vU\,]׮@Q7WqXQ7C<֮KyDm뼮m(1Zm}+ulEL2O p Ω0 눃 U ܿDOf7'KCT QI’Y< R^kW p5#Ya,b!eIJA\ Z1ZnHXͩdGZ@how'3EWûXgznȤ"d0C #5w!:  ˟Ẵ)пɣVW?]\b%׍}= 5*|薖@yH7b(℄ؘdKKG 3@ <\5( ՉLP(ĠlqI*';.7%HIM MOes (L9JKԈTJ|AJ,#ΓA̋L*gdF˹:UXPc*jUeaȋ9yf_RqMYn3U UupzM47Npp c pOp wv#٨|/!aDH_0Z|iI݈Zླྀ@E(̈́W#<-b5@P!'z"pzNu; ސTڨYp'op;QM] W5O?\ի /@ӧ_Pli>E5˯f!P[h}ܺb 2ZY{z9GĆfzŅCSg9r~VH'-9 9q9ҲܔlrTFT(3;](0p33:,;663<2-$"=4F!GSbcnr<bnr/#BS3tdRQUuiZݼ i|.k|.oxHWQ\Qԗ6jjC@m06N u1ϥu t z:4UlRKBDw}Υ<]RcRb)̔b:]Va0>,' ga~H(\#bgf NJ qcd izNfGeOŊ2fB )1a !YQ I䄢`^i +.ټ ZW\?0;2?W-ۗM/Uϕ OkePS3X8;a'ԜS7qRϧ=|"0} z7/uB':e90 U.RAׯ:vյ.AV'(X9qղvI۲ؽ~\d JY Ƒx@HW9} w}6ϋ K},]e-_\#I+;GW{Z5<rIr<2bb^|iTƭ ? LКOރv A7U.׺F;r%;@+G?LڿtN'+h׌P (''/#)+%>75>'%FA4Ϡ9)Z)$ "%R /CpY0HJl@|So`X@HZBJAVNAvf)-YE üsxLfWLM ώ*͌(Nũje}sS]goMpUD]۳֧'kM+GH7#ˆ0@ ->'<l^=#~@8-DD|\wڞe,.k KUuM-MVT屘ZIPR(-L*SOqCf]7}r[AٿEf$|be:J8z#ItöεڶemЌqr*67ހ/|O,O<“6 &DG;mz67tn`eq_vGQikCÓ=\hbJkZI;7Pt:̒H?kcv7ߕ^Vw5+;5R~i2J%19!yI5YBOӒꤔ:LCUM匲hAQ~IԬT!3HɈ gRbh0R7gĠTE#7)8'9uz˖ y55- m5[ Z0%z.(1P!UAs# b]aނ> Pn?m`#b !>gvNAh`}/ذOPQW__\ Z]שBNA)fDR2vNZkp'FO~7Fnx}SEvR$m1CmJe˒>qعbT#Y82}*ʋŵχ',f*\=ƒ>e;7o\nWOgtC?m1[|+%Ɠ)rKݵGT&Pm'}.n\rЛy Nd}# Σ**,~qVqj<-5(QH/kV5+LJ8;;Z[,lȢeyۦgF'KXL#E2iB1es뱶IU>~./f 1F؋C`-np{(*'QF :p2C8'8,pc{Fvk5T\R܂XVNXUi%qU\QFN 9f7-o[4D kHE}W^f[ۣw[p([w0Ǖmk(VOtW5/6/7vЏL#[ DOG^M#:*;)*]Zġ nT9u:AcPTccF4+m\#i~h֎@ǩs!\Ijkjs'卣Aq NݴvF^xa"NU P^haiʹz&jXZT/TUsFZ#P2=I*d6TpՒB~i:ŌU.8#4?ޠ0y89̷ 3{yˆeD`5J߳ ox݊ȷbٷ bٷw UY9hYCHLiCs嚮GU폴KHt,ٹK=k'T/|:&tf7_}erBr_7tѽ;齧Nݳ'GkTB+qT>p(i1vVFgOp{>&=ٽtG&f$3 2[%bVQ *JUB^I*L-dB X df6vY+ȕ$Ȋɕrv8CN-JVü8R t767uta$wtB eUry˒ '%}ҚAYMWꠥ ]V7H'dz AS_`)k&/>vN*jVԵka7m]xu]NRԔK2.U*cc"sSC)Xjd@f\9ĭ$3J%,T֠Urϸtr,LpD =:@~kep7h8X- {ЏIZ`^Dw/c^ݡwMۼy)ʦyծޑ5W+!pqLH|o)?senA?[[ht~셫7o\qݳ&>_p8W!Y_Ӗ+Zaej-QS2|},?sG,_]Ҿ<^nqᾔ(H85j!Kˈ/LFAbWn\0CNŠJAS USsuA֤RWT@uiCl[ԵY ^ZLƤQ٩djZD>9 ==1=>̕矝.$P⃓#< B6!­kg&ѱ?e %W(5f%;Xýs`Xw^=Du- vmp;x}&57(@?.u]b~a!nG}sw(e?KKッS1o_uѭ+ΝѶ$٥61fHΊrRPUJ\&r9WThxZBc9_/;~i6ps}kmwr}(1ҰLJA!"Jf%q Jң9Z:Wr4"FEx1J^H͌%3SibON J'{ŹƺRS3"R9 ʲPAʯknmǯ BXmsMu횪=h!{AQ4L*} ܕ(-ɪՋկ KݟiתZ櫛F:i!xBa"xGMtsBgjL ゐֻܤP _(|F>jbC|C\>ޡ2>V,VW7 pw#[_T:3]0xbG1 @_Ѳi]#hmO/ݿgD~>}yzl(_9ޮO|գpGܿ{v$g>AA19]#C] mZMJjR%)WK**LW!Qʸ"QBIM  p16qݻlJz>x;ܾr(/#\˫ѪY2^v^ˑ"S`$ozhz0⤨8I:]jd!U4sKs SCӢC]SB !0sBDdThTf66 %[,H *o;(:ܧ8jM2IKqe m M#GbVs% ΙQNnl)%:/9$F rKQ[ uKpYB6L NN[\킳p?_ϼ6o(7NF=uy 3ID8u%aYӼz9AZ*PSլڃWԴVXz+Xs؛/lJ `G_6DŸ?mg{=};vw`'o/$/7˗.8:%%%ёޡB*-S* G!cWdUbU 6:Nudֽ;ٷm。=;]8pafZ]A.gjeR)_GΎCO4** -#)5-k#C9i"v>eRc҂zN #9ZȞ,H biUrzukKm{G}P} jHOd k.zï릟sU_'KZZW>ҶVw"4[ӌ6Tό(ph/zb+!?][l(J)7,%;304\RáQ@١Ez8ZLwX/yM$)ɉ Z)a7B. AFl3~zk3_*= &A_P0 gFIVC*4t?SG-ܗʑ o^郭&^۩}c`L`M>sΞ<{'m|cWܲ|:[lz][q\bS=w7n\{u-/Qh@Ggs[kC}]eZ^*dhb-0hTVEЉ>W/:n޹[>i{][IWdm~!69?38'ZR e'3/-ڗG处d&zĺƻ.2~W4_R~xjxO?9w qI : qBG$TQ(:ׯި^N(3&o{ r=V#hd3h_dHa|V5THTc]wyNDeږG ?MWX;E:;mAC ~>G߹eMn_6v2r6vwu4giVo{xz:GED_x;I;v{مbqvv~jjf|tbh`^[U.V*z7j5*A (,n9mx7i;IgOn9w]'nńZQɭ6E椫}:)e_m)4Ղܘd#KɏH'rJ fB3^^Z]H ND"㢤z7'+DP+$ |fZtkƗo~筏;vԵ=E9[F-J  vH7O ) RIjF@Ic2b+9%+ڻ01 > 77>%'5 34#+=(;Y( 03C.,!"Vw7Kd ѮŕD&A_V&lhcp ߕ/t:J˗%f X Toܲ.(Jkè׹{ j < hד鐠tЏl߶CO:tp&t ܽiaef~ 8׫8z+Օ-]ANYccF֖v>}Ҟ=?H/eR'Mzj[65*+t5ꎆ*i{ r1#%6̑]>&<@ھ.Ҧv !;y}[Kq._*ߢb զ*+g6LjyYan`(#%;/TQ[V-NQ Sü"Bȑ4rX~FMh)aJVU0+5ujU5]8] "lN J JtɈr/JaƔd'eHXzKV+efǒ|CSO )̹0- *jnbvjWP*N NIDÂĔv_-N{": rfg1MMkR<eځ2)A &#VУ^Tҡ^Wt2z@y*/pP9ϗ$ZU-VMfpdh:?PY*nO ɸkj6#+oݸ4B6BRYefR>gMq\2ugB@eǣU1(#H"]sϟy`g߳w- '[7ܾ|ᣝk׏GFX;QhtVT\C@|n;[{9]rΎ.woٿo{ڍ]/^:皝VSZX]}+lt|Nש*k*E9.f6w>s}7޹im႕n݌!77:`eu&&>ijEIk5sS:.53%)%9 [Ҍ؜Xd/+VQ%ΔҒvĨ@Hi(Ɋ FtReb O[־Rg椄GzSrnجGgDBE:3+<4'.7! B@aA&c@nb$9}a5)+hʢf-RKSE96UWdGcCGYQboc@O>{޺xʙtlVk*O';Z_:}ՇN!9߶uwpN:vHltptlP~azUrnae43cC]m 5UVRWWH- hP'/ۇ7n;iס#IZ?Z 8V;ܹe-L]uEY+\̣&qKZ*#Je:.2ɍ/N .L fEe&x:E1S9,/HS&8gGy=jbCFW~BH^|hQr8t"$G%R455/)(+..1$86+.#'1N0kt*V872"&.gQ-g~lhmD-A965)ҷZcH$GIeK^"(-CXCF"{Q\gd:8?Dv.eѼ#3bJB/K{+*KUTwg[.+OH-fUۑV-CL[~pmH`טHRFf}tBy:[w Ї;Xgi롫Z\7']<|ajK',<.^zm # WkgHaa~#k9bLWXc]o{9iYwܾdlhr?64M{7]<,Z;z7o]۶op񌕵yp UWO=_mohnnnki5κκzB'VD*P/g$ 9wlFrkzۤ?ztzf{JJMB(5_\.+fIJVt4ISIвxijqh&E1R #Zz4xQa|?7]ƢT)#EHJCKi~_TdjhrAZ=#mtpZK#c~͵r?QrZ NJ? w0)/+!91/h_EdaO3UqF >Hť%܂&DĤF;ZD9FŅ;2kuca ^7u،D L0THks q Ktrqr0~u0̄4R1nmkhƶUO;[F|WKNO_&ʷutp5;Ϝr]s#{w;$R8#0-ʳ0g5/VLCrAb(#JTPV4L (3XdjJ$5%,'W*Koױu2~~-nk~wQe3i{Hhi{.w6CbׯVGg-w͏64U7*]mo&8egщ t:S9.WC/\bF2B¼Wg_S8'+k3{s GHGY^/—#ɧ ۟p 2 uLJN!Sr8"T +3.*#MS7̼흽<-YՖ:rh4'n:.~\߷г7/O6{7+~U;zK]1emgbꓐlw׶ıqw`$+ 7f*ˋ2 NNJ묯+tqHI]<-qz?' {wc#lӒB/X9p MM5tV}_'3W;zi}ۋ!!nv-}KR eNpG2<p'( 05 tmOFL~87|Y'\eu%44(604 @ LNCg@Tеggպ:KT[繘ـiܒd2: 4jT%tNqaR*'G%ݽv/:8N-t|`bcjlIGK[t9ks{%Ozp)G3{_{?_ĤȀؐ g+ Q1qyϲ{ERܭݬ(&r! *Zh0Q→&Oܼ 7..4Ec6!1^?䱃;n:{y1T1%LYwڧO^O~³U>- L§cb~vezM5X :Qm)5r>dou}6$k\OeZ6]aq"+ $p^RnQ*KQ[VVަc4踏,U"~Q|BٽCO 9x}V©&W| sSQvpY>)-!5T\ 7\ضTא##:jC}C|n/dqTjӳs$e%rUrv0c1,z.%+39W.;{u09wûϜhgZ\Ls|zMkťO>{/?WyP?Ц֚VmmI6aW)M u {|ǁ2cVmV41ٜ?7i+$fEi0U]Xp 382䡻{#Y;>zd;JuH bTiQȠT, bVW5նu4t%a!$'2]/s1 qNK VfGojyh_~-2[wȞdQsK Nwu r|pcK?;p7c}|옝5K~& QI7,oD8;X9ݶqek+:,=4-4?)<^?_3}`rwJDU=ؓ&S푮iu ½o4dvcG3272w5sUN5 1ILVi<GO(jP- poIZVYܿli*,ING1/?*jRq`#] ̼$%*#7Ҳ04lJs~Sslps53|p㶥=wΜO\|.pꖋCOOP_FiTƫUwVw ..M=zW^MOO tҠmU0h)WHʰ:ڝ+".~ҍm&;o  ܜ8OFO޲kBڽtG˸8znU(!I$3("-cr*:M}]M{Gsk|z9J­my+7]uᢳ@g4u ω A -d͌u~_)owN)*Vwi꟦*,,LC"]n:4(&l]&ǧxz]{ {yrHSrVHdg`SpKPO->!.>=M ǜ?CNN31t#8Yudzʶ'zoi@I _فT룺ާ+S*#||\}n4tڅgP8njvNSS|U]߹S#~ؙ|mlc ZSRa㑝:bjVSbX\!1H܂r:7"JQL FCC|\}T+K gnݿaealwpo|zΝܷG;.;r`:ȑ'O~|vԵkgDS/ϟ=dnvy|ldp]R[+ElFaF|swa3=tvݍkwl%FځfZ`MC èP tjq]yekJRPSV_[' )Y^;rbv;| ޏ7]mAkto7]}ɍ;@˗!F-?㌭]-FxR]L=hly;;~av1>d`.!1^AH!adf% =:%#̫@Gs7"2?[cT B\CE$ JC X$Op' p~ N}W»]~嫗Y9Z؆f #|,-L Tյ_p>_. 4q^U8 :0ZYWV|^ᡍ#.L v͌MB{17)(}B&V^tkHJAIJ(IHGE˸i1dLJ!ӳ龎с1RQTPݫC}#8?bjr i{{Vf7^yp֑/=vvl߽{HwԇX "|̎G?_~駯쥫뫫4|6#16)=/:h|V$/!'ljB@UUJ@]BW.Ȗ֞TST7ww46͠F8$ݱCG>x ˸y'`bvOK/>(prG% Ԅ0Z3O8rgX75y`kjI'z N8Á3 Inޡ^>~&.^;H4>)((?=bPhamp79{%{$9ٹݳu GnfYyCm4ifeci枵Y|?7-_}& 騖ie2L׽;^ձ #<1#W <{7"6q%ylwG_o@rT:$/p?PV^Aowwug\tپP#l{8ԴxN1<ҳ2gONNYI~'xy[F9'Tp~5<*55pjUjzS`'4A;N:{}s^ΦfF&FZ591!<2BƗq{=#Ȗ%|<15mSYqV@IY)*'{z>ƙ3gwRCx:-&22b(l;07wKGsp0>#s_/6%3,<'󗮞{ǶZ]qpwG.M+ -~!ў>Vpq~.֦Vw@<|\|!$Xy4Xjx; 򢛯-ɭ^Fsg@wp ©X^7pG 2sO[Gёq`ޔd B$8zg䇟ziSˀR\;@בUS.~?G_x2?sYh N)1i،iPWg}:`7&Q Bt$&a.*4k3?W቙P)(ZvQfBT\tF[((C>811A/rsudd#}bK2iξHxgP]-<ݢ=mL\P zGOٿɵ;tܵwܺu!<ܗ˥ԨF=Z}xm~nl2I.AI4_WаРRvՍ7tBW%-%1#W/9}mrMOqvR>P.2sft9r?T<}H" p!'KZn]\.fJDd0rќ060M˻wЮ?(:ëK陔LS`f>O4]GNlmtꢙ%gNq+.<]/6쳥yHL)$;-**'DV*ى^܌wA)UK UW%Vyxd'ƵT)"qDF,ONsم)|,=' #K+,ej$оñ3_P>05/-*Sfũ9>Q aid[_GsWk7O{7W&7/_vҙc' ٱk>.]9nm{?"!KOgSO@o`_gWN)d%:!Z&)iU2R/'EA^DIpr&҉v|'-"lmmOHh 6;;?s )#8L -ccrrjw[CA){\\bQ߆zLPVFc2J=MQZڸ}.,q*. 񵰺xSHg/.^ _c7:s Ww>CsM@xLٻܻt- $~a^@%fDzZ?Щm `8:J($%$QUUhihLAfrK$iI1Iٴ|J1klۂ/vZ :;]|?3fl(Ki6hߋٕ١pzRQQZBLZPRIs[d7?=y4Si29*Q#T$U QAEY-Xj$X߀h%B͍ gEeP2CC)ɲãgd'􇫱 3 3cqNT0JC AB  w 4k}S7X:*$bda%* ;xrG۷޿}nܬP9XT*wssqk;=<>غ3"&/57'N622ho q郇|bS[ Įm7AQ1JER̾f(`ny̡c\8ASgH>ã,l.=Ε[~鋛.|ܮ'>~OW8{F}|C`2sXq6-bs;fBc]}Cm_?mW;qtV3f6@|562EJJHXeTn Wj}ʩu bU ]uKExC^zR}3rxN%)ىPdM>@a{Af ݻru '}N.5311,$RO s>JdF78UB1=M ]M ˣ=OuBQyO͋OKEEݹF"gY䎺x:UMZtFNrw ʔ)>.NP9bSeDؘˈΊ:I%eE9.vbfme#x邠-J~.䰐?qOKc=ˇF6 ?'۳mf5iQ][zVY XAӡJd2J]^H-O)gZZkгڤgwj~ZC0 ę(p)dݧO\>s@Vhn~-" ƒ0º3丅y* eQb7WytC̱LNG/8rHGN}ܻVN&>A~.6&N^8qmtSsNmzhjse{PhwoB=ni1 V;:>lDxsM{g3{g;]ݝ,M=tYZ&H{o8ӱ pcs~]\ĝv쨟Zv &oil`?N6,nvяvg~:ʏL2s=@ПM ѵvrfFݤ.A^N^$QR*KafD3B$)QIQԢ-TjǃõlnjRQTJRKLX+8 Em A1q 4*+R_I ,IJ(J- v>^|?gGDx'LA;wE\FhᬟNH OF ,'慫O4q >DEy#u*6S͢⠹Ġml~qѡv߿u SY'( zhwMͬ}p^mѯ}L:vHȖNtnw‚,c#\>ont9,!n9i 5jeAVC;68AE54-J(/+FQ?$nSK&%O ,VJRTx=MkK#U?X~:W/GG{ZG{eL5DV.IA_pf\AneBʫr p(eoPL VBˍRyՒ0!^0?gOr(QY &vwAB5*0%*HeˊZd͊J%RY]s*Q~󲞬,P N94::fkjF+kZP;ur\^u+.#w-W\Jϼw󾧫pW+%!AC>UAղd*EHDNR<tAI!.aPyE7zz$%ndimǏwЦ3gI&G=9rt{|tsW߽i{/#ĎMs9a1o=<;g]3~p[N_rIӇo;8Y'.|9T|{V|$rҨ$kxhMSVt>^I4X/[w> ]{ ྞoZmgLn7yܲ s z{9;3IHkLx`bL=nI)(GտK!~A(cB3W= Z-oeח V+ j,-CF.JGT̐0Ol}:eY4Ԧhv=^tiW;k5 *~S^!4BVFLXjD(-3394"-"R̊IˌAS츔p߆rq.- JҲxЌ8#S;'H9a^!v&-ٛ?554kc 0"A)MLϝ<{WV~'GiũM\Pefo,ש8u1K:qtڞ7.>0cd"-ę;9-ix-;mik柔&`ݒ9ŝ8";}W/n^^(l~wҽw}8XرAIEފ^m`]הP&Tw _Pfj5 {?ӰcG2Ա4GO7kO>}ݐ`r\BA~. bbo_^he~Cl,~v|  6S#vaA>vh5UB"-/] #5ܴvM P$|r8V fexXaJjF`]dL7T_ڬqR*Zqn"k%9}՟-6?lYk\MtakMsUm&P`plQQ_oP @EY\TxA:%(#^ţc3knrPR'sB%)gEzQq/?TӃPܯ?s楽{`ߠŃ"v>gm~?,?.&÷ B>%W֢oF n(zhUl^?GZmO(8'=}-[>LFqKPMCx @9R( ||gI尽B)vMcOnSK[ė~xϞ?rK&^INi(s{|]Q:vʮn31~pGϿklshJp-\JG$,&7WKT|C`S8oK (G{[Y=Rd4))kzp|.E虊 OAf_»ctX+W}I;,aM"G al^q!78(?\Fuy~VJ}!):joE/-lnQ@ҙoucQ'*d4:T/H6 䙽UYY„jVr%-D$zTOq5”FY0?")D)fec-z%`:%PKkjih!e6kK'zԳKcua󅁩sC-mJlQ_MF*l-D,()!E0zjD^Oq?8矯j)?jnoPK}D&h2VW# ӧ˿EٛW.&De?F(_M-^6>.^q'_߼pԁVF7m%FcV)"T8z"܇ˁ%iٹ'yC b]=qℝq47 k{]rcmdǜ!8o?s3٧`c(T/KEIJa\y7s$Z'&.ݸqvwXK0cS[pD-ULVkjQYT* JsP^^ͨkؔ~^+0Vp dxsk8ɽѺƒڂ^mN2S6X=X4Jĩu4%,KAœQ-9hP̎*xSЩ4+^Ù ’6-gvbH*`{f$?{ mm9r`2肯Q~~jNBZ\22PïGZtR/~0tq{:;5Ae%>Vvfw<<-Q@Fm9L ώ rVJ)0&6&o_s jio^t6pX"εEq{w^t1qqx 9-5𮉽w?pʍm\gGvG K9͏:wM0?66$}|w.{{::xYzރyC<ؾ<ǡ2s>u}g5_8HciNyUG[k>iy1YcOj靫lnz8eDg*ObivR )(fs%w[D+koG+" iw?E7Ƃds[cO"/j{(9964#5SV*WbV&r&6Uh42t֪?RSSQ{[S3*i&ñ}G"\B*]ZQ7Wm԰4dYn(VCKhQfw늰&(Q¼P>%$ɋh$u2$ >m怖2˚ocR{*oZڨ,-6߉-tqɉs)L*Nƣ몢4(ӿ$;ȣGa+JrYݵP]FC'_~ӓI1!BvmLnRRQid/M/L6_d)P/}kȸP=W^9jaoΆ$?XOgH5ډ:% mnG^<]nkG;NFFzdt$6ݘ_~=Ƕvb=ӻ1}ۦ&ܷ 6rq+ ҕ!!Yff6.ޡaѹ>AFG^|c'E٬Ф/ݸ{gH{t4Fɗ%c󣎮WڜٶȻ(Czةw^\.ŠN(/ЫsǏuN˵-RMX-T$w.B:20W߽3k?_5''KRLsK"S\[`)]PKi9.G*!9ʋY@IIC $5 rm}]um\SB\PI%|:ʣrUtmZ&&ĸ8\qݻmƖ}u]+U!acr%p bj^Xd]_*vW5Vy(;J a1}䅑vi^eir5+EveByuߨXgsk33+w=,[;[@ousat}a3hd=;`:}wQ`dnauMOnžl9y}mO]LRۍ=wya+dKlzx(ٟ.eZ:C(ong Z"iZq.8Ȫ{cigS:p^Lh}kF$I5_ k[J[7.[}^k{a> XԤ4@###cmE^F]D\,Kb6_ 2QX?K@/QR1/m?y(=omW:_}ݽz("'ͻ0ۗ[)š]8A7$x9dS(9D5쾪rj3CGVE3x~AD=RZQHbde n,/(\mQA.Ήс8&'%hy~xbp?GszNQ(Pǜ>ޮ6h0>*y0V27ɬBhkP#wPR?KP'??}|;hSuaGxBӾheemyrz::[?ɳmQ{C !6 !HH{=d( "*Z[WZ?_^C:mM^|9દ j(NƲ:jZhcp\\)bac Flb6ߛk=\9AEΞd*/p+ e8,Ax4FNY% PR|o#*?2/- <#crXgM}[jJYBlAOƅh7tm,h_2ž3]sa;ۗ՟d$$\޼rI(/*ilo {*/#.3%VKHbSHaA~qBDf[Ξ={N=vx[vn߰yo,]ቾUc]k׭]۶nm.!&Vua{~~j||8Rʍjke,%>bBa]JA6rRv6z`$ ?[z2'66Һ֡{:Ձb́ك;t6箟j[3Z Q㫐oKhhcP@TGfGð,'712"5FnlUwSܚӇv.ͭxL6ѶKrR|Hoٟ?q|݅s;8mG-{ۗ_kO 8ӛ1=rxG1L '~#v~|qhb0' o8QZncOWP%:z¹cm-_<8?2o`jQkpd]E&۟d㨊BcuGz2R J Ij;[.JŰ bN V`~I#8S%"?#+39 a^B\Ce*,Lz\VCVgwjCsW~NmR\. #k4~A"+x] \ P:}#l\lMK~'rrr !.,  k|3PKˈ7UOEDCd1vanJAnFeyE[KPooow{{{AAQQb*r'vwe^|ɥٍ?3a a` km\?\u3CXvh6M̌!̃*¢A@wa{/ ? 2P0Zv.i"d ;FMEhڿ}qTpȶ7;:XM4Ly!a4k{e,J ]aʍ %^DxBI"Wf,w[+#mUKk'ݑ5q(scTzxM_XN^\!ôt\P)":?<5=cҡC_Ac/?rjC޽ťM sK۶ wqq[lD%4k~~rιlZK6LLv BC9 WG{SC=y@ǥ "slJE4S ?42y,o_9q.y=u/ N&޾600:;&+{{[:K@ׂ$D a ?twf{Sh_ץ}YZ'8}8ᇩ퉣KOnanΥ֦s9խ۽]Mj(BMa,Oϯ>~qW&{DvdCڐ}w-NmuuG|ZZdD$ = c3=m4(.Sڕq#,bWБ7⮧o)AgxtV[(㥕X!M${™DQsV6 ;h/0E%w ۢ)`Bf׷Ee 6Zh`'wikdZ4W톆XQ"ldk M<cqnnPog+a?3PW0wqq׸=;NpŋW<}ዳW/t~ϑcN_{x۞C[vݸmmvڵoރذiaz;oݸ\l۝,lˆ-VM 4w6奇#n0+Wi mm-OvO7b{hǃ$ǿ_{aw?yفsG޻y T//94 @Ouq<7Kf~7_]qg/'˟O[7.]:l!=st773=8n{-665!I L #BGOXՌ$0<).&$n(Avv ɣ3Y!dGE IBUs%؞ŠkkK*U͔+Жu# []?WvNAzOlZ Ǖ/CqS$A%*[T6xln0:zmp-ŃWgw.,Du|f`*<) c}e2Ɂle iTxvV467.62Q6 řg1OTD؈pf0Ρ<=ӿ?//!7#ipw(ӣ1^޾r_jg cKK`whl[ڵ뗮|yڗ@C鳧N:@CG>z ݿg]ٽwK[6oݾiqqjnvbŅvlm;~Cu}F6LV% Smnզޙm`. nŵiF7L={Ϟ]时oZ?;9ajmsk޹kq▩mKkߴs:{zo߽q㫟.ضmûw`8o޲nMQzjnR=XKf8XlI{8*/ܼ Q51'/ox78>}W~mwLNɠrX!F2[M;8Y jiHj愦Xh) ˈ `DmFhH+Z:T^G-3UBG01VЕ47D"ab*Lhcr3:u'3DFV+qSDe繢wIt޼.{Otޛ;:p֎Cg''7X8pŃס{cߞV0%XЎ "#$@Ý憽ϗDqw1ll& Y酙) zJa\*+ ~!^ѬJ}h7O5`ad>ñC;NHl\]235uvM?6l 7_Vػs/^8}7/_E}G';srSq'jJVE|lhHZd =]+C}]~VVBb7bj5սC=1QB sI(v0$=^P_3ոcC;~zwPQ7 ?ۿPM]K/F8d.F撦.I񃊋+VG 9!tBE1u6 3|-H h%0Ȇj&%INP0R"|VN:JZFf>;y1ʹ$I&*8%a1p1` IJh-3>ѵs{ͻ MLU6v޸qC-in;ՍurZ~KsGan"]L(9.%",TSC7ҔEvv%L/˫,ʌv5Pq霚]%<߹i~ۆQk=͛ǪpQMEy-B _AW{Pw{KmsC%\:7n9tjko޹w;翸~…Kׯ:up`<0hEWMH}{zvڸ~ڵ#huܹ굋/_=y/?}~?߾!'~GwS͍%ڪ+p5ז6TV2P%骘k)x98p<|A C'եْbaKSU12逰mY3ٿmjĆ龵P^"*HeŃQWw8/ܽcLbrE\B>aOՄڱd0;$9 RC3%}CCyY~ 3+uZN f7iBuU e]BQphh$mdBUk#G:ZzkP앬,U4ete . y>ҵ9؇GUx ^OM^aDGotY%EN~sp~#vc7zۻO8|ի:`IϫOcLpwXݩ,J* +Eɱx'+C0oDiFnQۚliaQ=N̸VSo26ܹ~zhxڵ]~ 5#]f.@tr"d+=ey RVU$ðBUY<$M?oX s2kPߏ^n]8$_شw>@A6_8%0RwnۈjaIOvbY@f{{zѼݽ}'۱7fea Sb8'GnNJ-IJm5ҳPR3 )p\^:"9 oOPĠSRᳶ37JRlL REVdCE;5]diRb5>Ԑlm86D80"3sC''Gkkk& +k¡z Bin4s77G559;; 6CIQֆr(IMMʼnL đҖ"d9&w[=(̉A=[3bƢ|fgw6U"2S9FWN MX-ڶlZؿ{*5@Arڧ|ś;7/m^\X7?6ܱfuHO3KPl\?Jry6i~B ΅0mxj݉θ=0QI)1Yk e> MB@ރgX\k{ a21JxJAYsT12G𣞹w99;(Pu* U!HvD~)oiHyYJs}M}UYYqBumjWoM]C-. }G'&7ίol(/jh޵Ȓ68g²  ,Zj ښ+gÇ~'i,gd G<5'v ÷o nV≃5Pׯ?ݾ|$fCTkkSt,Q gUkKBD>7#:Rl7f% jK];i;?{P맯7$#kKВr#`#eegnQ̓-RTYy~&-Y}릾 *+NN)~:}z#^<b,|篗>< =uӱ5eƦ p5 ̺酅3kz:0gCFNv&40FOK-E[ եU^cTPo^oqS`lÉT&R:;ђY p xDlDA]㎣7,۱rMuwdllKdBZYP\r0tMɱrg̬|xѣC7lXkOg$䎏d<^]a!\?>}MYn'۶A˫K}7X޽]7qpahrrv|5H8Z+K` d@w$ ߿vaa\_?0"iN6i@:jm㛞Kj_iu';/^=~n|GڲmyΓSV__YPJ!4J|Aysfh5miٜܪkhA!Q+JZHiJJS2"fHnblJ%+ZnyiqG̭ۘT Ug#Y,[tx6KPYj%Y'tLID'edN'DKpԪ* ғ>UTF "<jrfyQ5Eui5p{Gu==ݗ* dĦٴ4'{0a@nI5~|a2jʫW7/.l#XJ޽;IlѺƢwzK{{Zk7|оTg1sÂᬋ=[kbhԎV|sEmM5PC]:Xdn\(/NGPgvذnbݍӰ3\N~z̒_alZRk=aS}}{lGUFyw/G(W?13:P+gzOϞ<ܷgH(I3hfLo'k'[@?w[G$A52ڇc 'ƇaӆZ.%mfn^7>bIB4wuTXij4P wo<}|̜֕dmMXJP>`x LTlTGM+E%`Hf Xjk 4@d xz8*2bUaVQ'Z +5P8HpR<|w0fdhMœBlN^)i勦dvjJZ$E6,_~MUb~/Z䟞(bsiuYّqB>gE#v<=9ZXbcMFUNvaÅ(JJ%8 1\BHLIKˈŒ5=)/Y{y5Տ_gz;[O ~ڿefb;ϯNou宍і\|}$ǿ)GVwVn_:?5Dު2QH0BAZQ/ o߾}Y^:Z{|W`g$^޵!Cā urB]Sg){:+Ξ:~׎b;5>|'Olݺ5#9x/NJ$[iKqbǧwzFQa"~(l>.Ī)/][$gzKKl  ڐ/#C g7G jK*a3p@]afp s$bYx_l#&':E_\PZOT6QUR-,u ӝ&Ch`mf'kFTVRWUS[!:ǞdwbJ1OVVVVZ4m:ӄoLIN`"ۙF350U{}],}i(^ 3Lu!"!ƽ9v2hlAYimMF1#XXB_z"/IG07#<5!e1 R+J 9SǏA@Ĝ!?ZӛCĈKP+áXb^@T;W~e[XX~æu'zG!zCePY$Fg$44WUS32ڌ[awm͖I1':*J3,ȧ'n]AZtoc1VbeBVDOA_S{M}➶KN۾eOT#žJfWεgv,> ط{cAvzNjn(3I8̊A&HMM)-Yvs$11[EE/7bo,<N_6Q^ vvdtH38CcCz *85z ZKC_7GР@dXFVN$FGQڛ怯۸>쏰Q0{wL4IP. [=IL""9'J dal EJjVE9TL*3DEU}$s=:͞d<"1G' d 2K b|x vz*(WUSVu NƢzr//Lck}aqnfv%{+Gw,N"7&?ٿEsӜC|`M%%m働nkAL v%<EGk#dY6Ud'fWW$oLEv*v/yXnf_G??=rn .oڪͿ .nQM ŵ 6Vf8r*ftѡ|(j*'V5k&;ڛq^0y_?㧻Ÿ?y76Ǐ/~V[WWVZö40LOYvj [k¼ [lٿt(+DVNHInzQrw/t;>KTKR)gChZG=8tV<;(9dY"ZR،!Z&~fzd-MYY1(*b`Bʦ}@dK2ss(.LLN ҋ:sFw-hkiᅦttcoeJ !-!93=L-$*<0 ~ D$t&D9 ԼL~]e*dlHDr$><+Y*nMKN,ȩ by%HԀk7;10=V,4% AxOiQI*[_\ܳu?FO.?vOEoݐ$7|?a ;Yp<WM {px{%@UW LPxz)tEEb.+6ז?:g: ~˟^ܻ Ozp>,U5͎v]Rl$|S7n۴i`wweq NsQZkcOc(4ƙcXO_zxG޶75}ƒƦ/RKAxwa(\Qww[WWS^QBuhjOڳoarM}[7*J)^ng90=Fgm=@cl9`bcrqf8&VT][*V˙.iCYI"YI9H mS6èSRSqh#0_ibLf {&gtE2>Fr¸(?3tyVaXZ7-.ZJ.0"F%&8&z ;iBiI! cӈ^ pthI>-+9'm#@I*US0lyIIh!Iw73Pq#8"OaJ) !V%\`c 4;ދ0ukW}|CaG?߾i#/Aw n߿9q`͖ͅ3o^j(;`]ȵ)ܦܑ5|ыW'G8.w$P8,Ɠ{?rP_K5T(_=෇oO;`,Sw_?}xg"qzEЂ++;И b071 @%g&Co*1T]V_~2Ъ"ͦEGLJ՗'Mj=]%L#^ڹفSǗpN\ݍd<{7qw֍S׾8|Ɖ+~CDv"sy'|O?߶1\\^D 70ᬷ:?IT냛bGorrʽ]&S'Fk6:d ӈֱ֮>oFJ啚̂8]Y$S;TTO{ A2D~wLOm[Vy֐wƒ\mHue?|H^ػˏ˯!G ־&?:7onlhXӡAMQq0F.joCHtbXPSS; :3v0===] "b0X;܇YUUAުʢҼ #3=k ҂ >*5*, ,l3ME{5;=S3wGJkMmSebҎ O0=9L ̽ miK˟n^w˝ڻ'f'j[6>}\+8[R8 1Qќ ;#CRK9NsD!⇦D%8Z0 eG]=`'~ře] %E(ߋӫ3Y΋V/o-~mCIv~Lg3+Y}|~PVz2ƀE[FP/)>- 8YKKX:8#]-U9pdC"FS,a(,"Ʌơ,]~o?/Nz{{yyĈ`&jf*PpC @4$FfrP~VpEQXSmlI>/#ό,O]Vbo;tV&fF B|-llAeEC@2X>Sm[wgOʎu16@?ϞYIp}i)1)Ѽk'6G,^3ˠه!:#~8b zWy Tj2T)չIj*;8}p ,05؍'=;6Ab ı]Oh G 4!^<ʋ]y&h#K 9<_s ٿķh|eז }Ux5޾~c5C] d@#b,2 tLÛ?z)Daj|wwΡP^_Ϗo^Va$~~#^~z#R$6 O-L Dz.569?ʪc MG(ʁ g\h 9_mL5S@@AOOW?#RU)LVl}[{>~ώu@76\GG'XQr#J݄P!Llt5|V$Fĥ@S cCXSK͓`-eO[VW_O3رӠ>\#El* RCYXdK@k`RŠxPƒKINHE[moxbvׇ͏7~xGKmialOTVC2 vskE(Z `7H#8:,479&#-S}ýqQ(d#?57,Ho^=yTGyA~rnQ?^;o(hnJ-ҹݍUxtomqyR[oݹ7n` o\y̱CK_ܺx蠯 ǷtW@hv6~Ƈvoɽs}?{}ӷ_>F n[i&'3Ǹ{vϑ}{ woF;u䃯 pEBXDP@Gm5ښHH faR& #7?NvֽKY,w6Q_;s {`Mk_ۙ}𻹑+'6}X\7_=g!KZYY9ёgdPUync[s yF~~ajj/{}~10ԾgƣK~2/a#<{+꥝Khnxi{6w-ENpdq|ql/f_khK~+$fb9huM~Gvl^}`ܚѓί <a7v.nƜ8~(JL_Y{^;X(忼pQ~eyر=$G7WزW;6ѿtأM uVt?g>yt ]?xG|5P9%ߏE?WQV% ,-S$_ &\|C#e]'GYwѻ_b;}}`f=?:/wϭ9s~v'n\Tk{اAuon]N!3H[P%b8H3uXhr޾L3UqB+y>XˈfF_8_>/?{׳y0B@bni"nil\ItW*@&&N -BD 098–j 'x3b= dkǛq}bU3>A2𪡲{ņ&ɦыrh6W㨃F$Z1X8#vxDݹt.\ߝ޾3Z[q^XdiYEiXS$$S#y]m1{ۑaMw@JWE~_GOy@ry3VY\XYN7͊lVROOQrP ՕBu;9y0SҊV22YL+jG0 L4 'sYOJkk *UNC?a:,r2 "~rBdRGY1CxغZ̭ˋC M@Cx c6<cvmF4/5*i scu-Yj^K+ |g07v^xj1߹qMOgC6Nia!a0& ٔjZy1E HtuAHɁxᖉpح닲N =KuhA2=yk<a3:J GXP]W6Z[PvKp*mB[V̦4֔G0<<(>4\Lmc;)t䁎"X&33gWB[Z ׌ 5ݾr]kzN/z4]U<㴝XZBq"`f'ĥó0 2A{:9ZBl&NT%`/K =6SdScyt];{Ak\Hwj~v("*0(:6>op`&#Ɗ󺦊|L@hxz[}LDs3sK*yxOwsK %+ĘN5@l`mД45Aa) 5m}Vq4 9=BQB鰏GZjv\Tڄ@[R8`aDF*jL-?؇lB8 H^Y~:H_Hkt4dS0/N-@3դ4 _GP QC\4\>⅁I@\WZTg\8ev0h`@2巤bpjmDF ռ ~: ae )W[[tylps఍t8K-=1%EǢ9L抦+\6u6RZzb;b+.&,>Nc~NivfYCm~ܤH^3H&c#yVHY.N|Ow~!|}p mM͈ mByyY܉hDM~۲⤟zbXy_9uN{"0mvMc1<4؅ݩWԣDîb9+cl0f}5nGS6֎tx9r; ‹<}fϦuG[vo-n{Fr|_-kWz@L{0zǃot*J 4Q(=yð(9;:N06W4U޻qezU?nlnjՉK_>VZ}~=; ]=Ç-曗o~ԑxB қǻ˯߶mHeIGǥ;8 uJ+ t􍬂8QlIPG)[:~liωǰX;~.N2Hw0p24!Qrp1ЭT&@⮥4Jb2M^ϟ<Y[hB8<-KĴ*ˡF5@áؐy--?zԊF?݋&G[붭s0rUy>$+<珯Ś//lo(pInlcUƍKXOE@g}FǏ r0b禩҂9HwSίKN+56hh\l0G \t}.X_bj|x-6-6 !'$z4Ou+JШH`fjRTо4W%@TBn P8t:͞t=x "ZDLl)gn*- bʭ@4")"B(iki0T#{g}cvv<%UB~d?:̏HwwO_R&%e d.b}t[ڳ;75zl`i"o[D|, z8?r+ԊUg",߽kǏncW[ OpJS&uE) [7d&E$Gǯ?܅p*?)غ{__;q<\.#||\;׼9vB\m+݋s#,,L kYڊ6l|Vul{cɚuCw/=tK AwVl*_`BPw\>%n~1pO//pW+~s bcF=;v>(,--i),jwc+ks K|' FJhs)Bϰp7F:(d.~U:( ,e\NK.A~T_ 6fjTK3GsmA04ϙ22寧"FiP'2ũ"D" ā@3jp ˠAwLYUi&w027oL-jt!E4ה1RV6TS8l?$!r($6WqCwGYcC$ 5__Sd^p-s>z^^t=p}|M|\M55դThokb kH=< eehe.ee*IX+~nk,^٣3RXF=t(+lo#{ºPT,G-A }~lz̛7O:jN_BcCk%|3WNx-T_oڳ0ow\WBsnmW-lDW$yՋ۾gz bٱn08 / Mboӫ 089g^,3jP-~@r$]]EuUNA!7=C/X~8:uv/ݷ}fzu+䨽/a QO ܵyvdfT5U_ytZau޲2:z!<(M͐oL2QSSD9fBah(חF'Xm 23\ 0$+m7/_Vf<5jz1F|DiDE2|w%u'K@kJ=hbfHy)3.W ?[PFӳ@TBcpCV!\ vnA%}*a"-')':46\zׯ2YQ| ƍη00Jύ %f sJRь&vlIU8!vPVTLwǁͳ兩8Y?q":%Yk)홃G RRP~R_7jrb@ËGbN FE_u_|e(ε?߿q:RKzp 85<2| qTXvOHvV_=!!y[km~Z!ύ5`I^;؆GK#d Sħ忧=gW#YϖdۧWp>xjWlF[F$*aDg'p? oœܜzR$? G_GWͱ {??n^>}ڙxNcYUH58:Pl' 0WsC))Xq =6 e*@STÅ/K-mo$*!0&Y N4w#Nݔvfp AF$a`t' y%t--V6wpS kI#;[ _JlH L͂bN D<FrIe c}HGbhЕSPlK[Bg\YѠj3`b@$:9O};fn=z|7G;J\?rƙ[f_ ;+PW[.֔cG~bRt'@HSc]u=Hڅ0w\x,i,Oۦ_|'\^o$)q};d}џu幉Aԡ.Ƙ^X['Wcyn8ǣ(o_㐀C3˃v/޸n,?;/8>sܖ}~b⠉ͯoPy9<7> ;\KҐ^6XOs@9@g%#aG^~i[~/=1#5~_ſ)߽lʈVT, P5".(thf8kmB­a$A<5LD55Qq)ޖ(rD/[ǟcҙ {+k)gWX + tS+~%!H@MkF9Ns9?g C^aDyj20 @Ĭp/@-=ݯΧZTxضeze&b9Gr@.M x'^G(g3=la:8z;\)NdkscT+.AOIfpQ'1XnvgstuqƱK 0Ƃ(4+4!مP47!T!?)<" eX|܄@:%:C\_7* 6&wḚR[RX:TYTQ\UZR{Mi>\aDjuI^kmusU5ӸƆڛ:b@]T3PBj) 4kIDATXƖH3)yaHEBSh2B6x`*E}be/MqS2X{@S@Rdex&Xyzj#LGH&K+)4!V^idOSCȤXgfk}> ũ/l F`|T$3$MyeI[cS0o`2~H*挹uAnN>t[+}=PQE)[m:l!)( T]h)gN[}d٢CQ-XZÚ), Рp/rc g G2yX߽ufb ~['KouRl(_\3ԃ?|HyNԈP3E+L VVr6RZyBuU,sq%hN%#J %<XAx(rdQmPe޻{f.<4ՍP}*=[SSmy@C eM팕 &*ࣹ \8 ^X wJ2zz{98\ Z(9:<.lvAx<.PBgn/;GP_{}~Nr0(6 ~:lr*F2+($qNtE:J#Dƙ*iEoF+ban-ϒ*ߟ`ɊgIzaPJO/5] Mn4m_ojjf'Xf.iYdvrQ`~xhϞ߹RBZMXY^m`6NȤ<JbᕙYBvhf|zbt+?. T8OH' 14K1]yTc:Of̃xū.%BN0VBsRRDzrooXAPFVl4̄`O ϟ.0 /_jdD]NVUvE٩L$aAsңdG A?O6G"CpFpwJu ]q.d,tئp ikD~Jc=h}_{o?4<./+/|TOoib_~`؋?BǗg`Yȕ'V7\'޽8F-g}l>T% Y)`}% SD! `FCq65[U@2P6P!) P\HmhƦzR骯Д'LLu4VjȮ0RW$+$>|XNfG$JT̚J3ERIm QcbCȑBx*7̚`lhHXYI K5e镀$JʄeCXbrR+ }=f["cYʚp$;nJ(W.rZ%'NLT_?,fe,gg`խ '$w_M].4DQUmS(䄔T& -򆌰)Jkɂh`c*8"IG[X͕:jgDDŽz9]"|B<RhTXgK[q5{@G]uQyI. #%152׽<_rsN+LOMA b@<(I1XB폜& )aAuP%r&2b"Ek"8jrDJTkd !'Φ L^E?Ǽ}po8K<^P#w֊XN AgG؆F;ڊkh|u ڛDž&D1l)JB \P1EO֔bS)Fq)Q{]9H.ߠ$bq0ԗ24%,$,W @BL#=HXʚhȘj( p.07QZ (O@ عh#m}hnWQ0T64FZ#EKdzei&.͍d;UEH'9JKD\$@+T$UQic #!I%S*8R=4|p*@+$ Pxxkj"\bN&FKEܾ\!z$$c<*ˎ@|G樂D @$=!3md&b/ 6o3—s+r G;+6 B$׏f ]ZR'ERށd2}ߺR䄕7WZ5Nό[^S[ ]YY |]~L(Ew v0E򑡀V]wOUE}}-HA(&b1i#DZ ݢS|cY9itone˧ߟKΊqACca:Siom'LJMK%0κJqED{qA6+uLH#yL'sC؄P`B<9F?'/e,q 1 go:u:]UglٹaIxFrں{{B [Q۷̮c{W5oظIwTz]~*0$ #?}nq DEOo@Ҽ Y1I1mk'S'%%m^TkUUǏX75jnlM޴u>9i/Sgrs ( }mrKO8{K[C |iB㳫;ۆ;mھz HqZ,t >"9.?%b!/巳 Ik/T72`kJdO=\ڏsdxtr.oK0;/G8ɑ 3 i+=Yw;[/h`GRps64x^jJ ML%Nyi`@$ƺt qa[}'L ` L)+M͛ 9Lo(nO`/ $èA|h_ć8kx1u9z94$VJ.}\u*rDP}q+,x~qqkdGTVc}nU /D|7S-S0 Eox&3]l"VząRE8Q2N ؘ XҢ}%dW Hŏ ⰉT`"`sUz8аoH*-\ڶwnn[Aq6ӧ!s vA%'13uVUw<O8uh:fjCzrfl,ҍ`b+ЃbҫQBQ }-mU(d-86I vj_XZY߾Ȫm['-椆:frsz#rb֓\?enbσov|/?D $WIE%/u՟N)"KIad#3YW 5!]ٝm,4s7v!_Wtp{_aƉc6c |UaFYN2H%\AS‹b\ZfBJgM 7ϴdcA]G%ؕ\ERVM0Q24R\n@uB`9rPa:`BPW@Vw;8'S!8Cm F3IÞG2TXS]2jUeQVwcedz{  tx!rv4!ʡ4>2 yAbkbi-em-<]}L%t$$<_P3 ;a/W!naf?,vh?qk>‰޿mͫ c響Uۘ[t~@AlihmX@mŹH\ɊEGlБbdbjZ zOBBZ рpePK b}f2d# +3;m݀ BzB*]GGEɂ6^]~Jx6  ݃v.tM7o]N9=$e[RzGj9/ bʋGj }}BK@ _G Y)pJ+B2tgM,wDEL5!LP&2ܳ.3^\nj SL7gIpIHdj+ kK 4Y{3ZӜ5$M5W+%1|JKIAY'%*) ^0өؑ *341kk99=>ZUZq䆺'Dݹ"""$-5!=-l *p򠿯֑in`bS%n]y#+1QE6 ^^㰜̬,z0p>}Ήa418<NX'# 4$nTo}SrOGTm 50##Pg%H!7(dd e$Vr+ e%ˏdm\73P,?B_\_ Z{3O;KMuG9塆R LrVrKU{=Oo>wPOUqU `״)ӇC{:g#m%`ekn#hT@3 H=FrZ1:qdg7Tn @^soW{K3EW{/+4m4r4S c uWo\ k?XjCU  =buF+ӍB:sVTVaת+O~z{᲼ K3^ d1A{8uPBО䳩ۃl\Rp1Qk_R#$$ d /]RV_p $39IxnJ"7%' `A?0Y|%IruQ? p0 9,kB1{2Е ͤl$|i!N A<><ږ2}O7;UU)mdn(|!( "Np`XC-"3͉e4g ,^0;-!N..~~~i)PG mtt^H'Ą$SIuͩ}=*V~ 49!>MwLoH:m&1ʭГ!{=% cU( BrUAuoc/MG^,lBi0tuK5U0Ѭ,5T"-(j]E1ذn{x81p$ml .kS}|B"xWw/.|Q]^rWbzz2utke B6)Vaq<4P9hd[)x4$%FfRTM''eWWHJL -imX !?&>AHBcv) ƺay)';Y]]ӔƧD =2>m Iy $B2رtlD56%t${trdLB/4gtT66{yȮԓvustŰ7A!;1.#5iCS#E[V )`d*)VUkDyE(t%=s?X;PCفHʂքC H]B3as6s&*-M2QЇfKwSrRHBE\0;NE$d&GϏil$8/Įfb6w6GV2splvv77't$HM2h㓤usId3?'Gk b-뚃7m+6wE4%& ^\dpT7EV4wneUON0 S`75F7wħf2su%ȋ.}>62/*x:B1bfvݥ[ؽ!.I4ǧH[n+J/MA 2HfskzV>SC`19~N_=>3ڕzܑ6MY暏!po={l8!߸fWoegw\_RG1G6T; |xp la^ 3Y `OFʫhA7;+vE\00w8I>a!&rh֚*I{z9 7Y˛i& /܍+pNJg8h땔^\GP ?5 L_y#PxܽI I+%%@2+ 5$-#Yc3io#GKwꫡo^)BH3V54WH Nꖤ&f`B#E((ˬ*KLb"k؛i ȦbXڥ兑{v!@ݓnƅԌ@mbg!#4){l}>!(,|8JD+Zk C}8>g[eu$-Tkowl)%E17ecS)9 QeUtV^1he/_]ᅒf$ ZGg|>Bv y 7k)C)O/LFnGbV&бc]ZDGn|DWUnALt*TTv0M6sGc 83ʝNjǻWmۣó?Wu"Esg5+ a0hoLPj|+>qTHW4So(Nh+qWܽ~\O$; '(׵5f{SGږ} 뉓yl/iodxiĴaVмF*( Pb{XƇ%(o(/ Ź;4hmDRՃdx46^f\S`CT7ƝNe&vj$W0q_R /(|]@Q`5FH-zeU )J]M BYI ЀG0%ECC*#?"Ԥ oe ֻakhZ  d0?<D~ο4As=#՟Lt(BXX!uNNzz. _.˨w PE:+V^ڙ[TW76vdf VI./Ќ⪝Dc=qYF8GY'&zOMTFh̃}{lvj5JMu1}eJh첮F*3aCGkE>@ :DO#ſsꉽ$ e`F3m8iڟ^*΋gb3Ɇ±]%DoVYXfuu* \z+[X>usgV-53)؛=dgu-ܲ 'jROO眪+sJr9WW=9jQN!Dd0mlgwV5a=g~߄g47y7^^/`aͩFϡ@WHaknrڬيaC]I?:wIȝ+|U%Or3RJ1| QQBיe14qSC{N?ѧ~{G?he}_33Tf1 'аCERᡑSt٧g}{`=ݔX#,iKdgfz?ҥL?GXG:PLY\YC" aE*psbFߧK{KH"~公&&dKJC^/YЈt_+۹5K-1//ֶ 5wes: 1mqNڦX?sf AqdxĀsrZ+yT2y3g !(Z1kb_éƕ曟}z ͣ7r6ұ0Ƥ"CHnvlq噧C7|K;#LԉoXz X*Jw?'_zvϭ]RxR!՟}s%ޥZ%3Q, 7γ͝ tv*ԇ:AƊy5ܹ3>ѻO>&`/s-d1Pm,lKJݹt6rWzG{f'^ە ӯ#pߏ6d"vPX\( ieDJЬYז=X6⅃zP̫1bZLՒd& R:.$ &\R03V wO~LiaA{^Y0bQj)l1 ʁG[(ɚ{YpHdׂ_ܛ_tsL:Ê'D{W)Gȧ;xy "w_A!98^/+'7ֆbf#qU˯~ GXg?x?}koi !ߨ\i?:\T$U;[UH9 !wB[_˷@ߢvqֶ* vv&}U񔳶J*%CW[ҧ_s~^[?g>S'|.Bɟ7:Vo׮~Z+zFgn}W>w^[z幥^z6_}+7^{~6/֮{S6PUm:t1RY^="C0z)LG^ _X,gAUf;97BsK3SЃp2nqOШRy.D!! ](HG=nwtL#A:5V_K1rQ9k.E#ӻ]["A"Ks KsJ(Q\EMsi\R@L7Z uc*e J1K-u}(դͶvB*6s PF8~ꉔT 3 G3 N}ɲ Ű?̕hBnDO?_g|z]sy_#g#_OlU?w10!ԷT+ ?o/4ӿ_!\Rq!_n~~>Mzm{DHo}4b)H8D[;=)6~?ܕ iWʘ8S]zى^eSzaICDǢQ)!olY3,<,x}|g1:~CçuV݇{9T`=׋&7N8{OzG>t-Z ޳p:gz'}E:6˘tO=qzbhlDwgOBl`wbXC?xg>"mf4TCDŽ|޻H !cLOSgf&wQg DcgO>@>âHdS& 5ޠʕ%~rflis+S>K=˟:02¹aM\HkUK!(~'Dsv:wbv+T')S0&;˪=Sw;vum({e:⹈iꇘG eE*#+PSO6w/ԶYKW@jⲁɌCe:'#_<`}[(4Y_'󙷯 D`W߂R>?;<{"髆H_յ 2D*{h f{uj'Տw5H_\Y> `f?-8mTWh )|~sǾ-,6shg`3!9$ =r{23Z>tdʳWVύKX pQ)fI6e\ʙGG&wa9AAo3˔r30jj4>Fө*cHàK)K\А6a9 e2!=,tf|r~lW)zLM̤T;vkt%b<%l)^mU059tn:mJٓ:]fPΞyȠ(LL q:]}'Ξ@]7QHÔcV(fEp$kef %Bqk0(n3cn5 1枀Y7 Pb,cR$Q(QKښ'f*L~>]$ѷm<%N^:( :},pnlt)ɵ,emT YZknm.9mTf|ᗷoݯ V-p{%d ǿOwj!8bsj *}xxcUO~@ G})?+QdfgCKynQL[W#0΅k7B_{|kϮثE\zK l=7%m.fGV2V=_E6 4"1r U697!+WwۼNLcm62Bǝ`prFﰥFøzVe* @ڮpYS~ ^RC!Kګ V3&XGa61o>ԱPZ{N<`PqLAq5v#:X3`bS{!S!pxj82f#'fOcz :T:jmS) aa{|fTMfcPBߪ~b$ࣲ__ɕ}~? r)zS MS& y'OL i[]QkP59 oNt)eݠ$lm8=tZNs9]>m4,;~{lk/V$KJ⋳Vܟ}鼮]:ȗ- [ɏyE}k￱_,Frn3ޚ'G 6L%$V:CK A7w_KN-cv%İVFU Y߼Ukz⫕_~g~VW;a{> yo7!P”8 ,bI(cN{:POf@!R21b" Ud=PE8,Lj`F@@o =DMnG9-<҉U?/E"@0E#-le?a}x%A;Ym/iבTLv'q<HHj:!$J}3}=0uc={N=DS =݋;ް{vV#rEGC[ sv!y"m(v^W*ZCAB:$yl|BgTMm5S 0J )sܧUApa A?lx >>Zyj95U/J<͈j}69>#=LV\L*+*EC~AOlUQ_4-NQN&fS鎊s[ yx_NxD#f×n>*zC?s&טTJiȘ`r4J~=:beް,d}i- G&1Di1 Hy,YtOA wa@~7/g?!ŷ`k}cހ3C?!q)91 x`+1, <;oÀVV"(=Gս&: b.qJrq=!&+q;|H eM%N N"( !mK"6#pF;r=QI$Rv*8aZ !t`O:@k2Ia]Hڡ#l:bwm̱#S; i?٩7Sl#43c;4?s3~r9)X:)ͪaK8,Jsq#~!ȕN="9KzͫdFLWMM04_9n@'qe\ʹcjڼ fbha!,%<Л\t on{s7׮\[ʗ߸| n [+^D[{t3/][IyŘo!JݦKW u9*e=uc4kprG .CϚ#=zh쩄˒vBj\^4qH"kP=3A2dٮa!|]F!q6fU,*!1Z2Jѯ~Nt$uo̡S@(JcfpkvȯWõ8neZx: }&jA N=C6|x{w^;DԬ Ʃ!#]ɬ=3띬ywzPWf-_bb'+jpiaQ@Ā\ҏ8FvbaY\ X6wZE!EsB9l,fri4-R9~éu8~abHxjnxm*U7=-5 w!1kǝRVrNT9A$N k⒕.86G{dzOJ]uѮS&L*-7E]ERe1` <9UwE%[u1j1j}DXZ0h+(!ٴPvye)VF噢afVK >*TX8wDQEPRۭƢKMnʅn;ŵw6l_ _[^KՌ{Z͸K8one7d;N+rU AkZ#%!3;A0]*AP;4Rr)/2JPQK,YܖB[5\hfBv40tйQ YI=Ч`AvB3'`B*d3<:] Q! 7-B1D>u j ;сӏ4u8 va >zs  +)cxޠ]b:fD<".VMźU]'}«??ݔN7R2(OzźN%Z(T֮,bH6J0t FﱛGMiF'Z1H%`$Z'JL2TW#֎أ<_Țs5s (%.i[4?[[|wBGClлY:X<vcsi3}㞆pJq!(U #^Yv3^ ˬaXX3A:6-R'T &4q訧3B!S5)cЁ0ǡRĭqۄٔU%H+dѧ9 + B }~+򂽹3| &g^)8ThgZtK[ݕplOn梳 :%m\5$J 0K!|ƚԲrJ.Y.GƱT<9y4ٸxpO3AM@ f8~k4se_jM(PH"v) +؅S3gjJTn,O?>P1L[ ec,n]ayٵ_l!rp]-XF1 qpk7;oԮ'wKKjj#}kPqJ]T#I9v.̘s|%ͬ;}-{JÏo{W|r[k+vҼ[vBfLO="zdT z&i#VpʸΠF:$O+R1Q,,R-zbj b2('{Ov1gs.$hцJRXWwn x3 3ЩFyb%reL}RIF3IKrNVJke lJI 5 X7 Ëvqp'[FDIdΝ5*Ϡ#33G'gMAKOHWI(QfOS f u0+n-_\\2wr)O?{4X>䟞bZF}!1MD<3^m'u;^ue/$F̻{5,,Yz˛fP5\L^&Jvʟ\g_{G_}^]__K5]D,jF5? ?_#NRJME|ѫn[>ŏ; 1Ι2tF1Xk7|vqm|}Ju͢VެHC2Oq"Xil_٬#+,IF6;p0U":> (#9|j~{(Iٰ5=.+wn}~n_~vidI SMji~+1CbȸXsbN< mG葑QxpK ⨀ÒHPbN)$ä sM==yNƘGv E}`C*3rh=̛=BÙlYKGyl t1 hnofcZ͹tN,8 ,NMyq$Ui>!qr;5QQ9 2B+7V"51e 1ɤ0/ҙ"T#a2N䰟 bR?i# ʆlTUKd(*3Mh-YɾGGF.V;emk+d‚m4vJ{i7SVڎBŜJp7*n/(Y DdS}gc20ꪈ^"2q4`T)"Ny\ Xf#^Oۥfr;]on7/}j+/~v&F5)q9븲||u3 zi o}׾iOjG'h)ťaZpg Kmg iw\WePOzZf x ZVl %0O,'CZ_˚Y5*4x Tњݛ[;-'Y!!fw)v 4(NkZ3:檟} ;Kztq8] OyK.a*dLE}b7 Ę]y{+e^/bچSVtLzۼV^f嵳3G:ʕbM6 ꈇ2<&,;1 b|l JBK0h }ffIHKƕ=Fqp^lgkEu:&Xu=AG:g{“}VE&RCX֦ʼR[%B%UkpS\!f%1D.׻ J99y3Zo` I=1m4m&B~=*ӸXZ i>ժ B6N 2@_ωÏ?p]SN)k8iv/ ~H>L0q ԣw~'z>vgP!EճR@K.#C-Kǔ~\ 7#5 9t+"UC.®elDHa6N|># FZ%/B͋<^\ LqF{.Uo{bA\4lf%Wf 9:e}ŜQ+dݧNw |8C0\Ne4)=R1KTi ~kA`xxotwp*cG>0QqvW?à$?k9}*5H* `,j%_7t*H%qTD3:f/ -3D%xn!f;/m٥O7S6X%H'_y[o͵~oySw6lƣ}[_zN5r(1jjaD/?~JpeLmX·*1Wm:4,gdjFC>fs[5"*eHƑ8[7d0XֻR*kDfM!t&i ^D-ItP9 PAklGLI]AˣA/f'!ܘJ汦nf86IڃBa.d?"zv'ztǺУ5Y_.C 4k/O;6cdlPɚ:ʜ<6G=vR#sj£Z69]N։&O M"x|>Is>:%Exg8}]g(g 8驧#O=56GgOuF}"{u]8keNj6ǥVbܵBVRIN%ND\y#R2{bCR.^kl~El4 #5az4C℗OlN.aM@d.L`::?qjb4$ڨA?Sb{@`,1ᐅf&ƑBw7ow.5/팧-G ` U4GvV!|]Wy֪ޏ^n-7FbVv\\^)^Z.\h^TbNmFi٣vc!9~)/$@KYXmf>XT *,qc0iƻ$Aם0Se6:C9JJVDvS6Pla(G%˕SP5kL  m)z]v$I%YlhZ}D6Zx*wRΨIyׇ>& ->qϱ'qH%>gB.EF 4R a$!ZҾq[-sGmM齰!0&iG4ѕ wE$ċo3X%^y1@ 0)jIl::TJيYU48l(t|G'AeCbc>s7bs'wID9DG?:9LvԂtPp6'~v4[uu?Je)9t2"1˫w,*@5JCs?^5%5]rbtu3juS0# ` *wX u[PHT<1;i k̯̾.$jOIdKc!畭_xw#Fײ7RkvzD֣f:9cp +SV+|`{T ~iM.h h@c7sN f~ZŋQyCdIL>NwT"):J= ^v?Wl,1r  GT\]u%FN 3 YŌ!VK%2[US@`J1B8隮Vvni㡁Ѯ.:!-=`24@x#{jǏBq+ 9eBKʍ\+0A \3dSii6.PJ*+kQ(䖭AݵgzMQ- ʻˮ06DSijUe8'ͶS8k2 ^7AO/j"u#]2-!VX /ᄍwvq}1BW_\; {[̠739N-u-gV9Xo'JкSGR@&*rrJWwRȂ{w.,HPKfވE7#%"`^gn{ٞX#"#h\߼kҕr^j$.9l3G:M\.-˨Oq4,/M3NQ+JA#zVdc1p|揿zw6Z(symF f46%*|,cJfrN7Oc"Ü`"ltTF?Wig5S|ŸX9Qt6FG.QB b`(j pj_q!L,gBͪPpYN+a-*4`:wFuYlI`䫵|۰׌"1\^Jm]hDoQ ^6J0q٧F_zzѰU9mUXsVeeyzPXIfv!D&W;!mg=n9ż:XTf>ʤ|hS |xnATvF ?-1SYIH̳Od̉.>XǪ$ZPjB`PL{|a+DX^q',TU[09j$+roE+MU7XߓR|2-%ќ4dRO>L^]Llföwds#V[ iA)%OUM_\O8_r^}?~gnnχ]#JΥ4!&I4b!?=.!?U8#um3I[M> .+>(،{,= p{,Y$'dWڝc je[Z23&ׄ#@Hi 0yKW&< ͫ`vVDU薖ZRS>?śU0F&=z. &v#k<o!o7<32Yy*%$ni ki]\,9$o_.Zx_-ٖ杒{Ԍ씼`&nUV/__ګ'VFL9T ArJ zg'r@7Gc't\࿵zկ cVUY5S/rܱ#+;T Yt3BD ^$jXfMƢv25`i'LѼ."S]Ovګ9?*nm d"~>u.^ 럺~|FrN+܎}k٭RتKsXdR*~S1jDl[Tt[A8.uF'\yY u+oUwZ+UO8*"!h͚,;! ǴV+[ \]'Z܂g.J2(`fY5d,L]l;abIӭR <մ@_V_(&J +CQ%µD SmY8!r+5хs|zfg3zl'r%}ـ0 $Cf 2/zC﫪5֩$o ZD?jt[TXG|jT˞i; “Q|T,vo0MDNC;i< ),;U+sEz\[ +4ڿ l:R,8:j`fQl,ɔy*6~3}vs3!:%Hd3gOu?:Cgp 9r #N-4UӓzHx >;ЫM'Ԫ*~p\ud9 VsɮGX'b=q0qY, Y\I _f=%` Ųϭ}~[K竡gKggg_xՅrƵe0Z9煵r2GЭF^U^j9f+qy9z z#ɵ쑒؅ U(qm:n09V|!uRzw* IU508p0=w<8כa'!]rCA9dblTֱ x؋Rɴ%%U ޠF$QXK*ԗTi%k.ɭ 8mVdDkFTےleESA*&-H޼@ U _&3mAhXyL:$ʘ[! kXp Oer+?^6%z˽ZBy+Y2iG&=c=mi?xG}گgzxh O>UmȻssSf2FDq f|Z)ips3S͞%  i|~1m\pߨ"*|`=ðB%9Zl1^3Ō/iJmo]Z^dJ(۟\ێΕҥg6//߬l)Q4$m@utuP)SnC6 k 4:,m-Uwb՝%,0fJlYi ;BإYL{U t:RHK%$ >@恸ᫍ5Xyy Rr|O2 )$f`laq8'"̯n-R3XÄG⡒ɦE~ٙj!yo1_Y'#U_"(cM[vUXۖxe@ .D9x95\FόOD3P! K3DnVI'uW i3RYC5*RK)><&E C:D:jKl̔%F'3 Vpx@Άч)s'B!MS  D5ZE5L}جjaI' tra<0=B8lP|*vDgt⥴7njcͤ (%<$gnn|L\V̵nɽ p1FMB V뱭z`,%Zlww(Eb)9#9P공H Kj^Li#SOE[`l@Bh6f6:ϵKF)(g酪I)|M0c{DN?$[E_*o+/> !?He;7Y?U7ʵqGa%)U:>Y0x+1؞*icEu~Z,!%kl,k=9 PEpGFGgڶvE#;eoD9_:B= Nl=Jw;{G"B?P TF垬cqYZSUN 6/ %_vgup{&&C0= wf )-~u3u..ـ#>>֛qIA#TԑɗK9Gc>:WH4f%"` 9h+dh$8!rT0hj^G%y;Hj@x]zzA}R+xCZũ)WCOAHyyݖ 'm$\\Дt6T =o :GRXڥ_$(G#eOCŜ[I~zaYt׷c +!@ΝNOח1 EI `ͅMs=j0ܿxFP&\_H 9 D9xE6|(q=<aѷ؉#Zbzqz~R_V0Q2(i%6ap e:K2a:}OHw!fJز1M5MVS+JpRxKk˦.cV<*oI\.ozN @j[r w\\=2}v^^  EѲ57AKl 輂)n'+yBon@F_gDw}RVJP?c@(p-)W['8!#8n8g'Ao_9SLe#,- 8f'SgpE^U`t Ħy1i GlԒ&ae"FS+SMS1fwP` ȠFb mUwQ-zգ۪*aGuXhܦƠ'H&ǼṞI9Jtb*\Q j` @`B'Vs#Y'ErZT%G"lB @96".疗L3uG{=lc@t\.p|QDF7mgL <~fg; y6̎X\,l,x9Nr3/PNЄB URX >Y!NPQ2ۼу7#6PPeC"X  @E9eL5suȭ쪩jkؒ.V*HR{˭3K"y46AFIs%_7.$*T)PXw2@" ߝuP8~QBN10LKsYLx#4Y8Z=:үʗ 5kq1AGs6@=fJ(nDZ]2sҀCbeH< _ Jusf@Oi(h`>C?pIy9p$mAr\ZZiA H1Ft*g?hdTH+^MxNŝvTJKj= +$>%T0R%oTwA{\إ<="@ v$sxI.^%ZT7U Z:&ظ4a0(*!af>7yJ+mi5ra7r˅IhWNtvWp%G9!*hq%*O#tޙ:4=iD'HFP.:DH"IV@e gcYDAbJX™㻋"D|bŀbB,:c F= |GG#[Xw|s*B 9(@GAG҂#NhLg5D*𩩝\kHp;Q24WYbᰏ>v9 /*%`*s٘n7(H5ȓ! M3<cs^Q dq+<@5B&\#ViԪtdʯ}v[YPmoSń˨bM?38n6SX@KX0(b01K8 \Y e MZ|8A5<YQ!uI:ФV#LB|h7(w44`ƾY\īDlEIH Qrp!؋;Y½PpQh^'S>g־3U":8:Jd.G#еPcMM(xv/n}($WKɄrVЋ}K [8FH%.> wf1xJsafBv nskmʎOF: HEP`EXSZ16l`;=[ftTHw9;Jv$x\#ʕ n\ mQ3!Fc)<|GPn1y0@ S!HNzPN01(QWv;s6,O:!Er/4{x>YF#](VP qC,R6v敋Thf5(uy9){d ʐQ> '_ c.TlTܦiIPk Zs8x1ayn>]Z3nIӠ6AG, h.P%U۸,+,䔭 (!{Δ iFAPF b/" &%KA sƶg}95,i 8'3&=Qk.RB0N/KPqwFDPLނ.+Ya_BGoJE!LʉnAXŤGv@(2HJfS[޶`MB:GiȃUI"4ːZ4փŵ@fZ%PIQI#=AT.deKf~ۅ: |xpAW@0a|](p:B#wRHН\8rIM3> Mơ#Jd  ,lt^70:btάp3HTF=hBU<9<^X7Զha W+VMN/P 4v7>`^|>awcg|^b-J k1gH=Dw}5SQVtk4Ab G^ 7*>ЯqC{\$czl&XԔ)B8 pSj(L5c,i׽:ž8RiL(EzB*"vS|%wx!i` ,TcRِ@0 3Nbf!>s?rnBe8Ótt*:,XIQBjB ,c.B:M֜f(R"t/}U>Io:ngŴ9$na&&pd`wܢ(/磍 V6ZtAl%ZLG?PL|Y ǠѓKjS +e,SƐF; ȘM8Is&73Arԫ" vx2'MB_pƋJ?O8WrCvIHq=ea뒽gYj}[yQ.:25iJwNd˔[>AN`qD?R0;UM WCZA:/G{r67(WDAr$^yP@坈N ߗ v;`pEn fyS:< #瀀=S њ8xDFtQ(x1esV9y" Ć1tlaj 2Z&+K*.cpz\gͲ848S Q,If6`.G9ʻ;N좃TD;w%?zep1Xz ZFbZ&f=CYU)速,&ԑPa.؞766 FH=ړ7#La$E+x)q1gX)t˝lz1'ZZ$P@ `΂aS@D YlGz3\#0uAPP|\ i` M/EcNC"4 ?} @WRh)u7^|p$EAaR:͈iȠbABɊ(Gv49`IHa !hX]BwH춳`tJu!0c+"ցxB(IB-4Q26z_Opg8P~7$͏ Q [gL)[P̸:<<0hG@㴪 qabU`Ԝ5DjMCon烫W#UA%-SumeYX&R lu 8n".+ܪY<"XɬОkj ڛ#6UGHAGG=\ۗBҦAvGD9jP`rEGF|wK׃a%|}P0 (ipxq˗EFt#QK-9 0Q%d. t J~<IENDB`jexcelapi/resources/functions_en.properties0000750000175000017500000001021111016653676021544 0ustar drazzibdrazzib# The default names (the English) for all function names in java abs=ABS absref=ABSREF acos=ACOS acosh=ACOSH address=ADDRESS and=AND areas=AREAS argument=ARGUMENT asc=ASC asin=ASIN asinh=ASINH atan=ATAN atan2=ATAN2 atanh=ATANH avedev=AVEDEV average=AVERAGE averagea=AVERAGEA betadist=BETADIST betainv=BETAINV binomdist=BINOMDIST call=CALL caller=CALLER ceiling=CEILING cell=CELL char=CHAR chidist=CHIDIST chiinv=CHIINV chitest=CHITEST choose=CHOOSE clean=CLEAN code=CODE column=COLUMN columns=COLUMNS combin=COMBIN concatenate=CONCATENATE confidence=CONFIDENCE correl=CORREL cos=COS cosh=COSH count=COUNT counta=COUNTA countblank=COUNTBLANK countif=COUNTIF covar=COVAR critbinom=CRITBINOM date=DATE datedif=DATEDIF datestring=DATESTRING datevalue=DATEVALUE daverage=DAVERAGE day=DAY days360=DAYS360 db=DB dbcs=DBCS dcount=DCOUNT dcounta=DCOUNTA ddb=DDB degrees=DEGREES deref=DEREF devsq=DEVSQ dget=DGET directory=DIRECTORY dmax=DMAX dmin=DMIN documents=DOCUMENTS dollar=DOLLAR dproduct=DPRODUCT dstdev=DSTDEV dstdevp=DSTDEVP dsum=DSUM dvar=DVAR dvarp=DVARP echo=ECHO error=ERROR evaluate=EVALUATE even=EVEN exact=EXACT exec=EXEC execute=EXECUTE exp=EXP expondist=EXPONDIST fact=FACT fclose=FCLOSE fdist=FDIST files=FILES find=FIND findb=FINDB finv=FINV fisher=FISHER fisherinv=FISHERINV fixed=FIXED floor=FLOOR fopen=FOPEN forecast=FORECAST fpos=FPOS fread=FREAD freadln=FREADLN frequency=FREQUENCY fsize=FSIZE ftest=FTEST fv=FV fwrite=FWRITE fwriteln=FWRITELN gammadist=GAMMADIST gammainv=GAMMAINV gammaln=GAMMALN geomean=GEOMEAN goto=GOTO group=GROUP growth=GROWTH halt=HALT harmean=HARMEAN help=HELP hlookup=HLOOKUP hour=HOUR hyperlink=HYPERLINK hypgeomdist=HYPGEOMDIST if=IF index=INDEX indirect=INDIRECT info=INFO initiate=INITIATE input=INPUT int=INT intercept=INTERCEPT ipmt=IPMT irr=IRR isblank=ISBLANK iserr=ISERR iserror=ISERROR islogical=ISLOGICAL isna=ISNA isnontext=ISNONTEXT isnumber=ISNUMBER ispmt=ISPMT isref=ISREF istext=ISTEXT kurt=KURT large=LARGE left=LEFT leftb=LEFTB len=LEN lenb=LENB linest=LINEST links=LINKS ln=LN log=LOG log10=LOG10 logest=LOGEST loginv=LOGINV lognormdist=LOGNORMDIST lookup=LOOKUP lower=LOWER match=MATCH max=MAX maxa=MAXA mdeterm=MDETERM median=MEDIAN mid=MID midb=MIDB min=MIN mina=MINA minute=MINUTE minverse=MINVERSE mirr=MIRR mmult=MMULT mod=MOD mode=MODE month=MONTH n=N na=NA names=NAMES negbinomdist=NEGBINOMDIST normdist=NORMDIST norminv=NORMINV normsdist=NORMSDIST normsinv=NORMSINV not=NOT note=NOTE now=NOW nper=NPER npv=NPV numberstring=NUMBERSTRING odd=ODD offset=OFFSET or=OR pause=PAUSE pearson=PEARSON percentile=PERCENTILE percentrank=PERCENTRANK permut=PERMUT pi=PI pmt=PMT poisson=POISSON poke=POKE power=POWER ppmt=PPMT prob=PROB product=PRODUCT proper=PROPER pv=PV quartile=QUARTILE radians=RADIANS rand=RAND rank=RANK rate=RATE reftext=REFTEXT register=REGISTER relref=RELREF replace=REPLACE replaceb=REPLACEB rept=REPT request=REQUEST restart=RESTART result=RESULT resume=RESUME right=RIGHT rightb=RIGHTB roman=ROMAN round=ROUND rounddown=ROUNDDOWN roundup=ROUNDUP row=ROW rows=ROWS rsq=RSQ search=SEARCH searchb=SEARCHB second=SECOND selection=SELECTION series=SERIES sign=SIGN sin=SIN sinh=SINH skew=SKEW sln=SLN slope=SLOPE small=SMALL sqrt=SQRT standardize=STANDARDIZE stdev=STDEV stdeva=STDDEVA stdevp=STDEVP stdevpa=STDDEVPA step=STEP steyx=STEYX substitute=SUBSTITUTE subtotal=SUBTOTAL sum=SUM sumif=SUMIF sumproduct=SUMPRODUCT sumsq=SUMSQ sumx2my2=SUMX2MY2 sumx2py2=SUMX2PY2 sumxmy2=SUMXMY2 syd=SYD t=T tan=TAN tanh=TANH tdist=TDIST terminate=TERMINATE text=TEXT textref=TEXTREF time=TIME timevalue=TIMEVALUE tinv=TINV today=TODAY transpose=TRANSPOSE trend=TREND trim=TRIM trimmean=TRIMMEAN trunc=TRUNC ttest=TTEST type=TYPE unregister=UNREGISTER upper=UPPER usdollar=USDOLLAR value=VALUE var=VAR vara=VARA varp=VARP varpa=VARPA vdb=VDB vlookup=VLOOKUP volatile=VOLATILE weekday=WEEKDAY weibull=WEIBULL windows=WINDOWS year=YEAR ztest=ZTEST false=FALSE true=TRUE jexcelapi/index.html0000750000175000017500000002310011016653672014714 0ustar drazzibdrazzib A Java API to read, write and modify Excel spreadsheets

Java Excel API - A Java API to read, write and modify Excel spreadsheets

This is the home page of Java Excel API - open source Java API which allows Java developers to read Excel spreadsheets and to generate Excel spreadsheets dynamically. In addition, it contains a mechanism which allows java applications to read in a spreadsheet, modify some cells and write out the new spreadsheet.

This API allows non Windows operating systems to run pure Java applications which can both process and deliver Excel spreadsheets. Because it is Java, this API may be invoked from within a servlet, thus giving access to Excel functionality over internet and intranet web applications.

Features

  • Reads data from Excel 95, 97, 2000 workbooks
  • Reads and writes formulas (Excel 97 and later only)
  • Generates spreadsheets in Excel 2000 format
  • Supports font, number and date formatting
  • Supports shading and colouring of cells
  • Modifies existing worksheets
  • Supports image creation
  • Preserves macros on copy
  • Customizable logging
  • Limitations

  • JExcelApi does not generate or chart, graph or macro information. This information is however preserved when spreadsheets are copied
  • When adding images to a sheet, only PNG image formats are supported
  • Getting started

    The distribution comes with a number of demo programs which illustrate how the API may be used.

    Reading Spreadsheets

    When reading a spreadsheet, the demo programs may be used "as is" to convert Excel files to CSV and XML formats in a reasonable manner.

    java -jar jxl.jar -csv myspreadsheet.xls

    To view the spreadsheet as XML, invoke the demo as follows

    java -jar jxl.jar -xml myspreadsheet.xls

    In order to present the data the demo uses the classes xlrd/CSV.java and xlrd/XML.java respectively. For more sophisticated processing, these classes may be used as a starting point. Click here for a tutorial.

    Generating Spreadsheets

    The write demo illustrates the functionality accessible within JExcelApi to generate spreadsheets. The spreadsheet generated by the demo includes different fonts, number formatting, date formatting, colours and borders.

    To generate the demo spreadsheet, invoke JExcelApi as follows:

    java -jar jxl.jar -write myspreadsheet.xls

    This will generate the sample spreadsheet called myspreadsheet.xls in the current working directory. The class used to generate this spreadheet is jxl/Write.java. This may be used as a starting point for bespoke processing.

    Copying Spreadsheets

    JExcelApi may be used to copy and modify a spreadsheet. Included with the JExcelApi is a spreadsheet called jxlrwtest.xls, which is hardcoded into the demo program. If this spreadsheet is passed as a command line argument to the demo, then a copy of this spreadsheet will be generated, with the second sheet containing modified values.

    DO NOT MODIFY THE DEMO SPREADSHEET otherwise the modification demo will not work.

    To run this demo, from the directory containing jxlrwtest.xls type

    java -jar jxl.jar -rw jxlrwtest.xls myoutput.xls

    This will generate an output spreadsheet called myoutput.xls. The first sheet (called "original") is unchanged, but the second sheet (called "modified" has had its cell contents changed, as indicated by the labels.

    The class for the modification demo is jxl/ReadWrite.java.

    Requirements

    JExcelApi requires Java 2 JDK to run.

    When dealing with large spreadsheets, particularly when using the copy functionality, it is recommended that users allocate sufficient memory to the JVM using the -Xms and -Xmx options on the java command line.

    Installation

    JExcelApi comes packaged as a zipped tar file, called something like jexcelapi_2_0.tar.gz. To unpack on UNIX systems, at the command line type

    gunzip jexcelapi_2_0.tar.gz      followed by
    tar xf jexcelapi_2_0.tar

    On Linux systems this can be accomplished within the single command

    tar zxf jexcelapi_2_0.tar.gz

    On Windows/NT systems, the archive may be unpacked visually using a utility such as Winzip.

    Whatever the unpacking process, the application will be placed in a subdirectory called jexcelapi. The top level directory contains this html page and the pre-built jar file, jxl.jar. The docs directory contains the javadoc documentation for the public classes, the build directory contains the buildfile (requires ant ) and the src directory contains the source code for the java classes.

    Excel Versions

    JExcelApi will read workbooks created in Excel 95, 97 and 2000, and will generate workbooks that can be read by Excel 97 and later.

    Licensing

    JExcelApi is issued on under the GNU Lesser General Public License. For further information click here.

    Further Notes

    A tutorial is available for those who wish guidance on how to use the API for reading, writing and copying spreadsheets.

    When writing out spreadsheets, JExcelApi has limited support for graphs charts and macros during the copy process, but they cannot be created via the API.

    For further technical information, including how JExcelApi handles dates and unicode characters, read the technical notes

    Download JExcelApi

    Change History



    I endeavour to answer all emails, but it's taking up more and more time. Before emailing me with a question please check the FAQ first.

    Eric Jung has set up a yahoo group  here. As well as providing a discussion forum I will also post a message to this group whenever a new version of JExcelApi is released.

    Please check out these resources before emailing me - if I can keep the amount of time spent answering emails to a reasonable level then I can still expend effort on enhancing the software.
    Contact me

    Stefano has ported JExcelApi to .net. You can access the software here

    Make a Donation

    JExcelApi is free software and will remain so. If JExcelApi has been of benefit to you or your company, perhaps you might like to make a voluntary donation to JExcelApi using PayPal

    Return to my home directory

    This site last updated 10th April, 2005

    jexcelapi/.classpath0000750000175000017500000000046711016653670014713 0ustar drazzibdrazzib jexcelapi/.project0000750000175000017500000000062011016653670014366 0ustar drazzibdrazzib excelClassExceptionDebug org.eclipse.jdt.core.javabuilder org.eclipse.jdt.core.javanature jexcelapi/formatworkbook.dtd0000750000175000017500000000246111016653672016471 0ustar drazzibdrazzib jexcelapi/src/0000750000175000017500000000000011207000610013463 5ustar drazzibdrazzibjexcelapi/src/jxl/0000750000175000017500000000000011270605332014274 5ustar drazzibdrazzibjexcelapi/src/jxl/Sheet.java0000750000175000017500000002102111207000610016172 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl; import java.util.regex.Pattern; import jxl.format.CellFormat; /** * Represents a sheet within a workbook. Provides a handle to the individual * cells, or lines of cells (grouped by Row or Column) */ public interface Sheet { /** * Returns the cell specified at this row and at this column. * If a column/row combination forms part of a merged group of cells * then (unless it is the first cell of the group) a blank cell * will be returned * * @param column the column number * @param row the row number * @return the cell at the specified co-ordinates */ public Cell getCell(int column, int row); /** * Returns the cell for the specified location eg. "A4". Note that this * method is identical to calling getCell(CellReferenceHelper.getColumn(loc), * CellReferenceHelper.getRow(loc)) and its implicit performance * overhead for string parsing. As such,this method should therefore * be used sparingly * * @param loc the cell reference * @return the cell at the specified co-ordinates */ public Cell getCell(String loc); /** * Returns the number of rows in this sheet * * @return the number of rows in this sheet */ public int getRows(); /** * Returns the number of columns in this sheet * * @return the number of columns in this sheet */ public int getColumns(); /** * Gets all the cells on the specified row * * @param row the rows whose cells are to be returned * @return the cells on the given row */ public Cell[] getRow(int row); /** * Gets all the cells on the specified column * * @param col the column whose cells are to be returned * @return the cells on the specified column */ public Cell[] getColumn(int col); /** * Gets the name of this sheet * * @return the name of the sheet */ public String getName(); /** * Determines whether the sheet is hidden * * @return whether or not the sheet is hidden * @deprecated in favour of the getSettings() method */ public boolean isHidden(); /** * Determines whether the sheet is protected * * @return whether or not the sheet is protected * @deprecated in favour of the getSettings() method */ public boolean isProtected(); /** * Gets the cell whose contents match the string passed in. * If no match is found, then null is returned. The search is performed * on a row by row basis, so the lower the row number, the more * efficiently the algorithm will perform * * @param contents the string to match * @return the Cell whose contents match the paramter, null if not found */ public Cell findCell(String contents); /** * Gets the cell whose contents match the string passed in. * If no match is found, then null is returned. The search is performed * on a row by row basis, so the lower the row number, the more * efficiently the algorithm will perform * * @param contents the string to match * @param firstCol the first column within the range * @param firstRow the first row of the range * @param lastCol the last column within the range * @param lastRow the last row within the range * @param reverse indicates whether to perform a reverse search or not * @return the Cell whose contents match the parameter, null if not found */ public Cell findCell(String contents, int firstCol, int firstRow, int lastCol, int lastRow, boolean reverse); /** * Gets the cell whose contents match the regular expressionstring passed in. * If no match is found, then null is returned. The search is performed * on a row by row basis, so the lower the row number, the more * efficiently the algorithm will perform * * @param pattern the regular expression string to match * @param firstCol the first column within the range * @param firstRow the first row of the rang * @param lastCol the last column within the range * @param lastRow the last row within the range * @param reverse indicates whether to perform a reverse search or not * @return the Cell whose contents match the parameter, null if not found */ public Cell findCell(Pattern pattern, int firstCol, int firstRow, int lastCol, int lastRow, boolean reverse); /** * Gets the cell whose contents match the string passed in. * If no match is found, then null is returned. The search is performed * on a row by row basis, so the lower the row number, the more * efficiently the algorithm will perform. This method differs * from the findCell method in that only cells with labels are * queried - all numerical cells are ignored. This should therefore * improve performance. * * @param contents the string to match * @return the Cell whose contents match the paramter, null if not found */ public LabelCell findLabelCell(String contents); /** * Gets the hyperlinks on this sheet * * @return an array of hyperlinks */ public Hyperlink[] getHyperlinks(); /** * Gets the cells which have been merged on this sheet * * @return an array of range objects */ public Range[] getMergedCells(); /** * Gets the settings used on a particular sheet * * @return the sheet settings */ public SheetSettings getSettings(); /** * Gets the column format for the specified column * * @param col the column number * @return the column format, or NULL if the column has no specific format * @deprecated Use getColumnView and the CellView bean instead */ public CellFormat getColumnFormat(int col); /** * Gets the column width for the specified column * * @param col the column number * @return the column width, or the default width if the column has no * specified format * @deprecated Use getColumnView instead */ public int getColumnWidth(int col); /** * Gets the column width for the specified column * * @param col the column number * @return the column format, or the default format if no override is specified */ public CellView getColumnView(int col); /** * Gets the row height for the specified column * * @param row the row number * @return the row height, or the default height if the column has no * specified format * @deprecated use getRowView instead */ public int getRowHeight(int row); /** * Gets the row height for the specified column * * @param row the row number * @return the row format, which may be the default format if no format * is specified */ public CellView getRowView(int row); /** * Accessor for the number of images on the sheet * * @return the number of images on this sheet */ public int getNumberOfImages(); /** * Accessor for the image * * @param i the 0 based image number * @return the image at the specified position */ public Image getDrawing(int i); /** * Accessor for the page breaks on this sheet * * @return the page breaks on this sheet */ public int[] getRowPageBreaks(); /** * Accessor for the page breaks on this sheet * * @return the page breaks on this sheet */ public int[] getColumnPageBreaks(); } jexcelapi/src/jxl/StringFormulaCell.java0000750000175000017500000000216711207000610020530 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl; /** * A mixin interface for numerical formulas, which combines the interfaces * for formulas and for strings */ public interface StringFormulaCell extends LabelCell, FormulaCell { } jexcelapi/src/jxl/HeaderFooter.java0000750000175000017500000002175511207000610017507 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan, Eric Jung * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl; /** * Class which represents an Excel header or footer. */ public final class HeaderFooter extends jxl.biff.HeaderFooter { /** * The contents - a simple wrapper around a string buffer */ public static class Contents extends jxl.biff.HeaderFooter.Contents { /** * The constructor */ Contents() { super(); } /** * Constructor used when reading worksheets. The string contains all * the formatting (but not alignment characters * * @param s the format string */ Contents(String s) { super(s); } /** * Copy constructor * * @param copy the contents to copy */ Contents(Contents copy) { super(copy); } /** * Appends the text to the string buffer * * @param txt the text to append */ public void append(String txt) { super.append(txt); } /** * Turns bold printing on or off. Bold printing * is initially off. Text subsequently appended to * this object will be bolded until this method is * called again. */ public void toggleBold() { super.toggleBold(); } /** * Turns underline printing on or off. Underline printing * is initially off. Text subsequently appended to * this object will be underlined until this method is * called again. */ public void toggleUnderline() { super.toggleUnderline(); } /** * Turns italics printing on or off. Italics printing * is initially off. Text subsequently appended to * this object will be italicized until this method is * called again. */ public void toggleItalics() { super.toggleItalics(); } /** * Turns strikethrough printing on or off. Strikethrough printing * is initially off. Text subsequently appended to * this object will be striked out until this method is * called again. */ public void toggleStrikethrough() { super.toggleStrikethrough(); } /** * Turns double-underline printing on or off. Double-underline printing * is initially off. Text subsequently appended to * this object will be double-underlined until this method is * called again. */ public void toggleDoubleUnderline() { super.toggleDoubleUnderline(); } /** * Turns superscript printing on or off. Superscript printing * is initially off. Text subsequently appended to * this object will be superscripted until this method is * called again. */ public void toggleSuperScript() { super.toggleSuperScript(); } /** * Turns subscript printing on or off. Subscript printing * is initially off. Text subsequently appended to * this object will be subscripted until this method is * called again. */ public void toggleSubScript() { super.toggleSubScript(); } /** * Turns outline printing on or off (Macintosh only). * Outline printing is initially off. Text subsequently appended * to this object will be outlined until this method is * called again. */ public void toggleOutline() { super.toggleOutline(); } /** * Turns shadow printing on or off (Macintosh only). * Shadow printing is initially off. Text subsequently appended * to this object will be shadowed until this method is * called again. */ public void toggleShadow() { super.toggleShadow(); } /** * Sets the font of text subsequently appended to this * object.. Previously appended text is not affected. *

    * Note: no checking is performed to * determine if fontName is a valid font. * * @param fontName name of the font to use */ public void setFontName(String fontName) { super.setFontName(fontName); } /** * Sets the font size of text subsequently appended to this * object. Previously appended text is not affected. *

    * Valid point sizes are between 1 and 99 (inclusive). If * size is outside this range, this method returns false * and does not change font size. If size is within this * range, the font size is changed and true is returned. * * @param size The size in points. Valid point sizes are * between 1 and 99 (inclusive). * @return true if the font size was changed, false if font * size was not changed because 1 > size > 99. */ public boolean setFontSize(int size) { return super.setFontSize(size); } /** * Appends the page number */ public void appendPageNumber() { super.appendPageNumber(); } /** * Appends the total number of pages */ public void appendTotalPages() { super.appendTotalPages(); } /** * Appends the current date */ public void appendDate() { super.appendDate(); } /** * Appends the current time */ public void appendTime() { super.appendTime(); } /** * Appends the workbook name */ public void appendWorkbookName() { super.appendWorkbookName(); } /** * Appends the worksheet name */ public void appendWorkSheetName() { super.appendWorkSheetName(); } /** * Clears the contents of this portion */ public void clear() { super.clear(); } /** * Queries if the contents are empty * * @return TRUE if the contents are empty, FALSE otherwise */ public boolean empty() { return super.empty(); } } /** * Default constructor. */ public HeaderFooter() { super(); } /** * Copy constructor * * @param hf the item to copy */ public HeaderFooter(HeaderFooter hf) { super(hf); } /** * Constructor used when reading workbooks to separate the left, right * a central part of the strings into their constituent parts * * @param s the header string */ public HeaderFooter(String s) { super(s); } /** * Retrieves a Stringified * version of this object * * @return the header string */ public String toString() { return super.toString(); } /** * Accessor for the contents which appear on the right hand side of the page * * @return the right aligned contents */ public Contents getRight() { return (Contents) super.getRightText(); } /** * Accessor for the contents which in the centre of the page * * @return the centrally aligned contents */ public Contents getCentre() { return (Contents) super.getCentreText(); } /** * Accessor for the contents which appear on the left hand side of the page * * @return the left aligned contents */ public Contents getLeft() { return (Contents) super.getLeftText(); } /** * Clears the contents of the header/footer */ public void clear() { super.clear(); } /** * Creates internal class of the appropriate type * * @return the created contents */ protected jxl.biff.HeaderFooter.Contents createContents() { return new Contents(); } /** * Creates internal class of the appropriate type * * @param s the string to create the contents * @return the created contents */ protected jxl.biff.HeaderFooter.Contents createContents(String s) { return new Contents(s); } /** * Creates internal class of the appropriate type * * @param c the contents to copy * @return the new contents */ protected jxl.biff.HeaderFooter.Contents createContents(jxl.biff.HeaderFooter.Contents c) { return new Contents((Contents) c); } } jexcelapi/src/jxl/Image.java0000750000175000017500000000663511207000610016162 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2004 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl; import jxl.common.LengthUnit; import java.io.File; /** * Accessor functions for an image */ public interface Image { /** * Accessor for the image position * * @return the column number at which the image is positioned */ public double getColumn(); /** * Accessor for the image position * * @return the row number at which the image is positioned */ public double getRow(); /** * Accessor for the image dimensions * * @return the number of columns this image spans */ public double getWidth(); /** * Accessor for the image dimensions * * @return the number of rows which this image spans */ public double getHeight(); /** * Accessor for the image file * * @return the file which the image references */ public File getImageFile(); /** * Accessor for the image data * * @return the image data */ public byte[] getImageData(); /** * Get the width of this image as rendered within Excel * * @param unit the unit of measurement * @return the width of the image within Excel */ public double getWidth(LengthUnit unit); /** * Get the height of this image as rendered within Excel * * @param unit the unit of measurement * @return the height of the image within Excel */ public double getHeight(LengthUnit unit); /** * Gets the width of the image. Note that this is the width of the * underlying image, and does not take into account any size manipulations * that may have occurred when the image was added into Excel * * @return the image width in pixels */ public int getImageWidth(); /** * Gets the height of the image. Note that this is the height of the * underlying image, and does not take into account any size manipulations * that may have occurred when the image was added into Excel * * @return the image height in pixels */ public int getImageHeight(); /** * Gets the horizontal resolution of the image, if that information * is available. * * @return the number of dots per unit specified, if available, 0 otherwise */ public double getHorizontalResolution(LengthUnit unit); /** * Gets the vertical resolution of the image, if that information * is available. * * @return the number of dots per unit specified, if available, 0 otherwise */ public double getVerticalResolution(LengthUnit unit); } jexcelapi/src/jxl/CellReferenceHelper.java0000750000175000017500000002021211232307321020770 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl; import jxl.write.WritableWorkbook; /** * Exposes some cell reference helper methods to the public interface. * This class merely delegates to the internally used reference helper */ public final class CellReferenceHelper { /** * Hide the default constructor */ private CellReferenceHelper() { } /** * Appends the cell reference for the column and row passed in to the string * buffer * * @param column the column * @param row the row * @param buf the string buffer to append */ public static void getCellReference(int column, int row, StringBuffer buf) { jxl.biff.CellReferenceHelper.getCellReference(column, row, buf); } /** * Overloaded method which prepends $ for absolute reference * * @param column the column number * @param colabs TRUE if the column reference is absolute * @param row the row number * @param rowabs TRUE if the row reference is absolute * @param buf the string buffer */ public static void getCellReference(int column, boolean colabs, int row, boolean rowabs, StringBuffer buf) { jxl.biff.CellReferenceHelper.getCellReference(column, colabs, row, rowabs, buf); } /** * Gets the cell reference for the specified column and row * * @param column the column * @param row the row * @return the cell reference */ public static String getCellReference(int column, int row) { return jxl.biff.CellReferenceHelper.getCellReference(column, row); } /** * Gets the columnn number of the string cell reference * * @param s the string to parse * @return the column portion of the cell reference */ public static int getColumn(String s) { return jxl.biff.CellReferenceHelper.getColumn(s); } /** * Gets the column letter corresponding to the 0-based column number * * @param c the column number * @return the letter for that column number */ public static String getColumnReference(int c) { return jxl.biff.CellReferenceHelper.getColumnReference(c); } /** * Gets the row number of the cell reference * @param s the cell reference * @return the row number */ public static int getRow(String s) { return jxl.biff.CellReferenceHelper.getRow(s); } /** * Sees if the column component is relative or not * * @param s the cell * @return TRUE if the column is relative, FALSE otherwise */ public static boolean isColumnRelative(String s) { return jxl.biff.CellReferenceHelper.isColumnRelative(s); } /** * Sees if the row component is relative or not * * @param s the cell * @return TRUE if the row is relative, FALSE otherwise */ public static boolean isRowRelative(String s) { return jxl.biff.CellReferenceHelper.isRowRelative(s); } /** * Gets the fully qualified cell reference given the column, row * external sheet reference etc * * @param sheet the sheet index * @param column the column index * @param row the row index * @param workbook the workbook * @param buf a string buffer */ public static void getCellReference (int sheet, int column, int row, Workbook workbook, StringBuffer buf) { jxl.biff.CellReferenceHelper.getCellReference (sheet, column, row, (jxl.biff.formula.ExternalSheet) workbook, buf); } /** * Gets the fully qualified cell reference given the column, row * external sheet reference etc * * @param sheet the sheet * @param column the column * @param row the row * @param workbook the workbook * @param buf the buffer */ public static void getCellReference(int sheet, int column, int row, WritableWorkbook workbook, StringBuffer buf) { jxl.biff.CellReferenceHelper.getCellReference (sheet, column, row, (jxl.biff.formula.ExternalSheet) workbook, buf); } /** * Gets the fully qualified cell reference given the column, row * external sheet reference etc * * @param sheet the sheet * @param column the column * @param colabs TRUE if the column is an absolute reference * @param row the row * @param rowabs TRUE if the row is an absolute reference * @param workbook the workbook * @param buf the string buffer */ public static void getCellReference (int sheet, int column, boolean colabs, int row, boolean rowabs, Workbook workbook, StringBuffer buf) { jxl.biff.CellReferenceHelper.getCellReference (sheet, column, colabs, row, rowabs, (jxl.biff.formula.ExternalSheet) workbook, buf); } /** * Gets the fully qualified cell reference given the column, row * external sheet reference etc * * @param sheet the sheet * @param column the column * @param row the row * @param workbook the workbook * @return the cell reference in the form 'Sheet 1'!A1 */ public static String getCellReference (int sheet, int column, int row, Workbook workbook) { return jxl.biff.CellReferenceHelper.getCellReference (sheet, column, row, (jxl.biff.formula.ExternalSheet) workbook); } /** * Gets the fully qualified cell reference given the column, row * external sheet reference etc * * @param sheet the sheet * @param column the column * @param row the row * @param workbook the workbook * @return the cell reference in the form 'Sheet 1'!A1 */ public static String getCellReference(int sheet, int column, int row, WritableWorkbook workbook) { return jxl.biff.CellReferenceHelper.getCellReference (sheet, column, row, (jxl.biff.formula.ExternalSheet) workbook); } /** * Gets the sheet name from the cell reference string * * @param ref the cell reference * @return the sheet name */ public static String getSheet(String ref) { return jxl.biff.CellReferenceHelper.getSheet(ref); } /** * Gets the cell reference for the cell * * @param the cell */ public static String getCellReference(Cell c) { return getCellReference(c.getColumn(), c.getRow()); } /** * Gets the cell reference for the cell * * @param c the cell * @param sb string buffer */ public static void getCellReference(Cell c, StringBuffer sb) { getCellReference(c.getColumn(), c.getRow(), sb); } } jexcelapi/src/jxl/BooleanCell.java0000750000175000017500000000317711207000610017315 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl; /** * This type represents the Microsoft concept of a Boolean. Accordingly, this * cell represents either TRUE, FALSE or an error condition. This third * state naturally makes handling BooleanCells quite tricky, and use of * the specific access methods should be handled with care */ public interface BooleanCell extends Cell { /** * Gets the boolean value stored in this cell. If this cell contains an * error, then returns FALSE. Always query this cell type using the * accessor method isError() prior to calling this method * * @return TRUE if this cell contains TRUE, FALSE if it contains FALSE or * an error code */ public boolean getValue(); } jexcelapi/src/jxl/FormulaCell.java0000750000175000017500000000247611207000610017344 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl; import jxl.biff.formula.FormulaException; /** * Interface for formulas which allow clients to read the Excel formula */ public interface FormulaCell extends Cell { /** * Gets the formula as a string * * @return the formula as a string * @exception FormulaException if an error occurred whilst parsing */ public String getFormula() throws FormulaException; } jexcelapi/src/jxl/LabelCell.java0000750000175000017500000000231611207000610016747 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl; /** * A label cell */ public interface LabelCell extends Cell { /** * Gets the label for this cell. The value returned will be the same * as for the getContents method in the base class * * @return the cell contents */ public String getString(); } jexcelapi/src/jxl/ErrorCell.java0000750000175000017500000000271111207000610017020 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl; /** * This type represents a cell which contains an error. This error will * usually, but not always be the result of some error resulting from * a formula */ public interface ErrorCell extends Cell { /** * Gets the error code for this cell. If this cell does not represent * an error, then it returns 0. Always use the method isError() to * determine this prior to calling this method * * @return the error code if this cell contains an error, 0 otherwise */ public int getErrorCode(); } jexcelapi/src/jxl/CellView.java0000750000175000017500000001152211207000610016641 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl; import jxl.format.CellFormat; /** * This is a bean which client applications may use to get/set various * properties for a row or column on a spreadsheet */ public final class CellView { /** * The dimension for the associated group of cells. For columns this * will be width in characters, for rows this will be the * height in points * This attribute is deprecated in favour of the size attribute */ private int dimension; /** * The size for the associated group of cells. For columns this * will be width in characters multiplied by 256, for rows this will be the * height in points */ private int size; /** * Indicates whether the deprecated function was used to set the dimension */ private boolean depUsed; /** * Indicates whether or not this sheet is hidden */ private boolean hidden; /** * The cell format for the row/column */ private CellFormat format; /** * Indicates that this column/row should be autosized */ private boolean autosize; /** * Default constructor */ public CellView() { hidden = false; depUsed = false; dimension = 1; size = 1; autosize = false; } /** * Copy constructor */ public CellView(CellView cv) { hidden = cv.hidden; depUsed = cv.depUsed; dimension = cv.dimension; size = cv.size; autosize = cv.autosize; } /** * Sets the hidden status of this row/column * * @param h the hidden flag */ public void setHidden(boolean h) { hidden = h; } /** * Accessor for the hidden nature of this row/column * * @return TRUE if this row/column is hidden, FALSE otherwise */ public boolean isHidden() { return hidden; } /** * Sets the dimension for this view * * @param d the width of the column in characters, or the height of the * row in 1/20ths of a point * @deprecated use the setSize method instead */ public void setDimension(int d) { dimension = d; depUsed = true; } /** * Sets the dimension for this view * * @param d the width of the column in characters multiplied by 256, * or the height of the row in 1/20ths of a point */ public void setSize(int d) { size = d; depUsed = false; } /** * Gets the width of the column in characters or the height of the * row in 1/20ths * * @return the dimension * @deprecated use getSize() instead */ public int getDimension() { return dimension; } /** * Gets the width of the column in characters multiplied by 256, or the * height of the row in 1/20ths of a point * * @return the dimension */ public int getSize() { return size; } /** * Sets the cell format for this group of cells * * @param cf the format for every cell in the column/row */ public void setFormat(CellFormat cf) { format = cf; } /** * Accessor for the cell format for this group. * * @return the format for the column/row, or NULL if no format was * specified */ public CellFormat getFormat() { return format; } /** * Accessor for the depUsed attribute * * @return TRUE if the deprecated methods were used to set the size, * FALSE otherwise */ public boolean depUsed() { return depUsed; } /** * Sets the autosize flag. Currently, this only works for column views * * @param a autosize */ public void setAutosize(boolean a) { autosize = a; } /** * Accessor for the autosize flag * NOTE: use of the autosize function is very processor intensive, so * use with care * * @return TRUE if this row/column is to be autosized */ public boolean isAutosize() { return autosize; } } jexcelapi/src/jxl/write/0000750000175000017500000000000011270605332015426 5ustar drazzibdrazzibjexcelapi/src/jxl/write/BoldStyle.java0000750000175000017500000000224311207000610020162 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write; /** * Enumeration class containing the various bold styles for data */ public final class BoldStyle extends jxl.format.BoldStyle { /** * Constructor * * @param val a dummy value */ private BoldStyle(int val) { super(0, ""); } } jexcelapi/src/jxl/write/NumberFormats.java0000750000175000017500000002057111207000610021051 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write; import jxl.biff.DisplayFormat; import jxl.format.Format; /** * Static class which contains the available list of built in Number formats */ public final class NumberFormats { /** * Inner class which holds the format index */ private static class BuiltInFormat implements DisplayFormat, Format { /** * The built in number format index */ private int index; /** * The format string */ private String formatString; /** * Constructor, using the predetermined index * * @param i the index * @param s the string */ public BuiltInFormat(int i, String s) { index = i; formatString = s; } /** * Accessor for the format index * * @return the index */ public int getFormatIndex() { return index; } /** * Accessor to determine if this format has been initialized. Since it is * built in, this will always return TRUE * * @return TRUE, since this is a built in format */ public boolean isInitialized() { return true; } /** * Determines whether this format is a built in format * * @return TRUE, since this is a built in numerical format */ public boolean isBuiltIn() { return true; } /** * Initializes this format with a dynamically determined index value. * Since this is a built in, and hence the index value is predetermined, * this method has an empty body * * @param pos the pos in the number formats list */ public void initialize(int pos) { } /** * Accesses the excel format string which is applied to the cell * Note that this is the string that excel uses, and not the java * equivalent * * @return the cell format string */ public String getFormatString() { return formatString; } /** * Standard equals method * * @param o the object to compare * @return TRUE if the two objects are equal, FALSE otherwise */ public boolean equals(Object o) { if (o == this) { return true; } if (!(o instanceof BuiltInFormat)) { return false; } BuiltInFormat bif = (BuiltInFormat) o; return index == bif.index; } /** * Standard hash code method * * @return the hash code */ public int hashCode() { return index; } } // The available built in number formats // First describe the fairly bog standard formats /** * The default format. This is equivalent to a number format of '#' */ public static final DisplayFormat DEFAULT = new BuiltInFormat(0x0, "#"); /** * Formatting for an integer number. This is equivalent to a DecimalFormat * of "0" */ public static final DisplayFormat INTEGER = new BuiltInFormat(0x1, "0"); /** * Formatting for a float. This formats number to two decimal places. It * is equivalent to a DecimalFormat of "0.00" */ public static final DisplayFormat FLOAT = new BuiltInFormat(0x2, "0.00"); /** * Formatting for an integer that has a thousands separator. * Equivalent to a DecimalFormat of "#,##0" */ public static final DisplayFormat THOUSANDS_INTEGER = new BuiltInFormat(0x3, "#,##0"); /** * Formatting for a float that has a thousands separator. * Equivalent to a DecimalFormat of "#,##0.00" */ public static final DisplayFormat THOUSANDS_FLOAT = new BuiltInFormat(0x4, "#,##0.00"); /** * Formatting for an integer which is presented in accounting format * (ie. deficits appear in parentheses) * Equivalent to a DecimalFormat of "$#,##0;($#,##0)" */ public static final DisplayFormat ACCOUNTING_INTEGER = new BuiltInFormat(0x5, "$#,##0;($#,##0)"); /** * As ACCOUNTING_INTEGER except that deficits appear coloured red */ public static final DisplayFormat ACCOUNTING_RED_INTEGER = new BuiltInFormat(0x6, "$#,##0;($#,##0)"); /** * Formatting for an integer which is presented in accounting format * (ie. deficits appear in parentheses) * Equivalent to a DecimalFormat of "$#,##0;($#,##0)" */ public static final DisplayFormat ACCOUNTING_FLOAT = new BuiltInFormat(0x7, "$#,##0;($#,##0)"); /** * As ACCOUNTING_FLOAT except that deficits appear coloured red */ public static final DisplayFormat ACCOUNTING_RED_FLOAT = new BuiltInFormat(0x8, "$#,##0;($#,##0)"); /** * Formatting for an integer presented as a percentage * Equivalent to a DecimalFormat of "0%" */ public static final DisplayFormat PERCENT_INTEGER = new BuiltInFormat(0x9, "0%"); /** * Formatting for a float percentage * Equivalent to a DecimalFormat "0.00%" */ public static final DisplayFormat PERCENT_FLOAT = new BuiltInFormat(0xa, "0.00%"); /** * Formatting for exponential or scientific notation * Equivalent to a DecimalFormat "0.00E00" */ public static final DisplayFormat EXPONENTIAL = new BuiltInFormat(0xb, "0.00E00"); /** * Formatting for one digit fractions */ public static final DisplayFormat FRACTION_ONE_DIGIT = new BuiltInFormat(0xc,"?/?"); /** * Formatting for two digit fractions */ public static final DisplayFormat FRACTION_TWO_DIGITS = new BuiltInFormat(0xd,"??/??"); // Now describe the more obscure formats /** * Equivalent to a DecimalFormat "#,##0;(#,##0)" */ public static final DisplayFormat FORMAT1 = new BuiltInFormat(0x25, "#,##0;(#,##0)"); /** * Equivalent to FORMAT1 except deficits are coloured red */ public static final DisplayFormat FORMAT2 = new BuiltInFormat(0x26, "#,##0;(#,##0)"); /** * Equivalent to DecimalFormat "#,##0.00;(#,##0.00)" */ public static final DisplayFormat FORMAT3 = new BuiltInFormat(0x27, "#,##0.00;(#,##0.00)"); /** * Equivalent to FORMAT3 except deficits are coloured red */ public static final DisplayFormat FORMAT4 = new BuiltInFormat(0x28, "#,##0.00;(#,##0.00)"); /** * Equivalent to DecimalFormat "#,##0;(#,##0)" */ public static final DisplayFormat FORMAT5 = new BuiltInFormat(0x29, "#,##0;(#,##0)"); /** * Equivalent to FORMAT5 except deficits are coloured red */ public static final DisplayFormat FORMAT6 = new BuiltInFormat(0x2a, "#,##0;(#,##0)"); /** * Equivalent to DecimalFormat "#,##0.00;(#,##0.00)" */ public static final DisplayFormat FORMAT7 = new BuiltInFormat(0x2b, "#,##0.00;(#,##0.00)"); /** * Equivalent to FORMAT7 except deficits are coloured red */ public static final DisplayFormat FORMAT8 = new BuiltInFormat(0x2c, "#,##0.00;(#,##0.00)"); /** * Equivalent to FORMAT7 */ public static final DisplayFormat FORMAT9 = new BuiltInFormat(0x2e, "#,##0.00;(#,##0.00)"); /** * Equivalent to DecimalFormat "##0.0E0" */ public static final DisplayFormat FORMAT10 = new BuiltInFormat(0x30, "##0.0E0"); /** * Forces numbers to be interpreted as text */ public static final DisplayFormat TEXT = new BuiltInFormat(0x31, "@"); } jexcelapi/src/jxl/write/Boolean.java0000750000175000017500000000553011207000610017642 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2001 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write; import jxl.BooleanCell; import jxl.format.CellFormat; import jxl.write.biff.BooleanRecord; /** * A cell, created by user applications, which contains a boolean (or * in some cases an error) value */ public class Boolean extends BooleanRecord implements WritableCell, BooleanCell { /** * Constructs a boolean value, which, when added to a spreadsheet, will * display the specified value at the column/row position indicated. * * @param c the column * @param r the row * @param val the value */ public Boolean(int c, int r, boolean val) { super(c, r, val); } /** * Constructs a boolean, which, when added to a spreadsheet, will display the * specified value at the column/row position with the specified CellFormat. * The CellFormat may specify font information * * @param c the column * @param r the row * @param val the value * @param st the cell format */ public Boolean(int c, int r, boolean val, CellFormat st) { super(c, r, val, st); } /** * Constructor used internally by the application when making a writable * copy of a spreadsheet that has been read in * * @param nc the cell to copy */ public Boolean(BooleanCell nc) { super(nc); } /** * Copy constructor used for deep copying * * @param col the column * @param row the row * @param b the cell to copy */ protected Boolean(int col, int row, Boolean b) { super(col, row, b); } /** * Sets the boolean value for this cell * * @param val the value */ public void setValue(boolean val) { super.setValue(val); } /** * Implementation of the deep copy function * * @param col the column which the new cell will occupy * @param row the row which the new cell will occupy * @return a copy of this cell, which can then be added to the sheet */ public WritableCell copyTo(int col, int row) { return new Boolean(col, row, this); } } jexcelapi/src/jxl/write/Formula.java0000750000175000017500000000412311207000610017665 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2001 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write; import jxl.format.CellFormat; import jxl.write.biff.FormulaRecord; /** * A cell, created by user applications, which contains a numerical value */ public class Formula extends FormulaRecord implements WritableCell { /** * Constructs the formula * * @param c the column * @param r the row * @param form the formula */ public Formula(int c, int r, String form) { super(c, r, form); } /** * Constructs a formula * * @param c the column * @param r the row * @param form the formula * @param st the cell style */ public Formula(int c, int r, String form, CellFormat st) { super(c, r, form, st); } /** * Copy constructor * * @param c the column * @param r the row * @param f the record to copy */ protected Formula(int c, int r, Formula f) { super(c, r, f); } /** * Implementation of the deep copy function * * @param col the column which the new cell will occupy * @param row the row which the new cell will occupy * @return a copy of this cell, which can then be added to the sheet */ public WritableCell copyTo(int col, int row) { return new Formula(col, row, this); } } jexcelapi/src/jxl/write/Pattern.java0000750000175000017500000000237611207000610017705 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write; /** * Enumeration class which contains the various patterns available within * the standard Excel pattern palette * * @deprecated Repackaged as jxl.format.Pattern */ public final class Pattern extends jxl.format.Pattern { /** * Private constructor * * @param val */ private Pattern() { super(0, null); } } jexcelapi/src/jxl/write/Number.java0000750000175000017500000000567711207000610017527 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2001 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write; import jxl.NumberCell; import jxl.format.CellFormat; import jxl.write.biff.NumberRecord; /** * A cell, created by user applications, which contains a numerical value */ public class Number extends NumberRecord implements WritableCell, NumberCell { /** * Constructs a number, which, when added to a spreadsheet, will display the * specified value at the column/row position indicated. By default, the * cell will display with an accuracy of 3 decimal places * * @param c the column * @param r the row * @param val the value */ public Number(int c, int r, double val) { super(c, r, val); } /** * Constructs a number, which, when added to a spreadsheet, will display the * specified value at the column/row position with the specified CellFormat. * The CellFormat may specify font information and number format information * such as the number of decimal places * * @param c the column * @param r the row * @param val the value * @param st the cell format */ public Number(int c, int r, double val, CellFormat st) { super(c, r, val, st); } /** * Constructor used internally by the application when making a writable * copy of a spreadsheet that has been read in * * @param nc the cell to copy */ public Number(NumberCell nc) { super(nc); } /** * Sets the numerical value for this cell * * @param val the value */ public void setValue(double val) { super.setValue(val); } /** * Copy constructor used for deep copying * * @param col the column * @param row the row * @param n the number to copy */ protected Number(int col, int row, Number n) { super(col, row, n); } /** * Implementation of the deep copy function * * @param col the column which the new cell will occupy * @param row the row which the new cell will occupy * @return a copy of this cell, which can then be added to the sheet */ public WritableCell copyTo(int col, int row) { return new Number(col, row, this); } } jexcelapi/src/jxl/write/WritableCellFeatures.java0000750000175000017500000001161411262606002022343 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2004 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write; import java.util.Collection; import jxl.CellFeatures; import jxl.biff.BaseCellFeatures; /** * Container for any additional cell features */ public class WritableCellFeatures extends CellFeatures { // shadow the conditions in the base class so that they appear on // the public generated javadoc public static final ValidationCondition BETWEEN = BaseCellFeatures.BETWEEN; public static final ValidationCondition NOT_BETWEEN = BaseCellFeatures.NOT_BETWEEN; public static final ValidationCondition EQUAL = BaseCellFeatures.EQUAL; public static final ValidationCondition NOT_EQUAL = BaseCellFeatures.NOT_EQUAL; public static final ValidationCondition GREATER_THAN = BaseCellFeatures.GREATER_THAN; public static final ValidationCondition LESS_THAN = BaseCellFeatures.LESS_THAN; public static final ValidationCondition GREATER_EQUAL = BaseCellFeatures.GREATER_EQUAL; public static final ValidationCondition LESS_EQUAL = BaseCellFeatures.LESS_EQUAL; /** * Constructor */ public WritableCellFeatures() { super(); } /** * Copy constructor * * @param cf the cell to copy */ public WritableCellFeatures(CellFeatures cf) { super(cf); } /** * Sets the cell comment * * @param s the comment */ public void setComment(String s) { super.setComment(s); } /** * Sets the cell comment and sets the size of the text box (in cells) * in which the comment is displayed * * @param s the comment * @param width the width of the comment box in cells * @param height the height of the comment box in cells */ public void setComment(String s, double width, double height) { super.setComment(s, width, height); } /** * Removes the cell comment, if present */ public void removeComment() { super.removeComment(); } /** * Removes any data validation, if present */ public void removeDataValidation() { super.removeDataValidation(); } /** * The list of items to validate for this cell. For each object in the * collection, the toString() method will be called and the data entered * will be validated against that string * * @param c the list of valid values */ public void setDataValidationList(Collection c) { super.setDataValidationList(c); } /** * The list of items to validate for this cell in the form of a cell range. * * @param col1 the first column containing the data to validate against * @param row1 the first row containing the data to validate against * @param col2 the second column containing the data to validate against * @param row2 the second row containing the data to validate against */ public void setDataValidationRange(int col1, int row1, int col2, int row2) { super.setDataValidationRange(col1, row1, col2, row2); } /** * Sets the data validation based upon a named range. If the namedRange * is an empty string ("") then the cell is effectively made read only * * @param namedRange the workbook named range defining the validation * boundaries */ public void setDataValidationRange(String namedRange) { super.setDataValidationRange(namedRange); } /** * Sets the numeric value against which to validate * * @param val the number * @param c the validation condition */ public void setNumberValidation(double val, ValidationCondition c) { super.setNumberValidation(val, c); } /** * Sets the numeric range against which to validate the data * * @param val1 the first number * @param val2 the second number * @param c the validation condition */ public void setNumberValidation(double val1, double val2, ValidationCondition c) { super.setNumberValidation(val1, val2, c); } } jexcelapi/src/jxl/write/WritableCellFormat.java0000750000175000017500000001401111207000610021777 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2001 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write; import jxl.biff.DisplayFormat; import jxl.format.Alignment; import jxl.format.Border; import jxl.format.BorderLineStyle; import jxl.format.CellFormat; import jxl.format.Colour; import jxl.format.Orientation; import jxl.format.Pattern; import jxl.format.VerticalAlignment; import jxl.write.biff.CellXFRecord; /** * A user specified cell format, which may be reused across many cells. * The constructors takes parameters, such as font details and the numerical * date formats, which specify to Excel how cells with this format should be * displayed. * Once a CellFormat has been added to a Cell which has been added to * a sheet, then the CellFormat becomes immutable (to prevent unforeseen * effects on other cells which share the same format). Attempts to * call the various set... functions on a WritableCellFormat after this * time will result in a runtime exception. */ public class WritableCellFormat extends CellXFRecord { /** * A default constructor, which uses the default font and format. * This constructor should be used in conjunction with the more * advanced two-phase methods setAlignment, setBorder etc. */ public WritableCellFormat() { this(WritableWorkbook.ARIAL_10_PT, NumberFormats.DEFAULT); } /** * A CellFormat which specifies the font for cells with this format * * @param font the font */ public WritableCellFormat(WritableFont font) { this(font, NumberFormats.DEFAULT); } /** * A constructor which specifies a date/number format for Cells which * use this format object * * @param format the format */ public WritableCellFormat(DisplayFormat format) { this(WritableWorkbook.ARIAL_10_PT, format); } /** * A constructor which specifies the font and date/number format for cells * which wish to use this format * * @param font the font * @param format the date/number format */ public WritableCellFormat(WritableFont font, DisplayFormat format) { super(font, format); } /** * A public copy constructor which can be used for copy formats between * different sheets * @param format the cell format to copy */ public WritableCellFormat(CellFormat format) { super(format); } /** * Sets the horizontal alignment for this format * * @param a the alignment * @exception WriteException */ public void setAlignment(Alignment a) throws WriteException { super.setAlignment(a); } /** * Sets the vertical alignment for this format * * @param va the vertical alignment * @exception WriteException */ public void setVerticalAlignment(VerticalAlignment va) throws WriteException { super.setVerticalAlignment(va); } /** * Sets the text orientation for this format * * @param o the orientation * @exception WriteException */ public void setOrientation(Orientation o) throws WriteException { super.setOrientation(o); } /** * Sets the wrap indicator for this format. If the wrap is set to TRUE, then * Excel will wrap data in cells with this format so that it fits within the * cell boundaries * * @param w the wrap flag * @exception jxl.write.WriteException */ public void setWrap(boolean w) throws WriteException { super.setWrap(w); } /** * Sets the specified border for this format * * @param b the border * @param ls the border line style * @exception jxl.write.WriteException */ public void setBorder(Border b, BorderLineStyle ls) throws WriteException { super.setBorder(b, ls, Colour.BLACK); } /** * Sets the specified border for this format * * @param b the border * @param ls the border line style * @param c the colour of the specified border * @exception jxl.write.WriteException */ public void setBorder(Border b, BorderLineStyle ls, Colour c) throws WriteException { super.setBorder(b, ls, c); } /** * Sets the background colour for this cell format * * @param c the bacground colour * @exception jxl.write.WriteException */ public void setBackground(Colour c) throws WriteException { this.setBackground(c, Pattern.SOLID); } /** * Sets the background colour and pattern for this cell format * * @param c the colour * @param p the pattern * @exception jxl.write.WriteException */ public void setBackground(Colour c, Pattern p) throws WriteException { super.setBackground(c, p); } /** * Sets the shrink to fit flag * * @param s shrink to fit flag * @exception WriteException */ public void setShrinkToFit(boolean s) throws WriteException { super.setShrinkToFit(s); } /** * Sets the indentation of the cell text * * @param i the indentation */ public void setIndentation(int i) throws WriteException { super.setIndentation(i); } /** * Sets whether or not this XF record locks the cell. For this to * have any effect, the sheet containing cells with this format must * also be locke3d * * @param l the locked flag * @exception WriteException */ public void setLocked(boolean l) throws WriteException { super.setLocked(l); } } jexcelapi/src/jxl/write/WritableImage.java0000750000175000017500000001346411207000610021004 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write; import java.io.File; import jxl.biff.drawing.Drawing; import jxl.biff.drawing.DrawingGroup; import jxl.biff.drawing.DrawingGroupObject; /** * Allows an image to be created, or an existing image to be manipulated * Note that co-ordinates and dimensions are given in cells, so that if for * example the width or height of a cell which the image spans is altered, * the image will have a correspondign distortion */ public class WritableImage extends Drawing { // Shadow these values from the superclass. The only practical reason // for doing this is that they appear nicely in the javadoc /** * Image anchor properties which will move and resize an image * along with the cells */ public static ImageAnchorProperties MOVE_AND_SIZE_WITH_CELLS = Drawing.MOVE_AND_SIZE_WITH_CELLS; /** * Image anchor properties which will move an image * when cells are inserted or deleted */ public static ImageAnchorProperties MOVE_WITH_CELLS = Drawing.MOVE_WITH_CELLS; /** * Image anchor properties which will leave an image unaffected when * other cells are inserted, removed or resized */ public static ImageAnchorProperties NO_MOVE_OR_SIZE_WITH_CELLS = Drawing.NO_MOVE_OR_SIZE_WITH_CELLS; /** * Constructor * * @param x the column number at which to position the image * @param y the row number at which to position the image * @param width the number of columns cells which the image spans * @param height the number of rows which the image spans * @param image the source image file */ public WritableImage(double x, double y, double width, double height, File image) { super(x, y, width, height, image); } /** * Constructor * * @param x the column number at which to position the image * @param y the row number at which to position the image * @param width the number of columns cells which the image spans * @param height the number of rows which the image spans * @param imageData the image data */ public WritableImage(double x, double y, double width, double height, byte[] imageData) { super(x, y, width, height, imageData); } /** * Constructor, used when copying sheets * * @param d the image to copy * @param dg the drawing group */ public WritableImage(DrawingGroupObject d, DrawingGroup dg) { super(d, dg); } /** * Accessor for the image position * * @return the column number at which the image is positioned */ public double getColumn() { return super.getX(); } /** * Accessor for the image position * * @param c the column number at which the image should be positioned */ public void setColumn(double c) { super.setX(c); } /** * Accessor for the image position * * @return the row number at which the image is positions */ public double getRow() { return super.getY(); } /** * Accessor for the image position * * @param c the row number at which the image should be positioned */ public void setRow(double c) { super.setY(c); } /** * Accessor for the image dimensions * * @return the number of columns this image spans */ public double getWidth() { return super.getWidth(); } /** * Accessor for the image dimensions * Note that the actual size of the rendered image will depend on the * width of the columns it spans * * @param c the number of columns which this image spans */ public void setWidth(double c) { super.setWidth(c); } /** * Accessor for the image dimensions * * @return the number of rows which this image spans */ public double getHeight() { return super.getHeight(); } /** * Accessor for the image dimensions * Note that the actual size of the rendered image will depend on the * height of the rows it spans * * @param c the number of rows which this image should span */ public void setHeight(double c) { super.setHeight(c); } /** * Accessor for the image file * * @return the file which the image references */ public File getImageFile() { return super.getImageFile(); } /** * Accessor for the image data * * @return the image data */ public byte[] getImageData() { return super.getImageData(); } /** * Accessor for the anchor properties */ public void setImageAnchor(ImageAnchorProperties iap) { super.setImageAnchor(iap); } /** * Accessor for the anchor properties */ public ImageAnchorProperties getImageAnchor() { return super.getImageAnchor(); } } jexcelapi/src/jxl/write/NumberFormat.java0000750000175000017500000001034511207000610020664 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write; import java.text.DecimalFormat; import jxl.biff.DisplayFormat; import jxl.write.biff.NumberFormatRecord; /** * A custom user defined number format, which may be instantiated within user * applications in order to present numerical values to the appropriate level * of accuracy. * The string format used to create a number format adheres to the standard * java specification, and JExcelAPI makes the necessary modifications so * that it is rendered in Excel as the nearest possible equivalent. * Once created, this may be used within a CellFormat object, which in turn * is a parameter passed to the constructor of the Number cell */ public class NumberFormat extends NumberFormatRecord implements DisplayFormat { /** * Pass in to the constructor to bypass the format validation */ public static final NonValidatingFormat COMPLEX_FORMAT = new NumberFormatRecord.NonValidatingFormat(); // Some format strings /** * Constant format string for the Euro currency symbol where it precedes * the format */ public static final String CURRENCY_EURO_PREFIX = "[$-2]"; /** * Constant format string for the Euro currency symbol where it precedes * the format */ public static final String CURRENCY_EURO_SUFFIX = "[$-1]"; /** * Constant format string for the UK pound sign */ public static final String CURRENCY_POUND = ""; /** * Constant format string for the Japanese Yen sign */ public static final String CURRENCY_JAPANESE_YEN = "[$-411]"; /** * Constant format string for the US Dollar sign */ public static final String CURRENCY_DOLLAR = "[$$-409]"; /** * Constant format string for three digit fractions */ public static final String FRACTION_THREE_DIGITS = "???/???"; /** * Constant format string for fractions as halves */ public static final String FRACTION_HALVES = "?/2"; /** * Constant format string for fractions as quarter */ public static final String FRACTION_QUARTERS = "?/4"; /** * Constant format string for fractions as eighths */ public static final String FRACTIONS_EIGHTHS = "?/8"; /** * Constant format string for fractions as sixteenths */ public static final String FRACTION_SIXTEENTHS = "?/16"; /** * Constant format string for fractions as tenths */ public static final String FRACTION_TENTHS = "?/10"; /** * Constant format string for fractions as hundredths */ public static final String FRACTION_HUNDREDTHS = "?/100"; /** * Constructor, taking in the Java compliant number format * * @param format the format string */ public NumberFormat(String format) { super(format); // Verify that the format is valid DecimalFormat df = new DecimalFormat(format); } /** * Constructor, taking in the non-Java compliant number format. This * may be used for currencies and more complex custom formats, which * will not be subject to the standard validation rules. * As there is no validation, there is a resultant risk that the * generated Excel file will be corrupt * * USE THIS CONSTRUCTOR ONLY IF YOU ARE CERTAIN THAT THE NUMBER FORMAT * YOU ARE USING IS EXCEL COMPLIANT * * @param format the format string * @param dummy dummy parameter */ public NumberFormat(String format, NonValidatingFormat dummy) { super(format, dummy); } } jexcelapi/src/jxl/write/Border.java0000750000175000017500000000213511207000610017476 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write; /** * @deprecated repackaged as jxl.format.Border */ public final class Border extends jxl.format.Border { /** * Constructor */ private Border() { super(null); } } jexcelapi/src/jxl/write/DateFormat.java0000750000175000017500000000365511207000610020317 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write; import java.text.SimpleDateFormat; import jxl.biff.DisplayFormat; import jxl.write.biff.DateFormatRecord; /** * A custom user defined number format which may be instantiated within user * applications in order to present date and time values in the appropriate * format. * The string format used to create a DateFormat adheres to the standard * java specification, and JExcelApi makes the necessary modifications so * that it is rendered as its nearest equivalent in Excel. * Once created, this may be used within a CellFormat object, which in turn * is a parameter passed to the constructor of the DateTime cell */ public class DateFormat extends DateFormatRecord implements DisplayFormat { /** * Constructor. The date format that is passed should comply to the standard * Java date formatting conventions * * @param format the date format */ public DateFormat(String format) { super(format); // Verify that the format is valid SimpleDateFormat df = new SimpleDateFormat(format); } } jexcelapi/src/jxl/write/WritableFont.java0000750000175000017500000002215011207000610020660 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write; import jxl.format.Colour; import jxl.format.Font; import jxl.format.ScriptStyle; import jxl.format.UnderlineStyle; import jxl.write.biff.WritableFontRecord; /** * A class which is instantiated when the user application wishes to specify * the font for a particular cell */ public class WritableFont extends WritableFontRecord { /** * Static inner class used for classifying the font names */ public static class FontName { /** * The name */ String name; /** * Constructor * * @param s the font name */ FontName(String s) { name = s; } } /** * Static inner class used for the boldness of the fonts */ /*private*/ static class BoldStyle { /** * The value */ public int value; /** * Constructor * * @param val the value */ BoldStyle(int val) { value = val; } } /** * Objects created with this font name will be rendered within Excel as ARIAL * fonts */ public static final FontName ARIAL = new FontName("Arial"); /** * Objects created with this font name will be rendered within Excel as TIMES * fonts */ public static final FontName TIMES = new FontName("Times New Roman"); /** * Objects created with this font name will be rendered within Excel as * COURIER fonts */ public static final FontName COURIER = new FontName("Courier New"); /** * Objects created with this font name will be rendered within Excel as * TAHOMA fonts */ public static final FontName TAHOMA = new FontName("Tahoma"); // The bold styles /** * Indicates that this font should not be presented as bold */ public static final BoldStyle NO_BOLD = new BoldStyle(0x190); /** * Indicates that this font should be presented in a BOLD style */ public static final BoldStyle BOLD = new BoldStyle(0x2bc); /** * The default point size for all Fonts */ public static final int DEFAULT_POINT_SIZE = 10; /** * Creates a default font, vanilla font of the specified face and with * default point size. * * @param fn the font name */ public WritableFont(FontName fn) { this(fn, DEFAULT_POINT_SIZE, NO_BOLD, false, UnderlineStyle.NO_UNDERLINE, Colour.BLACK, ScriptStyle.NORMAL_SCRIPT); } /** * Publicly available copy constructor * * @param f the font to copy */ public WritableFont(Font f) { super(f); } /** * Constructs of font of the specified face and of size given by the * specified point size * * @param ps the point size * @param fn the font name */ public WritableFont(FontName fn, int ps) { this(fn, ps, NO_BOLD, false, UnderlineStyle.NO_UNDERLINE, Colour.BLACK, ScriptStyle.NORMAL_SCRIPT); } /** * Creates a font of the specified face, point size and bold style * * @param ps the point size * @param bs the bold style * @param fn the font name */ public WritableFont(FontName fn, int ps, BoldStyle bs) { this(fn, ps, bs, false, UnderlineStyle.NO_UNDERLINE, Colour.BLACK, ScriptStyle.NORMAL_SCRIPT); } /** * Creates a font of the specified face, point size, bold weight and * italicised option. * * @param ps the point size * @param bs the bold style * @param italic italic flag * @param fn the font name */ public WritableFont(FontName fn, int ps, BoldStyle bs, boolean italic) { this(fn, ps, bs, italic, UnderlineStyle.NO_UNDERLINE, Colour.BLACK, ScriptStyle.NORMAL_SCRIPT); } /** * Creates a font of the specified face, point size, bold weight, * italicisation and underline style * * @param ps the point size * @param bs the bold style * @param us the underline style * @param fn the font name * @param it italic flag */ public WritableFont(FontName fn, int ps, BoldStyle bs, boolean it, UnderlineStyle us) { this(fn, ps, bs, it, us, Colour.BLACK, ScriptStyle.NORMAL_SCRIPT); } /** * Creates a font of the specified face, point size, bold style, * italicisation, underline style and colour * * @param ps the point size * @param bs the bold style * @param us the underline style * @param fn the font name * @param it italic flag * @param c the colour */ public WritableFont(FontName fn, int ps, BoldStyle bs, boolean it, UnderlineStyle us, Colour c) { this(fn, ps, bs, it, us, c, ScriptStyle.NORMAL_SCRIPT); } /** * Creates a font of the specified face, point size, bold style, * italicisation, underline style, colour, and script * style (superscript/subscript) * * @param ps the point size * @param bs the bold style * @param us the underline style * @param fn the font name * @param it the italic flag * @param c the colour * @param ss the script style */ public WritableFont(FontName fn, int ps, BoldStyle bs, boolean it, UnderlineStyle us, Colour c, ScriptStyle ss) { super(fn.name, ps, bs.value, it, us.getValue(), c.getValue(), ss.getValue()); } /** * Sets the point size for this font, if the font hasn't been initialized * * @param pointSize the point size * @exception WriteException, if this font is already in use elsewhere */ public void setPointSize(int pointSize) throws WriteException { super.setPointSize(pointSize); } /** * Sets the bold style for this font, if the font hasn't been initialized * * @param boldStyle the bold style * @exception WriteException, if this font is already in use elsewhere */ public void setBoldStyle(BoldStyle boldStyle) throws WriteException { super.setBoldStyle(boldStyle.value); } /** * Sets the italic indicator for this font, if the font hasn't been * initialized * * @param italic the italic flag * @exception WriteException, if this font is already in use elsewhere */ public void setItalic(boolean italic) throws WriteException { super.setItalic(italic); } /** * Sets the underline style for this font, if the font hasn't been * initialized * * @param us the underline style * @exception WriteException, if this font is already in use elsewhere */ public void setUnderlineStyle(UnderlineStyle us) throws WriteException { super.setUnderlineStyle(us.getValue()); } /** * Sets the colour for this font, if the font hasn't been * initialized * * @param colour the colour * @exception WriteException, if this font is already in use elsewhere */ public void setColour(Colour colour) throws WriteException { super.setColour(colour.getValue()); } /** * Sets the script style (eg. superscript, subscript) for this font, * if the font hasn't been initialized * * @param scriptStyle the colour * @exception WriteException, if this font is already in use elsewhere */ public void setScriptStyle(ScriptStyle scriptStyle) throws WriteException { super.setScriptStyle(scriptStyle.getValue()); } /** * Accessor for the strike-out flag * * @return the strike-out flag */ public boolean isStruckout() { return super.isStruckout(); } /** * Sets Accessor for the strike-out flag * * @param struckout TRUE if this is a struckout font * @return the strike-out flag * @exception WriteException, if this font is already in use elsewhere */ public void setStruckout(boolean struckout) throws WriteException { super.setStruckout(struckout); } /** * Factory method which creates the specified font name. This method * should be used with care, since the string used to create the font * name must be recognized by Excel's internal processing * * @param fontName the name of the Excel font * @return the font name */ public static FontName createFont(String fontName) { return new FontName(fontName); } } jexcelapi/src/jxl/write/WritableWorkbook.java0000750000175000017500000002274711207000610021563 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write; import java.io.IOException; import jxl.Range; import jxl.Sheet; import jxl.Workbook; import jxl.format.Colour; import jxl.format.UnderlineStyle; /** * A writable workbook */ public abstract class WritableWorkbook { // Globally available stuff /** * The default font for Cell formats */ public static final WritableFont ARIAL_10_PT = new WritableFont(WritableFont.ARIAL); /** * The font used for hyperlinks */ public static final WritableFont HYPERLINK_FONT = new WritableFont(WritableFont.ARIAL, WritableFont.DEFAULT_POINT_SIZE, WritableFont.NO_BOLD, false, UnderlineStyle.SINGLE, Colour.BLUE); /** * The default style for cells */ public static final WritableCellFormat NORMAL_STYLE = new WritableCellFormat(ARIAL_10_PT, NumberFormats.DEFAULT); /** * The style used for hyperlinks */ public static final WritableCellFormat HYPERLINK_STYLE = new WritableCellFormat(HYPERLINK_FONT); /** * A cell format used to hide the cell contents */ public static final WritableCellFormat HIDDEN_STYLE = new WritableCellFormat(new DateFormat(";;;")); /** * Constructor used by the implemenation class */ protected WritableWorkbook() { } /** * Gets the sheets within this workbook. Use of this method for * large worksheets can cause performance problems. * * @return an array of the individual sheets */ public abstract WritableSheet[] getSheets(); /** * Gets the sheet names * * @return an array of strings containing the sheet names */ public abstract String[] getSheetNames(); /** * Gets the specified sheet within this workbook * * @param index the zero based index of the reQuired sheet * @return The sheet specified by the index * @exception IndexOutOfBoundsException when index refers to a non-existent * sheet */ public abstract WritableSheet getSheet(int index) throws IndexOutOfBoundsException; /** * Gets the sheet with the specified name from within this workbook * * @param name the sheet name * @return The sheet with the specified name, or null if it is not found */ public abstract WritableSheet getSheet(String name); /** * Returns the cell for the specified location eg. "Sheet1!A4". * This is identical to using the CellReferenceHelper with its * associated performance overheads, consequently it should * be use sparingly * * @param loc the cell to retrieve * @return the cell at the specified location */ public abstract WritableCell getWritableCell(String loc); /** * Returns the number of sheets in this workbook * * @return the number of sheets in this workbook */ public abstract int getNumberOfSheets(); /** * Closes this workbook, and makes any memory allocated available * for garbage collection. Also closes the underlying output stream * if necessary. * * @exception IOException * @exception WriteException */ public abstract void close() throws IOException, WriteException; /** * Creates, and returns a worksheet at the specified position * with the specified name * If the index specified is less than or equal to zero, the new sheet * is created at the beginning of the workbook. If the index is greater * than the number of sheet, then the sheet is created at the * end of the workbook. * * @param name the sheet name * @param index the index number at which to insert * @return the new sheet */ public abstract WritableSheet createSheet(String name, int index); /** * Imports a sheet from a different workbook. Does a deep copy on all * elements within that sheet * * @param name the name of the new sheet * @param index the position for the new sheet within this workbook * @param sheet the sheet (from another workbook) to merge into this one * @return the new sheet */ public abstract WritableSheet importSheet(String name, int index, Sheet s); /** * Copy sheet within the same workbook. The sheet specified is copied to * the new sheet name at the position * * @param s the index of the sheet to copy * @param name the name of the new sheet * @param index the position of the new sheet */ public abstract void copySheet(int s, String name, int index); /** * Copies the specified sheet and places it at the index * specified by the parameter * * @param s the name of the sheet to copy * @param name the name of the new sheet * @param index the position of the new sheet */ public abstract void copySheet(String s, String name, int index); /** * Removes the sheet at the specified index from this workbook * * @param index the sheet index to remove */ public abstract void removeSheet(int index); /** * Moves the specified sheet within this workbook to another index * position. * * @param fromIndex the zero based index of the required sheet * @param toIndex the zero based index of the required sheet * @return the sheet that has been moved */ public abstract WritableSheet moveSheet(int fromIndex, int toIndex); /** * Writes out the data held in this workbook in Excel format * * @exception IOException */ public abstract void write() throws IOException; /** * Indicates whether or not this workbook is protected * * @param prot Protected flag */ public abstract void setProtected(boolean prot); /** * Sets the RGB value for the specified colour for this workbook * * @param c the colour whose RGB value is to be overwritten * @param r the red portion to set (0-255) * @param g the green portion to set (0-255) * @param b the blue portion to set (0-255) */ public abstract void setColourRGB(Colour c, int r, int g, int b); /** * This method can be used to create a writable clone of some other * workbook * * @param w the workdoock to copy * @deprecated Copying now occurs implicitly as part of the overloaded * factory method Workbook.createWorkbood */ public void copy(Workbook w) { // Was an abstract method - leave the method body blank } /** * Gets the named cell from this workbook. The name refers to a * range of cells, then the cell on the top left is returned. If * the name cannot be, null is returned * * @param name the name of the cell/range to search for * @return the cell in the top left of the range if found, NULL * otherwise */ public abstract WritableCell findCellByName(String name); /** * Gets the named range from this workbook. The Range object returns * contains all the cells from the top left to the bottom right * of the range. * If the named range comprises an adjacent range, * the Range[] will contain one object; for non-adjacent * ranges, it is necessary to return an array of length greater than * one. * If the named range contains a single cell, the top left and * bottom right cell will be the same cell * * @param name the name of the cell/range to search for * @return the range of cells */ public abstract Range[] findByName(String name); /** * Gets the named ranges * * @return the list of named cells within the workbook */ public abstract String[] getRangeNames(); /** * Removes the specified named range from the workbook. Note that * removing a name could cause formulas which use that name to * calculate their results incorrectly * * @param name the name to remove */ public abstract void removeRangeName(String name); /** * Add new named area to this workbook with the given information. * * @param name name to be created. * @param sheet sheet containing the name * @param firstCol first column this name refers to. * @param firstRow first row this name refers to. * @param lastCol last column this name refers to. * @param lastRow last row this name refers to. */ public abstract void addNameArea(String name, WritableSheet sheet, int firstCol, int firstRow, int lastCol, int lastRow); /** * Sets a new output file. This allows the same workbook to be * written to various different output files without having to * read in any templates again * * @param fileName the file name * @exception IOException */ public abstract void setOutputFile(java.io.File fileName) throws IOException; } jexcelapi/src/jxl/write/WritableSheet.java0000750000175000017500000003372211245771276021062 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write; import jxl.CellView; import jxl.Range; import jxl.Sheet; import jxl.format.CellFormat; import jxl.format.PageOrientation; import jxl.format.PaperSize; import jxl.write.biff.RowsExceededException; /** * Interface for a worksheet that may be modified. The most * important modification for a sheet is to have cells added to it */ public interface WritableSheet extends Sheet { /** * Adds a cell to this sheet * The RowsExceededException may be caught if client code wishes to * explicitly trap the case where too many rows have been written * to the current sheet. If this behaviour is not desired, it is * sufficient simply to handle the WriteException, since this is a base * class of RowsExceededException * * @param cell the cell to add * @exception jxl.write..WriteException * @exception jxl.write.biff.RowsExceededException */ public void addCell(WritableCell cell) throws WriteException, RowsExceededException; /** * Sets the name of this sheet * * @param name the name of the sheet */ public void setName(String name); /** * Indicates whether or not this sheet is hidden * * @param hidden hidden flag * @deprecated use the SheetSettings bean instead */ public void setHidden(boolean hidden); /** * Indicates whether or not this sheet is protected * * @param prot Protected flag * @deprecated use the SheetSettings bean instead */ public void setProtected(boolean prot); /** * Sets the width of the column on this sheet, in characters. This causes * Excel to resize the entire column. * If the columns specified already has view information associated * with it, then it is replaced by the new data * * @param col the column to be formatted * @param width the width of the column */ public void setColumnView(int col, int width); /** * Sets the width and style of every cell in the specified column. * If the columns specified already has view information associated * with it, then it is replaced by the new data * * @param col the column to be formatted * @param format the format of every cell in the column * @param width the width of the column, in characters * @deprecated Use the CellView bean instead */ public void setColumnView(int col, int width, CellFormat format); /** * Sets the view for this column * * @param col the column on which to set the view * @param view the view to set */ public void setColumnView(int col, CellView view); /** * Sets the height of the specified row, as well as its collapse status * * @param row the row to be formatted * @param height the row height in characters * @exception jxl.write.biff.RowsExceededException */ public void setRowView(int row, int height) throws RowsExceededException; /** * Sets the properties of the specified row * * @param row the row to be formatted * @param collapsed indicates whether the row is collapsed * @exception jxl.write.biff.RowsExceededException */ public void setRowView(int row, boolean collapsed) throws RowsExceededException; /** * Sets the height of the specified row, as well as its collapse status * * @param row the row to be formatted * @param height the row height in 1/20th of a point * @param collapsed indicates whether the row is collapsed * @exception jxl.write.biff.RowsExceededException */ public void setRowView(int row, int height, boolean collapsed) throws RowsExceededException; /** * Sets the view for this column * * @param row the column on which to set the view * @param view the view to set * @exception RowsExceededException */ public void setRowView(int row, CellView view) throws RowsExceededException; /** * Gets the writable cell from this sheet. Use of this method allows * the returned cell to be modified by the users application * * @param column the column * @param row the row * @return the cell at the specified position */ public WritableCell getWritableCell(int column, int row); /** * Returns the cell for the specified location eg. "A4". Note that this * method is identical to calling getCell(CellReferenceHelper.getColumn(loc), * CellReferenceHelper.getRow(loc)) and its implicit performance * overhead for string parsing. As such,this method should therefore * be used sparingly * * @param loc the cell reference * @return the cell at the specified co-ordinates */ public WritableCell getWritableCell(String loc); /** * Gets the writable hyperlinks from this sheet. The hyperlinks * that are returned may be modified by user applications * * @return the writable hyperlinks */ public WritableHyperlink[] getWritableHyperlinks(); /** * Inserts a blank row into this spreadsheet. If the row is out of range * of the rows in the sheet, then no action is taken * * @param row the row to insert */ public void insertRow(int row); /** * Inserts a blank column into this spreadsheet. If the column is out of * range of the columns in the sheet, then no action is taken * * @param col the column to insert */ public void insertColumn(int col); /** * Removes a column from this spreadsheet. If the column is out of range * of the columns in the sheet, then no action is taken * * @param col the column to remove */ public void removeColumn(int col); /** * Removes a row from this spreadsheet. If the row is out of * range of the columns in the sheet, then no action is taken * * @param row the row to remove */ public void removeRow(int row); /** * Merges the specified cells. Any clashes or intersections between * merged cells are resolved when the spreadsheet is written out * * @param col1 the column number of the top left cell * @param row1 the row number of the top left cell * @param col2 the column number of the bottom right cell * @param row2 the row number of the bottom right cell * @return the Range object representing the merged cells * @exception jxl.write..WriteException * @exception jxl.write.biff.RowsExceededException */ public Range mergeCells(int col1, int row1, int col2, int row2) throws WriteException, RowsExceededException; /** * Sets a row grouping * * @param row1 the first row of the group * @param row2 the last row of the group * @param collapsed should the group be collapsed? * @exception WriteException * @exception RowsExceededException */ public void setRowGroup(int row1, int row2, boolean collapsed) throws WriteException, RowsExceededException; /** * Unsets a row grouping * * @param row1 the first row to unset * @param row2 the last row to unset * @exception WriteException * @exception RowsExceededException */ public void unsetRowGroup(int row1, int row2) throws WriteException, RowsExceededException; /** * Sets a column grouping * * @param col1 the first column of the group * @param col2 the last column of the group * @param collapsed should the group be collapsed? * @exception WriteException * @exception RowsExceededException */ public void setColumnGroup(int col1, int col2, boolean collapsed) throws WriteException, RowsExceededException; /** * Unsets a column grouping * * @param col1 the first column to unset * @param col2 the last column to unset * @exception WriteException * @exception RowsExceededException */ public void unsetColumnGroup(int col1, int col2) throws WriteException, RowsExceededException; /** * Unmerges the specified cells. The Range passed in should be one that * has been previously returned as a result of the getMergedCells method * * @param r the range of cells to unmerge */ public void unmergeCells(Range r); /** * Adds the specified hyperlink. Adding a hyperlink causes any populated * cells in the range of the hyperlink to be set to empty * If the cells which activate this hyperlink clash with any other cells, * they are still added to the worksheet and it is left to Excel to * handle this. * * @param h the hyperlink * @exception jxl.write..WriteException * @exception jxl.write.biff.RowsExceededException */ public void addHyperlink(WritableHyperlink h) throws WriteException, RowsExceededException;; /** * Removes the specified hyperlink. Note that if you merely set the * cell contents to be an Empty cell, then the cells containing the * hyperlink will still be active. The contents of the cell which * activate the hyperlink are removed. * The hyperlink passed in must be a hyperlink retrieved using the * getHyperlinks method * * @param h the hyperlink to remove. */ public void removeHyperlink(WritableHyperlink h); /** * Removes the specified hyperlink. Note that if you merely set the * cell contents to be an Empty cell, then the cells containing the * hyperlink will still be active. * If the preserveLabel field is set, the cell contents of the * hyperlink are preserved, although the hyperlink is deactivated. If * this value is FALSE, the cell contents are removed * The hyperlink passed in must be a hyperlink retrieved using the * getHyperlinks method * * @param h the hyperlink to remove. * @param preserveLabel if TRUE preserves the label contents, if FALSE * removes them */ public void removeHyperlink(WritableHyperlink h, boolean preserveLabel); /** * Sets the header for this page * * @param l the print header to print on the left side * @param c the print header to print in the centre * @param r the print header to print on the right hand side * @deprecated use the SheetSettings bean */ public void setHeader(String l, String c, String r); /** * Sets the footer for this page * * @param l the print header to print on the left side * @param c the print header to print in the centre * @param r the print header to print on the right hand side * @deprecated use the SheetSettings bean */ public void setFooter(String l, String c, String r); /** * Sets the page setup details * * @param p the page orientation */ public void setPageSetup(PageOrientation p); /** * Sets the page setup details * * @param p the page orientation * @param hm the header margin, in inches * @param fm the footer margin, in inches */ public void setPageSetup(PageOrientation p, double hm, double fm); /** * Sets the page setup details * * @param p the page orientation * @param ps the paper size * @param hm the header margin, in inches * @param fm the footer margin, in inches */ public void setPageSetup(PageOrientation p, PaperSize ps, double hm, double fm); /** * Forces a page break at the specified row * * @param row the row to break at */ public void addRowPageBreak(int row); /** * Forces a page break at the specified column * * @param col the column to break at */ public void addColumnPageBreak(int col); /** * Adds an image to the sheet * * @param image the image to add */ public void addImage(WritableImage image); /** * Accessor for the number of images on the sheet * * @return the number of images on this sheet */ public int getNumberOfImages(); /** * Accessor for the image * * @param i the 0 based image number * @return the image at the specified position */ public WritableImage getImage(int i); /** * Removes the specified image from the sheet. The image passed in * must be the same instance as that previously retrieved using the * getImage() method * * @param wi the image to remove */ public void removeImage(WritableImage wi); /** * Extend the data validation contained in the specified cell across and * downwards. * NOTE: The source cell (top left) must have been added to the sheet prior * to this method being called * * @param col the number of cells accross to apply this data validation * @param row the number of cells downwards to apply this data validation */ public void applySharedDataValidation(WritableCell cell, int col, int row) throws WriteException; /** * Remove the shared data validation from multiple cells. The cell passed * in is the top left cell. The data validation is removed from this * cell and all cells which share the same validation. * * @param cell the top left cell containing the shared data validation */ public void removeSharedDataValidation(WritableCell cell) throws WriteException; } jexcelapi/src/jxl/write/WritableHyperlink.java0000750000175000017500000001742711207000610021732 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write; import java.io.File; import java.net.URL; import jxl.Hyperlink; import jxl.write.biff.HyperlinkRecord; /** * A writable hyperlink. Provides API to modify the contents of the hyperlink */ public class WritableHyperlink extends HyperlinkRecord implements Hyperlink { /** * Constructor used internally by the worksheet when making a copy * of worksheet * * @param h the hyperlink being read in * @param ws the writable sheet containing the hyperlink */ public WritableHyperlink(Hyperlink h, WritableSheet ws) { super(h, ws); } /** * Constructs a URL hyperlink in a single cell * * @param col the column containing this hyperlink * @param row the row containing this hyperlink * @param url the hyperlink */ public WritableHyperlink(int col, int row, URL url) { this(col, row, col, row, url); } /** * Constructs a url hyperlink to a range of cells * * @param col the column containing this hyperlink * @param row the row containing this hyperlink * @param lastcol the last column which activates this hyperlink * @param lastrow the last row which activates this hyperlink * @param url the hyperlink */ public WritableHyperlink(int col, int row, int lastcol, int lastrow, URL url) { this(col, row, lastcol, lastrow, url, null); } /** * Constructs a url hyperlink to a range of cells * * @param col the column containing this hyperlink * @param row the row containing this hyperlink * @param lastcol the last column which activates this hyperlink * @param lastrow the last row which activates this hyperlink * @param url the hyperlink * @param desc the description text to place in the cell */ public WritableHyperlink(int col, int row, int lastcol, int lastrow, URL url, String desc) { super(col, row, lastcol, lastrow, url, desc); } /** * Constructs a file hyperlink in a single cell * * @param col the column containing this hyperlink * @param row the row containing this hyperlink * @param file the hyperlink */ public WritableHyperlink(int col, int row, File file) { this(col, row, col, row, file, null); } /** * Constructs a file hyperlink in a single cell * * @param col the column containing this hyperlink * @param row the row containing this hyperlink * @param file the hyperlink * @param desc the hyperlink description */ public WritableHyperlink(int col, int row, File file, String desc) { this(col, row, col, row, file, desc); } /** * Constructs a File hyperlink to a range of cells * * @param col the column containing this hyperlink * @param row the row containing this hyperlink * @param lastcol the last column which activates this hyperlink * @param lastrow the last row which activates this hyperlink * @param file the hyperlink */ public WritableHyperlink(int col, int row, int lastcol, int lastrow, File file) { super(col, row, lastcol, lastrow, file, null); } /** * Constructs a File hyperlink to a range of cells * * @param col the column containing this hyperlink * @param row the row containing this hyperlink * @param lastcol the last column which activates this hyperlink * @param lastrow the last row which activates this hyperlink * @param file the hyperlink * @param desc the description */ public WritableHyperlink(int col, int row, int lastcol, int lastrow, File file, String desc) { super(col, row, lastcol, lastrow, file, desc); } /** * Constructs a hyperlink to some cells within this workbook * * @param col the column containing this hyperlink * @param row the row containing this hyperlink * @param desc the cell contents for this hyperlink * @param sheet the sheet containing the cells to be linked to * @param destcol the column number of the first destination linked cell * @param destrow the row number of the first destination linked cell */ public WritableHyperlink(int col, int row, String desc, WritableSheet sheet, int destcol, int destrow) { this(col, row, col, row, desc, sheet, destcol, destrow, destcol, destrow); } /** * Constructs a hyperlink to some cells within this workbook * * @param col the column containing this hyperlink * @param row the row containing this hyperlink * @param lastcol the last column which activates this hyperlink * @param lastrow the last row which activates this hyperlink * @param desc the cell contents for this hyperlink * @param sheet the sheet containing the cells to be linked to * @param destcol the column number of the first destination linked cell * @param destrow the row number of the first destination linked cell * @param lastdestcol the column number of the last destination linked cell * @param lastdestrow the row number of the last destination linked cell */ public WritableHyperlink(int col, int row, int lastcol, int lastrow, String desc, WritableSheet sheet, int destcol, int destrow, int lastdestcol, int lastdestrow) { super(col, row, lastcol, lastrow, desc, sheet, destcol, destrow, lastdestcol, lastdestrow); } /** * Sets the URL of this hyperlink * * @param url the url */ public void setURL(URL url) { super.setURL(url); } /** * Sets the file activated by this hyperlink * * @param file the file */ public void setFile(File file) { super.setFile(file); } /** * Sets the description to appear in the hyperlink cell * * @param desc the description */ public void setDescription(String desc) { super.setContents(desc); } /** * Sets the location of the cells to be linked to within this workbook * * @param desc the label describing the link * @param sheet the sheet containing the cells to be linked to * @param destcol the column number of the first destination linked cell * @param destrow the row number of the first destination linked cell * @param lastdestcol the column number of the last destination linked cell * @param lastdestrow the row number of the last destination linked cell */ public void setLocation(String desc, WritableSheet sheet, int destcol, int destrow, int lastdestcol, int lastdestrow) { super.setLocation(desc, sheet, destcol, destrow, lastdestcol, lastdestrow); } } jexcelapi/src/jxl/write/Blank.java0000750000175000017500000000506111207000610017311 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2001 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write; import jxl.Cell; import jxl.format.CellFormat; import jxl.write.biff.BlankRecord; /** * A blank cell. Despite not having any contents, it may contain * formatting information. Such cells are typically used when creating * templates */ public class Blank extends BlankRecord implements WritableCell { /** * Creates a cell which, when added to the sheet, will be presented at the * specified column and row co-ordinates * * @param c the column * @param r the row */ public Blank(int c, int r) { super(c, r); } /** * Creates a cell which, when added to the sheet, will be presented at the * specified column and row co-ordinates * in the manner specified by the CellFormat parameter * * @param c the column * @param r the row * @param st the cell format */ public Blank(int c, int r, CellFormat st) { super(c, r, st); } /** * Constructor used internally by the application when making a writable * copy of a spreadsheet being read in * * @param lc the cell to copy */ public Blank(Cell lc) { super(lc); } /** * Copy constructor used for deep copying * * @param col the column * @param row the row * @param b the balnk cell to copy */ protected Blank(int col, int row, Blank b) { super(col, row, b); } /** * Implementation of the deep copy function * * @param col the column which the new cell will occupy * @param row the row which the new cell will occupy * @return a copy of this cell, which can then be added to the sheet */ public WritableCell copyTo(int col, int row) { return new Blank(col, row, this); } } jexcelapi/src/jxl/write/Colour.java0000750000175000017500000000247011207000610017526 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write; /** * Enumeration class which contains the various colours available within * the standard Excel colour palette * * @deprecated This has been repackaged as jxl.format.Colour */ public final class Colour extends jxl.format.Colour { /** * Constructor * This is currently just a placeholder for backwards compatibility */ private Colour() { super(0, null, 0, 0, 0); } } jexcelapi/src/jxl/write/BorderLineStyle.java0000750000175000017500000000220311207000610021323 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write; /** * @deprecated Repackaged as jxl.format.BorderLineStyle */ public final class BorderLineStyle extends jxl.format.BorderLineStyle { /** * Constructor */ private BorderLineStyle() { super(0, null); } } jexcelapi/src/jxl/write/WriteException.java0000750000175000017500000000234511207000610021235 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write; import jxl.JXLException; /** * Exception thrown when using the API to generate an Excel file */ public abstract class WriteException extends JXLException { /** * Constructs this exception with the specified message * * @param s the message */ protected WriteException(String s) { super(s); } } jexcelapi/src/jxl/write/Label.java0000750000175000017500000000545211207000610017305 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2001 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write; import jxl.LabelCell; import jxl.format.CellFormat; import jxl.write.biff.LabelRecord; /** * A cell containing text which may be created by user applications */ public class Label extends LabelRecord implements WritableCell, LabelCell { /** * Creates a cell which, when added to the sheet, will be presented at the * specified column and row co-ordinates and will contain the specified text * * @param c the column * @param cont the text * @param r the row */ public Label(int c, int r, String cont) { super(c, r, cont); } /** * Creates a cell which, when added to the sheet, will be presented at the * specified column and row co-ordinates and will present the specified text * in the manner specified by the CellFormat parameter * * @param c the column * @param cont the data * @param r the row * @param st the cell format */ public Label(int c, int r, String cont, CellFormat st) { super(c, r, cont, st); } /** * Copy constructor used for deep copying * * @param col the column * @param row the row * @param l the label to copy */ protected Label(int col, int row, Label l) { super(col, row, l); } /** * Constructor used internally by the application when making a writable * copy of a spreadsheet being read in * * @param lc the label to copy */ public Label(LabelCell lc) { super(lc); } /** * Sets the string contents of this cell * * @param s the new data */ public void setString(String s) { super.setString(s); } /** * Implementation of the deep copy function * * @param col the column which the new cell will occupy * @param row the row which the new cell will occupy * @return a copy of this cell, which can then be added to the sheet */ public WritableCell copyTo(int col, int row) { return new Label(col, row, this); } } jexcelapi/src/jxl/write/biff/0000750000175000017500000000000011270605332016334 5ustar drazzibdrazzibjexcelapi/src/jxl/write/biff/PasswordRecord.java0000750000175000017500000000532011207000610022127 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.IntegerHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * A password record. Thanks to Michael Matthews for sending me the * code to actually store the password for the sheet */ class PasswordRecord extends WritableRecordData { /** * The password */ private String password; /** * The binary data */ private byte[] data; /** * Constructor * * @param pw the password */ public PasswordRecord(String pw) { super(Type.PASSWORD); password = pw; if (pw == null) { data = new byte[2]; IntegerHelper.getTwoBytes(0, data, 0); } else { byte [] passwordBytes = pw.getBytes(); int passwordHash = 0; for (int a = 0; a < passwordBytes.length; a++) { int shifted = rotLeft15Bit(passwordBytes[a], a + 1); passwordHash ^= shifted; } passwordHash ^= passwordBytes.length; passwordHash ^= 0xCE4B; data = new byte[2]; IntegerHelper.getTwoBytes(passwordHash, data, 0); } } /** * Constructor * * @param ph the password hash code */ public PasswordRecord(int ph) { super(Type.PASSWORD); data = new byte[2]; IntegerHelper.getTwoBytes(ph, data, 0); } /** * Gets the binary data for output to file * * @return the binary data */ public byte[] getData() { return data; } /** * Rotate the value by 15 bits. Thanks to Michael for this * * @param val * @param rotate * @return int */ private int rotLeft15Bit(int val, int rotate) { val = val &0x7FFF; for(; rotate > 0; rotate--) { if((val & 0x4000) != 0) { val = ((val << 1) & 0x7FFF) + 1; } else { val = (val << 1) & 0x7FFF; } } return val; } } jexcelapi/src/jxl/write/biff/EOFRecord.java0000750000175000017500000000250711207000610020742 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Record which marks the end of the current stream */ class EOFRecord extends WritableRecordData { /** * Constructor */ public EOFRecord() { super(Type.EOF); } /** * Returns the binary data to be written to the output file * * @return the binary data */ public byte[] getData() { return new byte[0]; } } jexcelapi/src/jxl/write/biff/TemplateRecord.java0000750000175000017500000000272211207000610022103 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2009 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Record which indicates whether or not this file is a template (Usually saved with .xlt file name extension) * should be refreshed when the workbook is loaded */ class TemplateRecord extends WritableRecordData { /** * Constructor * * @param template flag */ public TemplateRecord() { super(Type.TEMPLATE); } /** * Gets the binary data for output to file * * @return the binary data */ public byte[] getData() { return new byte[0]; } } jexcelapi/src/jxl/write/biff/Excel9FileRecord.java0000750000175000017500000000266611207000610022270 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2009 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Record which indicates whether this file has been generated by excel 2000 * should be refreshed when the workbook is loaded */ class Excel9FileRecord extends WritableRecordData { /** * Constructor * * @param template flag */ public Excel9FileRecord() { super(Type.EXCEL9FILE); } /** * Gets the binary data for output to file * * @return the binary data */ public byte[] getData() { return new byte[0]; } } jexcelapi/src/jxl/write/biff/CompoundFile.java30000750000175000017500000007323111207000610021643 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import java.io.OutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.HashMap; import common.Assert; import common.Logger; import jxl.biff.BaseCompoundFile; import jxl.biff.IntegerHelper; import jxl.read.biff.BiffException; /** * Writes out a compound file * * Header block is -1 * Excel data is e..n (where is the head extension blocks, normally 0 and * n is at least 8) * Summary information (8 blocks) * Document summary (8 blocks) * BBD is block p..q (where p=e+n+16 and q-p+1 is the number of BBD blocks) * Property storage block is q+b...r (normally 1 block) (where b is the number * of BBD blocks) */ final class CompoundFile extends BaseCompoundFile { /** * The logger */ private static Logger logger = Logger.getLogger(CompoundFile.class); /** * The stream to which the jumbled up data is written to */ private OutputStream out; /** * The organized biff records which form the actual excel data */ private byte[] excelData; /** * The size of the array */ private int size; /** * The size the excel data should be in order to comply with the * general compound file format */ private int requiredSize; /** * The number of blocks it takes to store the big block depot */ private int numBigBlockDepotBlocks; /** * The number of blocks it takes to store the small block depot chain */ private int numSmallBlockDepotChainBlocks; /** * The number of blocks it takes to store the small block depot */ private int numSmallBlockDepotBlocks; /** * The number of extension blocks required for the header to describe * the BBD */ private int numExtensionBlocks; /** * The extension block for the header */ private int extensionBlock; /** * The number of blocks it takes to store the excel data */ private int excelDataBlocks; /** * The start block of the root entry */ private int rootStartBlock; /** * The start block of the excel data */ private int excelDataStartBlock; /** * The start block of the big block depot */ private int bbdStartBlock; /** * The number of big blocks required for additional property sets */ private int additionalPropertyBlocks; /** * The total number of property sets in this compound file */ private int numPropertySets; /** * The number of blocks required to store the root entry property sets * and small block depot */ private int numRootEntryBlocks; /** * The list of additional, non standard property sets names */ private ArrayList additionalPropertySets; /** * A hash map of the original property sets keyed on name */ private HashMap readPropertySets; /** * The array of standard property set mappings */ private int[] standardPropertySetMappings; private ReadPropertyStorage rootEntryPropertySet; /** * Structure used to store the property set and the data */ private static final class ReadPropertyStorage { PropertyStorage propertyStorage; byte[] data; int number; ReadPropertyStorage(PropertyStorage ps, byte[] d, int n) { propertyStorage = ps; data = d; number = n; } } // The following member variables are used across methods when // writing out the big block depot /** * The current position within the bbd. Used when writing out the * BBD */ private int bbdPos; /** * The current bbd block */ private byte[] bigBlockDepot; /** * Constructor * * @param l the length of the data * @param os the output stream to write to * @param data the excel data * @param rcf the read compound */ public CompoundFile(byte[] data, int l, OutputStream os, jxl.read.biff.CompoundFile rcf) throws CopyAdditionalPropertySetsException, IOException { super(); size = l; excelData = data; readAdditionalPropertySets(rcf); numRootEntryBlocks = 1; numPropertySets = 4 + (additionalPropertySets != null ? additionalPropertySets.size() : 0); if (additionalPropertySets != null) { try { rootEntryPropertySet = new ReadPropertyStorage(rcf.getPropertySet(ROOT_ENTRY_NAME), rcf.getStream(ROOT_ENTRY_NAME), 0); int blocks = rootEntryPropertySet.data.length >= SMALL_BLOCK_THRESHOLD ? getBigBlocksRequired(rootEntryPropertySet.data.length) : SMALL_BLOCK_THRESHOLD / BIG_BLOCK_SIZE; additionalPropertyBlocks += blocks; } catch(BiffException e) { e.printStackTrace(); } numRootEntryBlocks += getBigBlocksRequired (additionalPropertySets.size() * PROPERTY_STORAGE_BLOCK_SIZE); } logger.debug("root entry requires " + numRootEntryBlocks + " blocks"); int blocks = getBigBlocksRequired(l); // First pad the data out so that it fits nicely into a whole number // of blocks if (l < SMALL_BLOCK_THRESHOLD) { requiredSize = SMALL_BLOCK_THRESHOLD; } else { requiredSize = blocks * BIG_BLOCK_SIZE; } out = os; // logger.debug("smallBlockDepot requires " + numSmallBlockDepotBlocks + " big blocks"); // Do the calculations excelDataBlocks = requiredSize/BIG_BLOCK_SIZE; numBigBlockDepotBlocks = 1; int blockChainLength = (BIG_BLOCK_SIZE - BIG_BLOCK_DEPOT_BLOCKS_POS)/4; int startTotalBlocks = excelDataBlocks + 8 + // summary block 8 + // document information additionalPropertyBlocks + numRootEntryBlocks; int totalBlocks = startTotalBlocks + numBigBlockDepotBlocks; // Calculate the number of BBD blocks needed to hold this info numBigBlockDepotBlocks = (int) Math.ceil( (double) totalBlocks / (double) (BIG_BLOCK_SIZE/4)); // Does this affect the total? totalBlocks = startTotalBlocks + numBigBlockDepotBlocks; // And recalculate numBigBlockDepotBlocks = (int) Math.ceil( (double) totalBlocks / (double) (BIG_BLOCK_SIZE/4)); // Does this affect the total? totalBlocks = startTotalBlocks + numBigBlockDepotBlocks; // See if the excel bbd chain can fit into the header block. // Remember to allow for the end of chain indicator if (numBigBlockDepotBlocks > blockChainLength - 1 ) { // Sod it - we need an extension block. We have to go through // the whole tiresome calculation again extensionBlock = 0; // Compute the number of extension blocks int bbdBlocksLeft = numBigBlockDepotBlocks - blockChainLength + 1; numExtensionBlocks = (int) Math.ceil((double) bbdBlocksLeft / (double) (BIG_BLOCK_SIZE/4 - 1)); // Modify the total number of blocks required and recalculate the // the number of bbd blocks totalBlocks = startTotalBlocks + numExtensionBlocks + numBigBlockDepotBlocks; numBigBlockDepotBlocks = (int) Math.ceil( (double) totalBlocks / (double) (BIG_BLOCK_SIZE/4)); // The final total totalBlocks = startTotalBlocks + numExtensionBlocks + numBigBlockDepotBlocks; } else { extensionBlock = -2; numExtensionBlocks = 0; } // Set the excel data start block to be after the header (and // its extensions) excelDataStartBlock = numExtensionBlocks; logger.debug("excelDataStartBlock " + excelDataStartBlock); // Set the bbd start block to be after all the excel data bbdStartBlock = excelDataStartBlock + excelDataBlocks + additionalPropertyBlocks + 16; logger.debug("bbdStartBlock " + bbdStartBlock); // Set the root start block to be after all the big block depot blocks rootStartBlock = bbdStartBlock + numBigBlockDepotBlocks; if (totalBlocks != rootStartBlock + numRootEntryBlocks) { logger.warn("Root start block and total blocks are inconsistent " + " generated file may be corrupt"); logger.warn("RootStartBlock " + rootStartBlock + " totalBlocks " + totalBlocks); } } /** * Reads the additional property sets from the read in compound file * * @return the number of blocks needed to store these property sets */ private void readAdditionalPropertySets (jxl.read.biff.CompoundFile readCompoundFile) throws CopyAdditionalPropertySetsException, IOException { if (readCompoundFile == null) { return; } additionalPropertySets = new ArrayList(); readPropertySets = new HashMap(); String[] psnames = readCompoundFile.getPropertySetNames(); int blocksRequired = 0; standardPropertySetMappings = new int[STANDARD_PROPERTY_SETS.length]; for (int i = 0 ; i < psnames.length ; i++) { // Add it to the hash map for later PropertyStorage ps = readCompoundFile.getPropertySet(psnames[i]); // If the name is non standard, then retrieve the property set // information boolean standard = false; for (int j = 0 ; j < STANDARD_PROPERTY_SETS.length && !standard ; j++) { if (psnames[i].equalsIgnoreCase(STANDARD_PROPERTY_SETS[j])) { standard = true; ReadPropertyStorage rps = new ReadPropertyStorage(ps, null, i); readPropertySets.put(psnames[i], rps); } } if (!standard) { try { byte[] data = null; if (ps.size > 0 ) { data = readCompoundFile.getStream(ps.name); } else { data = new byte[0]; } ReadPropertyStorage rps = new ReadPropertyStorage(ps, data, i); readPropertySets.put(psnames[i], rps); additionalPropertySets.add(rps); int blocks = data.length >= SMALL_BLOCK_THRESHOLD ? getBigBlocksRequired(data.length) : SMALL_BLOCK_THRESHOLD / BIG_BLOCK_SIZE; blocksRequired += blocks; } catch (BiffException e) { logger.error(e); throw new CopyAdditionalPropertySetsException(); } } } additionalPropertyBlocks = blocksRequired; } /** * Writes out the excel file in OLE compound file format * * @exception IOException */ public void write() throws IOException { writeHeader(); writeExcelData(); writeDocumentSummaryData(); writeSummaryData(); writeAdditionalPropertySets(); writeBigBlockDepot(); writePropertySets(); // Don't flush or close the stream - this is handled by the enclosing File // object } /** * Writes out any additional property sets */ private void writeAdditionalPropertySets() throws IOException { if (additionalPropertySets == null) { return; } logger.debug("Writing property set " + rootEntryPropertySet.propertyStorage.name); int numBlocks2 = rootEntryPropertySet.data.length >= SMALL_BLOCK_THRESHOLD ? getBigBlocksRequired(rootEntryPropertySet.data.length) : SMALL_BLOCK_THRESHOLD / BIG_BLOCK_SIZE; int requiredSize2 = numBlocks2 * BIG_BLOCK_SIZE; out.write(rootEntryPropertySet.data, 0, rootEntryPropertySet.data.length); byte[] padding2 = new byte[requiredSize2 - rootEntryPropertySet.data.length]; out.write(padding2, 0, padding2.length); logger.debug("data length " + rootEntryPropertySet.data.length + " Padding " + padding2.length); for (Iterator i = additionalPropertySets.iterator(); i.hasNext() ;) { ReadPropertyStorage rps = (ReadPropertyStorage) i.next(); byte[] data = rps.data; logger.debug("Writing property set " + rps.propertyStorage.name); int numBlocks = data.length >= SMALL_BLOCK_THRESHOLD ? getBigBlocksRequired(data.length) : SMALL_BLOCK_THRESHOLD / BIG_BLOCK_SIZE; int requiredSize = numBlocks * BIG_BLOCK_SIZE; out.write(data, 0, data.length); byte[] padding = new byte[requiredSize - data.length]; out.write(padding, 0, padding.length); } } /** * Writes out the excel data, padding it out with empty bytes as * necessary * Also write out empty * * @exception IOException */ private void writeExcelData() throws IOException { logger.debug("num excel data blocks " + excelDataBlocks + " excelData size " + requiredSize); out.write(excelData, 0, size); byte[] padding = new byte[requiredSize - size]; out.write(padding); } /** * Write out the document summary data. This is just blank * * @exception IOException */ private void writeDocumentSummaryData() throws IOException { byte[] padding = new byte[SMALL_BLOCK_THRESHOLD]; // Write out the summary information out.write(padding); } /** * Write out the summary data. This is just blank * * @exception IOException */ private void writeSummaryData() throws IOException { byte[] padding = new byte[SMALL_BLOCK_THRESHOLD]; // Write out the summary information out.write(padding); } /** * Writes the compound file header * * @exception IOException */ private void writeHeader() throws IOException { logger.debug("num extensions blocks for header: " + numExtensionBlocks); // Build up the header array byte[] headerBlock = new byte[BIG_BLOCK_SIZE]; byte[] extensionBlockData = new byte[BIG_BLOCK_SIZE * numExtensionBlocks]; // Copy in the identifier System.arraycopy(IDENTIFIER, 0, headerBlock, 0, IDENTIFIER.length); // Copy in some magic values - no idea what they mean headerBlock[0x18] = 0x3e; headerBlock[0x1a] = 0x3; headerBlock[0x1c] = (byte) 0xfe; headerBlock[0x1d] = (byte) 0xff; headerBlock[0x1e] = 0x9; headerBlock[0x20] = 0x6; headerBlock[0x39] = 0x10; // Set the number of BBD blocks IntegerHelper.getFourBytes(numBigBlockDepotBlocks, headerBlock, NUM_BIG_BLOCK_DEPOT_BLOCKS_POS); // Set the small block depot chain to -2 ie. no small block chain IntegerHelper.getFourBytes(-2, headerBlock, SMALL_BLOCK_DEPOT_BLOCK_POS); // Set the extension block IntegerHelper.getFourBytes(extensionBlock, headerBlock, EXTENSION_BLOCK_POS); // Set the number of extension blocks to be the number of BBD blocks - 1 IntegerHelper.getFourBytes(numExtensionBlocks, headerBlock, NUM_EXTENSION_BLOCK_POS); // Set the root start block IntegerHelper.getFourBytes(rootStartBlock, headerBlock, ROOT_START_BLOCK_POS); // Set the block numbers for the BBD. Set the BBD running // after the excel data and summary information int pos = BIG_BLOCK_DEPOT_BLOCKS_POS; // See how many blocks fit into the header int blocksToWrite = Math.min(numBigBlockDepotBlocks, (BIG_BLOCK_SIZE - BIG_BLOCK_DEPOT_BLOCKS_POS)/4); int extensionBlock = 0; int blocksWritten = 0; for (int i = 0 ; i < blocksToWrite; i++) { IntegerHelper.getFourBytes(bbdStartBlock + i, headerBlock, pos); pos += 4; blocksWritten++; } // Pad out the rest of the header with blanks for (int i = pos; i < BIG_BLOCK_SIZE; i++) { headerBlock[i] = (byte) 0xff; } out.write(headerBlock); // Write out the extension blocks pos = 0; for (int extBlock = 0; extBlock < numExtensionBlocks; extBlock++) { blocksToWrite = Math.min(numBigBlockDepotBlocks - blocksWritten, BIG_BLOCK_SIZE/4 -1); for(int j = 0 ; j < blocksToWrite; j++) { IntegerHelper.getFourBytes(bbdStartBlock + blocksWritten + j, extensionBlockData, pos); pos += 4; } blocksWritten += blocksToWrite; // Indicate the next block, or the termination of the chain int nextBlock = (blocksWritten == numBigBlockDepotBlocks) ? -2 : extBlock+1 ; IntegerHelper.getFourBytes(nextBlock, extensionBlockData, pos); pos +=4; } if (numExtensionBlocks > 0) { // Pad out the rest of the extension block with blanks for (int i = pos; i < extensionBlockData.length; i++) { extensionBlockData[i] = (byte) 0xff; } out.write(extensionBlockData); } } /** * Checks that the data can fit into the current BBD block. If not, * then it moves on to the next block * * @exception IOException */ private void checkBbdPos() throws IOException { if (bbdPos >= BIG_BLOCK_SIZE) { // Write out the extension block. This will simply be the next block out.write(bigBlockDepot); // Create a new block bigBlockDepot = new byte[BIG_BLOCK_SIZE]; bbdPos = 0; } } /** * Writes out the big block chain * * @param startBlock the starting block of the big block chain * @param numBlocks the number of blocks in the chain * @exception IOException */ private void writeBlockChain(int startBlock, int numBlocks) throws IOException { int blocksToWrite = numBlocks - 1; int blockNumber = startBlock + 1; while (blocksToWrite > 0) { int bbdBlocks = Math.min(blocksToWrite, (BIG_BLOCK_SIZE - bbdPos)/4); for (int i = 0 ; i < bbdBlocks; i++) { IntegerHelper.getFourBytes(blockNumber, bigBlockDepot, bbdPos); bbdPos +=4 ; blockNumber++; } blocksToWrite -= bbdBlocks; checkBbdPos(); } // Write the end of the block chain IntegerHelper.getFourBytes(-2, bigBlockDepot, bbdPos); bbdPos += 4; checkBbdPos(); } /** * Writes the block chains for the additional property sets * * @exception IOException */ private void writeAdditionalPropertySetBlockChains() throws IOException { if (additionalPropertySets == null) { return; } int blockNumber = excelDataStartBlock + excelDataBlocks + 16; int numBlocks2 = rootEntryPropertySet.data.length >= SMALL_BLOCK_THRESHOLD ? getBigBlocksRequired(rootEntryPropertySet.data.length) : SMALL_BLOCK_THRESHOLD / BIG_BLOCK_SIZE; String psname2 = rootEntryPropertySet.propertyStorage.name; logger.debug("writing big block chain for " + psname2 + " block " + blockNumber + " numBlocks " + numBlocks2); writeBlockChain(blockNumber, numBlocks2); blockNumber += numBlocks2; for (Iterator i = additionalPropertySets.iterator(); i.hasNext() ; ) { ReadPropertyStorage rps = (ReadPropertyStorage) i.next(); int numBlocks = rps.data.length >= SMALL_BLOCK_THRESHOLD ? getBigBlocksRequired(rps.data.length) : SMALL_BLOCK_THRESHOLD / BIG_BLOCK_SIZE; String psname = rps.propertyStorage.name; logger.debug("writing big block chain for " + psname + " block " + blockNumber + " numBlocks " + numBlocks); writeBlockChain(blockNumber, numBlocks); blockNumber += numBlocks; } } /** * Writes out the Big Block Depot * * @exception IOException */ private void writeBigBlockDepot() throws IOException { // This is after the excel data, the summary information, the // big block property sets and the small block depot bigBlockDepot = new byte[BIG_BLOCK_SIZE]; bbdPos = 0; // Write out the extension blocks, indicating them as special blocks for (int i = 0 ; i < numExtensionBlocks; i++) { IntegerHelper.getFourBytes(-3, bigBlockDepot, bbdPos); bbdPos += 4; checkBbdPos(); } writeBlockChain(excelDataStartBlock, excelDataBlocks); // The excel data has been written. Now write out the rest of it // Write the block chain for the summary information int summaryInfoBlock = excelDataStartBlock + excelDataBlocks + additionalPropertyBlocks; for (int i = summaryInfoBlock; i < summaryInfoBlock + 7; i++) { IntegerHelper.getFourBytes(i + 1, bigBlockDepot, bbdPos); bbdPos +=4 ; checkBbdPos(); } // Write the end of the block chain for the summary info block IntegerHelper.getFourBytes(-2, bigBlockDepot, bbdPos); bbdPos += 4; checkBbdPos(); // Write the block chain for the document summary information for (int i = summaryInfoBlock + 8; i < summaryInfoBlock + 15; i++) { IntegerHelper.getFourBytes(i + 1, bigBlockDepot, bbdPos); bbdPos +=4 ; checkBbdPos(); } // Write the end of the block chain for the document summary IntegerHelper.getFourBytes(-2, bigBlockDepot, bbdPos); bbdPos += 4; checkBbdPos(); // Write out the block chain for the copied property sets, if present writeAdditionalPropertySetBlockChains(); // The Big Block Depot immediately follows the document summary. Denote // these as a special block for (int i = 0; i < numBigBlockDepotBlocks; i++) { IntegerHelper.getFourBytes(-3, bigBlockDepot, bbdPos); bbdPos += 4; checkBbdPos(); } // Write the root entry writeBlockChain(rootStartBlock, numRootEntryBlocks); // Pad out the remainder of the block if (bbdPos != 0) { for (int i = bbdPos; i < BIG_BLOCK_SIZE; i++) { bigBlockDepot[i] = (byte) 0xff; } out.write(bigBlockDepot); } } /** * Calculates the number of big blocks required to store data of the * specified length * * @param length the length of the data * @return the number of big blocks required to store the data */ private int getBigBlocksRequired(int length) { int blocks = length / BIG_BLOCK_SIZE; return (length % BIG_BLOCK_SIZE > 0 )? blocks + 1 : blocks; } /** * Calculates the number of small blocks required to store data of the * specified length * * @param length the length of the data * @return the number of small blocks required to store the data */ private int getSmallBlocksRequired(int length) { int blocks = length / SMALL_BLOCK_SIZE; return (length % SMALL_BLOCK_SIZE > 0 )? blocks + 1 : blocks; } /** * Writes out the property sets * * @exception IOException */ private void writePropertySets() throws IOException { byte[] propertySetStorage = new byte[BIG_BLOCK_SIZE * numRootEntryBlocks]; int pos = 0; int[] mappings = null; // Build up the mappings array if (additionalPropertySets != null) { mappings = new int[numPropertySets]; // Map the standard ones to the first four for (int i = 0 ; i < STANDARD_PROPERTY_SETS.length ; i++) { ReadPropertyStorage rps = (ReadPropertyStorage) readPropertySets.get(STANDARD_PROPERTY_SETS[i]); mappings[rps.number] = i; } // Now go through the original ones int newMapping = STANDARD_PROPERTY_SETS.length; for (Iterator i = additionalPropertySets.iterator(); i.hasNext(); ) { ReadPropertyStorage rps = (ReadPropertyStorage) i.next(); mappings[rps.number] = newMapping; newMapping++; } } int dir = 0; int previous = 0; int next = 0; // Set the root entry property set PropertyStorage ps = new PropertyStorage(ROOT_ENTRY_NAME); ps.setType(5); ps.setStartBlock(-2); ps.setSize(0); ps.setPrevious(-1); ps.setNext(-1); ps.setColour(0); dir = 2; if (additionalPropertySets != null) { ReadPropertyStorage rps = (ReadPropertyStorage) readPropertySets.get(ROOT_ENTRY_NAME); dir = mappings[rps.propertyStorage.directory]; } ps.setDirectory(dir); System.arraycopy(ps.data, 0, propertySetStorage, pos, PROPERTY_STORAGE_BLOCK_SIZE); pos += PROPERTY_STORAGE_BLOCK_SIZE; // Set the workbook property set ps = new PropertyStorage(WORKBOOK_NAME); ps.setType(2); ps.setStartBlock(excelDataStartBlock); // start the excel data after immediately after this block ps.setSize(requiredSize); // alway use a big block stream - none of that messing around // with small blocks ps.setColour(1); previous = 3; if (additionalPropertySets != null) { ReadPropertyStorage rps = (ReadPropertyStorage) readPropertySets.get(WORKBOOK_NAME); previous = mappings[rps.propertyStorage.previous]; } ps.setPrevious(previous); ps.setNext(-1); ps.setDirectory(-1); ps.setColour(1); System.arraycopy(ps.data, 0, propertySetStorage, pos, PROPERTY_STORAGE_BLOCK_SIZE); pos += PROPERTY_STORAGE_BLOCK_SIZE; // Set the summary information ps = new PropertyStorage(SUMMARY_INFORMATION_NAME); ps.setType(2); ps.setStartBlock(excelDataStartBlock + excelDataBlocks); ps.setSize(SMALL_BLOCK_THRESHOLD); ps.setColour(1); previous = 1; next = 3; if (additionalPropertySets != null) { ReadPropertyStorage rps = (ReadPropertyStorage) readPropertySets.get(SUMMARY_INFORMATION_NAME); previous = rps.propertyStorage.previous != - 1 ? mappings[rps.propertyStorage.previous] : -1 ; next = rps.propertyStorage.next != - 1 ? mappings[rps.propertyStorage.next] : -1 ; } ps.setPrevious(previous); ps.setNext(next); ps.setDirectory(-1); ps.setColour(1); System.arraycopy(ps.data, 0, propertySetStorage, pos, PROPERTY_STORAGE_BLOCK_SIZE); pos += PROPERTY_STORAGE_BLOCK_SIZE; // Set the document summary information ps = new PropertyStorage(DOCUMENT_SUMMARY_INFORMATION_NAME); ps.setType(2); ps.setStartBlock(excelDataStartBlock + excelDataBlocks + 8); ps.setSize(SMALL_BLOCK_THRESHOLD); ps.setPrevious(-1); ps.setNext(-1); ps.setDirectory(-1); ps.setColour(1); System.arraycopy(ps.data, 0, propertySetStorage, pos, PROPERTY_STORAGE_BLOCK_SIZE); pos += PROPERTY_STORAGE_BLOCK_SIZE; // Write out the additional property sets if (additionalPropertySets == null) { out.write(propertySetStorage); return; } int bigBlock = excelDataStartBlock + excelDataBlocks + 16 + 18; for (Iterator i = additionalPropertySets.iterator() ; i.hasNext(); ) { ReadPropertyStorage rps = (ReadPropertyStorage) i.next(); ps = new PropertyStorage(rps.propertyStorage.name); ps.setType(rps.propertyStorage.type); ps.setStartBlock(bigBlock); ps.setSize(Math.max(rps.propertyStorage.size, SMALL_BLOCK_THRESHOLD)); previous = rps.propertyStorage.previous != -1 ? mappings[rps.propertyStorage.previous] : -1; next = rps.propertyStorage.next != -1 ? mappings[rps.propertyStorage.next] : -1; dir = rps.propertyStorage.directory != -1 ? mappings[rps.propertyStorage.directory] : -1; ps.setPrevious(previous); ps.setNext(next); ps.setDirectory(dir); ps.setColour(1); System.arraycopy(ps.data, 0, propertySetStorage, pos, PROPERTY_STORAGE_BLOCK_SIZE); pos += PROPERTY_STORAGE_BLOCK_SIZE; if (rps.data.length >= SMALL_BLOCK_THRESHOLD) { bigBlock += getBigBlocksRequired(rps.data.length); } else { bigBlock += SMALL_BLOCK_THRESHOLD / BIG_BLOCK_SIZE; } } out.write(propertySetStorage); } } jexcelapi/src/jxl/write/biff/CompoundFile.java40000750000175000017500000007335311207000610021651 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import java.io.OutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.HashMap; import common.Assert; import common.Logger; import jxl.biff.BaseCompoundFile; import jxl.biff.IntegerHelper; import jxl.read.biff.BiffException; /** * Writes out a compound file * * Header block is -1 * Excel data is e..n (where is the head extension blocks, normally 0 and * n is at least 8) * Summary information (8 blocks) * Document summary (8 blocks) * BBD is block p..q (where p=e+n+16 and q-p+1 is the number of BBD blocks) * Property storage block is q+b...r (normally 1 block) (where b is the number * of BBD blocks) */ final class CompoundFile extends BaseCompoundFile { /** * The logger */ private static Logger logger = Logger.getLogger(CompoundFile.class); /** * The stream to which the jumbled up data is written to */ private OutputStream out; /** * The organized biff records which form the actual excel data */ private byte[] excelData; /** * The size of the array */ private int size; /** * The size the excel data should be in order to comply with the * general compound file format */ private int requiredSize; /** * The number of blocks it takes to store the big block depot */ private int numBigBlockDepotBlocks; /** * The number of blocks it takes to store the small block depot chain */ private int numSmallBlockDepotChainBlocks; /** * The number of blocks it takes to store the small block depot */ private int numSmallBlockDepotBlocks; /** * The number of extension blocks required for the header to describe * the BBD */ private int numExtensionBlocks; /** * The extension block for the header */ private int extensionBlock; /** * The number of blocks it takes to store the excel data */ private int excelDataBlocks; /** * The start block of the root entry */ private int rootStartBlock; /** * The start block of the excel data */ private int excelDataStartBlock; /** * The start block of the big block depot */ private int bbdStartBlock; /** * The number of big blocks required for additional property sets */ private int additionalPropertyBlocks; /** * The total number of property sets in this compound file */ private int numPropertySets; /** * The number of blocks required to store the root entry property sets * and small block depot */ private int numRootEntryBlocks; /** * The list of additional, non standard property sets names */ private ArrayList additionalPropertySets; /** * A hash map of the original property sets keyed on name */ private HashMap readPropertySets; /** * The array of standard property set mappings */ private int[] standardPropertySetMappings; private ReadPropertyStorage rootEntryPropertySet; /** * Structure used to store the property set and the data */ private static final class ReadPropertyStorage { PropertyStorage propertyStorage; byte[] data; int number; ReadPropertyStorage(PropertyStorage ps, byte[] d, int n) { propertyStorage = ps; data = d; number = n; } } // The following member variables are used across methods when // writing out the big block depot /** * The current position within the bbd. Used when writing out the * BBD */ private int bbdPos; /** * The current bbd block */ private byte[] bigBlockDepot; /** * Constructor * * @param l the length of the data * @param os the output stream to write to * @param data the excel data * @param rcf the read compound */ public CompoundFile(byte[] data, int l, OutputStream os, jxl.read.biff.CompoundFile rcf) throws CopyAdditionalPropertySetsException, IOException { super(); size = l; excelData = data; readAdditionalPropertySets(rcf); numRootEntryBlocks = 1; numPropertySets = 4 + (additionalPropertySets != null ? additionalPropertySets.size() : 0); if (additionalPropertySets != null) { /* try { rootEntryPropertySet = new ReadPropertyStorage(rcf.getPropertySet(ROOT_ENTRY_NAME), rcf.getStream(ROOT_ENTRY_NAME), 0); int blocks = rootEntryPropertySet.data.length >= SMALL_BLOCK_THRESHOLD ? getBigBlocksRequired(rootEntryPropertySet.data.length) : SMALL_BLOCK_THRESHOLD / BIG_BLOCK_SIZE; additionalPropertyBlocks += blocks; } catch(BiffException e) { e.printStackTrace(); } */ numRootEntryBlocks += getBigBlocksRequired (additionalPropertySets.size() * PROPERTY_STORAGE_BLOCK_SIZE); } logger.debug("root entry requires " + numRootEntryBlocks + " blocks"); int blocks = getBigBlocksRequired(l); // First pad the data out so that it fits nicely into a whole number // of blocks if (l < SMALL_BLOCK_THRESHOLD) { requiredSize = SMALL_BLOCK_THRESHOLD; } else { requiredSize = blocks * BIG_BLOCK_SIZE; } out = os; // logger.debug("smallBlockDepot requires " + numSmallBlockDepotBlocks + " big blocks"); // Do the calculations excelDataBlocks = requiredSize/BIG_BLOCK_SIZE; numBigBlockDepotBlocks = 1; int blockChainLength = (BIG_BLOCK_SIZE - BIG_BLOCK_DEPOT_BLOCKS_POS)/4; int startTotalBlocks = excelDataBlocks + 8 + // summary block 8 + // document information additionalPropertyBlocks + numRootEntryBlocks; int totalBlocks = startTotalBlocks + numBigBlockDepotBlocks; // Calculate the number of BBD blocks needed to hold this info numBigBlockDepotBlocks = (int) Math.ceil( (double) totalBlocks / (double) (BIG_BLOCK_SIZE/4)); // Does this affect the total? totalBlocks = startTotalBlocks + numBigBlockDepotBlocks; // And recalculate numBigBlockDepotBlocks = (int) Math.ceil( (double) totalBlocks / (double) (BIG_BLOCK_SIZE/4)); // Does this affect the total? totalBlocks = startTotalBlocks + numBigBlockDepotBlocks; // See if the excel bbd chain can fit into the header block. // Remember to allow for the end of chain indicator if (numBigBlockDepotBlocks > blockChainLength - 1 ) { // Sod it - we need an extension block. We have to go through // the whole tiresome calculation again extensionBlock = 0; // Compute the number of extension blocks int bbdBlocksLeft = numBigBlockDepotBlocks - blockChainLength + 1; numExtensionBlocks = (int) Math.ceil((double) bbdBlocksLeft / (double) (BIG_BLOCK_SIZE/4 - 1)); // Modify the total number of blocks required and recalculate the // the number of bbd blocks totalBlocks = startTotalBlocks + numExtensionBlocks + numBigBlockDepotBlocks; numBigBlockDepotBlocks = (int) Math.ceil( (double) totalBlocks / (double) (BIG_BLOCK_SIZE/4)); // The final total totalBlocks = startTotalBlocks + numExtensionBlocks + numBigBlockDepotBlocks; } else { extensionBlock = -2; numExtensionBlocks = 0; } // Set the excel data start block to be after the header (and // its extensions) excelDataStartBlock = numExtensionBlocks; logger.debug("excelDataStartBlock " + excelDataStartBlock); // Set the bbd start block to be after all the excel data bbdStartBlock = excelDataStartBlock + excelDataBlocks + additionalPropertyBlocks + 16; logger.debug("bbdStartBlock " + bbdStartBlock); // Set the root start block to be after all the big block depot blocks rootStartBlock = bbdStartBlock + numBigBlockDepotBlocks; if (totalBlocks != rootStartBlock + numRootEntryBlocks) { logger.warn("Root start block and total blocks are inconsistent " + " generated file may be corrupt"); logger.warn("RootStartBlock " + rootStartBlock + " totalBlocks " + totalBlocks); } } /** * Reads the additional property sets from the read in compound file * * @return the number of blocks needed to store these property sets */ private void readAdditionalPropertySets (jxl.read.biff.CompoundFile readCompoundFile) throws CopyAdditionalPropertySetsException, IOException { if (readCompoundFile == null) { return; } additionalPropertySets = new ArrayList(); readPropertySets = new HashMap(); String[] psnames = readCompoundFile.getPropertySetNames(); int blocksRequired = 0; standardPropertySetMappings = new int[STANDARD_PROPERTY_SETS.length]; for (int i = 0 ; i < psnames.length ; i++) { // Add it to the hash map for later PropertyStorage ps = readCompoundFile.getPropertySet(psnames[i]); // If the name is non standard, then retrieve the property set // information boolean standard = false; for (int j = 0 ; j < STANDARD_PROPERTY_SETS.length && !standard ; j++) { if (psnames[i].equalsIgnoreCase(STANDARD_PROPERTY_SETS[j])) { standard = true; ReadPropertyStorage rps = new ReadPropertyStorage(ps, null, i); readPropertySets.put(psnames[i], rps); } } if (!standard) { try { byte[] data = null; if (ps.size > 0 ) { data = readCompoundFile.getStream(ps.name); } else { data = new byte[0]; } ReadPropertyStorage rps = new ReadPropertyStorage(ps, data, i); readPropertySets.put(psnames[i], rps); additionalPropertySets.add(rps); int blocks = data.length >= SMALL_BLOCK_THRESHOLD ? getBigBlocksRequired(data.length) : SMALL_BLOCK_THRESHOLD / BIG_BLOCK_SIZE; blocksRequired += blocks; } catch (BiffException e) { logger.error(e); throw new CopyAdditionalPropertySetsException(); } } } additionalPropertyBlocks = blocksRequired; } /** * Writes out the excel file in OLE compound file format * * @exception IOException */ public void write() throws IOException { writeHeader(); writeExcelData(); writeDocumentSummaryData(); writeSummaryData(); writeAdditionalPropertySets(); writeBigBlockDepot(); writePropertySets(); // Don't flush or close the stream - this is handled by the enclosing File // object } /** * Writes out any additional property sets */ private void writeAdditionalPropertySets() throws IOException { if (additionalPropertySets == null) { return; } /* logger.debug("Writing property set " + rootEntryPropertySet.propertyStorage.name); int numBlocks2 = rootEntryPropertySet.data.length >= SMALL_BLOCK_THRESHOLD ? getBigBlocksRequired(rootEntryPropertySet.data.length) : SMALL_BLOCK_THRESHOLD / BIG_BLOCK_SIZE; int requiredSize2 = numBlocks2 * BIG_BLOCK_SIZE; out.write(rootEntryPropertySet.data, 0, rootEntryPropertySet.data.length); byte[] padding2 = new byte[requiredSize2 - rootEntryPropertySet.data.length]; out.write(padding2, 0, padding2.length); logger.debug("data length " + rootEntryPropertySet.data.length + " Padding " + padding2.length); */ for (Iterator i = additionalPropertySets.iterator(); i.hasNext() ;) { ReadPropertyStorage rps = (ReadPropertyStorage) i.next(); byte[] data = rps.data; logger.debug("Writing property set " + rps.propertyStorage.name); int numBlocks = data.length >= SMALL_BLOCK_THRESHOLD ? getBigBlocksRequired(data.length) : SMALL_BLOCK_THRESHOLD / BIG_BLOCK_SIZE; int requiredSize = numBlocks * BIG_BLOCK_SIZE; out.write(data, 0, data.length); byte[] padding = new byte[requiredSize - data.length]; out.write(padding, 0, padding.length); } } /** * Writes out the excel data, padding it out with empty bytes as * necessary * Also write out empty * * @exception IOException */ private void writeExcelData() throws IOException { logger.debug("num excel data blocks " + excelDataBlocks + " excelData size " + requiredSize); out.write(excelData, 0, size); byte[] padding = new byte[requiredSize - size]; out.write(padding); } /** * Write out the document summary data. This is just blank * * @exception IOException */ private void writeDocumentSummaryData() throws IOException { byte[] padding = new byte[SMALL_BLOCK_THRESHOLD]; // Write out the summary information out.write(padding); } /** * Write out the summary data. This is just blank * * @exception IOException */ private void writeSummaryData() throws IOException { byte[] padding = new byte[SMALL_BLOCK_THRESHOLD]; // Write out the summary information out.write(padding); } /** * Writes the compound file header * * @exception IOException */ private void writeHeader() throws IOException { logger.debug("num extensions blocks for header: " + numExtensionBlocks); // Build up the header array byte[] headerBlock = new byte[BIG_BLOCK_SIZE]; byte[] extensionBlockData = new byte[BIG_BLOCK_SIZE * numExtensionBlocks]; // Copy in the identifier System.arraycopy(IDENTIFIER, 0, headerBlock, 0, IDENTIFIER.length); // Copy in some magic values - no idea what they mean headerBlock[0x18] = 0x3e; headerBlock[0x1a] = 0x3; headerBlock[0x1c] = (byte) 0xfe; headerBlock[0x1d] = (byte) 0xff; headerBlock[0x1e] = 0x9; headerBlock[0x20] = 0x6; headerBlock[0x39] = 0x10; // Set the number of BBD blocks IntegerHelper.getFourBytes(numBigBlockDepotBlocks, headerBlock, NUM_BIG_BLOCK_DEPOT_BLOCKS_POS); // Set the small block depot chain to -2 ie. no small block chain IntegerHelper.getFourBytes(-2, headerBlock, SMALL_BLOCK_DEPOT_BLOCK_POS); // Set the extension block IntegerHelper.getFourBytes(extensionBlock, headerBlock, EXTENSION_BLOCK_POS); // Set the number of extension blocks to be the number of BBD blocks - 1 IntegerHelper.getFourBytes(numExtensionBlocks, headerBlock, NUM_EXTENSION_BLOCK_POS); // Set the root start block IntegerHelper.getFourBytes(rootStartBlock, headerBlock, ROOT_START_BLOCK_POS); // Set the block numbers for the BBD. Set the BBD running // after the excel data and summary information int pos = BIG_BLOCK_DEPOT_BLOCKS_POS; // See how many blocks fit into the header int blocksToWrite = Math.min(numBigBlockDepotBlocks, (BIG_BLOCK_SIZE - BIG_BLOCK_DEPOT_BLOCKS_POS)/4); int extensionBlock = 0; int blocksWritten = 0; for (int i = 0 ; i < blocksToWrite; i++) { IntegerHelper.getFourBytes(bbdStartBlock + i, headerBlock, pos); pos += 4; blocksWritten++; } // Pad out the rest of the header with blanks for (int i = pos; i < BIG_BLOCK_SIZE; i++) { headerBlock[i] = (byte) 0xff; } out.write(headerBlock); // Write out the extension blocks pos = 0; for (int extBlock = 0; extBlock < numExtensionBlocks; extBlock++) { blocksToWrite = Math.min(numBigBlockDepotBlocks - blocksWritten, BIG_BLOCK_SIZE/4 -1); for(int j = 0 ; j < blocksToWrite; j++) { IntegerHelper.getFourBytes(bbdStartBlock + blocksWritten + j, extensionBlockData, pos); pos += 4; } blocksWritten += blocksToWrite; // Indicate the next block, or the termination of the chain int nextBlock = (blocksWritten == numBigBlockDepotBlocks) ? -2 : extBlock+1 ; IntegerHelper.getFourBytes(nextBlock, extensionBlockData, pos); pos +=4; } if (numExtensionBlocks > 0) { // Pad out the rest of the extension block with blanks for (int i = pos; i < extensionBlockData.length; i++) { extensionBlockData[i] = (byte) 0xff; } out.write(extensionBlockData); } } /** * Checks that the data can fit into the current BBD block. If not, * then it moves on to the next block * * @exception IOException */ private void checkBbdPos() throws IOException { if (bbdPos >= BIG_BLOCK_SIZE) { // Write out the extension block. This will simply be the next block out.write(bigBlockDepot); // Create a new block bigBlockDepot = new byte[BIG_BLOCK_SIZE]; bbdPos = 0; } } /** * Writes out the big block chain * * @param startBlock the starting block of the big block chain * @param numBlocks the number of blocks in the chain * @exception IOException */ private void writeBlockChain(int startBlock, int numBlocks) throws IOException { int blocksToWrite = numBlocks - 1; int blockNumber = startBlock + 1; while (blocksToWrite > 0) { int bbdBlocks = Math.min(blocksToWrite, (BIG_BLOCK_SIZE - bbdPos)/4); for (int i = 0 ; i < bbdBlocks; i++) { IntegerHelper.getFourBytes(blockNumber, bigBlockDepot, bbdPos); bbdPos +=4 ; blockNumber++; } blocksToWrite -= bbdBlocks; checkBbdPos(); } // Write the end of the block chain IntegerHelper.getFourBytes(-2, bigBlockDepot, bbdPos); bbdPos += 4; checkBbdPos(); } /** * Writes the block chains for the additional property sets * * @exception IOException */ private void writeAdditionalPropertySetBlockChains() throws IOException { if (additionalPropertySets == null) { return; } int blockNumber = excelDataStartBlock + excelDataBlocks + 16; /* int numBlocks2 = rootEntryPropertySet.data.length >= SMALL_BLOCK_THRESHOLD ? getBigBlocksRequired(rootEntryPropertySet.data.length) : SMALL_BLOCK_THRESHOLD / BIG_BLOCK_SIZE; String psname2 = rootEntryPropertySet.propertyStorage.name; logger.debug("writing big block chain for " + psname2 + " block " + blockNumber + " numBlocks " + numBlocks2); writeBlockChain(blockNumber, numBlocks2); blockNumber += numBlocks2; */ for (Iterator i = additionalPropertySets.iterator(); i.hasNext() ; ) { ReadPropertyStorage rps = (ReadPropertyStorage) i.next(); int numBlocks = rps.data.length >= SMALL_BLOCK_THRESHOLD ? getBigBlocksRequired(rps.data.length) : SMALL_BLOCK_THRESHOLD / BIG_BLOCK_SIZE; String psname = rps.propertyStorage.name; logger.debug("writing big block chain for " + psname + " block " + blockNumber + " numBlocks " + numBlocks); writeBlockChain(blockNumber, numBlocks); blockNumber += numBlocks; } } /** * Writes out the Big Block Depot * * @exception IOException */ private void writeBigBlockDepot() throws IOException { // This is after the excel data, the summary information, the // big block property sets and the small block depot bigBlockDepot = new byte[BIG_BLOCK_SIZE]; bbdPos = 0; // Write out the extension blocks, indicating them as special blocks for (int i = 0 ; i < numExtensionBlocks; i++) { IntegerHelper.getFourBytes(-3, bigBlockDepot, bbdPos); bbdPos += 4; checkBbdPos(); } writeBlockChain(excelDataStartBlock, excelDataBlocks); // The excel data has been written. Now write out the rest of it // Write the block chain for the summary information int summaryInfoBlock = excelDataStartBlock + excelDataBlocks + additionalPropertyBlocks; for (int i = summaryInfoBlock; i < summaryInfoBlock + 7; i++) { IntegerHelper.getFourBytes(i + 1, bigBlockDepot, bbdPos); bbdPos +=4 ; checkBbdPos(); } // Write the end of the block chain for the summary info block IntegerHelper.getFourBytes(-2, bigBlockDepot, bbdPos); bbdPos += 4; checkBbdPos(); // Write the block chain for the document summary information for (int i = summaryInfoBlock + 8; i < summaryInfoBlock + 15; i++) { IntegerHelper.getFourBytes(i + 1, bigBlockDepot, bbdPos); bbdPos +=4 ; checkBbdPos(); } // Write the end of the block chain for the document summary IntegerHelper.getFourBytes(-2, bigBlockDepot, bbdPos); bbdPos += 4; checkBbdPos(); // Write out the block chain for the copied property sets, if present writeAdditionalPropertySetBlockChains(); // The Big Block Depot immediately follows the document summary. Denote // these as a special block for (int i = 0; i < numBigBlockDepotBlocks; i++) { IntegerHelper.getFourBytes(-3, bigBlockDepot, bbdPos); bbdPos += 4; checkBbdPos(); } // Write the root entry writeBlockChain(rootStartBlock, numRootEntryBlocks); // Pad out the remainder of the block if (bbdPos != 0) { for (int i = bbdPos; i < BIG_BLOCK_SIZE; i++) { bigBlockDepot[i] = (byte) 0xff; } out.write(bigBlockDepot); } } /** * Calculates the number of big blocks required to store data of the * specified length * * @param length the length of the data * @return the number of big blocks required to store the data */ private int getBigBlocksRequired(int length) { int blocks = length / BIG_BLOCK_SIZE; return (length % BIG_BLOCK_SIZE > 0 )? blocks + 1 : blocks; } /** * Calculates the number of small blocks required to store data of the * specified length * * @param length the length of the data * @return the number of small blocks required to store the data */ private int getSmallBlocksRequired(int length) { int blocks = length / SMALL_BLOCK_SIZE; return (length % SMALL_BLOCK_SIZE > 0 )? blocks + 1 : blocks; } /** * Writes out the property sets * * @exception IOException */ private void writePropertySets() throws IOException { byte[] propertySetStorage = new byte[BIG_BLOCK_SIZE * numRootEntryBlocks]; int pos = 0; int[] mappings = null; // Build up the mappings array if (additionalPropertySets != null) { mappings = new int[numPropertySets]; // Map the standard ones to the first four for (int i = 0 ; i < STANDARD_PROPERTY_SETS.length ; i++) { ReadPropertyStorage rps = (ReadPropertyStorage) readPropertySets.get(STANDARD_PROPERTY_SETS[i]); mappings[rps.number] = i; } // Now go through the original ones int newMapping = STANDARD_PROPERTY_SETS.length; for (Iterator i = additionalPropertySets.iterator(); i.hasNext(); ) { ReadPropertyStorage rps = (ReadPropertyStorage) i.next(); mappings[rps.number] = newMapping; newMapping++; } } int dir = 0; int previous = 0; int next = 0; // Set the root entry property set PropertyStorage ps = new PropertyStorage(ROOT_ENTRY_NAME); ps.setType(5); ps.setStartBlock(-2); ps.setSize(0); ps.setPrevious(-1); ps.setNext(-1); ps.setColour(0); dir = 2; if (additionalPropertySets != null) { ReadPropertyStorage rps = (ReadPropertyStorage) readPropertySets.get(ROOT_ENTRY_NAME); dir = mappings[rps.propertyStorage.directory]; } ps.setDirectory(dir); System.arraycopy(ps.data, 0, propertySetStorage, pos, PROPERTY_STORAGE_BLOCK_SIZE); pos += PROPERTY_STORAGE_BLOCK_SIZE; // Set the workbook property set ps = new PropertyStorage(WORKBOOK_NAME); ps.setType(2); ps.setStartBlock(excelDataStartBlock); // start the excel data after immediately after this block ps.setSize(requiredSize); // alway use a big block stream - none of that messing around // with small blocks ps.setColour(1); previous = 3; if (additionalPropertySets != null) { ReadPropertyStorage rps = (ReadPropertyStorage) readPropertySets.get(WORKBOOK_NAME); previous = mappings[rps.propertyStorage.previous]; } ps.setPrevious(previous); ps.setNext(-1); ps.setDirectory(-1); // ps.setColour(1); System.arraycopy(ps.data, 0, propertySetStorage, pos, PROPERTY_STORAGE_BLOCK_SIZE); pos += PROPERTY_STORAGE_BLOCK_SIZE; // Set the summary information ps = new PropertyStorage(SUMMARY_INFORMATION_NAME); ps.setType(2); ps.setStartBlock(excelDataStartBlock + excelDataBlocks); ps.setSize(SMALL_BLOCK_THRESHOLD); // ps.setColour(1); previous = 1; next = 3; if (additionalPropertySets != null) { ReadPropertyStorage rps = (ReadPropertyStorage) readPropertySets.get(SUMMARY_INFORMATION_NAME); previous = rps.propertyStorage.previous != - 1 ? mappings[rps.propertyStorage.previous] : -1 ; next = rps.propertyStorage.next != - 1 ? mappings[rps.propertyStorage.next] : -1 ; } ps.setPrevious(previous); ps.setNext(next); ps.setDirectory(-1); // ps.setColour(1); System.arraycopy(ps.data, 0, propertySetStorage, pos, PROPERTY_STORAGE_BLOCK_SIZE); pos += PROPERTY_STORAGE_BLOCK_SIZE; // Set the document summary information ps = new PropertyStorage(DOCUMENT_SUMMARY_INFORMATION_NAME); ps.setType(2); ps.setStartBlock(excelDataStartBlock + excelDataBlocks + 8); ps.setSize(SMALL_BLOCK_THRESHOLD); ps.setPrevious(-1); ps.setNext(-1); ps.setDirectory(-1); // ps.setColour(1); System.arraycopy(ps.data, 0, propertySetStorage, pos, PROPERTY_STORAGE_BLOCK_SIZE); pos += PROPERTY_STORAGE_BLOCK_SIZE; // Write out the additional property sets if (additionalPropertySets == null) { out.write(propertySetStorage); return; } int bigBlock = excelDataStartBlock + excelDataBlocks + 16 + 18; for (Iterator i = additionalPropertySets.iterator() ; i.hasNext(); ) { ReadPropertyStorage rps = (ReadPropertyStorage) i.next(); ps = new PropertyStorage(rps.propertyStorage.name); ps.setType(rps.propertyStorage.type); ps.setStartBlock(bigBlock); ps.setSize(Math.max(rps.propertyStorage.size, SMALL_BLOCK_THRESHOLD)); previous = rps.propertyStorage.previous != -1 ? mappings[rps.propertyStorage.previous] : -1; next = rps.propertyStorage.next != -1 ? mappings[rps.propertyStorage.next] : -1; dir = rps.propertyStorage.directory != -1 ? mappings[rps.propertyStorage.directory] : -1; ps.setPrevious(previous); ps.setNext(next); ps.setDirectory(dir); // ps.setColour(1); System.arraycopy(ps.data, 0, propertySetStorage, pos, PROPERTY_STORAGE_BLOCK_SIZE); pos += PROPERTY_STORAGE_BLOCK_SIZE; if (rps.data.length >= SMALL_BLOCK_THRESHOLD) { bigBlock += getBigBlocksRequired(rps.data.length); } else { bigBlock += SMALL_BLOCK_THRESHOLD / BIG_BLOCK_SIZE; } } out.write(propertySetStorage); } } jexcelapi/src/jxl/write/biff/IterationRecord.java0000750000175000017500000000307511207000610022270 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Stores the iteration option from the dialog box */ class IterationRecord extends WritableRecordData { /** * The iterate flag */ private boolean iterate; /** * The binary data */ private byte[] data; /** * Constructor * * @param it the iterator flag */ public IterationRecord(boolean it) { super(Type.ITERATION); iterate = it; data = new byte[2]; if (iterate) { data[0] = 1; } } /** * Gets the binary data for output * * @return the binary data */ public byte[] getData() { return data; } } jexcelapi/src/jxl/write/biff/TopMarginRecord.java0000750000175000017500000000213511207000610022226 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.Type; /** * The settings for the left margin */ class TopMarginRecord extends MarginRecord { TopMarginRecord(double v) { super(Type.TOPMARGIN, v); } } jexcelapi/src/jxl/write/biff/PrintHeadersRecord.java0000750000175000017500000000315111207000610022715 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * The headings options from the Page Setup dialog box */ class PrintHeadersRecord extends WritableRecordData { /** * The binary data */ private byte[] data; /** * Flag to print headers */ private boolean printHeaders; /** * Constructor * * @param ph print headers flag */ public PrintHeadersRecord(boolean ph) { super(Type.PRINTHEADERS); printHeaders = ph; data = new byte[2]; if (printHeaders) { data[0] = 1; } } /** * Gets the binary data for output to file * * @return the binary data */ public byte[] getData() { return data; } } jexcelapi/src/jxl/write/biff/LeftMarginRecord.java0000750000175000017500000000214011207000610022352 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.Type; /** * The settings for the left margin */ class LeftMarginRecord extends MarginRecord { LeftMarginRecord(double v) { super(Type.LEFTMARGIN, v); } } jexcelapi/src/jxl/write/biff/DateRecord.java0000750000175000017500000002022211207000610021200 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2001 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import java.text.DateFormat; import java.util.Calendar; import java.util.Date; import jxl.common.Logger; import jxl.CellType; import jxl.DateCell; import jxl.biff.DoubleHelper; import jxl.biff.Type; import jxl.format.CellFormat; import jxl.write.DateFormats; import jxl.write.WritableCellFormat; /** * A date stored in the database */ public abstract class DateRecord extends CellValue { /** * The logger */ private static Logger logger = Logger.getLogger(DateRecord.class); /** * The excel value of the date */ private double value; /** * The java representation of the date */ private Date date; /** * Indicates whether this is a full date, or just a time only */ private boolean time; // The number of days between 01 Jan 1900 and 01 Jan 1970 - this gives // the UTC offset /** */ private final static int utcOffsetDays = 25569; // The number of milliseconds in a day /** */ private final static long msInADay = 24 * 60 * 60 * 1000; /** * This is package protected so that the worksheet might detect * whether or not to override it with the column cell format */ static final WritableCellFormat defaultDateFormat = new WritableCellFormat(DateFormats.DEFAULT); // The number of days between 1 Jan 1900 and 1 March 1900. Excel thinks // the day before this was 29th Feb 1900, but it was 28th Feb 19000. // I guess the programmers thought nobody would notice that they // couldn't be bothered to program this dating anomaly properly /** */ private final static int nonLeapDay = 61; /** * Class definition for a dummy variable */ protected static final class GMTDate { public GMTDate(){} }; /** * Constructor invoked by the user API * * @param c the column * @param r the row * @param d the date */ protected DateRecord(int c, int r, Date d) { this(c, r, d, defaultDateFormat, false); } /** * Constructor invoked by the user API * * @param c the column * @param r the row * @param d the date * @param a adjust timezone */ protected DateRecord(int c, int r, Date d, GMTDate a) { this(c, r, d, defaultDateFormat, false); } /** * Constructor invoked from the user API * * @param c the column * @param r the row * @param st the format for the date * @param d the date */ protected DateRecord(int c, int r, Date d, CellFormat st) { super(Type.NUMBER, c, r,st); date = d; calculateValue(true); } /** * Constructor invoked from the user API * * @param c the column * @param r the row * @param st the format for the date * @param d the date * @param a adjust for the timezone */ protected DateRecord(int c, int r, Date d, CellFormat st, GMTDate a) { super(Type.NUMBER, c, r, st); date = d; calculateValue(false); } /** * Constructor invoked from the API * * @param c the column * @param r the row * @param st the date format * @param tim time indicator * @param d the date */ protected DateRecord(int c, int r, Date d, CellFormat st, boolean tim) { super(Type.NUMBER, c, r, st); date = d; time = tim; calculateValue(false); } /** * Constructor invoked when copying a readable spreadsheet * * @param dc the date to copy */ protected DateRecord(DateCell dc) { super(Type.NUMBER, dc); date = dc.getDate(); time = dc.isTime(); calculateValue(false); } /** * Copy constructor * * @param c the column * @param r the row * @param dr the record to copy */ protected DateRecord(int c, int r, DateRecord dr) { super(Type.NUMBER, c, r, dr); value = dr.value; time = dr.time; date = dr.date; } /** * Calculates the 1900 based numerical value based upon the utc value held * in the date object * * @param adjust TRUE if we want to incorporate timezone information * into the raw UTC date eg. when copying from a spreadsheet */ private void calculateValue(boolean adjust) { // Offsets for current time zone long zoneOffset = 0; long dstOffset = 0; // Get the timezone and dst offsets if we want to take these into // account if (adjust) { // Get the current calender, replete with timezone information Calendar cal = Calendar.getInstance(); cal.setTime(date); zoneOffset = cal.get(Calendar.ZONE_OFFSET); dstOffset = cal.get(Calendar.DST_OFFSET); } long utcValue = date.getTime() + zoneOffset + dstOffset; // Convert this to the number of days, plus fractions of a day since // 01 Jan 1970 double utcDays = (double) utcValue / (double) msInADay; // Add in the offset to get the number of days since 01 Jan 1900 value = utcDays + utcOffsetDays; // Work round a bug in excel. Excel seems to think there is a date // called the 29th Feb, 1900 - but this was not a leap year. // Therefore for values less than 61, we must subtract 1. Only do // this for full dates, not times if (!time && value < nonLeapDay) { value -= 1; } // If this refers to a time, then get rid of the integer part if (time) { value = value - (int) value; } } /** * Returns the content type of this cell * * @return the content type for this cell */ public CellType getType() { return CellType.DATE; } /** * Gets the binary data for writing * * @return the binary data */ public byte[] getData() { byte[] celldata = super.getData(); byte[] data = new byte[celldata.length + 8]; System.arraycopy(celldata, 0, data, 0, celldata.length); DoubleHelper.getIEEEBytes(value, data, celldata.length); return data; } /** * Quick and dirty function to return the contents of this cell as a string. * For more complex manipulation of the contents, it is necessary to cast * this interface to correct subinterface * * @return the contents of this cell as a string */ public String getContents() { return date.toString(); } /** * Sets the date in this cell * * @param d the date */ protected void setDate(Date d) { date = d; calculateValue(true); } /** * Sets the date in this cell, taking the timezone into account * * @param d the date * @param a adjust for timezone */ protected void setDate(Date d, GMTDate a) { date = d; calculateValue(false); } /** * Gets the date contained in this cell * * @return the cell contents */ public Date getDate() { return date; } /** * Indicates whether the date value contained in this cell refers to a date, * or merely a time. When writing a cell, all dates are fully defined, * even if they refer to a time * * @return FALSE if this is full date, TRUE if a time */ public boolean isTime() { return time; } /** * Gets the DateFormat used to format the cell. This will normally be * the format specified in the excel spreadsheet, but in the event of any * difficulty parsing this, it will revert to the default date/time format. * * @return the DateFormat object used to format the date in the original * excel cell */ public DateFormat getDateFormat() { return null; } } jexcelapi/src/jxl/write/biff/BookboolRecord.java0000750000175000017500000000335111207000610022075 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.IntegerHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Writes out the workbook option flag (should it save the external * link options) */ class BookboolRecord extends WritableRecordData { /** * The external link option flag */ private boolean externalLink; /** * The binary data to write out */ private byte[] data; /** * Constructor * * @param extlink the external link options flag */ public BookboolRecord(boolean extlink) { super(Type.BOOKBOOL); externalLink = extlink; data = new byte[2]; if (!externalLink) { IntegerHelper.getTwoBytes(1, data, 0); } } /** * Gets the binary data to write to the output file * * @return the binary data */ public byte[] getData() { return data; } } jexcelapi/src/jxl/write/biff/PLSRecord.java0000750000175000017500000000336411207000610020771 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Record which specifies a print header for a work sheet */ class PLSRecord extends WritableRecordData { /** * The binary data */ private byte[] data; /** * Consructor invoked when copying a spreadsheet * * @param hr the read header record */ public PLSRecord(jxl.read.biff.PLSRecord hr) { super(Type.PLS); data = hr.getData(); } /** * Consructor invoked when copying a sheets * * @param hr the read header record */ public PLSRecord(PLSRecord hr) { super(Type.PLS); data = new byte[hr.data.length]; System.arraycopy(hr.data, 0, data, 0, data.length); } /** * Gets the binary data for output to file * * @return the binary data */ public byte[] getData() { return data; } } jexcelapi/src/jxl/write/biff/RefreshAllRecord.java0000750000175000017500000000341411207000610022356 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.IntegerHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Record which indicates whether or not data ranges and pivot tables * should be refreshed when the workbook is loaded */ class RefreshAllRecord extends WritableRecordData { /** * The refresh all flag */ private boolean refreshall; /** * The binary data */ private byte[] data; /** * Constructor * * @param refresh refresh all flag */ public RefreshAllRecord(boolean refresh) { super(Type.REFRESHALL); refreshall = refresh; // Hard code in an unprotected workbook data = new byte[2]; if (refreshall) { IntegerHelper.getTwoBytes(1, data, 0); } } /** * Gets the binary data for output to file * * @return the binary data */ public byte[] getData() { return data; } } jexcelapi/src/jxl/write/biff/PaneRecord.java0000750000175000017500000000531711207000610021216 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.IntegerHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Contains the window attributes for a worksheet */ class PaneRecord extends WritableRecordData { /** * The number of rows visible in the top left pane */ private int rowsVisible; /** * The number of columns visible in the top left pane */ private int columnsVisible; /** * The pane codes */ private final static int topLeftPane = 0x3; private final static int bottomLeftPane = 0x2; private final static int topRightPane = 0x1; private final static int bottomRightPane = 0x0; /** * Code /** * Constructor */ public PaneRecord(int cols, int rows) { super(Type.PANE); rowsVisible = rows; columnsVisible = cols; } /** * Gets the binary data for output to file * * @return the binary data */ public byte[] getData() { byte[] data = new byte[10]; // The x position IntegerHelper.getTwoBytes(columnsVisible, data, 0); // The y position IntegerHelper.getTwoBytes(rowsVisible, data, 2); // The top row visible in the bottom pane if (rowsVisible > 0) { IntegerHelper.getTwoBytes(rowsVisible, data, 4); } // The left most column visible in the right pane if (columnsVisible > 0) { IntegerHelper.getTwoBytes(columnsVisible, data, 6); } // The active pane int activePane = topLeftPane; if (rowsVisible > 0 && columnsVisible == 0) { activePane = bottomLeftPane; } else if (rowsVisible == 0 && columnsVisible > 0) { activePane = topRightPane; } else if (rowsVisible > 0 && columnsVisible > 0) { activePane = bottomRightPane; } // always present IntegerHelper.getTwoBytes(activePane, data, 8); return data; } } jexcelapi/src/jxl/write/biff/Weird1Record.java0000750000175000017500000000260311207000610021461 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Don't know what this does - something to do with freezing panes I think */ class Weird1Record extends WritableRecordData { /** * Constructor */ public Weird1Record() { super(Type.WEIRD1); } /** * Gets the binary data for output to file * * @return the binary data */ public byte[] getData() { byte[] data = new byte[6]; data[2] = 0x37; return data; } } jexcelapi/src/jxl/write/biff/BlankRecord.java0000750000175000017500000000515711207000610021364 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2001 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.common.Logger; import jxl.Cell; import jxl.CellType; import jxl.biff.Type; import jxl.format.CellFormat; /** * A blank record, which is used to contain formatting information */ public abstract class BlankRecord extends CellValue { /** * The logger */ private static Logger logger = Logger.getLogger(BlankRecord.class); /** * Consructor used when creating a label from the user API * * @param c the column * @param cont the contents * @param r the row */ protected BlankRecord(int c, int r) { super(Type.BLANK, c, r); } /** * Constructor used when creating a label from the API. This is * overloaded to allow formatting information to be passed to the record * * @param c the column * @param r the row * @param st the format applied to the cell */ protected BlankRecord(int c, int r, CellFormat st) { super(Type.BLANK, c, r, st); } /** * Constructor used when copying a formatted blank cell from a read only * spreadsheet * * @param c the blank cell to copy */ protected BlankRecord(Cell c) { super(Type.BLANK, c); } /** * Copy constructor * * @param c the column * @param r the row * @param b the record to copy */ protected BlankRecord(int c, int r, BlankRecord br) { super(Type.BLANK, c, r, br); } /** * Returns the content type of this cell * * @return the content type for this cell */ public CellType getType() { return CellType.EMPTY; } /** * Quick and dirty function to return the contents of this cell as a string. * * @return the contents of this cell as a string */ public String getContents() { return ""; } } jexcelapi/src/jxl/write/biff/CompoundFile.java0000750000175000017500000007722611207000610021570 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import jxl.common.Assert; import jxl.common.Logger; import jxl.biff.BaseCompoundFile; import jxl.biff.IntegerHelper; import jxl.read.biff.BiffException; /** * Writes out a compound file * * Header block is -1 * Excel data is e..n (where e is the head extension blocks, normally 0 and * n is at least 8) * Summary information (8 blocks) * Document summary (8 blocks) * BBD is block p..q (where p=e+n+16 and q-p+1 is the number of BBD blocks) * Property storage block is q+b...r (normally 1 block) (where b is the number * of BBD blocks) */ final class CompoundFile extends BaseCompoundFile { /** * The logger */ private static Logger logger = Logger.getLogger(CompoundFile.class); /** * The stream to which the jumbled up data is written to */ private OutputStream out; /** * The organized biff records which form the actual excel data */ private ExcelDataOutput excelData; /** * The size of the array */ private int size; /** * The size the excel data should be in order to comply with the * general compound file format */ private int requiredSize; /** * The number of blocks it takes to store the big block depot */ private int numBigBlockDepotBlocks; /** * The number of blocks it takes to store the small block depot chain */ private int numSmallBlockDepotChainBlocks; /** * The number of blocks it takes to store the small block depot */ private int numSmallBlockDepotBlocks; /** * The number of extension blocks required for the header to describe * the BBD */ private int numExtensionBlocks; /** * The extension block for the header */ private int extensionBlock; /** * The number of blocks it takes to store the excel data */ private int excelDataBlocks; /** * The start block of the root entry */ private int rootStartBlock; /** * The start block of the excel data */ private int excelDataStartBlock; /** * The start block of the big block depot */ private int bbdStartBlock; /** * The start block of the small block depot */ private int sbdStartBlockChain; /** * The start block of the small block depot */ private int sbdStartBlock; /** * The number of big blocks required for additional property sets */ private int additionalPropertyBlocks; /** * The number of small blocks */ private int numSmallBlocks; /** * The total number of property sets in this compound file */ private int numPropertySets; /** * The number of blocks required to store the root entry property sets * and small block depot */ private int numRootEntryBlocks; /** * The list of additional, non standard property sets names */ private ArrayList additionalPropertySets; /** * The map of standard property sets, keyed on name */ private HashMap standardPropertySets; /** * Structure used to store the property set and the data */ private static final class ReadPropertyStorage { PropertyStorage propertyStorage; byte[] data; int number; ReadPropertyStorage(PropertyStorage ps, byte[] d, int n) { propertyStorage = ps; data = d; number = n; } } // The following member variables are used across methods when // writing out the big block depot /** * The current position within the bbd. Used when writing out the * BBD */ private int bbdPos; /** * The current bbd block */ private byte[] bigBlockDepot; /** * Constructor * * @param l the length of the data * @param os the output stream to write to * @param data the excel data * @param rcf the read compound */ public CompoundFile(ExcelDataOutput data, int l, OutputStream os, jxl.read.biff.CompoundFile rcf) throws CopyAdditionalPropertySetsException, IOException { super(); size = l; excelData = data; readAdditionalPropertySets(rcf); numRootEntryBlocks = 1; numPropertySets = 4 + (additionalPropertySets != null ? additionalPropertySets.size() : 0); if (additionalPropertySets != null) { numSmallBlockDepotChainBlocks = getBigBlocksRequired(numSmallBlocks * 4); numSmallBlockDepotBlocks = getBigBlocksRequired (numSmallBlocks * SMALL_BLOCK_SIZE); numRootEntryBlocks += getBigBlocksRequired (additionalPropertySets.size() * PROPERTY_STORAGE_BLOCK_SIZE); } int blocks = getBigBlocksRequired(l); // First pad the data out so that it fits nicely into a whole number // of blocks if (l < SMALL_BLOCK_THRESHOLD) { requiredSize = SMALL_BLOCK_THRESHOLD; } else { requiredSize = blocks * BIG_BLOCK_SIZE; } out = os; // Do the calculations excelDataBlocks = requiredSize/BIG_BLOCK_SIZE; numBigBlockDepotBlocks = 1; int blockChainLength = (BIG_BLOCK_SIZE - BIG_BLOCK_DEPOT_BLOCKS_POS)/4; int startTotalBlocks = excelDataBlocks + 8 + // summary block 8 + // document information additionalPropertyBlocks + numSmallBlockDepotBlocks + numSmallBlockDepotChainBlocks + numRootEntryBlocks; int totalBlocks = startTotalBlocks + numBigBlockDepotBlocks; // Calculate the number of BBD blocks needed to hold this info numBigBlockDepotBlocks = (int) Math.ceil( (double) totalBlocks / (double) (BIG_BLOCK_SIZE/4)); // Does this affect the total? totalBlocks = startTotalBlocks + numBigBlockDepotBlocks; // And recalculate numBigBlockDepotBlocks = (int) Math.ceil( (double) totalBlocks / (double) (BIG_BLOCK_SIZE/4)); // Does this affect the total? totalBlocks = startTotalBlocks + numBigBlockDepotBlocks; // See if the excel bbd chain can fit into the header block. // Remember to allow for the end of chain indicator if (numBigBlockDepotBlocks > blockChainLength - 1 ) { // Sod it - we need an extension block. We have to go through // the whole tiresome calculation again extensionBlock = 0; // Compute the number of extension blocks int bbdBlocksLeft = numBigBlockDepotBlocks - blockChainLength + 1; numExtensionBlocks = (int) Math.ceil((double) bbdBlocksLeft / (double) (BIG_BLOCK_SIZE/4 - 1)); // Modify the total number of blocks required and recalculate the // the number of bbd blocks totalBlocks = startTotalBlocks + numExtensionBlocks + numBigBlockDepotBlocks; numBigBlockDepotBlocks = (int) Math.ceil( (double) totalBlocks / (double) (BIG_BLOCK_SIZE/4)); // The final total totalBlocks = startTotalBlocks + numExtensionBlocks + numBigBlockDepotBlocks; } else { extensionBlock = -2; numExtensionBlocks = 0; } // Set the excel data start block to be after the header (and // its extensions) excelDataStartBlock = numExtensionBlocks; // Set the start block of the small block depot sbdStartBlock = -2; if (additionalPropertySets != null && numSmallBlockDepotBlocks != 0) { sbdStartBlock = excelDataStartBlock + excelDataBlocks + additionalPropertyBlocks + 16; } // Set the sbd chain start block to be after the excel data and the // small block depot sbdStartBlockChain = -2; if (sbdStartBlock != -2) { sbdStartBlockChain = sbdStartBlock + numSmallBlockDepotBlocks; } // Set the bbd start block to be after all the excel data if (sbdStartBlockChain != -2) { bbdStartBlock = sbdStartBlockChain + numSmallBlockDepotChainBlocks; } else { bbdStartBlock = excelDataStartBlock + excelDataBlocks + additionalPropertyBlocks + 16; } // Set the root start block to be after all the big block depot blocks rootStartBlock = bbdStartBlock + numBigBlockDepotBlocks; if (totalBlocks != rootStartBlock + numRootEntryBlocks) { logger.warn("Root start block and total blocks are inconsistent " + " generated file may be corrupt"); logger.warn("RootStartBlock " + rootStartBlock + " totalBlocks " + totalBlocks); } } /** * Reads the additional property sets from the read in compound file * * @param readCompoundFile the file read in * @exception CopyAdditionalPropertySetsException * @exception IOException */ private void readAdditionalPropertySets (jxl.read.biff.CompoundFile readCompoundFile) throws CopyAdditionalPropertySetsException, IOException { if (readCompoundFile == null) { return; } additionalPropertySets = new ArrayList(); standardPropertySets = new HashMap(); int blocksRequired = 0; int numPropertySets = readCompoundFile.getNumberOfPropertySets(); for (int i = 0 ; i < numPropertySets ; i++) { PropertyStorage ps = readCompoundFile.getPropertySet(i); boolean standard = false; if (ps.name.equalsIgnoreCase(ROOT_ENTRY_NAME)) { standard = true; ReadPropertyStorage rps = new ReadPropertyStorage(ps, null, i); standardPropertySets.put(ROOT_ENTRY_NAME, rps); } // See if it is a standard property set for (int j = 0 ; j < STANDARD_PROPERTY_SETS.length && !standard ; j++) { if (ps.name.equalsIgnoreCase(STANDARD_PROPERTY_SETS[j])) { // See if it comes directly off the root entry PropertyStorage ps2 = readCompoundFile.findPropertyStorage(ps.name); Assert.verify(ps2 != null); if (ps2 == ps) { standard = true; ReadPropertyStorage rps = new ReadPropertyStorage(ps, null, i); standardPropertySets.put(STANDARD_PROPERTY_SETS[j], rps); } } } if (!standard) { try { byte[] data = null; if (ps.size > 0 ) { data = readCompoundFile.getStream(i); } else { data = new byte[0]; } ReadPropertyStorage rps = new ReadPropertyStorage(ps, data, i); additionalPropertySets.add(rps); if (data.length > SMALL_BLOCK_THRESHOLD) { int blocks = getBigBlocksRequired(data.length); blocksRequired += blocks; } else { int blocks = getSmallBlocksRequired(data.length); numSmallBlocks += blocks; } } catch (BiffException e) { logger.error(e); throw new CopyAdditionalPropertySetsException(); } } } additionalPropertyBlocks = blocksRequired; } /** * Writes out the excel file in OLE compound file format * * @exception IOException */ public void write() throws IOException { writeHeader(); writeExcelData(); writeDocumentSummaryData(); writeSummaryData(); writeAdditionalPropertySets(); writeSmallBlockDepot(); writeSmallBlockDepotChain(); writeBigBlockDepot(); writePropertySets(); // Don't flush or close the stream - this is handled by the enclosing File // object } /** * Writes out any additional property sets */ private void writeAdditionalPropertySets() throws IOException { if (additionalPropertySets == null) { return; } for (Iterator i = additionalPropertySets.iterator(); i.hasNext() ;) { ReadPropertyStorage rps = (ReadPropertyStorage) i.next(); byte[] data = rps.data; if (data.length > SMALL_BLOCK_THRESHOLD) { int numBlocks = getBigBlocksRequired(data.length); int requiredSize = numBlocks * BIG_BLOCK_SIZE; out.write(data, 0, data.length); byte[] padding = new byte[requiredSize - data.length]; out.write(padding, 0, padding.length); } } } /** * Writes out the excel data, padding it out with empty bytes as * necessary * Also write out empty * * @exception IOException */ private void writeExcelData() throws IOException { excelData.writeData(out); byte[] padding = new byte[requiredSize - size]; out.write(padding); } /** * Write out the document summary data. This is just blank * * @exception IOException */ private void writeDocumentSummaryData() throws IOException { byte[] padding = new byte[SMALL_BLOCK_THRESHOLD]; // Write out the summary information out.write(padding); } /** * Write out the summary data. This is just blank * * @exception IOException */ private void writeSummaryData() throws IOException { byte[] padding = new byte[SMALL_BLOCK_THRESHOLD]; // Write out the summary information out.write(padding); } /** * Writes the compound file header * * @exception IOException */ private void writeHeader() throws IOException { // Build up the header array byte[] headerBlock = new byte[BIG_BLOCK_SIZE]; byte[] extensionBlockData = new byte[BIG_BLOCK_SIZE * numExtensionBlocks]; // Copy in the identifier System.arraycopy(IDENTIFIER, 0, headerBlock, 0, IDENTIFIER.length); // Copy in some magic values - no idea what they mean headerBlock[0x18] = 0x3e; headerBlock[0x1a] = 0x3; headerBlock[0x1c] = (byte) 0xfe; headerBlock[0x1d] = (byte) 0xff; headerBlock[0x1e] = 0x9; headerBlock[0x20] = 0x6; headerBlock[0x39] = 0x10; // Set the number of BBD blocks IntegerHelper.getFourBytes(numBigBlockDepotBlocks, headerBlock, NUM_BIG_BLOCK_DEPOT_BLOCKS_POS); // Set the small block depot chain IntegerHelper.getFourBytes(sbdStartBlockChain, headerBlock, SMALL_BLOCK_DEPOT_BLOCK_POS); // Set the number of blocks in the small block depot chain IntegerHelper.getFourBytes(numSmallBlockDepotChainBlocks, headerBlock, NUM_SMALL_BLOCK_DEPOT_BLOCKS_POS); // Set the extension block IntegerHelper.getFourBytes(extensionBlock, headerBlock, EXTENSION_BLOCK_POS); // Set the number of extension blocks to be the number of BBD blocks - 1 IntegerHelper.getFourBytes(numExtensionBlocks, headerBlock, NUM_EXTENSION_BLOCK_POS); // Set the root start block IntegerHelper.getFourBytes(rootStartBlock, headerBlock, ROOT_START_BLOCK_POS); // Set the block numbers for the BBD. Set the BBD running // after the excel data and summary information int pos = BIG_BLOCK_DEPOT_BLOCKS_POS; // See how many blocks fit into the header int blocksToWrite = Math.min(numBigBlockDepotBlocks, (BIG_BLOCK_SIZE - BIG_BLOCK_DEPOT_BLOCKS_POS)/4); int blocksWritten = 0; for (int i = 0 ; i < blocksToWrite; i++) { IntegerHelper.getFourBytes(bbdStartBlock + i, headerBlock, pos); pos += 4; blocksWritten++; } // Pad out the rest of the header with blanks for (int i = pos; i < BIG_BLOCK_SIZE; i++) { headerBlock[i] = (byte) 0xff; } out.write(headerBlock); // Write out the extension blocks pos = 0; for (int extBlock = 0; extBlock < numExtensionBlocks; extBlock++) { blocksToWrite = Math.min(numBigBlockDepotBlocks - blocksWritten, BIG_BLOCK_SIZE/4 -1); for(int j = 0 ; j < blocksToWrite; j++) { IntegerHelper.getFourBytes(bbdStartBlock + blocksWritten + j, extensionBlockData, pos); pos += 4; } blocksWritten += blocksToWrite; // Indicate the next block, or the termination of the chain int nextBlock = (blocksWritten == numBigBlockDepotBlocks) ? -2 : extBlock+1 ; IntegerHelper.getFourBytes(nextBlock, extensionBlockData, pos); pos +=4; } if (numExtensionBlocks > 0) { // Pad out the rest of the extension block with blanks for (int i = pos; i < extensionBlockData.length; i++) { extensionBlockData[i] = (byte) 0xff; } out.write(extensionBlockData); } } /** * Checks that the data can fit into the current BBD block. If not, * then it moves on to the next block * * @exception IOException */ private void checkBbdPos() throws IOException { if (bbdPos >= BIG_BLOCK_SIZE) { // Write out the extension block. This will simply be the next block out.write(bigBlockDepot); // Create a new block bigBlockDepot = new byte[BIG_BLOCK_SIZE]; bbdPos = 0; } } /** * Writes out the big block chain * * @param startBlock the starting block of the big block chain * @param numBlocks the number of blocks in the chain * @exception IOException */ private void writeBlockChain(int startBlock, int numBlocks) throws IOException { int blocksToWrite = numBlocks - 1; int blockNumber = startBlock + 1; while (blocksToWrite > 0) { int bbdBlocks = Math.min(blocksToWrite, (BIG_BLOCK_SIZE - bbdPos)/4); for (int i = 0 ; i < bbdBlocks; i++) { IntegerHelper.getFourBytes(blockNumber, bigBlockDepot, bbdPos); bbdPos +=4 ; blockNumber++; } blocksToWrite -= bbdBlocks; checkBbdPos(); } // Write the end of the block chain IntegerHelper.getFourBytes(-2, bigBlockDepot, bbdPos); bbdPos += 4; checkBbdPos(); } /** * Writes the block chains for the additional property sets * * @exception IOException */ private void writeAdditionalPropertySetBlockChains() throws IOException { if (additionalPropertySets == null) { return; } int blockNumber = excelDataStartBlock + excelDataBlocks + 16; for (Iterator i = additionalPropertySets.iterator(); i.hasNext() ; ) { ReadPropertyStorage rps = (ReadPropertyStorage) i.next(); if (rps.data.length > SMALL_BLOCK_THRESHOLD) { int numBlocks = getBigBlocksRequired(rps.data.length); writeBlockChain(blockNumber, numBlocks); blockNumber += numBlocks; } } } /** * Writes out the chains for the small block depot */ private void writeSmallBlockDepotChain() throws IOException { if (sbdStartBlockChain == -2) { return; } byte[] smallBlockDepotChain = new byte[numSmallBlockDepotChainBlocks * BIG_BLOCK_SIZE]; int pos = 0; int sbdBlockNumber = 1; for (Iterator i = additionalPropertySets.iterator(); i.hasNext() ; ) { ReadPropertyStorage rps = (ReadPropertyStorage) i.next(); if (rps.data.length <= SMALL_BLOCK_THRESHOLD && rps.data.length != 0) { int numSmallBlocks = getSmallBlocksRequired(rps.data.length); for (int j = 0 ; j < numSmallBlocks - 1 ; j++) { IntegerHelper.getFourBytes(sbdBlockNumber, smallBlockDepotChain, pos); pos += 4; sbdBlockNumber++; } // Write out the end of chain IntegerHelper.getFourBytes(-2, smallBlockDepotChain, pos); pos += 4; sbdBlockNumber++; } } out.write(smallBlockDepotChain); } /** * Writes out all the data in the small block depot * * @exception */ private void writeSmallBlockDepot() throws IOException { if (additionalPropertySets == null) { return; } byte[] smallBlockDepot = new byte[numSmallBlockDepotBlocks * BIG_BLOCK_SIZE]; int pos = 0; for (Iterator i = additionalPropertySets.iterator() ; i.hasNext() ; ) { ReadPropertyStorage rps = (ReadPropertyStorage) i.next(); if (rps.data.length <= SMALL_BLOCK_THRESHOLD) { int smallBlocks = getSmallBlocksRequired(rps.data.length); int length = smallBlocks * SMALL_BLOCK_SIZE; System.arraycopy(rps.data, 0, smallBlockDepot, pos, rps.data.length); pos += length; } } out.write(smallBlockDepot); } /** * Writes out the Big Block Depot * * @exception IOException */ private void writeBigBlockDepot() throws IOException { // This is after the excel data, the summary information, the // big block property sets and the small block depot bigBlockDepot = new byte[BIG_BLOCK_SIZE]; bbdPos = 0; // Write out the extension blocks, indicating them as special blocks for (int i = 0 ; i < numExtensionBlocks; i++) { IntegerHelper.getFourBytes(-3, bigBlockDepot, bbdPos); bbdPos += 4; checkBbdPos(); } writeBlockChain(excelDataStartBlock, excelDataBlocks); // The excel data has been written. Now write out the rest of it // Write the block chain for the summary information int summaryInfoBlock = excelDataStartBlock + excelDataBlocks + additionalPropertyBlocks; for (int i = summaryInfoBlock; i < summaryInfoBlock + 7; i++) { IntegerHelper.getFourBytes(i + 1, bigBlockDepot, bbdPos); bbdPos +=4 ; checkBbdPos(); } // Write the end of the block chain for the summary info block IntegerHelper.getFourBytes(-2, bigBlockDepot, bbdPos); bbdPos += 4; checkBbdPos(); // Write the block chain for the document summary information for (int i = summaryInfoBlock + 8; i < summaryInfoBlock + 15; i++) { IntegerHelper.getFourBytes(i + 1, bigBlockDepot, bbdPos); bbdPos +=4 ; checkBbdPos(); } // Write the end of the block chain for the document summary IntegerHelper.getFourBytes(-2, bigBlockDepot, bbdPos); bbdPos += 4; checkBbdPos(); // Write out the block chain for the copied property sets, if present writeAdditionalPropertySetBlockChains(); if (sbdStartBlock != -2) { // Write out the block chain for the small block depot writeBlockChain(sbdStartBlock, numSmallBlockDepotBlocks); // Write out the block chain for the small block depot chain writeBlockChain(sbdStartBlockChain, numSmallBlockDepotChainBlocks); } // The Big Block Depot immediately follows. Denote these as a special // block for (int i = 0; i < numBigBlockDepotBlocks; i++) { IntegerHelper.getFourBytes(-3, bigBlockDepot, bbdPos); bbdPos += 4; checkBbdPos(); } // Write the root entry writeBlockChain(rootStartBlock, numRootEntryBlocks); // Pad out the remainder of the block if (bbdPos != 0) { for (int i = bbdPos; i < BIG_BLOCK_SIZE; i++) { bigBlockDepot[i] = (byte) 0xff; } out.write(bigBlockDepot); } } /** * Calculates the number of big blocks required to store data of the * specified length * * @param length the length of the data * @return the number of big blocks required to store the data */ private int getBigBlocksRequired(int length) { int blocks = length / BIG_BLOCK_SIZE; return (length % BIG_BLOCK_SIZE > 0 )? blocks + 1 : blocks; } /** * Calculates the number of small blocks required to store data of the * specified length * * @param length the length of the data * @return the number of small blocks required to store the data */ private int getSmallBlocksRequired(int length) { int blocks = length / SMALL_BLOCK_SIZE; return (length % SMALL_BLOCK_SIZE > 0 )? blocks + 1 : blocks; } /** * Writes out the property sets * * @exception IOException */ private void writePropertySets() throws IOException { byte[] propertySetStorage = new byte[BIG_BLOCK_SIZE * numRootEntryBlocks]; int pos = 0; int[] mappings = null; // Build up the mappings array if (additionalPropertySets != null) { mappings = new int[numPropertySets]; // Map the standard ones to the first four for (int i = 0 ; i < STANDARD_PROPERTY_SETS.length ; i++) { ReadPropertyStorage rps = (ReadPropertyStorage) standardPropertySets.get(STANDARD_PROPERTY_SETS[i]); if (rps != null) { mappings[rps.number] = i; } else { logger.warn("Standard property set " + STANDARD_PROPERTY_SETS[i] + " not present in source file"); } } // Now go through the original ones int newMapping = STANDARD_PROPERTY_SETS.length; for (Iterator i = additionalPropertySets.iterator(); i.hasNext(); ) { ReadPropertyStorage rps = (ReadPropertyStorage) i.next(); mappings[rps.number] = newMapping; newMapping++; } } int child = 0; int previous = 0; int next = 0; // Compute the size of the root property set int size = 0; if (additionalPropertySets != null) { // Workbook size += getBigBlocksRequired(requiredSize) * BIG_BLOCK_SIZE; // The two information blocks size += getBigBlocksRequired(SMALL_BLOCK_THRESHOLD) * BIG_BLOCK_SIZE; size += getBigBlocksRequired(SMALL_BLOCK_THRESHOLD) * BIG_BLOCK_SIZE; // Additional property sets for (Iterator i = additionalPropertySets.iterator(); i.hasNext(); ) { ReadPropertyStorage rps = (ReadPropertyStorage) i.next(); if (rps.propertyStorage.type != 1) { if (rps.propertyStorage.size >= SMALL_BLOCK_THRESHOLD) { size += getBigBlocksRequired(rps.propertyStorage.size) * BIG_BLOCK_SIZE; } else { size += getSmallBlocksRequired(rps.propertyStorage.size) * SMALL_BLOCK_SIZE; } } } } // Set the root entry property set PropertyStorage ps = new PropertyStorage(ROOT_ENTRY_NAME); ps.setType(5); ps.setStartBlock(sbdStartBlock); ps.setSize(size); ps.setPrevious(-1); ps.setNext(-1); ps.setColour(0); child = 1; if (additionalPropertySets != null) { ReadPropertyStorage rps = (ReadPropertyStorage) standardPropertySets.get(ROOT_ENTRY_NAME); child = mappings[rps.propertyStorage.child]; } ps.setChild(child); System.arraycopy(ps.data, 0, propertySetStorage, pos, PROPERTY_STORAGE_BLOCK_SIZE); pos += PROPERTY_STORAGE_BLOCK_SIZE; // Set the workbook property set ps = new PropertyStorage(WORKBOOK_NAME); ps.setType(2); ps.setStartBlock(excelDataStartBlock); // start the excel data after immediately after this block ps.setSize(requiredSize); // always use a big block stream - none of that messing around // with small blocks previous = 3; next = -1; if (additionalPropertySets != null) { ReadPropertyStorage rps = (ReadPropertyStorage) standardPropertySets.get(WORKBOOK_NAME); previous = rps.propertyStorage.previous != -1 ? mappings[rps.propertyStorage.previous] : -1; next = rps.propertyStorage.next != -1 ? mappings[rps.propertyStorage.next] : -1 ; } ps.setPrevious(previous); ps.setNext(next); ps.setChild(-1); System.arraycopy(ps.data, 0, propertySetStorage, pos, PROPERTY_STORAGE_BLOCK_SIZE); pos += PROPERTY_STORAGE_BLOCK_SIZE; // Set the summary information ps = new PropertyStorage(SUMMARY_INFORMATION_NAME); ps.setType(2); ps.setStartBlock(excelDataStartBlock + excelDataBlocks); ps.setSize(SMALL_BLOCK_THRESHOLD); previous = 1; next = 3; if (additionalPropertySets != null) { ReadPropertyStorage rps = (ReadPropertyStorage) standardPropertySets.get(SUMMARY_INFORMATION_NAME); if (rps != null) { previous = rps.propertyStorage.previous != - 1 ? mappings[rps.propertyStorage.previous] : -1 ; next = rps.propertyStorage.next != - 1 ? mappings[rps.propertyStorage.next] : -1 ; } } ps.setPrevious(previous); ps.setNext(next); ps.setChild(-1); System.arraycopy(ps.data, 0, propertySetStorage, pos, PROPERTY_STORAGE_BLOCK_SIZE); pos += PROPERTY_STORAGE_BLOCK_SIZE; // Set the document summary information ps = new PropertyStorage(DOCUMENT_SUMMARY_INFORMATION_NAME); ps.setType(2); ps.setStartBlock(excelDataStartBlock + excelDataBlocks + 8); ps.setSize(SMALL_BLOCK_THRESHOLD); ps.setPrevious(-1); ps.setNext(-1); ps.setChild(-1); System.arraycopy(ps.data, 0, propertySetStorage, pos, PROPERTY_STORAGE_BLOCK_SIZE); pos += PROPERTY_STORAGE_BLOCK_SIZE; // Write out the additional property sets if (additionalPropertySets == null) { out.write(propertySetStorage); return; } int bigBlock = excelDataStartBlock + excelDataBlocks + 16; int smallBlock = 0; for (Iterator i = additionalPropertySets.iterator() ; i.hasNext(); ) { ReadPropertyStorage rps = (ReadPropertyStorage) i.next(); int block = rps.data.length > SMALL_BLOCK_THRESHOLD ? bigBlock : smallBlock; ps = new PropertyStorage(rps.propertyStorage.name); ps.setType(rps.propertyStorage.type); ps.setStartBlock(block); ps.setSize(rps.propertyStorage.size); // ps.setColour(rps.propertyStorage.colour); previous = rps.propertyStorage.previous != -1 ? mappings[rps.propertyStorage.previous] : -1; next = rps.propertyStorage.next != -1 ? mappings[rps.propertyStorage.next] : -1; child = rps.propertyStorage.child != -1 ? mappings[rps.propertyStorage.child] : -1; ps.setPrevious(previous); ps.setNext(next); ps.setChild(child); System.arraycopy(ps.data, 0, propertySetStorage, pos, PROPERTY_STORAGE_BLOCK_SIZE); pos += PROPERTY_STORAGE_BLOCK_SIZE; if (rps.data.length > SMALL_BLOCK_THRESHOLD) { bigBlock += getBigBlocksRequired(rps.data.length); } else { smallBlock += getSmallBlocksRequired(rps.data.length); } } out.write(propertySetStorage); } } jexcelapi/src/jxl/write/biff/Prot4RevRecord.java0000750000175000017500000000325111207000610022013 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.IntegerHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * The shared workbook protection flag */ class Prot4RevRecord extends WritableRecordData { /** * The protection flag */ private boolean protection; /** * The binary data */ private byte[] data; /** * Constructor * * @param prot protection flag */ public Prot4RevRecord(boolean prot) { super(Type.PROT4REV); protection = prot; // Hard code in an unprotected workbook data = new byte[2]; if (protection) { IntegerHelper.getTwoBytes(1, data, 0); } } /** * Gets the binary data for output to file * * @return the binary data */ public byte[] getData() { return data; } } jexcelapi/src/jxl/write/biff/ReadStringFormulaRecord.java0000750000175000017500000000646711207000610023732 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2004 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.common.Assert; import jxl.common.Logger; import jxl.StringFormulaCell; import jxl.biff.FormulaData; import jxl.biff.IntegerHelper; import jxl.biff.formula.FormulaException; import jxl.biff.formula.FormulaParser; /** * Class for read number formula records */ class ReadStringFormulaRecord extends ReadFormulaRecord implements StringFormulaCell { // the logger private static Logger logger = Logger.getLogger(ReadFormulaRecord.class); /** * Constructor * * @param f */ public ReadStringFormulaRecord(FormulaData f) { super(f); } /** * Gets the string contents for this cell. * * @return the cell contents */ public String getString() { return ( (StringFormulaCell) getReadFormula()).getString(); } /** * String formula specific exception handling. Can't really create * a formula (as it will look for a cell of that name, so just * create a STRING record containing the contents * * @return the bodged data */ protected byte[] handleFormulaException() { byte[] expressiondata = null; byte[] celldata = super.getCellData(); // Generate an appropriate dummy formula WritableWorkbookImpl w = getSheet().getWorkbook(); FormulaParser parser = new FormulaParser("\"" + getContents() +"\"", w, w, w.getSettings()); // Get the bytes for the dummy formula try { parser.parse(); } catch(FormulaException e2) { logger.warn(e2.getMessage()); parser = new FormulaParser("\"ERROR\"", w, w, w.getSettings()); try {parser.parse();} catch(FormulaException e3) {Assert.verify(false);} } byte[] formulaBytes = parser.getBytes(); expressiondata = new byte[formulaBytes.length + 16]; IntegerHelper.getTwoBytes(formulaBytes.length, expressiondata, 14); System.arraycopy(formulaBytes, 0, expressiondata, 16, formulaBytes.length); // Set the recalculate on load bit expressiondata[8] |= 0x02; byte[] data = new byte[celldata.length + expressiondata.length]; System.arraycopy(celldata, 0, data, 0, celldata.length); System.arraycopy(expressiondata, 0, data, celldata.length, expressiondata.length); // Set the type bits to indicate a string formula data[6] = 0; data[12] = -1; data[13] = -1; return data; } } jexcelapi/src/jxl/write/biff/CalcModeRecord.java0000750000175000017500000000424111207000610021775 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.IntegerHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * The calculation mode for the workbook, as set from the Options * dialog box */ class CalcModeRecord extends WritableRecordData { /** * The calculation mode (manual, automatic) */ private CalcMode calculationMode; private static class CalcMode { /** * The indicator as written to the output file */ int value; /** * Constructor * * @param m */ public CalcMode(int m) { value = m; } } /** * Manual calculation */ static CalcMode manual = new CalcMode(0); /** * Automatic calculation */ static CalcMode automatic = new CalcMode(1); /** * Automatic calculation, except tables */ static CalcMode automaticNoTables = new CalcMode(-1); /** * Constructor * * @param cm the calculation mode */ public CalcModeRecord(CalcMode cm) { super(Type.CALCMODE); calculationMode = cm; } /** * Gets the binary to data to write to the output file * * @return the binary data */ public byte[] getData() { byte[] data = new byte[2]; IntegerHelper.getTwoBytes(calculationMode.value, data, 0); return data; } } jexcelapi/src/jxl/write/biff/NumberRecord.java0000750000175000017500000001017111207000610021555 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2001 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import java.text.DecimalFormat; import java.text.NumberFormat; import jxl.CellType; import jxl.NumberCell; import jxl.biff.DoubleHelper; import jxl.biff.Type; import jxl.biff.XFRecord; import jxl.format.CellFormat; /** * The record which contains numerical values. All values are stored * as 64bit IEEE floating point values */ public abstract class NumberRecord extends CellValue { /** * The number */ private double value; /** * The java equivalent of the excel format */ private NumberFormat format; /** * The formatter to convert the value into a string */ private static DecimalFormat defaultFormat = new DecimalFormat("#.###"); /** * Constructor invoked by the user API * * @param c the column * @param r the row * @param val the value */ protected NumberRecord(int c, int r, double val) { super(Type.NUMBER, c, r); value = val; } /** * Overloaded constructor invoked from the API, which takes a cell * format * * @param c the column * @param r the row * @param val the value * @param st the cell format */ protected NumberRecord(int c, int r, double val, CellFormat st) { super(Type.NUMBER, c, r, st); value = val; } /** * Constructor used when copying a workbook * * @param nc the number to copy */ protected NumberRecord(NumberCell nc) { super(Type.NUMBER, nc); value = nc.getValue(); } /** * Copy constructor * * @param c the column * @param r the row * @param nr the record to copy */ protected NumberRecord(int c, int r, NumberRecord nr) { super(Type.NUMBER, c, r, nr); value = nr.value; } /** * Returns the content type of this cell * * @return the content type for this cell */ public CellType getType() { return CellType.NUMBER; } /** * Gets the binary data for output to file * * @return the binary data */ public byte[] getData() { byte[] celldata = super.getData(); byte[] data = new byte[celldata.length + 8]; System.arraycopy(celldata, 0, data, 0, celldata.length); DoubleHelper.getIEEEBytes(value, data, celldata.length); return data; } /** * Quick and dirty function to return the contents of this cell as a string. * For more complex manipulation of the contents, it is necessary to cast * this interface to correct subinterface * * @return the contents of this cell as a string */ public String getContents() { if (format == null) { format = ( (XFRecord) getCellFormat()).getNumberFormat(); if (format == null) { format = defaultFormat; } } return format.format(value); } /** * Gets the double contents for this cell. * * @return the cell contents */ public double getValue() { return value; } /** * Sets the value of the contents for this cell * * @param val the new value */ public void setValue(double val) { value = val; } /** * Gets the NumberFormat used to format this cell. This is the java * equivalent of the Excel format * * @return the NumberFormat used to format the cell */ public NumberFormat getNumberFormat() { return null; } } jexcelapi/src/jxl/write/biff/BoundsheetRecord.java0000750000175000017500000000441311207000610022427 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.StringHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Record which stores the sheet name, the sheet type and the stream * position */ class BoundsheetRecord extends WritableRecordData { /** * Hidden flag */ private boolean hidden; /** * Chart only flag */ private boolean chartOnly; /** * The name of the sheet */ private String name; /** * The data to write to the output file */ private byte[] data; /** * Constructor * * @param n the sheet name */ public BoundsheetRecord(String n) { super(Type.BOUNDSHEET); name = n; hidden = false; chartOnly = false; } /** * Sets the hidden flag */ void setHidden() { hidden = true; } /** * Sets the chart only flag */ void setChartOnly() { chartOnly = true; } /** * Gets the data to write out to the binary file * * @return the data to write out */ public byte[] getData() { data = new byte[name.length() * 2 + 8]; if (chartOnly) { data[5] = 0x02; } else { data[5] = 0; // set stream type to worksheet } if (hidden) { data[4] = 0x1; data[5] = 0x0; } data[6] = (byte) name.length(); data[7] = 1; StringHelper.getUnicodeBytes(name, data, 8); return data; } } jexcelapi/src/jxl/write/biff/ArbitraryRecord.java0000750000175000017500000000331011207000610022261 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.common.Logger; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Writes out some arbitrary record data. Used during the debug process */ class ArbitraryRecord extends WritableRecordData { /** * The logger */ private static Logger logger = Logger.getLogger(ArbitraryRecord.class); /** * The binary data */ private byte[] data; /** * Constructor * * @param type the biff code * @param d the data */ public ArbitraryRecord(int type, byte[] d) { super(Type.createType(type)); data = d; logger.warn("ArbitraryRecord of type " + type + " created"); } /** * Retrieves the data to be written to the binary file * * @return the binary data */ public byte[] getData() { return data; } } jexcelapi/src/jxl/write/biff/JxlWriteException.java0000750000175000017500000000421211207000610022614 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.write.WriteException; /** * Exception thrown when reading a biff file */ public class JxlWriteException extends WriteException { private static class WriteMessage { /** */ public String message; /** * Constructs this exception with the specified message * * @param m the messageA */ WriteMessage(String m) {message = m;} } /** */ static WriteMessage formatInitialized = new WriteMessage("Attempt to modify a referenced format"); /** */ static WriteMessage cellReferenced = new WriteMessage("Cell has already been added to a worksheet"); static WriteMessage maxRowsExceeded = new WriteMessage("The maximum number of rows permitted on a worksheet " + "been exceeded"); static WriteMessage maxColumnsExceeded = new WriteMessage("The maximum number of columns permitted on a " + "worksheet has been exceeded"); static WriteMessage copyPropertySets = new WriteMessage("Error encounted when copying additional property sets"); /** * Constructs this exception with the specified message * * @param m the message */ public JxlWriteException(WriteMessage m) { super(m.message); } } jexcelapi/src/jxl/write/biff/ColumnInfoRecord.java0000750000175000017500000002075011207000610022402 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.FormattingRecords; import jxl.biff.IndexMapping; import jxl.biff.IntegerHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; import jxl.biff.XFRecord; /** * Describes the column formatting for a particular column */ class ColumnInfoRecord extends WritableRecordData { /** * The binary data */ private byte[] data; /** * The column number which this format applies to */ private int column; /** * The style for the column */ private XFRecord style; /** * The index for the style of this column */ private int xfIndex; /** * The width of the column in 1/256 of a character */ private int width; /** * Flag to indicate the hidden status of this column */ private boolean hidden; /** * The column's outline level */ private int outlineLevel; /** * Column collapsed flag */ private boolean collapsed; /** * Constructor used when setting column information from the user * API * * @param w the width of the column in characters * @param col the column to format * @param xf the style for the column */ public ColumnInfoRecord(int col, int w, XFRecord xf) { super(Type.COLINFO); column = col; width = w; style = xf; xfIndex = style.getXFIndex(); hidden = false; } /** * Copy constructor used when copying from sheet to sheet within the * same workbook * * @param the record to copy */ public ColumnInfoRecord(ColumnInfoRecord cir) { super(Type.COLINFO); column = cir.column; width = cir.width; style = cir.style; xfIndex = cir.xfIndex; hidden = cir.hidden; outlineLevel = cir.outlineLevel; collapsed = cir.collapsed; } /** * Constructor used when copying an existing spreadsheet * * @param col the column number * @param cir the column info record read in * @param fr the format records */ public ColumnInfoRecord(jxl.read.biff.ColumnInfoRecord cir, int col, FormattingRecords fr) { super(Type.COLINFO); column = col; width = cir.getWidth(); xfIndex = cir.getXFIndex(); style = fr.getXFRecord(xfIndex); outlineLevel = cir.getOutlineLevel(); collapsed = cir.getCollapsed(); } /** * Constructor used when importing a sheet from another * spreadsheet * * @param col the column number * @param cir the column info record read in */ public ColumnInfoRecord(jxl.read.biff.ColumnInfoRecord cir, int col) { super(Type.COLINFO); column = col; width = cir.getWidth(); xfIndex = cir.getXFIndex(); outlineLevel = cir.getOutlineLevel(); collapsed = cir.getCollapsed(); } /** * Gets the column this format applies to * * @return the column which is formatted */ public int getColumn() { return column; } /** * Increments the column. Called when inserting a new column into * the sheet */ public void incrementColumn() { column++; } /** * Decrements the column. Called when removing a column from * the sheet */ public void decrementColumn() { column--; } /** * Accessor for the width * * @return the width */ int getWidth() { return width; } /** * Sets the width. Used when autosizing columns * * @param w the new width */ void setWidth(int w) { width = w; } /** * Gets the binary data to be written to the output file * * @return the data to write to file */ public byte[] getData() { data = new byte[0x0c]; IntegerHelper.getTwoBytes(column, data, 0); IntegerHelper.getTwoBytes(column, data, 2); IntegerHelper.getTwoBytes(width, data, 4); IntegerHelper.getTwoBytes(xfIndex, data, 6); // int options = 0x2; int options = 0x6 | (outlineLevel << 8); if (hidden) { options |= 0x1; } outlineLevel = ((options & 0x700) / 0x100); if (collapsed) { options |= 0x1000; } IntegerHelper.getTwoBytes(options, data, 8); // IntegerHelper.getTwoBytes(2, data, 10); return data; } /** * Gets the cell format associated with this column info record * * @return the cell format for this column */ public XFRecord getCellFormat() { return style; } /** * Sets the cell format. Used when importing spreadsheets * * @param xfr the xf record */ public void setCellFormat(XFRecord xfr) { style = xfr; } /** * Accessor for the xf index, used when importing from another spreadsheet * * @return the xf index */ public int getXfIndex() { return xfIndex; } /** * Rationalizes the sheets xf index mapping * @param xfmapping the index mapping */ void rationalize(IndexMapping xfmapping) { xfIndex = xfmapping.getNewIndex(xfIndex); } /** * Sets this column to be hidden (or otherwise) * * @param h TRUE if the column is to be hidden, FALSE otherwise */ void setHidden(boolean h) { hidden = h; } /** * Accessor for the hidden flag * * @return TRUE if this column is hidden, FALSE otherwise */ boolean getHidden() { return hidden; } /** * Standard equals method * * @return TRUE if these objects are equal, FALSE otherwise */ public boolean equals(Object o) { if (o == this) { return true; } if (!(o instanceof ColumnInfoRecord)) { return false; } ColumnInfoRecord cir = (ColumnInfoRecord) o; if (column != cir.column || xfIndex != cir.xfIndex || width != cir.width || hidden != cir.hidden || outlineLevel != cir.outlineLevel || collapsed != cir.collapsed) { return false; } if ((style == null && cir.style != null) || (style != null && cir.style == null)) { return false; } return style.equals(cir.style); } /** * Standard hashCode method * * @return the hashCode */ public int hashCode() { int hashValue = 137; int oddPrimeNumber = 79; hashValue = hashValue * oddPrimeNumber + column; hashValue = hashValue * oddPrimeNumber + xfIndex; hashValue = hashValue * oddPrimeNumber + width; hashValue = hashValue * oddPrimeNumber + (hidden ? 1:0); if (style != null) { hashValue ^= style.hashCode(); } return hashValue; } /** * Accessor for the column's outline level * * @return the column's outline level */ public int getOutlineLevel() { return outlineLevel; } /** * Accessor for whether the column is collapsed * * @return the column's collapsed state */ public boolean getCollapsed() { return collapsed; } /** * Increments the column's outline level. This is how groups are made * as well */ public void incrementOutlineLevel() { outlineLevel++; } /** * Decrements the column's outline level. This removes it from a * grouping level. If * all outline levels are gone the uncollapse the column. */ public void decrementOutlineLevel() { if (0 < outlineLevel) { outlineLevel--; } if (0==outlineLevel) { collapsed = false; } } /** * Sets the column's outline level * * @param level the column's outline level */ public void setOutlineLevel(int level) { outlineLevel = level; } /** * Sets the column's collapsed state * * @param value the column's collapsed state */ public void setCollapsed(boolean value) { collapsed = value; } } jexcelapi/src/jxl/write/biff/ColumnsExceededException.java0000750000175000017500000000232211207000610024113 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2005 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; /** * Exception thrown when attempting to add a column to a spreadsheet which * has already reached the maximum amount */ public class ColumnsExceededException extends JxlWriteException { /** * Constructor */ public ColumnsExceededException() { super(maxColumnsExceeded); } } jexcelapi/src/jxl/write/biff/CalcCountRecord.java0000750000175000017500000000326511207000610022206 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.IntegerHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Record which stores the maximum iterations option from the Options * dialog box */ class CalcCountRecord extends WritableRecordData { /** * The iteration count */ private int calcCount; /** * The binary data to write to the output file */ private byte[] data; /** * Constructor * * @param cnt the count indicator */ public CalcCountRecord(int cnt) { super(Type.CALCCOUNT); calcCount = cnt; } /** * Gets the data to write out to the file * * @return the binary data */ public byte[] getData() { byte[] data = new byte[2]; IntegerHelper.getTwoBytes(calcCount, data, 0); return data; } } jexcelapi/src/jxl/write/biff/LabelRecord.java0000750000175000017500000001256411207000610021354 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2001 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.common.Assert; import jxl.common.Logger; import jxl.CellType; import jxl.LabelCell; import jxl.biff.FormattingRecords; import jxl.biff.IntegerHelper; import jxl.biff.Type; import jxl.format.CellFormat; /** * A label record, used for writing out string */ public abstract class LabelRecord extends CellValue { /** * The logger */ private static Logger logger = Logger.getLogger(LabelRecord.class); /** * The string */ private String contents; /** * A handle to the shared strings used within this workbook */ private SharedStrings sharedStrings; /** * The index of the string in the shared string table */ private int index; /** * Constructor used when creating a label from the user API * * @param c the column * @param cont the contents * @param r the row */ protected LabelRecord(int c, int r, String cont) { super(Type.LABELSST, c, r); contents = cont; if (contents == null) { contents=""; } } /** * Constructor used when creating a label from the API. This is * overloaded to allow formatting information to be passed to the record * * @param c the column * @param cont the contents * @param r the row * @param st the format applied to the cell */ protected LabelRecord(int c, int r, String cont, CellFormat st) { super(Type.LABELSST, c, r, st); contents = cont; if (contents == null) { contents=""; } } /** * Copy constructor * * @param c the column * @param r the row * @param nr the record to copy */ protected LabelRecord(int c, int r, LabelRecord lr) { super(Type.LABELSST, c, r, lr); contents = lr.contents; } /** * Constructor used when copying a label from a read only * spreadsheet * * @param lc the label to copy */ protected LabelRecord(LabelCell lc) { super(Type.LABELSST, lc); contents = lc.getString(); if (contents == null) { contents = ""; } } /** * Returns the content type of this cell * * @return the content type for this cell */ public CellType getType() { return CellType.LABEL; } /** * Gets the binary data for output to file * * @return the binary data */ public byte[] getData() { byte[] celldata = super.getData(); byte[] data = new byte[celldata.length + 4]; System.arraycopy(celldata, 0, data, 0, celldata.length); IntegerHelper.getFourBytes(index, data, celldata.length); return data; } /** * Quick and dirty function to return the contents of this cell as a string. * For more complex manipulation of the contents, it is necessary to cast * this interface to correct subinterface * * @return the contents of this cell as a string */ public String getContents() { return contents; } /** * Gets the label for this cell. The value returned will be the same * as for the getContents method in the base class * * @return the cell contents */ public String getString() { return contents; } /** * Sets the string contents of this cell * * @param s the new string contents */ protected void setString(String s) { if (s == null) { s = ""; } contents = s; // Don't bother doing anything if this cell has not been referenced // yet - everything will be set up in due course if (!isReferenced()) { return; } Assert.verify(sharedStrings != null); // Initalize the shared string index index = sharedStrings.getIndex(contents); // Use the sharedStrings reference instead of this object's own // handle - this means that the bespoke copy becomes eligible for // garbage collection contents = sharedStrings.get(index); } /** * Overrides the method in the base class in order to add the string * content to the shared string table, and to store its shared string * index * * @param fr the formatting records * @param ss the shared strings used within the workbook * @param s */ void setCellDetails(FormattingRecords fr, SharedStrings ss, WritableSheetImpl s) { super.setCellDetails(fr, ss, s); sharedStrings = ss; index = sharedStrings.getIndex(contents); // Use the sharedStrings reference instead of this object's own // handle - this means that the bespoke copy becomes eligible for // garbage collection contents = sharedStrings.get(index); } } jexcelapi/src/jxl/write/biff/ExtendedSSTRecord.java0000750000175000017500000000745311207000610022470 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.IntegerHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Indicates an extension to the Shared String Table. Currently this * contains blank records * * Thanks to Guenther for contributing a proper implementation of the EXTSST * record, replacing my previous dummy version */ class ExtendedSSTRecord extends WritableRecordData { private static final int infoRecordSize = 8; private int numberOfStrings; private int[] absoluteStreamPositions; private int[] relativeStreamPositions; private int currentStringIndex = 0; /** * Constructor * * @param numstrings the number of strings per bucket * @param streampos the absolute stream position of the beginning of * the SST record */ public ExtendedSSTRecord(int newNumberOfStrings) { super(Type.EXTSST); numberOfStrings = newNumberOfStrings; int numberOfBuckets = getNumberOfBuckets(); absoluteStreamPositions = new int[numberOfBuckets]; relativeStreamPositions = new int[numberOfBuckets]; currentStringIndex = 0; } public int getNumberOfBuckets() { int numberOfStringsPerBucket = getNumberOfStringsPerBucket(); return numberOfStringsPerBucket != 0 ? (numberOfStrings + numberOfStringsPerBucket - 1) / numberOfStringsPerBucket : 0; } public int getNumberOfStringsPerBucket() { // XXX // should come up with a more clever calculation // bucket limit should not be bigger than 1024, otherwise we end // up with too many buckets and would have to write continue records // for the EXTSST record which we want to avoid for now. final int bucketLimit = 128; return (numberOfStrings + bucketLimit - 1) / bucketLimit; } public void addString(int absoluteStreamPosition, int relativeStreamPosition) { absoluteStreamPositions[currentStringIndex] = absoluteStreamPosition + relativeStreamPosition; relativeStreamPositions[currentStringIndex] = relativeStreamPosition; currentStringIndex++; } /** * Gets the binary data to be written out * * @return the binary data */ public byte[] getData() { int numberOfBuckets = getNumberOfBuckets(); byte[] data = new byte[2 + (8 * numberOfBuckets)]; // number of strings per bucket IntegerHelper.getTwoBytes(getNumberOfStringsPerBucket(), data, 0); for (int i = 0; i < numberOfBuckets; i++) { // absolute stream position IntegerHelper.getFourBytes(absoluteStreamPositions[i], data, 2 + (i * infoRecordSize)); // relative offset IntegerHelper.getTwoBytes(relativeStreamPositions[i], data, 6 + (i * infoRecordSize)); // reserved // IntegerHelper.getTwoBytes(0x0, data, 8 + (i * infoRecordSize)); } return data; } } jexcelapi/src/jxl/write/biff/PrintGridLinesRecord.java0000750000175000017500000000320111207000610023216 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * The grid lines option from the Page Setup dialog box */ class PrintGridLinesRecord extends WritableRecordData { /** * The binary data */ private byte[] data; /** * The print grid lines option */ private boolean printGridLines; /** * Constructor * * @param pgl the grid lines option */ public PrintGridLinesRecord(boolean pgl) { super(Type.PRINTGRIDLINES); printGridLines = pgl; data = new byte[2]; if (printGridLines) { data[0] = 1; } } /** * Gets the binary data for output to file * * @return the binary data */ public byte[] getData() { return data; } } jexcelapi/src/jxl/write/biff/BackupRecord.java0000750000175000017500000000335511207000610021540 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.IntegerHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Record which indicates whether Excel should save backup versions of the * file */ class BackupRecord extends WritableRecordData { /** * Flag to indicate whether or not Excel should make backups */ private boolean backup; /** * The data array */ private byte[] data; /** * Constructor * * @param bu backup flag */ public BackupRecord(boolean bu) { super(Type.BACKUP); backup = bu; // Hard code in an unprotected workbook data = new byte[2]; if (backup) { IntegerHelper.getTwoBytes(1, data, 0); } } /** * Returns the binary data for writing to the output file * * @return the binary data */ public byte[] getData() { return data; } } jexcelapi/src/jxl/write/biff/SSTRecord.java0000750000175000017500000001054511207000610021003 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import java.util.ArrayList; import java.util.Iterator; import jxl.biff.IntegerHelper; import jxl.biff.StringHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * A shared string table record. */ class SSTRecord extends WritableRecordData { /** * The number of string references in the workbook */ private int numReferences; /** * The number of strings in this table */ private int numStrings; /** * The list of strings */ private ArrayList strings; /** * The list of string lengths */ private ArrayList stringLengths; /** * The binary data */ private byte[] data; /** * The count of bytes needed so far to contain this record */ private int byteCount; /** * The maximum amount of bytes available for the SST record */ private static int maxBytes = 8228 - // max length 8 - // bytes for string count fields 4; // standard biff record header /** * Constructor * * @param numRefs the number of string references in the workbook * @param s the number of strings */ public SSTRecord(int numRefs, int s) { super(Type.SST); numReferences = numRefs; numStrings = s; byteCount = 0; strings = new ArrayList(50); stringLengths = new ArrayList(50); } /** * Adds a string to this SST record. It returns the number of string * characters not added, due to space constraints. In the event * of this being non-zero, a continue record will be needed * * @param s the string to add * @return the number of characters not added */ public int add(String s) { int bytes = s.length() * 2 + 3; // Must be able to add at least the first character of the string // onto the SST if (byteCount >= maxBytes - 5) { return s.length() > 0 ? s.length() : -1; // need to return some non-zero // value in order to force the creation of a continue record } stringLengths.add(new Integer(s.length())); if (bytes + byteCount < maxBytes) { // add the string and return strings.add(s); byteCount += bytes; return 0; } // Calculate the number of characters we can add int bytesLeft = maxBytes - 3 - byteCount; int charsAvailable = bytesLeft % 2 == 0 ? bytesLeft / 2 : (bytesLeft - 1) / 2; // Add what strings we can strings.add(s.substring(0, charsAvailable)); byteCount += charsAvailable * 2 + 3; return s.length() - charsAvailable; } /** * Gets the current offset into this record, excluding the header fields * * @return the number of bytes after the header field */ public int getOffset() { return byteCount + 8; } /** * Gets the binary data for output to file * * @return the binary data */ public byte[] getData() { data = new byte[byteCount+8]; IntegerHelper.getFourBytes(numReferences, data, 0); IntegerHelper.getFourBytes(numStrings, data, 4); int pos = 8; int count = 0; Iterator i = strings.iterator(); String s = null; int length = 0; while (i.hasNext()) { s = (String) i.next(); length = ( (Integer) stringLengths.get(count)).intValue(); IntegerHelper.getTwoBytes(length, data, pos); data[pos+2] = 0x01; StringHelper.getUnicodeBytes(s, data, pos+3); pos += s.length() * 2 + 3; count++; } return data; } } jexcelapi/src/jxl/write/biff/HorizontalCentreRecord.java0000750000175000017500000000315511207000610023623 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Record which indicates the whether the horizontal center option has * been set */ class HorizontalCentreRecord extends WritableRecordData { /** * The binary data */ private byte[] data; /** * The centre flag */ private boolean centre; /** * Constructor * * @param ce the centre flag */ public HorizontalCentreRecord(boolean ce) { super(Type.HCENTER); centre = ce; data = new byte[2]; if (centre) { data[0] = 1; } } /** * Gets the binary data for output to file * * @return the binary data */ public byte[] getData() { return data; } } jexcelapi/src/jxl/write/biff/Prot4RevPassRecord.java0000750000175000017500000000270111207000610022641 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Stores the shared workbook protection flag */ class Prot4RevPassRecord extends WritableRecordData { /** * The binary data */ private byte[] data; /** * Constructor */ public Prot4RevPassRecord() { super(Type.PROT4REVPASS); // Hard code in an unprotected workbook data = new byte[2]; } /** * Gets the binary data for output to file * * @return the binary data */ public byte[] getData() { return data; } } jexcelapi/src/jxl/write/biff/GridSetRecord.java0000750000175000017500000000313211207000610021665 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Record which indicates that the user changed the stae of the * GridLines option */ class GridSetRecord extends WritableRecordData { /** * The binary data */ private byte[] data; /** * Gridset flag */ private boolean gridSet; /** * Constructor * * @param gs grid set flag */ public GridSetRecord(boolean gs) { super(Type.GRIDSET); gridSet = gs; data = new byte[2]; if (gridSet) { data[0] = 1; } } /** * Gets the binary data for output to file * * @return the binary data */ public byte[] getData() { return data; } } jexcelapi/src/jxl/write/biff/StyleXFRecord.java0000750000175000017500000000342111207000610021663 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.DisplayFormat; import jxl.biff.FontRecord; import jxl.biff.XFRecord; /** * A style XF Record */ public class StyleXFRecord extends XFRecord { /** * Constructor * * @param fnt the font for this style * @param form the format of this style */ public StyleXFRecord(FontRecord fnt, DisplayFormat form) { super(fnt, form); setXFDetails(XFRecord.style, 0xfff0); } /** * Sets the raw cell options. Called by WritableFormattingRecord * when setting the built in cell formats * * @param opt the cell options */ public final void setCellOptions(int opt) { super.setXFCellOptions(opt); } /** * Sets whether or not this XF record locks the cell * * @param l the locked flag * @exception WriteException */ public void setLocked(boolean l) { super.setXFLocked(l); } } jexcelapi/src/jxl/write/biff/ReadNumberFormulaRecord.java0000750000175000017500000000673111207000610023706 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2004 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import java.text.NumberFormat; import jxl.common.Logger; import jxl.NumberFormulaCell; import jxl.biff.DoubleHelper; import jxl.biff.FormulaData; import jxl.biff.IntegerHelper; import jxl.biff.formula.FormulaException; import jxl.biff.formula.FormulaParser; /** * Class for read number formula records */ class ReadNumberFormulaRecord extends ReadFormulaRecord implements NumberFormulaCell { // The logger private static Logger logger = Logger.getLogger(ReadNumberFormulaRecord.class); /** * Constructor * * @param f */ public ReadNumberFormulaRecord(FormulaData f) { super(f); } /** * Gets the double contents for this cell. * * @return the cell contents */ public double getValue() { return ( (NumberFormulaCell) getReadFormula()).getValue(); } /** * Gets the NumberFormat used to format this cell. This is the java * equivalent of the Excel format * * @return the NumberFormat used to format the cell */ public NumberFormat getNumberFormat() { return ( (NumberFormulaCell) getReadFormula()).getNumberFormat(); } /** * Error formula specific exception handling. Can't really create * a formula (as it will look for a cell of that name, so just * create a STRING record containing the contents * * @return the bodged data */ protected byte[] handleFormulaException() { byte[] expressiondata = null; byte[] celldata = super.getCellData(); // Generate an appropriate dummy formula WritableWorkbookImpl w = getSheet().getWorkbook(); FormulaParser parser = new FormulaParser(Double.toString(getValue()), w, w, w.getSettings()); // Get the bytes for the dummy formula try { parser.parse(); } catch(FormulaException e2) { logger.warn(e2.getMessage()); } byte[] formulaBytes = parser.getBytes(); expressiondata = new byte[formulaBytes.length + 16]; IntegerHelper.getTwoBytes(formulaBytes.length, expressiondata, 14); System.arraycopy(formulaBytes, 0, expressiondata, 16, formulaBytes.length); // Set the recalculate on load bit expressiondata[8] |= 0x02; byte[] data = new byte[celldata.length + expressiondata.length]; System.arraycopy(celldata, 0, data, 0, celldata.length); System.arraycopy(expressiondata, 0, data, celldata.length, expressiondata.length); // Store the value in the formula DoubleHelper.getIEEEBytes(getValue(), data, 6); return data; } } jexcelapi/src/jxl/write/biff/SelectionRecord.java0000750000175000017500000000451111207000610022253 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.IntegerHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Stores the current selection */ class SelectionRecord extends WritableRecordData { /** * The pane type */ private PaneType pane; /** * The top left column in this pane */ private int column; /** * The top left row in this pane */ private int row; // Enumeration for the pane type private static class PaneType { int val; PaneType(int v) {val = v;} } // The pane types public final static PaneType lowerRight = new PaneType(0); public final static PaneType upperRight = new PaneType(1); public final static PaneType lowerLeft = new PaneType(2); public final static PaneType upperLeft = new PaneType(3); /** * Constructor */ public SelectionRecord(PaneType pt, int col, int r) { super(Type.SELECTION); column = col; row = r; pane = pt; } /** * Gets the binary data * * @return the binary data */ public byte[] getData() { // hard code the data in for now byte[] data = new byte[15]; data[0] = (byte) pane.val; IntegerHelper.getTwoBytes(row, data, 1); IntegerHelper.getTwoBytes(column, data, 3); data[7] = (byte) 0x01; IntegerHelper.getTwoBytes(row, data, 9); IntegerHelper.getTwoBytes(row, data, 11); data[13] = (byte) column; data[14] = (byte) column; return data; } } jexcelapi/src/jxl/write/biff/HeaderRecord.java0000750000175000017500000000403611207000610021520 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.IntegerHelper; import jxl.biff.StringHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Record which specifies a print header for a work sheet */ class HeaderRecord extends WritableRecordData { /** * The binary data */ private byte[] data; /** * The print header string */ private String header; /** * Constructor * * @param s the header string */ public HeaderRecord(String h) { super(Type.HEADER); header = h; } /** * Consructor invoked when copying a sheets * * @param hr the read header record */ public HeaderRecord(HeaderRecord hr) { super(Type.HEADER); header = hr.header; } /** * Gets the binary data for output to file * * @return the binary data */ public byte[] getData() { if (header == null || header.length() == 0) { data = new byte[0]; return data; } data = new byte[header.length() * 2 + 3]; IntegerHelper.getTwoBytes(header.length(), data, 0); data[2] = (byte) 0x1; StringHelper.getUnicodeBytes(header, data, 3); return data; } } jexcelapi/src/jxl/write/biff/SCLRecord.java0000750000175000017500000000326111207000610020750 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan, Adam Caldwell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.IntegerHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Record which specifies a margin value */ class SCLRecord extends WritableRecordData { /** * The zoom factor */ private int zoomFactor; /** * Constructor * * @param zf the zoom factor as a percentage */ public SCLRecord(int zf) { super(Type.SCL); zoomFactor = zf; } /** * Gets the binary data for output to file * * @return the binary data */ public byte[] getData() { byte[] data = new byte[4]; int numerator = zoomFactor; int denominator = 100; IntegerHelper.getTwoBytes(numerator,data,0); IntegerHelper.getTwoBytes(denominator,data,2); return data; } } jexcelapi/src/jxl/write/biff/CellXFRecord.java0000750000175000017500000001350411207000610021445 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.DisplayFormat; import jxl.biff.FontRecord; import jxl.biff.XFRecord; import jxl.format.Alignment; import jxl.format.Border; import jxl.format.BorderLineStyle; import jxl.format.CellFormat; import jxl.format.Colour; import jxl.format.Orientation; import jxl.format.Pattern; import jxl.format.VerticalAlignment; import jxl.write.WriteException; /** * A cell XF Record */ public class CellXFRecord extends XFRecord { /** * Constructor * * @param fnt the font * @param form the format */ protected CellXFRecord(FontRecord fnt, DisplayFormat form ) { super(fnt, form); setXFDetails(XFRecord.cell,0); } /** * Copy constructor. Invoked when copying formats to handle cell merging * * @param fmt the format to copy */ CellXFRecord(XFRecord fmt ) { super(fmt); setXFDetails(XFRecord.cell,0); } /** * A public copy constructor which can be used for copy formats between * different sheets */ protected CellXFRecord(CellFormat format) { super(format); } /** * Sets the alignment for the cell * * @exception WriteException * @param a the alignment */ public void setAlignment(Alignment a) throws WriteException { if (isInitialized()) { throw new JxlWriteException(JxlWriteException.formatInitialized); } super.setXFAlignment(a); } /** * Sets the background for the cell * * @exception WriteException * @param c the background colour * @param p the background patter */ public void setBackground(Colour c, Pattern p) throws WriteException { if (isInitialized()) { throw new JxlWriteException(JxlWriteException.formatInitialized); } super.setXFBackground(c, p); super.setXFCellOptions(0x4000); } /** * Sets whether or not this XF record locks the cell * * @param l the locked flag * @exception WriteException */ public void setLocked(boolean l) throws WriteException { if (isInitialized()) { throw new JxlWriteException(JxlWriteException.formatInitialized); } super.setXFLocked(l); super.setXFCellOptions(0x8000); } /** * Sets the indentation of the cell text * * @param i the indentation */ public void setIndentation(int i) throws WriteException { if (isInitialized()) { throw new JxlWriteException(JxlWriteException.formatInitialized); } super.setXFIndentation(i); } /** * Sets the shrink to fit flag * * @param b the shrink to fit flag */ public void setShrinkToFit(boolean s) throws WriteException { if (isInitialized()) { throw new JxlWriteException(JxlWriteException.formatInitialized); } super.setXFShrinkToFit(s); } /** * Sets the vertical alignment for cells with this style * * @exception WriteException * @param va the vertical alignment */ public void setVerticalAlignment(VerticalAlignment va) throws WriteException { if (isInitialized()) { throw new JxlWriteException(JxlWriteException.formatInitialized); } super.setXFVerticalAlignment(va); } /** * Sets the text orientation for cells with this style * * @exception WriteException * @param o the orientation */ public void setOrientation(Orientation o) throws WriteException { if (isInitialized()) { throw new JxlWriteException(JxlWriteException.formatInitialized); } super.setXFOrientation(o); } /** * Sets the text wrapping for cells with this style. If the parameter is * set to TRUE, then data in this cell will be wrapped around, and the * cell's height adjusted accordingly * * @exception WriteException * @param w the wrap */ public void setWrap(boolean w) throws WriteException { if (isInitialized()) { throw new JxlWriteException(JxlWriteException.formatInitialized); } super.setXFWrap(w); } /** * Sets the border style for cells with this format * * @exception WriteException * @param b the border * @param ls the line for the specified border */ public void setBorder(Border b, BorderLineStyle ls, Colour c) throws WriteException { if (isInitialized()) { throw new JxlWriteException(JxlWriteException.formatInitialized); } if (b == Border.ALL) { // Apply to all super.setXFBorder(Border.LEFT, ls, c); super.setXFBorder(Border.RIGHT, ls, c); super.setXFBorder(Border.TOP, ls, c); super.setXFBorder(Border.BOTTOM, ls, c); return; } if (b == Border.NONE) { // Apply to all super.setXFBorder(Border.LEFT, BorderLineStyle.NONE, Colour.BLACK); super.setXFBorder(Border.RIGHT, BorderLineStyle.NONE, Colour.BLACK); super.setXFBorder(Border.TOP, BorderLineStyle.NONE, Colour.BLACK); super.setXFBorder(Border.BOTTOM, BorderLineStyle.NONE, Colour.BLACK); return; } super.setXFBorder(b, ls, c); } } jexcelapi/src/jxl/write/biff/WritableFontRecord.java0000750000175000017500000001136411207000610022732 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.FontRecord; import jxl.format.Font; import jxl.write.WriteException; /** * A writable Font record. This class intercepts any set accessor calls * and throws and exception if the Font is already initialized */ public class WritableFontRecord extends FontRecord { /** * Constructor, used when creating a new font for writing out. * * @param bold the bold indicator * @param ps the point size * @param us the underline style * @param fn the name * @param it italicised indicator * @param c the colour * @param ss the script style */ protected WritableFontRecord(String fn, int ps, int bold, boolean it, int us, int ci, int ss) { super(fn, ps, bold, it, us, ci, ss); } /** * Publicly available copy constructor * * @param the font to copy */ protected WritableFontRecord(Font f) { super(f); } /** * Sets the point size for this font, if the font hasn't been initialized * * @param pointSize the point size * @exception WriteException, if this font is already in use elsewhere */ protected void setPointSize(int pointSize) throws WriteException { if (isInitialized()) { throw new JxlWriteException(JxlWriteException.formatInitialized); } super.setFontPointSize(pointSize); } /** * Sets the bold style for this font, if the font hasn't been initialized * * @param boldStyle the bold style * @exception WriteException, if this font is already in use elsewhere */ protected void setBoldStyle(int boldStyle) throws WriteException { if (isInitialized()) { throw new JxlWriteException(JxlWriteException.formatInitialized); } super.setFontBoldStyle(boldStyle); } /** * Sets the italic indicator for this font, if the font hasn't been * initialized * * @param italic the italic flag * @exception WriteException, if this font is already in use elsewhere */ protected void setItalic(boolean italic) throws WriteException { if (isInitialized()) { throw new JxlWriteException(JxlWriteException.formatInitialized); } super.setFontItalic(italic); } /** * Sets the underline style for this font, if the font hasn't been * initialized * * @param us the underline style * @exception WriteException, if this font is already in use elsewhere */ protected void setUnderlineStyle(int us) throws WriteException { if (isInitialized()) { throw new JxlWriteException(JxlWriteException.formatInitialized); } super.setFontUnderlineStyle(us); } /** * Sets the colour for this font, if the font hasn't been * initialized * * @param colour the colour * @exception WriteException, if this font is already in use elsewhere */ protected void setColour(int colour) throws WriteException { if (isInitialized()) { throw new JxlWriteException(JxlWriteException.formatInitialized); } super.setFontColour(colour); } /** * Sets the script style (eg. superscript, subscript) for this font, * if the font hasn't been initialized * * @param scriptStyle the colour * @exception WriteException, if this font is already in use elsewhere */ protected void setScriptStyle(int scriptStyle) throws WriteException { if (isInitialized()) { throw new JxlWriteException(JxlWriteException.formatInitialized); } super.setFontScriptStyle(scriptStyle); } /** * Sets the struck out flag * * @param so TRUE if the font is struck out, false otherwise * @exception WriteException, if this font is already in use elsewhere */ protected void setStruckout(boolean os) throws WriteException { if (isInitialized()) { throw new JxlWriteException(JxlWriteException.formatInitialized); } super.setFontStruckout(os); } } jexcelapi/src/jxl/write/biff/InterfaceHeaderRecord.java0000750000175000017500000000264311207000610023343 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Marks the beginning of the user interface record */ class InterfaceHeaderRecord extends WritableRecordData { /** * Constructor */ public InterfaceHeaderRecord() { super(Type.INTERFACEHDR); } /** * Gets the binary data * * @return the binary data */ public byte[] getData() { // Return the character encoding byte[] data = new byte[] { (byte) 0xb0, (byte) 0x04}; return data; } } jexcelapi/src/jxl/write/biff/RowRecord.java0000750000175000017500000004110711264566262021126 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import jxl.common.Logger; import jxl.CellType; import jxl.SheetSettings; import jxl.WorkbookSettings; import jxl.biff.CellReferenceHelper; import jxl.biff.IndexMapping; import jxl.biff.IntegerHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; import jxl.biff.XFRecord; import jxl.write.Number; import jxl.write.WritableCellFeatures; import jxl.write.WritableSheet; /** * Contains all the cells for a given row in a sheet */ class RowRecord extends WritableRecordData { /** * The logger */ private static final Logger logger = Logger.getLogger(RowRecord.class); /** * The binary data */ private byte[] data; /** * The cells which comprise this row */ private CellValue[] cells; /** * The height of this row in 1/20ths of a point */ private int rowHeight; /** * Flag to indicate whether this row is outline collapsed or not */ private boolean collapsed; /** * The number of this row within the worksheet */ private int rowNumber; /** * The number of columns in this row. This is the largest column value + 1 */ private int numColumns; /** * The xfIndex for this row */ private int xfIndex; /** * The style for this row */ private XFRecord style; /** * Flag indicating that this row record has an default format */ private boolean defaultFormat; /** * Flag indicating whether this row matches the default font height */ private boolean matchesDefFontHeight; /** * The amount to grow the cells array by */ private static final int growSize = 10; /** * The maximum integer value that can be squeezed into 30 bits */ private static final int maxRKValue = 0x1fffffff; /** * The minimum integer value that can be squeezed into 30 bits */ private static final int minRKValue = -0x20000000; /** * Indicates that the row is default height */ private static int defaultHeightIndicator = 0xff; /** * The maximum number of columns */ private static int maxColumns = 256; /** * The outline level of the row */ private int outlineLevel; /** * Is this the icon indicator row of a group? */ private boolean groupStart; /** * A handle back to the sheet */ private WritableSheet sheet; /** * Constructs an empty row which has the specified row number * * @param rn the row number of this row */ public RowRecord(int rn, WritableSheet ws) { super(Type.ROW); rowNumber = rn; cells = new CellValue[0]; numColumns = 0; rowHeight = defaultHeightIndicator; collapsed = false; matchesDefFontHeight = true; sheet = ws; } /** * Sets the height of this row * * @param h the row height */ public void setRowHeight(int h) { if (h == 0) { setCollapsed(true); matchesDefFontHeight = false; } else { rowHeight = h; matchesDefFontHeight = false; } } /** * Sets the row details based upon the readable row record passed in * Called when copying spreadsheets * * @param height the height of the row record in 1/20ths of a point * @param mdfh matches the default font height * @param col the collapsed status of the row * @param ol the outline level * @param gs the group start * @param xf the xfrecord for the row (NULL if no default is set) */ void setRowDetails(int height, boolean mdfh, boolean col, int ol, boolean gs, XFRecord xfr) { rowHeight = height; collapsed = col; matchesDefFontHeight = mdfh; outlineLevel = ol; groupStart = gs; if (xfr != null) { defaultFormat = true; style = xfr; xfIndex = style.getXFIndex(); } } /** * Sets the collapsed status of this row * * @param c the collapsed flag */ public void setCollapsed(boolean c) { collapsed = c; } /** * Gets the row number of this row * * @return the row number */ public int getRowNumber() { return rowNumber; } /** * Adds a cell to this row, growing the array of cells as required * * @param cv the cell to add */ public void addCell(CellValue cv) { int col = cv.getColumn(); if (col >= maxColumns) { logger.warn("Could not add cell at " + CellReferenceHelper.getCellReference(cv.getRow(), cv.getColumn()) + " because it exceeds the maximum column limit"); return; } // Grow the array if needs be if (col >= cells.length) { CellValue[] oldCells = cells; cells = new CellValue[Math.max(oldCells.length + growSize, col+1)]; System.arraycopy(oldCells, 0, cells, 0, oldCells.length); oldCells = null; } // Remove any cell features from the cell being replaced if (cells[col] != null) { WritableCellFeatures wcf = cells[col].getWritableCellFeatures(); if (wcf != null) { wcf.removeComment(); // if the cell is part of a shared data validation,then don't remove // the validation if (wcf.getDVParser() != null && !wcf.getDVParser().extendedCellsValidation()) { wcf.removeDataValidation(); } } } cells[col] = cv; numColumns = Math.max(col+1, numColumns); } /** * Removes a cell from this row * * @param col the column at which to remove the cell */ public void removeCell(int col) { // Grow the array if needs be if (col >= numColumns) { return; } cells[col] = null; } /** * Writes out the row information data (but not the individual cells) * * @exception IOException * @param outputFile the output file */ public void write(File outputFile) throws IOException { outputFile.write(this); } /** * Writes out all the cells in this row. If more than three integer * values occur consecutively, then a MulRK record is used to group the * numbers * * @exception IOException * @param outputFile the output file */ public void writeCells(File outputFile) throws IOException { // This is the list for integer values ArrayList integerValues = new ArrayList(); boolean integerValue = false; // Write out all the records for (int i = 0; i < numColumns; i++) { integerValue = false; if (cells[i] != null) { // See if this cell is a 30-bit integer value (without additional // cell features) if (cells[i].getType() == CellType.NUMBER) { Number nc = (Number) cells[i]; if (nc.getValue() == (int) nc.getValue() && nc.getValue() < maxRKValue && nc.getValue() > minRKValue && nc.getCellFeatures() == null) { integerValue = true; } } if (integerValue) { // This cell is an integer, add it to the list integerValues.add(cells[i]); } else { // This cell is not an integer. Write out whatever integers we // have, and then write out this cell writeIntegerValues(integerValues, outputFile); outputFile.write(cells[i]); // If the cell is a string formula, write out the string record // immediately afterwards if (cells[i].getType() == CellType.STRING_FORMULA) { StringRecord sr = new StringRecord(cells[i].getContents()); outputFile.write(sr); } } } else { // Cell does not exist. Write out the list of integers that // we have writeIntegerValues(integerValues, outputFile); } } // All done. Write out any remaining integer values writeIntegerValues(integerValues, outputFile); } /** * Writes out the list of integer values. If there are more than three, * a MulRK record is used, otherwise a sequence of Numbers is used * * @exception IOException * @param outputFile the output file * @param integerValues the array of integer values */ private void writeIntegerValues(ArrayList integerValues, File outputFile) throws IOException { if (integerValues.size() == 0) { return; } if (integerValues.size() >= 3 ) { // Write out as a MulRK record MulRKRecord mulrk = new MulRKRecord(integerValues); outputFile.write(mulrk); } else { // Write out as number records Iterator i = integerValues.iterator(); while (i.hasNext()) { outputFile.write((CellValue) i.next()); } } // Clear out the list of integerValues integerValues.clear(); } /** * Gets the row data to output to file * * @return the binary data */ public byte[] getData() { // Write out the row record byte[] data = new byte[16]; // If the default row height has been changed in the sheet settings, // then we need to set the rowHeight on this row explicitly, as // specifying the "match default" flag doesn't work int rh = rowHeight; if (sheet.getSettings().getDefaultRowHeight() != SheetSettings.DEFAULT_DEFAULT_ROW_HEIGHT) { // the default row height has been changed. If this row does not // have a specific row height set on it, then set it to the default if (rh == defaultHeightIndicator) { rh = sheet.getSettings().getDefaultRowHeight(); } } IntegerHelper.getTwoBytes(rowNumber, data, 0); IntegerHelper.getTwoBytes(numColumns, data, 4); IntegerHelper.getTwoBytes(rh, data, 6); int options = 0x100 + outlineLevel; if (groupStart) { options |= 0x10; } if (collapsed) { options |= 0x20; } if (!matchesDefFontHeight) { options |= 0x40; } if (defaultFormat) { options |= 0x80; options |= (xfIndex << 16); } IntegerHelper.getFourBytes(options, data, 12); return data; } /** * Gets the maximum column value which occurs in this row * * @return the maximum column value */ public int getMaxColumn() { return numColumns; } /** * Gets the cell which occurs at the specified column value * * @param col the colun for which to return the cell * @return the cell value at the specified position, or null if the column * is invalid */ public CellValue getCell(int col) { return (col >= 0 && col < numColumns) ? cells[col] : null; } /** * Increments the row of this cell by one. Invoked by the sheet when * inserting rows */ void incrementRow() { rowNumber++; for (int i = 0; i < cells.length; i++) { if (cells[i] != null) { cells[i].incrementRow(); } } } /** * Decrements the row of this cell by one. Invoked by the sheet when * removing rows */ void decrementRow() { rowNumber--; for (int i = 0; i < cells.length; i++) { if (cells[i] != null) { cells[i].decrementRow(); } } } /** * Inserts a new column at the position specified. If the max column length * is already reached, then the last column simply gets dropped * * @param col the column to insert */ void insertColumn(int col) { // Don't bother doing anything unless there are cells after the // column to be inserted if (col >= numColumns) { return; } // Create a new array to hold the new column. Grow it if need be CellValue[] oldCells = cells; if (numColumns >= cells.length - 1) { cells = new CellValue[oldCells.length + growSize]; } else { cells = new CellValue[oldCells.length]; } // Copy in everything up to the new column System.arraycopy(oldCells, 0, cells, 0, col); // Copy in the remaining cells System.arraycopy(oldCells, col, cells, col+1, numColumns - col); // Increment all the internal column numbers by one for (int i = col+1; i <= numColumns; i++) { if (cells[i] != null) { cells[i].incrementColumn(); } } // Adjust the maximum column record numColumns = Math.min(numColumns+1, maxColumns); } /** * Remove the new column at the position specified * * @param col the column to remove */ void removeColumn(int col) { // Don't bother doing anything unless there are cells after the // column to be inserted if (col >= numColumns) { return; } // Create a new array to hold the new columns CellValue[] oldCells = cells; cells = new CellValue[oldCells.length]; // Copy in everything up to the column System.arraycopy(oldCells, 0, cells, 0, col); // Copy in the remaining cells after the column System.arraycopy(oldCells, col + 1, cells, col, numColumns - (col+1)); // Decrement all the internal column numbers by one for (int i = col; i < numColumns; i++) { if (cells[i] != null) { cells[i].decrementColumn(); } } // Adjust the maximum column record numColumns--; } /** * Interrogates whether this row is of default height * * @return TRUE if this is set to the default height, FALSE otherwise */ public boolean isDefaultHeight() { return rowHeight == defaultHeightIndicator; } /** * Gets the height of the row * * @return the row height */ public int getRowHeight() { return rowHeight; } /** * Queries whether the row is collapsed * * @return the collapsed indicator */ public boolean isCollapsed() { return collapsed; } /** * Rationalizes the sheets xf index mapping * @param xfmapping the index mapping */ void rationalize(IndexMapping xfmapping) { if (defaultFormat) { xfIndex = xfmapping.getNewIndex(xfIndex); } } /** * Accessor for the style. The returned value is only non-null if the * default style is overridden * * @return the style */ XFRecord getStyle() { return style; } /** * Accessor for the default format flag * * @return TRUE if this row has its own default format */ boolean hasDefaultFormat() { return defaultFormat; } /** * Accessor for the matches default font height flag * * @return TRUE if this row matches the default font height */ boolean matchesDefaultFontHeight() { return matchesDefFontHeight; } /** * Accessor for the column's outline level * * @return the column's outline level */ public int getOutlineLevel() { return outlineLevel; } /** * Accessor for row's groupStart state * * @return the row's groupStart state */ public boolean getGroupStart() { return groupStart; } /** * Increments the row's outline level. This is how groups are made as well */ public void incrementOutlineLevel() { outlineLevel++; } /** * Decrements the row's outline level. This removes it from a grouping * level. If * all outline levels are gone the uncollapse the row. */ public void decrementOutlineLevel() { if (0 < outlineLevel) { outlineLevel--; } if (0==outlineLevel) { collapsed = false; } } /** * Sets the row's outline level * * @param level the row's outline level */ public void setOutlineLevel(int level) { outlineLevel = level; } /** * Sets the row's group start state * * @param value the group start state */ public void setGroupStart(boolean value) { groupStart = value; } } jexcelapi/src/jxl/write/biff/SSTContinueRecord.java0000750000175000017500000001302211207000610022501 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import java.util.ArrayList; import java.util.Iterator; import jxl.biff.IntegerHelper; import jxl.biff.StringHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * A continuation of a shared string table record. */ class SSTContinueRecord extends WritableRecordData { /** * The first string is a special case */ private String firstString; /** * Indicates whether or not we need to include the length information * for the first string */ private boolean includeLength; /** * The length of the first string */ private int firstStringLength; /** * The list of strings */ private ArrayList strings; /** * The list of string lengths */ private ArrayList stringLengths; /** * The binary data */ private byte[] data; /** * The count of bytes needed so far to contain this record */ private int byteCount; /** * The maximum amount of bytes available for the SST record */ private static int maxBytes = 8228 - // max length 4; // standard biff record stuff /** * Constructor * * @param numRefs the number of string references in the workbook * @param s the number of strings */ public SSTContinueRecord() { super(Type.CONTINUE); byteCount = 0; strings = new ArrayList(50); stringLengths = new ArrayList(50); } /** * Adds the first string to this SST record * * @param s the string to add * @param b include the length information for the first string * @return the number of characters not added */ public int setFirstString(String s, boolean b) { includeLength = b; firstStringLength = s.length(); int bytes = 0; if (!includeLength) { bytes = s.length() * 2 + 1; } else { bytes = s.length() * 2 + 3; } if (bytes <= maxBytes) { firstString = s; byteCount += bytes; return 0; } // Calculate the number of characters we can add // The bytes variable will always be an odd number int charsAvailable = includeLength ? (maxBytes - 4) / 2 : (maxBytes - 2) / 2; // Add what part of the string we can firstString = s.substring(0, charsAvailable); byteCount = maxBytes - 1; return s.length() - charsAvailable; } /** * Gets the current offset into this record, excluding the header fields * * @return the number of bytes after the header field */ public int getOffset() { return byteCount; } /** * Adds a string to this record. It returns the number of string * characters not added, due to space constraints. In the event * of this being non-zero, a continue record will be needed * * @param s the string to add * @return the number of characters not added */ public int add(String s) { int bytes = s.length() * 2 + 3; // Must be able to add at least the first character of the string // onto the SST if (byteCount >= maxBytes - 5) { return s.length(); } stringLengths.add(new Integer(s.length())); if (bytes + byteCount < maxBytes) { // add the string and return strings.add(s); byteCount += bytes; return 0; } // Calculate the number of characters we can add int bytesLeft = maxBytes - 3 - byteCount; int charsAvailable = bytesLeft % 2 == 0 ? bytesLeft / 2 : (bytesLeft - 1) / 2; // Add what part of the string we can strings.add(s.substring(0, charsAvailable)); byteCount += charsAvailable * 2 + 3; return s.length() - charsAvailable; } /** * Gets the binary data for output to file * * @return the binary data */ public byte[] getData() { data = new byte[byteCount]; int pos = 0; // Write out the first string if (includeLength) { IntegerHelper.getTwoBytes(firstStringLength, data, 0); data[2] = 0x01; pos = 3; } else { // Just include the unicode indicator data[0] = 0x01; pos = 1; } StringHelper.getUnicodeBytes(firstString, data, pos); pos += firstString.length() * 2; // Now write out the remainder of the strings Iterator i = strings.iterator(); String s = null; int length = 0; int count = 0; while (i.hasNext()) { s = (String) i.next(); length = ( (Integer) stringLengths.get(count)).intValue(); IntegerHelper.getTwoBytes(length, data, pos); data[pos+2] = 0x01; StringHelper.getUnicodeBytes(s, data, pos+3); pos += s.length() * 2 + 3; count++; } return data; } } jexcelapi/src/jxl/write/biff/DimensionRecord.java0000750000175000017500000000346311207000610022260 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.IntegerHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Record which contains the bounds of the sheet */ class DimensionRecord extends WritableRecordData { /** * The number of rows in the sheet */ private int numRows; /** * The number of columns in the sheet */ private int numCols; /** * The binary data */ private byte[] data; /** * Constructor * * @param c the number of columns * @param r the number of rows */ public DimensionRecord(int r, int c) { super(Type.DIMENSION); numRows = r; numCols = c; data = new byte[14]; IntegerHelper.getFourBytes(numRows, data, 4); IntegerHelper.getTwoBytes(numCols, data, 10); } /** * Gets the binary data to be written to the output file * * @return the binary data */ protected byte[] getData() { return data; } } jexcelapi/src/jxl/write/biff/SetupRecord.java0000750000175000017500000001220311207000610021423 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.common.Logger; import jxl.SheetSettings; import jxl.biff.DoubleHelper; import jxl.biff.IntegerHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; import jxl.format.PageOrder; import jxl.format.PageOrientation; import jxl.format.PaperSize; /** * Stores the options and measurements from the Page Setup dialog box */ class SetupRecord extends WritableRecordData { /** * The logger */ Logger logger = Logger.getLogger(SetupRecord.class); /** * The binary data for output to file */ private byte[] data; /** * The header margin */ private double headerMargin; /** * The footer margin */ private double footerMargin; /** * The page orientation */ private PageOrientation orientation; /** * The page order */ private PageOrder order; /** * The paper size */ private int paperSize; /** * The scale factor */ private int scaleFactor; /** * The page start */ private int pageStart; /** * The fit width */ private int fitWidth; /** * The fit height */ private int fitHeight; /** * The horizontal print resolution */ private int horizontalPrintResolution; /** * The vertical print resolution */ private int verticalPrintResolution; /** * The number of copies */ private int copies; /** * Indicates whether the setup data should be initiliazed in the setup * box */ private boolean initialized; /** * Constructor, taking the sheet settings. This object just * takes the various fields from the bean in which it is interested * * @param the sheet settings */ public SetupRecord(SheetSettings s) { super(Type.SETUP); orientation = s.getOrientation(); order = s.getPageOrder(); headerMargin = s.getHeaderMargin(); footerMargin = s.getFooterMargin(); paperSize = s.getPaperSize().getValue(); horizontalPrintResolution = s.getHorizontalPrintResolution(); verticalPrintResolution = s.getVerticalPrintResolution(); fitWidth = s.getFitWidth(); fitHeight = s.getFitHeight(); pageStart = s.getPageStart(); scaleFactor = s.getScaleFactor(); copies = s.getCopies(); initialized = true; } /** * Sets the orientation * * @param o the orientation */ public void setOrientation(PageOrientation o) { orientation = o; } /** * Sets the page order * * @param o */ public void setOrder(PageOrder o) { order = o; } /** * Sets the header and footer margins * * @param hm the header margin * @param fm the footer margin */ public void setMargins(double hm, double fm) { headerMargin = hm; footerMargin = fm; } /** * Sets the paper size * * @param ps the paper size */ public void setPaperSize(PaperSize ps) { paperSize = ps.getValue(); } /** * Gets the binary data for output to file * * @return the binary data */ public byte[] getData() { data = new byte[34]; // Paper size IntegerHelper.getTwoBytes(paperSize, data, 0); // Scale factor IntegerHelper.getTwoBytes(scaleFactor, data, 2); // Page start IntegerHelper.getTwoBytes(pageStart, data, 4); // Fit width IntegerHelper.getTwoBytes(fitWidth, data, 6); // Fit height IntegerHelper.getTwoBytes(fitHeight, data, 8); // grbit int options = 0; if (order == PageOrder.RIGHT_THEN_DOWN) { options |= 0x01; } if (orientation == PageOrientation.PORTRAIT) { options |= 0x02; } if (pageStart != 0) { options |= 0x80; } if (!initialized) { options |= 0x04; } IntegerHelper.getTwoBytes(options, data, 10); // print resolution IntegerHelper.getTwoBytes(horizontalPrintResolution, data, 12); // vertical print resolution IntegerHelper.getTwoBytes(verticalPrintResolution, data, 14); // header margin DoubleHelper.getIEEEBytes(headerMargin, data, 16); // footer margin DoubleHelper.getIEEEBytes(footerMargin, data, 24); // Number of copies IntegerHelper.getTwoBytes(copies, data, 32); return data; } } jexcelapi/src/jxl/write/biff/SheetWriter.java0000750000175000017500000010152611234606537021464 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.TreeSet; import jxl.common.Assert; import jxl.common.Logger; import jxl.Cell; import jxl.CellFeatures; import jxl.CellReferenceHelper; import jxl.Range; import jxl.SheetSettings; import jxl.WorkbookSettings; import jxl.biff.AutoFilter; import jxl.biff.ConditionalFormat; import jxl.biff.DataValidation; import jxl.biff.DataValiditySettingsRecord; import jxl.biff.DVParser; import jxl.biff.WorkspaceInformationRecord; import jxl.biff.XFRecord; import jxl.biff.drawing.Chart; import jxl.biff.drawing.SheetDrawingWriter; import jxl.biff.formula.FormulaException; import jxl.format.Border; import jxl.format.BorderLineStyle; import jxl.format.Colour; import jxl.write.Blank; import jxl.write.WritableCell; import jxl.write.WritableCellFormat; import jxl.write.WritableHyperlink; import jxl.write.WriteException; /** * Contains the functionality necessary for writing out a sheet. Originally * this was incorporated in WritableSheetImpl, but was moved out into * a dedicated class in order to reduce the over bloated nature of that * class */ final class SheetWriter { /** * The logger */ private static Logger logger = Logger.getLogger(SheetWriter.class); /** * A handle to the output file which the binary data is written to */ private File outputFile; /** * The rows within this sheet */ private RowRecord[] rows; /** * A number of rows. This is a count of the maximum row number + 1 */ private int numRows; /** * The number of columns. This is a count of the maximum column number + 1 */ private int numCols; /** * The page header */ private HeaderRecord header; /** * The page footer */ private FooterRecord footer; /** * The settings for the sheet */ private SheetSettings settings; /** * The settings for the workbook */ private WorkbookSettings workbookSettings; /** * Array of row page breaks */ private ArrayList rowBreaks; /** * Array of column page breaks */ private ArrayList columnBreaks; /** * Array of hyperlinks */ private ArrayList hyperlinks; /** * Array of conditional formats */ private ArrayList conditionalFormats; /** * The autofilter info */ private AutoFilter autoFilter; /** * Array of validated cells */ private ArrayList validatedCells; /** * The data validation validations */ private DataValidation dataValidation; /** * The list of merged ranges */ private MergedCells mergedCells; /** * The environment specific print record */ private PLSRecord plsRecord; /** * The button property ste */ private ButtonPropertySetRecord buttonPropertySet; /** * The workspace options */ private WorkspaceInformationRecord workspaceOptions; /** * The column format overrides */ private TreeSet columnFormats; /** * The list of drawings */ private SheetDrawingWriter drawingWriter; /** * Flag indicates that this sheet contains just a chart, and nothing * else */ private boolean chartOnly; /** * The maximum row outline level */ private int maxRowOutlineLevel; /** * The maximum column outline level */ private int maxColumnOutlineLevel; /** * A handle back to the writable sheet, in order for this class * to invoke the get accessor methods */ private WritableSheetImpl sheet; /** * Creates a new SheetWriter instance. * * @param of the output file */ public SheetWriter(File of, WritableSheetImpl wsi, WorkbookSettings ws) { outputFile = of; sheet = wsi; workspaceOptions = new WorkspaceInformationRecord(); workbookSettings = ws; chartOnly = false; drawingWriter = new SheetDrawingWriter(ws); } /** * Writes out this sheet. First writes out the standard sheet * information then writes out each row in turn. * Once all the rows have been written out, it retrospectively adjusts * the offset references in the file * * @exception IOException */ public void write() throws IOException { Assert.verify(rows != null); // This worksheet consists of just one chart, so write it and return if (chartOnly) { drawingWriter.write(outputFile); return; } BOFRecord bof = new BOFRecord(BOFRecord.sheet); outputFile.write(bof); // Compute the number of blocks of 32 rows that will be needed int numBlocks = numRows / 32; if (numRows - numBlocks * 32 != 0) { numBlocks++; } int indexPos = outputFile.getPos(); // Write the index record out now in order to serve as a place holder // The bof passed in is the bof of the workbook, not this sheet IndexRecord indexRecord = new IndexRecord(0, numRows, numBlocks); outputFile.write(indexRecord); if (settings.getAutomaticFormulaCalculation()) { CalcModeRecord cmr = new CalcModeRecord(CalcModeRecord.automatic); outputFile.write(cmr); } else { CalcModeRecord cmr = new CalcModeRecord(CalcModeRecord.manual); outputFile.write(cmr); } CalcCountRecord ccr = new CalcCountRecord(0x64); outputFile.write(ccr); RefModeRecord rmr = new RefModeRecord(); outputFile.write(rmr); IterationRecord itr = new IterationRecord(false); outputFile.write(itr); DeltaRecord dtr = new DeltaRecord(0.001); outputFile.write(dtr); SaveRecalcRecord srr = new SaveRecalcRecord (settings.getRecalculateFormulasBeforeSave()); outputFile.write(srr); PrintHeadersRecord phr = new PrintHeadersRecord (settings.getPrintHeaders()); outputFile.write(phr); PrintGridLinesRecord pglr = new PrintGridLinesRecord (settings.getPrintGridLines()); outputFile.write(pglr); GridSetRecord gsr = new GridSetRecord(true); outputFile.write(gsr); GuttersRecord gutr = new GuttersRecord(); gutr.setMaxColumnOutline(maxColumnOutlineLevel + 1); gutr.setMaxRowOutline(maxRowOutlineLevel + 1); outputFile.write(gutr); DefaultRowHeightRecord drhr = new DefaultRowHeightRecord (settings.getDefaultRowHeight(), settings.getDefaultRowHeight() != SheetSettings.DEFAULT_DEFAULT_ROW_HEIGHT); outputFile.write(drhr); if (maxRowOutlineLevel > 0) { workspaceOptions.setRowOutlines(true); } if (maxColumnOutlineLevel > 0) { workspaceOptions.setColumnOutlines(true); } workspaceOptions.setFitToPages(settings.getFitToPages()); outputFile.write(workspaceOptions); if (rowBreaks.size() > 0) { int[] rb = new int[rowBreaks.size()]; for (int i = 0; i < rb.length; i++) { rb[i] = ( (Integer) rowBreaks.get(i)).intValue(); } HorizontalPageBreaksRecord hpbr = new HorizontalPageBreaksRecord(rb); outputFile.write(hpbr); } if (columnBreaks.size() > 0) { int[] rb = new int[columnBreaks.size()]; for (int i = 0; i < rb.length; i++) { rb[i] = ( (Integer) columnBreaks.get(i)).intValue(); } VerticalPageBreaksRecord hpbr = new VerticalPageBreaksRecord(rb); outputFile.write(hpbr); } HeaderRecord header = new HeaderRecord(settings.getHeader().toString()); outputFile.write(header); FooterRecord footer = new FooterRecord(settings.getFooter().toString()); outputFile.write(footer); HorizontalCentreRecord hcr = new HorizontalCentreRecord (settings.isHorizontalCentre()); outputFile.write(hcr); VerticalCentreRecord vcr = new VerticalCentreRecord (settings.isVerticalCentre()); outputFile.write(vcr); // Write out the margins if they don't equal the default if (settings.getLeftMargin() != settings.getDefaultWidthMargin()) { MarginRecord mr = new LeftMarginRecord(settings.getLeftMargin()); outputFile.write(mr); } if (settings.getRightMargin() != settings.getDefaultWidthMargin()) { MarginRecord mr = new RightMarginRecord(settings.getRightMargin()); outputFile.write(mr); } if (settings.getTopMargin() != settings.getDefaultHeightMargin()) { MarginRecord mr = new TopMarginRecord(settings.getTopMargin()); outputFile.write(mr); } if (settings.getBottomMargin() != settings.getDefaultHeightMargin()) { MarginRecord mr = new BottomMarginRecord(settings.getBottomMargin()); outputFile.write(mr); } if (plsRecord != null) { outputFile.write(plsRecord); } SetupRecord setup = new SetupRecord(settings); outputFile.write(setup); if (settings.isProtected()) { ProtectRecord pr = new ProtectRecord(settings.isProtected()); outputFile.write(pr); ScenarioProtectRecord spr = new ScenarioProtectRecord (settings.isProtected()); outputFile.write(spr); ObjectProtectRecord opr = new ObjectProtectRecord (settings.isProtected()); outputFile.write(opr); if (settings.getPassword() != null) { PasswordRecord pw = new PasswordRecord(settings.getPassword()); outputFile.write(pw); } else if (settings.getPasswordHash() != 0) { PasswordRecord pw = new PasswordRecord(settings.getPasswordHash()); outputFile.write(pw); } } indexRecord.setDataStartPosition(outputFile.getPos()); DefaultColumnWidth dcw = new DefaultColumnWidth(settings.getDefaultColumnWidth()); outputFile.write(dcw); // Get a handle to the normal styles WritableCellFormat normalStyle = sheet.getWorkbook().getStyles().getNormalStyle(); WritableCellFormat defaultDateFormat = sheet.getWorkbook().getStyles().getDefaultDateFormat(); // Write out all the column formats ColumnInfoRecord cir = null; for (Iterator colit = columnFormats.iterator(); colit.hasNext() ; ) { cir = (ColumnInfoRecord) colit.next(); // Writing out the column info with index 0x100 causes excel to crash if (cir.getColumn() < 0x100) { outputFile.write(cir); } XFRecord xfr = cir.getCellFormat(); if (xfr != normalStyle && cir.getColumn() < 0x100) { // Make this the format for every cell in the column Cell[] cells = getColumn(cir.getColumn()); for (int i = 0; i < cells.length; i++) { if (cells[i] != null && (cells[i].getCellFormat() == normalStyle || cells[i].getCellFormat() == defaultDateFormat)) { // The cell has no overriding format specified, so // set it to the column default ((WritableCell) cells[i]).setCellFormat(xfr); } } } } // Write out the auto filter if (autoFilter != null) { autoFilter.write(outputFile); } DimensionRecord dr = new DimensionRecord(numRows, numCols); outputFile.write(dr); // Write out all the rows, in blocks of 32 for (int block = 0; block < numBlocks; block++) { DBCellRecord dbcell = new DBCellRecord(outputFile.getPos()); int blockRows = Math.min(32, numRows - block * 32); boolean firstRow = true; // First write out all the row records for (int i = block * 32; i < block * 32 + blockRows; i++) { if (rows[i] != null) { rows[i].write(outputFile); if (firstRow) { dbcell.setCellOffset(outputFile.getPos()); firstRow = false; } } } // Now write out all the cells for (int i = block * 32; i < block * 32 + blockRows; i++) { if (rows[i] != null) { dbcell.addCellRowPosition(outputFile.getPos()); rows[i].writeCells(outputFile); } } // Now set the current file position in the index record indexRecord.addBlockPosition(outputFile.getPos()); // Set the position of the file pointer and write out the DBCell // record dbcell.setPosition(outputFile.getPos()); outputFile.write(dbcell); } // Do the drawings and charts if enabled if (!workbookSettings.getDrawingsDisabled()) { drawingWriter.write(outputFile); } Window2Record w2r = new Window2Record(settings); outputFile.write(w2r); // Handle the frozen panes if (settings.getHorizontalFreeze() != 0 || settings.getVerticalFreeze() != 0) { PaneRecord pr = new PaneRecord(settings.getHorizontalFreeze(), settings.getVerticalFreeze()); outputFile.write(pr); // Handle the selection record. First, there will always be a top left SelectionRecord sr = new SelectionRecord (SelectionRecord.upperLeft, 0, 0); outputFile.write(sr); // Top right if (settings.getHorizontalFreeze() != 0) { sr = new SelectionRecord (SelectionRecord.upperRight, settings.getHorizontalFreeze(), 0); outputFile.write(sr); } // Bottom left if (settings.getVerticalFreeze() != 0) { sr = new SelectionRecord (SelectionRecord.lowerLeft, 0, settings.getVerticalFreeze()); outputFile.write(sr); } // Bottom right if (settings.getHorizontalFreeze() != 0 && settings.getVerticalFreeze() != 0) { sr = new SelectionRecord (SelectionRecord.lowerRight, settings.getHorizontalFreeze(), settings.getVerticalFreeze()); outputFile.write(sr); } Weird1Record w1r = new Weird1Record(); outputFile.write(w1r); } else { // No frozen panes - just write out the selection record for the // whole sheet SelectionRecord sr = new SelectionRecord (SelectionRecord.upperLeft, 0, 0); outputFile.write(sr); } // Handle the zoom factor if (settings.getZoomFactor() != 100) { SCLRecord sclr = new SCLRecord(settings.getZoomFactor()); outputFile.write(sclr); } // Now write out all the merged cells mergedCells.write(outputFile); // Write out all the hyperlinks Iterator hi = hyperlinks.iterator(); WritableHyperlink hlr = null; while (hi.hasNext()) { hlr = (WritableHyperlink) hi.next(); outputFile.write(hlr); } if (buttonPropertySet != null) { outputFile.write(buttonPropertySet); } // Write out the data validations if (dataValidation != null || validatedCells.size() > 0) { writeDataValidation(); } // Write out the conditional formats if (conditionalFormats != null && conditionalFormats.size() > 0) { for (Iterator i = conditionalFormats.iterator() ; i.hasNext() ; ) { ConditionalFormat cf = (ConditionalFormat) i.next(); cf.write(outputFile); } } EOFRecord eof = new EOFRecord(); outputFile.write(eof); // Now the various cross reference offsets have been calculated, // retrospectively set the values in the output file outputFile.setData(indexRecord.getData(), indexPos+4); } /** * Gets the header. Called when copying sheets * * @return the page header */ final HeaderRecord getHeader() { return header; } /** * Gets the footer. Called when copying sheets * * @return the page footer */ final FooterRecord getFooter() { return footer; } /** * Sets the data necessary for writing out the sheet. This method must * be called immediately prior to writing * * @param rws the rows in the spreadsheet */ void setWriteData(RowRecord[] rws, ArrayList rb, ArrayList cb, ArrayList hl, MergedCells mc, TreeSet cf, int mrol, int mcol) { rows = rws; rowBreaks = rb; columnBreaks = cb; hyperlinks = hl; mergedCells = mc; columnFormats = cf; maxRowOutlineLevel = mrol; maxColumnOutlineLevel = mcol; } /** * Sets the dimensions of this spreadsheet. This method must be called * immediately prior to writing * * @param rws the number of rows * @param cls the number of columns */ void setDimensions(int rws, int cls) { numRows = rws; numCols = cls; } /** * Sets the sheet settings for this particular sheet. Must be * called immediately prior to writing * * @param sr the sheet settings */ void setSettings(SheetSettings sr) { settings = sr; } /** * Accessor for the workspace options * * @return the workspace options */ WorkspaceInformationRecord getWorkspaceOptions() { return workspaceOptions; } /** * Accessor for the workspace options * * @param wo the workspace options */ void setWorkspaceOptions(WorkspaceInformationRecord wo) { if (wo != null) { workspaceOptions = wo; } } /** * Sets the charts for this sheet * * @param ch the charts */ void setCharts(Chart[] ch) { drawingWriter.setCharts(ch); } /** * Sets the drawings on this sheet * * @param dr the list of drawings * @param mod a modified flag */ void setDrawings(ArrayList dr, boolean mod) { drawingWriter.setDrawings(dr, mod); } /** * Accessor for the charts on this sheet * * @return the charts */ Chart[] getCharts() { return drawingWriter.getCharts(); } /** * Check all the merged cells for borders. If the merge record has * borders, then we need to rejig the cell formats to take account of this. * This is called by the write method of the WritableWorkbookImpl, so that * any new XFRecords that are created may be written out with the others */ void checkMergedBorders() { Range[] mcells = mergedCells.getMergedCells(); ArrayList borderFormats = new ArrayList(); for (int mci = 0 ; mci < mcells.length ; mci++) { Range range = mcells[mci]; Cell topLeft = range.getTopLeft(); XFRecord tlformat = (XFRecord) topLeft.getCellFormat(); if (tlformat != null && tlformat.hasBorders() == true && !tlformat.isRead()) { try { CellXFRecord cf1 = new CellXFRecord(tlformat); Cell bottomRight = range.getBottomRight(); cf1.setBorder(Border.ALL, BorderLineStyle.NONE, Colour.BLACK); cf1.setBorder(Border.LEFT, tlformat.getBorderLine(Border.LEFT), tlformat.getBorderColour(Border.LEFT)); cf1.setBorder(Border.TOP, tlformat.getBorderLine(Border.TOP), tlformat.getBorderColour(Border.TOP)); if (topLeft.getRow() == bottomRight.getRow()) { cf1.setBorder(Border.BOTTOM, tlformat.getBorderLine(Border.BOTTOM), tlformat.getBorderColour(Border.BOTTOM)); } if (topLeft.getColumn() == bottomRight.getColumn()) { cf1.setBorder(Border.RIGHT, tlformat.getBorderLine(Border.RIGHT), tlformat.getBorderColour(Border.RIGHT)); } int index = borderFormats.indexOf(cf1); if (index != -1) { cf1 = (CellXFRecord) borderFormats.get(index); } else { borderFormats.add(cf1); } ( (WritableCell) topLeft).setCellFormat(cf1); // Handle the bottom left corner if (bottomRight.getRow() > topLeft.getRow()) { // Handle the corner cell if (bottomRight.getColumn() != topLeft.getColumn()) { CellXFRecord cf2 = new CellXFRecord(tlformat); cf2.setBorder(Border.ALL, BorderLineStyle.NONE, Colour.BLACK); cf2.setBorder(Border.LEFT, tlformat.getBorderLine(Border.LEFT), tlformat.getBorderColour(Border.LEFT)); cf2.setBorder(Border.BOTTOM, tlformat.getBorderLine(Border.BOTTOM), tlformat.getBorderColour(Border.BOTTOM)); index = borderFormats.indexOf(cf2); if (index != -1) { cf2 = (CellXFRecord) borderFormats.get(index); } else { borderFormats.add(cf2); } sheet.addCell(new Blank(topLeft.getColumn(), bottomRight.getRow(), cf2)); } // Handle the cells down the left hand side (and along the // right too, if necessary) for (int i = topLeft.getRow() + 1; i < bottomRight.getRow() ;i++) { CellXFRecord cf3 = new CellXFRecord(tlformat); cf3.setBorder(Border.ALL, BorderLineStyle.NONE, Colour.BLACK); cf3.setBorder(Border.LEFT, tlformat.getBorderLine(Border.LEFT), tlformat.getBorderColour(Border.LEFT)); if (topLeft.getColumn() == bottomRight.getColumn()) { cf3.setBorder(Border.RIGHT, tlformat.getBorderLine(Border.RIGHT), tlformat.getBorderColour(Border.RIGHT)); } index = borderFormats.indexOf(cf3); if (index != -1) { cf3 = (CellXFRecord) borderFormats.get(index); } else { borderFormats.add(cf3); } sheet.addCell(new Blank(topLeft.getColumn(), i, cf3)); } } // Handle the top right corner if (bottomRight.getColumn() > topLeft.getColumn()) { if (bottomRight.getRow() != topLeft.getRow()) { // Handle the corner cell CellXFRecord cf6 = new CellXFRecord(tlformat); cf6.setBorder(Border.ALL, BorderLineStyle.NONE, Colour.BLACK); cf6.setBorder(Border.RIGHT, tlformat.getBorderLine(Border.RIGHT), tlformat.getBorderColour(Border.RIGHT)); cf6.setBorder(Border.TOP, tlformat.getBorderLine(Border.TOP), tlformat.getBorderColour(Border.TOP)); index = borderFormats.indexOf(cf6); if (index != -1) { cf6 = (CellXFRecord) borderFormats.get(index); } else { borderFormats.add(cf6); } sheet.addCell(new Blank(bottomRight.getColumn(), topLeft.getRow(), cf6)); } // Handle the cells along the right for (int i = topLeft.getRow() + 1; i < bottomRight.getRow() ;i++) { CellXFRecord cf7 = new CellXFRecord(tlformat); cf7.setBorder(Border.ALL, BorderLineStyle.NONE, Colour.BLACK); cf7.setBorder(Border.RIGHT, tlformat.getBorderLine(Border.RIGHT), tlformat.getBorderColour(Border.RIGHT)); index = borderFormats.indexOf(cf7); if (index != -1) { cf7 = (CellXFRecord) borderFormats.get(index); } else { borderFormats.add(cf7); } sheet.addCell(new Blank(bottomRight.getColumn(), i, cf7)); } // Handle the cells along the top, and along the bottom too for (int i = topLeft.getColumn() + 1; i < bottomRight.getColumn() ;i++) { CellXFRecord cf8 = new CellXFRecord(tlformat); cf8.setBorder(Border.ALL, BorderLineStyle.NONE, Colour.BLACK); cf8.setBorder(Border.TOP, tlformat.getBorderLine(Border.TOP), tlformat.getBorderColour(Border.TOP)); if (topLeft.getRow() == bottomRight.getRow()) { cf8.setBorder(Border.BOTTOM, tlformat.getBorderLine(Border.BOTTOM), tlformat.getBorderColour(Border.BOTTOM)); } index = borderFormats.indexOf(cf8); if (index != -1) { cf8 = (CellXFRecord) borderFormats.get(index); } else { borderFormats.add(cf8); } sheet.addCell(new Blank(i, topLeft.getRow(), cf8)); } } // Handle the bottom right corner if (bottomRight.getColumn() > topLeft.getColumn() || bottomRight.getRow() > topLeft.getRow()) { // Handle the corner cell CellXFRecord cf4 = new CellXFRecord(tlformat); cf4.setBorder(Border.ALL, BorderLineStyle.NONE, Colour.BLACK); cf4.setBorder(Border.RIGHT, tlformat.getBorderLine(Border.RIGHT), tlformat.getBorderColour(Border.RIGHT)); cf4.setBorder(Border.BOTTOM, tlformat.getBorderLine(Border.BOTTOM), tlformat.getBorderColour(Border.BOTTOM)); if (bottomRight.getRow() == topLeft.getRow()) { cf4.setBorder(Border.TOP, tlformat.getBorderLine(Border.TOP), tlformat.getBorderColour(Border.TOP)); } if (bottomRight.getColumn() == topLeft.getColumn()) { cf4.setBorder(Border.LEFT, tlformat.getBorderLine(Border.LEFT), tlformat.getBorderColour(Border.LEFT)); } index = borderFormats.indexOf(cf4); if (index != -1) { cf4 = (CellXFRecord) borderFormats.get(index); } else { borderFormats.add(cf4); } sheet.addCell(new Blank(bottomRight.getColumn(), bottomRight.getRow(), cf4)); // Handle the cells along the bottom (and along the top // as well, if appropriate) for (int i = topLeft.getColumn() + 1; i < bottomRight.getColumn() ;i++) { CellXFRecord cf5 = new CellXFRecord(tlformat); cf5.setBorder(Border.ALL, BorderLineStyle.NONE, Colour.BLACK); cf5.setBorder(Border.BOTTOM, tlformat.getBorderLine(Border.BOTTOM), tlformat.getBorderColour(Border.BOTTOM)); if (topLeft.getRow() == bottomRight.getRow()) { cf5.setBorder(Border.TOP, tlformat.getBorderLine(Border.TOP), tlformat.getBorderColour(Border.TOP)); } index = borderFormats.indexOf(cf5); if (index != -1) { cf5 = (CellXFRecord) borderFormats.get(index); } else { borderFormats.add(cf5); } sheet.addCell(new Blank(i, bottomRight.getRow(), cf5)); } } } catch (WriteException e) { // just log e.toString(), not the whole stack trace logger.warn(e.toString()); } } } } /** * Get the cells in the column. Don't use the interface method * getColumn for this as this will create loads of empty cells, * and we could do without that overhead */ private Cell[] getColumn(int col) { // Find the last non-null cell boolean found = false; int row = numRows - 1; while (row >= 0 && !found) { if (rows[row] != null && rows[row].getCell(col) != null) { found = true; } else { row--; } } // Only create entries for non-empty cells Cell[] cells = new Cell[row+1]; for (int i = 0; i <= row; i++) { cells[i] = rows[i] != null ? rows[i].getCell(col) : null; } return cells; } /** * Sets a flag to indicate that this sheet contains a chart only */ void setChartOnly() { chartOnly = true; } /** * Sets the environment specific print record * * @param pls the print record */ void setPLS(PLSRecord pls) { plsRecord = pls; } /** * Sets the button property set record * * @param bps the button property set */ void setButtonPropertySet(ButtonPropertySetRecord bps) { buttonPropertySet = bps; } /** * Sets the data validations * * @param dv the read-in list of data validations * @param vc the api manipulated set of data validations */ void setDataValidation(DataValidation dv, ArrayList vc) { dataValidation = dv; validatedCells = vc; } /** * Sets the conditional formats * * @param cf the conditonal formats */ void setConditionalFormats(ArrayList cf) { conditionalFormats = cf; } /** * Sets the auto filter * * @param af the autofilter */ void setAutoFilter(AutoFilter af) { autoFilter = af; } /** * Writes out the data validations */ private void writeDataValidation() throws IOException { if (dataValidation != null && validatedCells.size() == 0) { // the only data validations are those read in - this should // never be the case now that shared data validations add // to the validatedCells list dataValidation.write(outputFile); return; } if (dataValidation == null && validatedCells.size() > 0) { // the only data validations are those which have been added by the // write API. Need to sort out the combo box id int comboBoxId = sheet.getComboBox() != null ? sheet.getComboBox().getObjectId() : DataValidation.DEFAULT_OBJECT_ID; dataValidation = new DataValidation(comboBoxId, sheet.getWorkbook(), sheet.getWorkbook(), workbookSettings); } for (Iterator i = validatedCells.iterator(); i.hasNext(); ) { CellValue cv = (CellValue) i.next(); CellFeatures cf = cv.getCellFeatures(); // Do not do anything if the DVParser has been copied, as it // will already by on the DataValidation record as a result // of the SheetCopier process if (!cf.getDVParser().copied()) { if (!cf.getDVParser().extendedCellsValidation()) { // DVParser is specific for a single cell validation - just add it DataValiditySettingsRecord dvsr = new DataValiditySettingsRecord(cf.getDVParser()); dataValidation.add(dvsr); } else { // Only add the DVParser once for shared validations // only add it if it is the top left cell if (cv.getColumn() == cf.getDVParser().getFirstColumn() && cv.getRow() == cf.getDVParser().getFirstRow()) { DataValiditySettingsRecord dvsr = new DataValiditySettingsRecord(cf.getDVParser()); dataValidation.add(dvsr); } } } } dataValidation.write(outputFile); } /* // There is a mixture of read and write validations for (Iterator i = validatedCells.iterator(); i.hasNext(); ) { CellValue cv = (CellValue) i.next(); CellFeatures cf = cv.getCellFeatures(); DataValiditySettingsRecord dvsr = new DataValiditySettingsRecord(cf.getDVParser()); dataValidation.add(dvsr); } dataValidation.write(outputFile); return; } */ } jexcelapi/src/jxl/write/biff/RightMarginRecord.java0000750000175000017500000000214311207000610022540 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.Type; /** * The settings for the left margin */ class RightMarginRecord extends MarginRecord { RightMarginRecord(double v) { super(Type.RIGHTMARGIN, v); } } jexcelapi/src/jxl/write/biff/Window1Record.java0000750000175000017500000000364311207000610021663 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.IntegerHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Contains workbook level windowing attributes */ class Window1Record extends WritableRecordData { /** * The binary data */ private byte[] data; /** * The selected sheet */ private int selectedSheet; /** * Constructor */ public Window1Record(int selSheet) { super(Type.WINDOW1); selectedSheet = selSheet; // hard code the data in for now data = new byte[] {(byte) 0x68, (byte) 0x1, (byte) 0xe, (byte) 0x1, (byte) 0x5c, (byte) 0x3a, (byte) 0xbe, (byte) 0x23, (byte) 0x38, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0x1, (byte) 0, (byte) 0x58, (byte) 0x2 }; IntegerHelper.getTwoBytes(selectedSheet, data, 10); } /** * Gets the binary data for output to file * * @return the binary data */ public byte[] getData() { return data; } } jexcelapi/src/jxl/write/biff/ObjectProtectRecord.java0000750000175000017500000000323111207000610023073 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.IntegerHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * The protection state for a sheet or workbook */ class ObjectProtectRecord extends WritableRecordData { /** * The protection state */ private boolean protection; /** * The binary data */ private byte[] data; /** * Constructor * * @param prot the protection state */ public ObjectProtectRecord(boolean prot) { super(Type.OBJPROTECT); protection = prot; data = new byte[2]; if (protection) { IntegerHelper.getTwoBytes(1, data, 0); } } /** * Gets the binary data for output to file * * @return the binary data */ public byte[] getData() { return data; } } jexcelapi/src/jxl/write/biff/SupbookRecord.java0000750000175000017500000001716611207000610021762 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.common.Assert; import jxl.common.Logger; import jxl.WorkbookSettings; import jxl.biff.EncodedURLHelper; import jxl.biff.IntegerHelper; import jxl.biff.StringHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Stores the supporting workbook information. For files written by * JExcelApi this will only reference internal sheets */ class SupbookRecord extends WritableRecordData { /** * The logger */ private static Logger logger = Logger.getLogger(SupbookRecord.class); /** * The type of this supbook record */ private SupbookType type; /** * The data to be written to the binary file */ private byte[] data; /** * The number of sheets - internal & external supbooks only */ private int numSheets; /** * The name of the external file */ private String fileName; /** * The names of the external sheets */ private String[] sheetNames; /** * The workbook settings */ private WorkbookSettings workbookSettings; /** * The type of supbook this refers to */ private static class SupbookType {}; public final static SupbookType INTERNAL = new SupbookType(); public final static SupbookType EXTERNAL = new SupbookType(); public final static SupbookType ADDIN = new SupbookType(); public final static SupbookType LINK = new SupbookType(); public final static SupbookType UNKNOWN = new SupbookType(); /** * Constructor for add in function names */ public SupbookRecord() { super(Type.SUPBOOK); type = ADDIN; } /** * Constructor for internal sheets */ public SupbookRecord(int sheets, WorkbookSettings ws) { super(Type.SUPBOOK); numSheets = sheets; type = INTERNAL; workbookSettings = ws; } /** * Constructor for external sheets * * @param fn the filename of the external supbook * @param ws the workbook settings */ public SupbookRecord(String fn, WorkbookSettings ws) { super(Type.SUPBOOK); fileName = fn; numSheets = 1; sheetNames = new String[0]; workbookSettings = ws; type = EXTERNAL; } /** * Constructor used when copying from an external workbook */ public SupbookRecord(jxl.read.biff.SupbookRecord sr, WorkbookSettings ws) { super(Type.SUPBOOK); workbookSettings = ws; if (sr.getType() == sr.INTERNAL) { type = INTERNAL; numSheets = sr.getNumberOfSheets(); } else if (sr.getType() == sr.EXTERNAL) { type = EXTERNAL; numSheets = sr.getNumberOfSheets(); fileName = sr.getFileName(); sheetNames = new String[numSheets]; for (int i = 0; i < numSheets; i++) { sheetNames[i] = sr.getSheetName(i); } } if (sr.getType() == sr.ADDIN) { logger.warn("Supbook type is addin"); } } /** * Initializes an internal supbook record * * @param sr the read supbook record to copy from */ private void initInternal(jxl.read.biff.SupbookRecord sr) { numSheets = sr.getNumberOfSheets(); initInternal(); } /** * Initializes an internal supbook record */ private void initInternal() { data = new byte[4]; IntegerHelper.getTwoBytes(numSheets, data, 0); data[2] = 0x1; data[3] = 0x4; type = INTERNAL; } /** * Adjust the number of internal sheets. Called by WritableSheet when * a sheet is added or or removed to the workbook * * @param sheets the new number of sheets */ void adjustInternal(int sheets) { Assert.verify(type == INTERNAL); numSheets = sheets; initInternal(); } /** * Initializes an external supbook record */ private void initExternal() { int totalSheetNameLength = 0; for (int i = 0; i < numSheets; i++) { totalSheetNameLength += sheetNames[i].length(); } byte[] fileNameData = EncodedURLHelper.getEncodedURL(fileName, workbookSettings); int dataLength = 2 + // numsheets 4 + fileNameData.length + numSheets * 3 + totalSheetNameLength * 2; data = new byte[dataLength]; IntegerHelper.getTwoBytes(numSheets, data, 0); // Add in the file name. Precede with a byte denoting that it is a // file name int pos = 2; IntegerHelper.getTwoBytes(fileNameData.length+1, data, pos); data[pos+2] = 0; // ascii indicator data[pos+3] = 1; // file name indicator System.arraycopy(fileNameData, 0, data, pos+4, fileNameData.length); pos += 4 + fileNameData.length; // Get the sheet names for (int i = 0; i < sheetNames.length; i++) { IntegerHelper.getTwoBytes(sheetNames[i].length(), data, pos); data[pos+2] = 1; // unicode indicator StringHelper.getUnicodeBytes(sheetNames[i], data, pos+3); pos += 3 + sheetNames[i].length() * 2; } } /** * Initializes the supbook record for add in functions */ private void initAddin() { data = new byte[] {0x1, 0x0, 0x1, 0x3a}; } /** * The binary data to be written out * * @return the binary data */ public byte[] getData() { if (type == INTERNAL) { initInternal(); } else if (type == EXTERNAL) { initExternal(); } else if (type == ADDIN) { initAddin(); } else { logger.warn("unsupported supbook type - defaulting to internal"); initInternal(); } return data; } /** * Gets the type of this supbook record * * @return the type of this supbook */ public SupbookType getType() { return type; } /** * Gets the number of sheets. This will only be non-zero for internal * and external supbooks * * @return the number of sheets */ public int getNumberOfSheets() { return numSheets; } /** * Accessor for the file name * * @return the file name */ public String getFileName() { return fileName; } /** * Adds the worksheet name to this supbook * * @param name the worksheet name * @return the index of this sheet in the supbook record */ public int getSheetIndex(String s) { boolean found = false; int sheetIndex = 0; for (int i = 0; i < sheetNames.length && !found; i++) { if (sheetNames[i].equals(s)) { found = true; sheetIndex = 0; } } if (found) { return sheetIndex; } // Grow the array String[] names = new String[sheetNames.length + 1]; System.arraycopy(sheetNames, 0, names, 0, sheetNames.length); names[sheetNames.length] = s; sheetNames = names; return sheetNames.length - 1; } /** * Accessor for the sheet name * * @param s the sheet index */ public String getSheetName(int s) { return sheetNames[s]; } } jexcelapi/src/jxl/write/biff/CountryRecord.java0000750000175000017500000000367511207000610022003 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.CountryCode; import jxl.biff.IntegerHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Record containing the localization information */ class CountryRecord extends WritableRecordData { /** * The user interface language */ private int language; /** * The regional settings */ private int regionalSettings; /** * Constructor */ public CountryRecord(CountryCode lang, CountryCode r) { super(Type.COUNTRY); language = lang.getValue(); regionalSettings = r.getValue(); } public CountryRecord(jxl.read.biff.CountryRecord cr) { super(Type.COUNTRY); language = cr.getLanguageCode(); regionalSettings = cr.getRegionalSettingsCode(); } /** * Retrieves the data to be written to the binary file * * @return the binary data */ public byte[] getData() { byte[] data = new byte[4]; IntegerHelper.getTwoBytes(language, data, 0); IntegerHelper.getTwoBytes(regionalSettings, data, 2); return data; } } jexcelapi/src/jxl/write/biff/ReadBooleanFormulaRecord.java0000750000175000017500000000265711207000610024040 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2004 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.BooleanFormulaCell; import jxl.biff.FormulaData; /** * Class for read number formula records */ class ReadBooleanFormulaRecord extends ReadFormulaRecord implements BooleanFormulaCell { /** * Constructor * * @param f */ public ReadBooleanFormulaRecord(FormulaData f) { super(f); } /** * Gets the boolean contents for this cell. * * @return the cell contents */ public boolean getValue() { return ( (BooleanFormulaCell) getReadFormula()).getValue(); } } jexcelapi/src/jxl/write/biff/MergedCells.java0000750000175000017500000001717711207000610021371 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import jxl.common.Assert; import jxl.common.Logger; import jxl.Cell; import jxl.CellType; import jxl.Range; import jxl.WorkbookSettings; import jxl.biff.SheetRangeImpl; import jxl.write.Blank; import jxl.write.WritableSheet; import jxl.write.WriteException; /** * Contains all the merged cells, and the necessary logic for checking * for intersections and for handling very large amounts of merging */ class MergedCells { /** * The logger */ private static Logger logger = Logger.getLogger(MergedCells.class); /** * The list of merged cells */ private ArrayList ranges; /** * The sheet containing the cells */ private WritableSheet sheet; /** * The maximum number of ranges per sheet */ private static final int maxRangesPerSheet = 1020; /** * Constructor */ public MergedCells(WritableSheet ws) { ranges = new ArrayList(); sheet = ws; } /** * Adds the range to the list of merged cells. Does no checking * at this stage * * @param range the range to add */ void add(Range r) { ranges.add(r); } /** * Used to adjust the merged cells following a row insertion */ void insertRow(int row) { // Adjust any merged cells SheetRangeImpl sr = null; Iterator i = ranges.iterator(); while (i.hasNext()) { sr = (SheetRangeImpl) i.next(); sr.insertRow(row); } } /** * Used to adjust the merged cells following a column insertion */ void insertColumn(int col) { SheetRangeImpl sr = null; Iterator i = ranges.iterator(); while (i.hasNext()) { sr = (SheetRangeImpl) i.next(); sr.insertColumn(col); } } /** * Used to adjust the merged cells following a column removal */ void removeColumn(int col) { SheetRangeImpl sr = null; Iterator i = ranges.iterator(); while (i.hasNext()) { sr = (SheetRangeImpl) i.next(); if (sr.getTopLeft().getColumn() == col && sr.getBottomRight().getColumn() == col) { // The column with the merged cells on has been removed, so get // rid of it from the list i.remove(); } else { sr.removeColumn(col); } } } /** * Used to adjust the merged cells following a row removal */ void removeRow(int row) { SheetRangeImpl sr = null; Iterator i = ranges.iterator(); while (i.hasNext()) { sr = (SheetRangeImpl) i.next(); if (sr.getTopLeft().getRow() == row && sr.getBottomRight().getRow() == row) { // The row with the merged cells on has been removed, so get // rid of it from the list i.remove(); } else { sr.removeRow(row); } } } /** * Gets the cells which have been merged on this sheet * * @return an array of range objects */ Range[] getMergedCells() { Range[] cells = new Range[ranges.size()]; for (int i=0; i < cells.length; i++) { cells[i] = (Range) ranges.get(i); } return cells; } /** * Unmerges the specified cells. The Range passed in should be one that * has been previously returned as a result of the getMergedCells method * * @param r the range of cells to unmerge */ void unmergeCells(Range r) { int index = ranges.indexOf(r); if (index != -1) { ranges.remove(index); } } /** * Called prior to writing out in order to check for intersections */ private void checkIntersections() { ArrayList newcells = new ArrayList(ranges.size()); for (Iterator mci = ranges.iterator(); mci.hasNext() ; ) { SheetRangeImpl r = (SheetRangeImpl) mci.next(); // Check that the range doesn't intersect with any existing range Iterator i = newcells.iterator(); SheetRangeImpl range = null; boolean intersects = false; while (i.hasNext() && !intersects) { range = (SheetRangeImpl) i.next(); if (range.intersects(r)) { logger.warn("Could not merge cells " + r + " as they clash with an existing set of merged cells."); intersects = true; } } if (!intersects) { newcells.add(r); } } ranges = newcells; } /** * Checks the cell ranges for intersections, or if the merged cells * contains more than one item of data */ private void checkRanges() { try { SheetRangeImpl range = null; // Check all the ranges to make sure they only contain one entry for (int i = 0; i < ranges.size(); i++) { range = (SheetRangeImpl) ranges.get(i); // Get the cell in the top left Cell tl = range.getTopLeft(); Cell br = range.getBottomRight(); boolean found = false; for (int c = tl.getColumn(); c <= br.getColumn(); c++) { for (int r = tl.getRow(); r <= br.getRow(); r++) { Cell cell = sheet.getCell(c, r); if (cell.getType() != CellType.EMPTY) { if (!found) { found = true; } else { logger.warn("Range " + range + " contains more than one data cell. " + "Setting the other cells to blank."); Blank b = new Blank(c, r); sheet.addCell(b); } } } } } } catch (WriteException e) { // This should already have been checked - bomb out Assert.verify(false); } } void write(File outputFile) throws IOException { if (ranges.size() == 0) { return; } WorkbookSettings ws = ( (WritableSheetImpl) sheet).getWorkbookSettings(); if (!ws.getMergedCellCheckingDisabled()) { checkIntersections(); checkRanges(); } // If they will all fit into one record, then create a single // record, write them and get out if (ranges.size() < maxRangesPerSheet) { MergedCellsRecord mcr = new MergedCellsRecord(ranges); outputFile.write(mcr); return; } int numRecordsRequired = ranges.size() / maxRangesPerSheet + 1; int pos = 0; for (int i = 0 ; i < numRecordsRequired ; i++) { int numranges = Math.min(maxRangesPerSheet, ranges.size() - pos); ArrayList cells = new ArrayList(numranges); for (int j = 0 ; j < numranges ; j++) { cells.add(ranges.get(pos+j)); } MergedCellsRecord mcr = new MergedCellsRecord(cells); outputFile.write(mcr); pos += numranges; } } } jexcelapi/src/jxl/write/biff/CellValue.java0000750000175000017500000004016111263366304021065 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2001 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.common.Assert; import jxl.common.Logger; import jxl.Cell; import jxl.CellFeatures; import jxl.CellReferenceHelper; import jxl.Sheet; import jxl.biff.DataValidation; import jxl.biff.DataValiditySettingsRecord; import jxl.biff.DVParser; import jxl.biff.FormattingRecords; import jxl.biff.IntegerHelper; import jxl.biff.NumFormatRecordsException; import jxl.biff.Type; import jxl.biff.WritableRecordData; import jxl.biff.XFRecord; import jxl.biff.drawing.ComboBox; import jxl.biff.drawing.Comment; import jxl.format.CellFormat; import jxl.write.WritableCell; import jxl.write.WritableCellFeatures; import jxl.write.WritableWorkbook; /** * Abstract class which stores the jxl.common.data used for cells, such * as row, column and formatting information. * Any record which directly represents the contents of a cell, such * as labels and numbers, are derived from this class * data store */ public abstract class CellValue extends WritableRecordData implements WritableCell { /** * The logger */ private static Logger logger = Logger.getLogger(CellValue.class); /** * The row in the worksheet at which this cell is located */ private int row; /** * The column in the worksheet at which this cell is located */ private int column; /** * The format applied to this cell */ private XFRecord format; /** * A handle to the formatting records, used in case we want * to change the format of the cell once it has been added * to the spreadsheet */ private FormattingRecords formattingRecords; /** * A flag to indicate that this record is already referenced within * a worksheet */ private boolean referenced; /** * A handle to the sheet */ private WritableSheetImpl sheet; /** * The cell features */ private WritableCellFeatures features; /** * Internal copied flag, to prevent cell features being added multiple * times to the drawing array */ private boolean copied; /** * Constructor used when building writable cells from the Java API * * @param c the column * @param t the type indicator * @param r the row */ protected CellValue(Type t, int c, int r) { this(t, c, r, WritableWorkbook.NORMAL_STYLE); copied = false; } /** * Constructor used when creating a writable cell from a read-only cell * (when copying a workbook) * * @param c the cell to clone * @param t the type of this cell */ protected CellValue(Type t, Cell c) { this(t, c.getColumn(), c.getRow()); copied = true; format = (XFRecord) c.getCellFormat(); if (c.getCellFeatures() != null) { features = new WritableCellFeatures(c.getCellFeatures()); features.setWritableCell(this); } } /** * Overloaded constructor used when building writable cells from the * Java API which also takes a format * * @param c the column * @param t the cell type * @param r the row * @param st the format to apply to this cell */ protected CellValue(Type t, int c, int r, CellFormat st) { super(t); row = r; column = c; format = (XFRecord) st; referenced = false; copied = false; } /** * Copy constructor * * @param c the column * @param t the cell type * @param r the row * @param cv the value to copy */ protected CellValue(Type t, int c, int r, CellValue cv) { super(t); row = r; column = c; format = cv.format; referenced = false; copied = false; // used during a deep copy, so the cell features need // to be added again if (cv.features != null) { features = new WritableCellFeatures(cv.features); features.setWritableCell(this); } } /** * An API function which sets the format to apply to this cell * * @param cf the format to apply to this cell */ public void setCellFormat(CellFormat cf) { format = (XFRecord) cf; // If the referenced flag has not been set, this cell has not // been added to the spreadsheet, so we don't need to perform // any further logic if (!referenced) { return; } // The cell has already been added to the spreadsheet, so the // formattingRecords reference must be initialized Assert.verify(formattingRecords != null); addCellFormat(); } /** * Returns the row number of this cell * * @return the row number of this cell */ public int getRow() { return row; } /** * Returns the column number of this cell * * @return the column number of this cell */ public int getColumn() { return column; } /** * Indicates whether or not this cell is hidden, by virtue of either * the entire row or column being collapsed * * @return TRUE if this cell is hidden, FALSE otherwise */ public boolean isHidden() { ColumnInfoRecord cir = sheet.getColumnInfo(column); if (cir != null && cir.getWidth() == 0) { return true; } RowRecord rr = sheet.getRowInfo(row); if (rr != null && (rr.getRowHeight() == 0 || rr.isCollapsed())) { return true; } return false; } /** * Gets the data to write to the output file * * @return the binary data */ public byte[] getData() { byte[] mydata = new byte[6]; IntegerHelper.getTwoBytes(row, mydata, 0); IntegerHelper.getTwoBytes(column, mydata, 2); IntegerHelper.getTwoBytes(format.getXFIndex(), mydata, 4); return mydata; } /** * Called when the cell is added to the worksheet in order to indicate * that this object is already added to the worksheet * This method also verifies that the associated formats and formats * have been initialized correctly * * @param fr the formatting records * @param ss the shared strings used within the workbook * @param s the sheet this is being added to */ void setCellDetails(FormattingRecords fr, SharedStrings ss, WritableSheetImpl s) { referenced = true; sheet = s; formattingRecords = fr; addCellFormat(); addCellFeatures(); } /** * Internal method to see if this cell is referenced within the workbook. * Once this has been placed in the workbook, it becomes immutable * * @return TRUE if this cell has been added to a sheet, FALSE otherwise */ final boolean isReferenced() { return referenced; } /** * Gets the internal index of the formatting record * * @return the index of the format record */ final int getXFIndex() { return format.getXFIndex(); } /** * API method which gets the format applied to this cell * * @return the format for this cell */ public CellFormat getCellFormat() { return format; } /** * Increments the row of this cell by one. Invoked by the sheet when * inserting rows */ void incrementRow() { row++; if (features != null) { Comment c = features.getCommentDrawing(); if (c != null) { c.setX(column); c.setY(row); } } } /** * Decrements the row of this cell by one. Invoked by the sheet when * removing rows */ void decrementRow() { row--; if (features != null) { Comment c = features.getCommentDrawing(); if ( c!= null) { c.setX(column); c.setY(row); } if (features.hasDropDown()) { logger.warn("need to change value for drop down drawing"); } } } /** * Increments the column of this cell by one. Invoked by the sheet when * inserting columns */ void incrementColumn() { column++; if (features != null) { Comment c = features.getCommentDrawing(); if (c != null) { c.setX(column); c.setY(row); } } } /** * Decrements the column of this cell by one. Invoked by the sheet when * removing columns */ void decrementColumn() { column--; if (features != null) { Comment c = features.getCommentDrawing(); if (c != null) { c.setX(column); c.setY(row); } } } /** * Called when a column is inserted on the specified sheet. Notifies all * RCIR cells of this change. The default implementation here does nothing * * @param s the sheet on which the column was inserted * @param sheetIndex the sheet index on which the column was inserted * @param col the column number which was inserted */ void columnInserted(Sheet s, int sheetIndex, int col) { } /** * Called when a column is removed on the specified sheet. Notifies all * RCIR cells of this change. The default implementation here does nothing * * @param s the sheet on which the column was inserted * @param sheetIndex the sheet index on which the column was inserted * @param col the column number which was inserted */ void columnRemoved(Sheet s, int sheetIndex, int col) { } /** * Called when a row is inserted on the specified sheet. Notifies all * RCIR cells of this change. The default implementation here does nothing * * @param s the sheet on which the column was inserted * @param sheetIndex the sheet index on which the column was inserted * @param row the column number which was inserted */ void rowInserted(Sheet s, int sheetIndex, int row) { } /** * Called when a row is inserted on the specified sheet. Notifies all * RCIR cells of this change. The default implementation here does nothing * * @param s the sheet on which the row was removed * @param sheetIndex the sheet index on which the column was removed * @param row the column number which was removed */ void rowRemoved(Sheet s, int sheetIndex, int row) { } /** * Accessor for the sheet containing this cell * * @return the sheet containing this cell */ public WritableSheetImpl getSheet() { return sheet; } /** * Adds the format information to the shared records. Performs the necessary * checks (and clones) to ensure that the formats are not shared. * Called from setCellDetails and setCellFormat */ private void addCellFormat() { // Check to see if the format is one of the shared Workbook defaults. If // so, then get hold of the Workbook's specific instance Styles styles = sheet.getWorkbook().getStyles(); format = styles.getFormat(format); try { if (!format.isInitialized()) { formattingRecords.addStyle(format); } } catch (NumFormatRecordsException e) { logger.warn("Maximum number of format records exceeded. Using " + "default format."); format = styles.getNormalStyle(); } } /** * Accessor for the cell features * * @return the cell features or NULL if this cell doesn't have any */ public CellFeatures getCellFeatures() { return features; } /** * Accessor for the cell features * * @return the cell features or NULL if this cell doesn't have any */ public WritableCellFeatures getWritableCellFeatures() { return features; } /** * Sets the cell features * * @param cf the cell features */ public void setCellFeatures(WritableCellFeatures cf) { if (features != null) { logger.warn("current cell features for " + CellReferenceHelper.getCellReference(this) + " not null - overwriting"); // Check to see if the features include a shared data validation if (features.hasDataValidation() && features.getDVParser() != null && features.getDVParser().extendedCellsValidation()) { DVParser dvp = features.getDVParser(); logger.warn("Cannot add cell features to " + CellReferenceHelper.getCellReference(this) + " because it is part of the shared cell validation " + "group " + CellReferenceHelper.getCellReference(dvp.getFirstColumn(), dvp.getFirstRow()) + "-" + CellReferenceHelper.getCellReference(dvp.getLastColumn(), dvp.getLastRow())); return; } } features = cf; cf.setWritableCell(this); // If the cell is already on the worksheet, then add the cell features // to the workbook if (referenced) { addCellFeatures(); } } /** * Handles any addition cell features, such as comments or data * validation. Called internally from this class when a cell is * added to the workbook, and also externally from BaseCellFeatures * following a call to setComment */ public final void addCellFeatures() { if (features == null) { return; } if (copied == true) { copied = false; return; } if (features.getComment() != null) { Comment comment = new Comment(features.getComment(), column, row); comment.setWidth(features.getCommentWidth()); comment.setHeight(features.getCommentHeight()); sheet.addDrawing(comment); sheet.getWorkbook().addDrawing(comment); features.setCommentDrawing(comment); } if (features.hasDataValidation()) { try { features.getDVParser().setCell(column, row, sheet.getWorkbook(), sheet.getWorkbook(), sheet.getWorkbookSettings()); } catch (jxl.biff.formula.FormulaException e) { Assert.verify(false); } sheet.addValidationCell(this); if (!features.hasDropDown()) { return; } // Get the combo box drawing object for list validations if (sheet.getComboBox() == null) { // Need to add the combo box the first time, since even though // it doesn't need a separate Sp entry, it still needs to increment // the shape id ComboBox cb = new ComboBox(); sheet.addDrawing(cb); sheet.getWorkbook().addDrawing(cb); sheet.setComboBox(cb); } features.setComboBox(sheet.getComboBox()); } } /** * Internal function invoked by WritableSheetImpl called when shared data * validation is removed */ public final void removeCellFeatures() { /* // Remove the comment features.removeComment(); // Remove the data validation features.removeDataValidation(); */ features = null; } /** * Called by the cell features to remove a comment * * @param c the comment to remove */ public final void removeComment(Comment c) { sheet.removeDrawing(c); } /** * Called by the cell features to remove the data validation */ public final void removeDataValidation() { sheet.removeDataValidation(this); } /** * Called when doing a copy of a writable object to indicate the source * was writable than a read only copy and certain things (most notably * the comments will need to be re-evaluated) * * @param boolean the copied flag */ final void setCopied(boolean c) { copied = c; } } jexcelapi/src/jxl/write/biff/WriteAccessRecord.java0000750000175000017500000000416011207000610022542 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.Workbook; import jxl.biff.StringHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * The name used when Excel was installed. * When writing worksheets, it uses the value from the WorkbookSettings object, * if this is not set (null) this is hard coded as * Java Excel API + Version number */ class WriteAccessRecord extends WritableRecordData { /** * The data to output to file */ private byte[] data; // String of length 112 characters /** * The author of this workbook (ie. the Java Excel API) */ private final static String authorString = "Java Excel API"; private String userName; /** * Constructor */ public WriteAccessRecord(String userName) { super(Type.WRITEACCESS); data = new byte[112]; String astring = userName != null ? userName : authorString + " v" + Workbook.getVersion(); StringHelper.getBytes(astring, data, 0); // Pad out the record with space characters for (int i = astring.length() ; i < data.length ;i++) { data[i] = 0x20; } } /** * Gets the data for output to file * * @return the binary data */ public byte[] getData() { return data; } } jexcelapi/src/jxl/write/biff/File.java0000750000175000017500000001160211207000610020045 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import java.io.IOException; import java.io.OutputStream; import jxl.common.Logger; import jxl.WorkbookSettings; import jxl.biff.ByteData; /** * A file of excel data to be written out. All the excel data is held * in memory, and when the close method is called a CompoundFile object * is used to write the Biff oriented excel data in the CompoundFile * format */ public final class File { /** * The logger */ private static Logger logger = Logger.getLogger(File.class); /** * The data from the excel 97 file */ private ExcelDataOutput data; /** * The current position within the file */ private int pos; /** * The output stream */ private OutputStream outputStream; /** * The initial file size */ private int initialFileSize; /** * The amount to increase the growable array by */ private int arrayGrowSize; /** * The workbook settings */ private WorkbookSettings workbookSettings; /** * The read compound file. This will only be non-null if there are macros * or other property sets of that ilk which that we should be copying */ jxl.read.biff.CompoundFile readCompoundFile; /** * Constructor * * @param os the output stream * @param ws the configuration settings for this workbook * @param rcf the rea compound file */ File(OutputStream os, WorkbookSettings ws, jxl.read.biff.CompoundFile rcf) throws IOException { outputStream = os; workbookSettings = ws; readCompoundFile = rcf; createDataOutput(); } private void createDataOutput() throws IOException { if (workbookSettings.getUseTemporaryFileDuringWrite()) { data = new FileDataOutput (workbookSettings.getTemporaryFileDuringWriteDirectory()); } else { initialFileSize = workbookSettings.getInitialFileSize(); arrayGrowSize = workbookSettings.getArrayGrowSize(); data = new MemoryDataOutput(initialFileSize, arrayGrowSize); } } /** * Closes the file. In fact, this writes out all the excel data * to disk using a CompoundFile object, and then frees up all the memory * allocated to the workbook * * @exception IOException * @param cs TRUE if this should close the stream, FALSE if the application * closes it */ void close(boolean cs) throws IOException, JxlWriteException { CompoundFile cf = new CompoundFile(data, data.getPosition(), outputStream, readCompoundFile); cf.write(); outputStream.flush(); data.close(); if (cs) { outputStream.close(); } // Cleanup the memory a bit data = null; if (!workbookSettings.getGCDisabled()) { System.gc(); } } /** * Adds the biff record data to the memory allocated for this File * * @exception IOException * @param record the record to add to the excel data */ public void write(ByteData record) throws IOException { byte[] bytes = record.getBytes(); data.write(bytes); } /** * Gets the current position within the file * * @return the current position */ int getPos() throws IOException { return data.getPosition(); } /** * Used to manually alter the contents of the written out data. This * is used when cross-referencing cell records * * @param pos the position to alter * @param newdata the data to modify */ void setData(byte[] newdata, int pos) throws IOException { data.setData(newdata, pos); } /** * Sets a new output file. This allows the same workbook to be * written to various different output files without having to * read in any templates again * * @param os the output stream */ public void setOutputFile(OutputStream os) throws IOException { if (data != null) { logger.warn("Rewriting a workbook with non-empty data"); } outputStream = os; createDataOutput(); } } jexcelapi/src/jxl/write/biff/ButtonPropertySetRecord.java0000750000175000017500000000322411207000610024022 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Any arbitrary excel record. Used during development only */ class ButtonPropertySetRecord extends WritableRecordData { /** * The binary data */ private byte[] data; /** * Constructor */ public ButtonPropertySetRecord(jxl.read.biff.ButtonPropertySetRecord bps) { super(Type.BUTTONPROPERTYSET); data = bps.getData(); } /** * Constructor */ public ButtonPropertySetRecord(ButtonPropertySetRecord bps) { super(Type.BUTTONPROPERTYSET); data = bps.getData(); } /** * Retrieves the data to be written to the binary file * * @return the binary data */ public byte[] getData() { return data; } } jexcelapi/src/jxl/write/biff/HorizontalPageBreaksRecord.java0000750000175000017500000000362311207000610024407 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.IntegerHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Contains the list of explicit horizontal page breaks on the current sheet */ class HorizontalPageBreaksRecord extends WritableRecordData { /** * The row breaks */ private int[] rowBreaks; /** * Constructor * * @param break the row breaks */ public HorizontalPageBreaksRecord(int[] breaks) { super(Type.HORIZONTALPAGEBREAKS); rowBreaks = breaks; } /** * Gets the binary data to write to the output file * * @return the binary data */ public byte[] getData() { byte[] data = new byte[rowBreaks.length * 6 + 2]; // The number of breaks on the list IntegerHelper.getTwoBytes(rowBreaks.length, data, 0); int pos = 2; for (int i = 0; i < rowBreaks.length; i++) { IntegerHelper.getTwoBytes(rowBreaks[i], data, pos); IntegerHelper.getTwoBytes(0xff, data, pos+4); pos += 6; } return data; } } jexcelapi/src/jxl/write/biff/FunctionGroupCountRecord.java0000750000175000017500000000317611207000610024147 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.IntegerHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Stores the number of build in function groups */ class FunctionGroupCountRecord extends WritableRecordData { /** * The binary data */ private byte[] data; /** * The number of built in function groups */ private int numFunctionGroups; /** * Constructor */ public FunctionGroupCountRecord() { super(Type.FNGROUPCOUNT); numFunctionGroups = 0xe; data = new byte[2]; IntegerHelper.getTwoBytes(numFunctionGroups, data, 0); } /** * Gets the binary data for output to file * * @return the binary data */ public byte[] getData() { return data; } } jexcelapi/src/jxl/write/biff/ScenarioProtectRecord.java0000750000175000017500000000323611207000610023435 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.IntegerHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * The protection state for a sheet or workbook */ class ScenarioProtectRecord extends WritableRecordData { /** * The protection state */ private boolean protection; /** * The binary data */ private byte[] data; /** * Constructor * * @param prot the protection state */ public ScenarioProtectRecord(boolean prot) { super(Type.SCENPROTECT); protection = prot; data = new byte[2]; if (protection) { IntegerHelper.getTwoBytes(1, data, 0); } } /** * Gets the binary data for output to file * * @return the binary data */ public byte[] getData() { return data; } } jexcelapi/src/jxl/write/biff/UsesElfsRecord.java0000750000175000017500000000315411207000610022061 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Stores the flag which indicates whether the version of excel can * understand natural language input for formulae */ class UsesElfsRecord extends WritableRecordData { /** * The binary data for output to file */ private byte[] data; /** * The uses ELFs flag */ private boolean usesElfs; /** * Constructor */ public UsesElfsRecord() { super(Type.USESELFS); usesElfs = true; data = new byte[2]; if (usesElfs) { data[0] = 1; } } /** * Gets the binary data for output to file * * @return the binary data */ public byte[] getData() { return data; } } jexcelapi/src/jxl/write/biff/DeltaRecord.java0000750000175000017500000000414311207000610021360 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.DoubleHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Record which stores the maximum change value from the Options * dialog */ class DeltaRecord extends WritableRecordData { /** * The binary data */ private byte[] data; /** * The number of iterations */ private double iterationValue; /** * Constructor * * @param itval */ public DeltaRecord(double itval) { super(Type.DELTA); iterationValue = itval; data = new byte[8]; } /** * Gets the binary data for writing to the output file * * @return the binary data */ public byte[] getData() { DoubleHelper.getIEEEBytes(iterationValue, data, 0); /* long val = Double.doubleToLongBits(iterationValue); data[0] = (byte) (val & 0xff); data[1] = (byte) ((val & 0xff00) >> 8); data[2] = (byte) ((val & 0xff0000) >> 16); data[3] = (byte) ((val & 0xff000000) >> 24); data[4] = (byte) ((val & 0xff00000000L) >> 32); data[5] = (byte) ((val & 0xff0000000000L) >> 40); data[6] = (byte) ((val & 0xff000000000000L) >> 48); data[7] = (byte) ((val & 0xff00000000000000L) >> 56) ; */ return data; } } jexcelapi/src/jxl/write/biff/MemoryDataOutput.java0000750000175000017500000000551311207000610022455 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2007 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import java.io.OutputStream; import java.io.IOException; import jxl.common.Logger; /** * Used to generate the excel biff data in memory. This class wraps a byte * array */ class MemoryDataOutput implements ExcelDataOutput { // The logger private static Logger logger = Logger.getLogger(MemoryDataOutput.class); /** * The excel data */ private byte[] data; /** * The grow size for the array */ private int growSize; /** * The current position within the array */ private int pos; /** * Constructor */ public MemoryDataOutput(int initialSize, int gs) { data = new byte[initialSize]; growSize = gs; pos = 0; } /** * Writes the bytes to the end of the array, growing the array * as needs dictate * * @param d the data to write to the end of the array */ public void write(byte[] bytes) { while (pos + bytes.length > data.length) { // Grow the array byte[] newdata = new byte[data.length + growSize]; System.arraycopy(data, 0, newdata, 0, pos); data = newdata; } System.arraycopy(bytes, 0, data, pos, bytes.length); pos += bytes.length; } /** * Gets the current position within the file * * @return the position within the file */ public int getPosition() { return pos; } /** * Sets the data at the specified position to the contents of the array * * @param pos the position to alter * @param newdata the data to modify */ public void setData(byte[] newdata, int pos) { System.arraycopy(newdata, 0, data, pos, newdata.length); } /** * Writes the data to the output stream */ public void writeData(OutputStream out) throws IOException { out.write(data, 0, pos); } /** * Called when the final compound file has been written. No cleanup is * necessary for in-memory file generation */ public void close() throws IOException { } } jexcelapi/src/jxl/write/biff/NumberFormatRecord.java0000750000175000017500000000737411207000610022741 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.common.Logger; import jxl.biff.FormatRecord; /** * A class which contains a number format */ public class NumberFormatRecord extends FormatRecord { /** * The logger */ private static Logger logger = Logger.getLogger(NumberFormatRecord.class); // Dummy class to specify non validation protected static class NonValidatingFormat{public NonValidatingFormat(){}}; /** * Constructor. Replaces some of the characters in the java number * format string with the appropriate excel format characters * * @param fmt the number format */ protected NumberFormatRecord(String fmt) { super(); // Do the replacements in the format string String fs = fmt; fs = replace(fs, "E0", "E+0"); fs = trimInvalidChars(fs); setFormatString(fs); } /** * Constructor. Replaces some of the characters in the java number * format string with the appropriate excel format characters * * @param fmt the number format */ protected NumberFormatRecord(String fmt, NonValidatingFormat dummy) { super(); // Do the replacements in the format string String fs = fmt; fs = replace(fs, "E0", "E+0"); setFormatString(fs); } /** * Remove all but the first characters preceding the # or the 0. * Remove all characters after the # or the 0, unless it is a ) * * @param fs the candidate number format * @return the string with spurious characters removed */ private String trimInvalidChars(String fs) { int firstHash = fs.indexOf('#'); int firstZero = fs.indexOf('0'); int firstValidChar = 0; if (firstHash == -1 && firstZero == -1) { // The string is complete nonsense. Return a default string return "#.###"; } if (firstHash != 0 && firstZero != 0 && firstHash != 1 && firstZero != 1) { // The string is dodgy. Find the first valid char firstHash = firstHash == -1?firstHash = Integer.MAX_VALUE:firstHash; firstZero = firstZero == -1?firstZero = Integer.MAX_VALUE:firstZero; firstValidChar = Math.min(firstHash, firstZero); StringBuffer tmp = new StringBuffer(); tmp.append(fs.charAt(0)); tmp.append(fs.substring(firstValidChar)); fs = tmp.toString(); } // Now strip of everything at the end that isn't a # or 0 int lastHash = fs.lastIndexOf('#'); int lastZero = fs.lastIndexOf('0'); if (lastHash == fs.length() || lastZero == fs.length()) { return fs; } // Find the last valid character int lastValidChar = Math.max(lastHash, lastZero); // Check for the existence of a ) or % while ((fs.length() > lastValidChar + 1) && (fs.charAt(lastValidChar+1) == ')' || (fs.charAt(lastValidChar+1) == '%'))) { lastValidChar++; } return fs.substring(0, lastValidChar+1); } } jexcelapi/src/jxl/write/biff/Window2Record.java0000750000175000017500000000523011207000610021656 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.SheetSettings; import jxl.biff.IntegerHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Contains the window attributes for a worksheet */ class Window2Record extends WritableRecordData { /** * The binary data for output to file */ private byte[] data; /** * Constructor */ public Window2Record(SheetSettings settings) { super(Type.WINDOW2); int options = 0; options |= 0x0; // display formula values, not formulas if (settings.getShowGridLines()) { options |= 0x02; } options |= 0x04; // display row and column headings options |= 0x0; // panes should be not frozen if (settings.getDisplayZeroValues()) { options |= 0x10; } options |= 0x20; // default header options |= 0x80; // display outline symbols // Handle the freeze panes if (settings.getHorizontalFreeze() != 0 || settings.getVerticalFreeze() != 0) { options |= 0x08; options |= 0x100; } // Handle the selected flag if (settings.isSelected()) { options |= 0x600; } // Handle the view mode if (settings.getPageBreakPreviewMode()) { options |= 0x800; } // hard code the data in for now data = new byte[18]; IntegerHelper.getTwoBytes(options, data, 0); IntegerHelper.getTwoBytes(0x40, data, 6); // grid line colour IntegerHelper.getTwoBytes(settings.getPageBreakPreviewMagnification(), data, 10); IntegerHelper.getTwoBytes(settings.getNormalMagnification(), data, 12); } /** * Gets the binary data for output to file * * @return the binary data */ public byte[] getData() { return data; } } jexcelapi/src/jxl/write/biff/ObjProjRecord.java0000750000175000017500000000262511207000610021677 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Record containing the obj proj record */ class ObjProjRecord extends WritableRecordData { /** * The binary data */ private byte[] data; /** * Constructor */ public ObjProjRecord() { super(Type.OBJPROJ); data = new byte[4]; } /** * Retrieves the data to be written to the binary file * * @return the binary data */ public byte[] getData() { return data; } } jexcelapi/src/jxl/write/biff/TabIdRecord.java0000750000175000017500000000310011207000610021302 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.IntegerHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Contains an array of sheet tab index numbers */ class TabIdRecord extends WritableRecordData { /** * The binary data */ private byte[] data; /** * Constructor * * @param sheets the number of sheets */ public TabIdRecord(int sheets) { super(Type.TABID); data = new byte[sheets * 2]; for (int i = 0 ; i < sheets; i++) { IntegerHelper.getTwoBytes(i+1, data, i * 2); } } /** * Gets the data for output to file * * @return the binary data */ public byte[] getData() { return data; } } jexcelapi/src/jxl/write/biff/MMSRecord.java0000750000175000017500000000361511207000610020766 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Stores the number of addmen and delmenu groups in the book stream */ class MMSRecord extends WritableRecordData { /** * The number of menu items added */ private byte numMenuItemsAdded; /** * The number of menu items deleted */ private byte numMenuItemsDeleted; /** * The binary data */ private byte[] data; /** * Constructor * * @param menuItemsAdded the number of menu items added * @param menuItemsDeleted the number of menu items deleted */ public MMSRecord(int menuItemsAdded, int menuItemsDeleted) { super(Type.MMS); numMenuItemsAdded = (byte) menuItemsAdded; numMenuItemsDeleted = (byte) menuItemsDeleted; data = new byte[2]; data[0] = numMenuItemsAdded; data[1] = numMenuItemsDeleted; } /** * Gets the binary data for output to file * * @return the binary data */ public byte[] getData() { return data; } } jexcelapi/src/jxl/write/biff/PaletteRecord.java0000750000175000017500000000267111207000610021731 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Stores the colour palette */ class PaletteRecord extends WritableRecordData { /** * The binary data */ private byte[] data; /** * Constructor * * @param p the palette record */ public PaletteRecord(jxl.read.biff.PaletteRecord p) { super(Type.PALETTE); data = p.getData(); } /** * Gets the binary data for output to file * * @return the binary data */ public byte[] getData() { return data; } } jexcelapi/src/jxl/write/biff/SheetCopier.java0000750000175000017500000007626411245003431021425 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2006 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import java.util.Arrays; import java.util.ArrayList; import java.util.HashMap; import java.util.TreeSet; import java.util.Iterator; import jxl.common.Assert; import jxl.common.Logger; import jxl.BooleanCell; import jxl.Cell; import jxl.CellType; import jxl.CellView; import jxl.DateCell; import jxl.HeaderFooter; import jxl.Hyperlink; import jxl.Image; import jxl.LabelCell; import jxl.NumberCell; import jxl.Range; import jxl.Sheet; import jxl.SheetSettings; import jxl.WorkbookSettings; import jxl.biff.AutoFilter; import jxl.biff.CellReferenceHelper; import jxl.biff.ConditionalFormat; import jxl.biff.DataValidation; import jxl.biff.FormattingRecords; import jxl.biff.FormulaData; import jxl.biff.IndexMapping; import jxl.biff.NumFormatRecordsException; import jxl.biff.SheetRangeImpl; import jxl.biff.XFRecord; import jxl.biff.drawing.Chart; import jxl.biff.drawing.CheckBox; import jxl.biff.drawing.ComboBox; import jxl.biff.drawing.Drawing; import jxl.biff.drawing.DrawingGroupObject; import jxl.format.CellFormat; import jxl.biff.formula.FormulaException; import jxl.read.biff.SheetImpl; import jxl.read.biff.NameRecord; import jxl.read.biff.WorkbookParser; import jxl.write.Blank; import jxl.write.Boolean; import jxl.write.DateTime; import jxl.write.Formula; import jxl.write.Label; import jxl.write.Number; import jxl.write.WritableCell; import jxl.write.WritableCellFormat; import jxl.write.WritableFont; import jxl.write.WritableHyperlink; import jxl.write.WritableImage; import jxl.write.WritableSheet; import jxl.write.WritableWorkbook; import jxl.write.WriteException; /** * A transient utility object used to copy sheets. This * functionality has been farmed out to a different class * in order to reduce the bloat of the WritableSheetImpl */ class SheetCopier { private static Logger logger = Logger.getLogger(SheetCopier.class); private SheetImpl fromSheet; private WritableSheetImpl toSheet; private WorkbookSettings workbookSettings; // Objects used by the sheet private TreeSet columnFormats; private FormattingRecords formatRecords; private ArrayList hyperlinks; private MergedCells mergedCells; private ArrayList rowBreaks; private ArrayList columnBreaks; private SheetWriter sheetWriter; private ArrayList drawings; private ArrayList images; private ArrayList conditionalFormats; private ArrayList validatedCells; private AutoFilter autoFilter; private DataValidation dataValidation; private ComboBox comboBox; private PLSRecord plsRecord; private boolean chartOnly; private ButtonPropertySetRecord buttonPropertySet; private int numRows; private int maxRowOutlineLevel; private int maxColumnOutlineLevel; // Objects used to maintain state during the copy process private HashMap xfRecords; private HashMap fonts; private HashMap formats; public SheetCopier(Sheet f, WritableSheet t) { fromSheet = (SheetImpl) f; toSheet = (WritableSheetImpl) t; workbookSettings = toSheet.getWorkbook().getSettings(); chartOnly = false; } void setColumnFormats(TreeSet cf) { columnFormats = cf; } void setFormatRecords(FormattingRecords fr) { formatRecords = fr; } void setHyperlinks(ArrayList h) { hyperlinks = h; } void setMergedCells(MergedCells mc) { mergedCells = mc; } void setRowBreaks(ArrayList rb) { rowBreaks = rb; } void setColumnBreaks(ArrayList cb) { columnBreaks = cb; } void setSheetWriter(SheetWriter sw) { sheetWriter = sw; } void setDrawings(ArrayList d) { drawings = d; } void setImages(ArrayList i) { images = i; } void setConditionalFormats(ArrayList cf) { conditionalFormats = cf; } void setValidatedCells(ArrayList vc) { validatedCells = vc; } AutoFilter getAutoFilter() { return autoFilter; } DataValidation getDataValidation() { return dataValidation; } ComboBox getComboBox() { return comboBox; } PLSRecord getPLSRecord() { return plsRecord; } boolean isChartOnly() { return chartOnly; } ButtonPropertySetRecord getButtonPropertySet() { return buttonPropertySet; } /** * Copies a sheet from a read-only version to the writable version. * Performs shallow copies */ public void copySheet() { shallowCopyCells(); // Copy the column info records jxl.read.biff.ColumnInfoRecord[] readCirs = fromSheet.getColumnInfos(); for (int i = 0 ; i < readCirs.length; i++) { jxl.read.biff.ColumnInfoRecord rcir = readCirs[i]; for (int j = rcir.getStartColumn(); j <= rcir.getEndColumn() ; j++) { ColumnInfoRecord cir = new ColumnInfoRecord(rcir, j, formatRecords); cir.setHidden(rcir.getHidden()); columnFormats.add(cir); } } // Copy the hyperlinks Hyperlink[] hls = fromSheet.getHyperlinks(); for (int i = 0 ; i < hls.length; i++) { WritableHyperlink hr = new WritableHyperlink (hls[i], toSheet); hyperlinks.add(hr); } // Copy the merged cells Range[] merged = fromSheet.getMergedCells(); for (int i = 0; i < merged.length; i++) { mergedCells.add(new SheetRangeImpl((SheetRangeImpl)merged[i], toSheet)); } // Copy the row properties try { jxl.read.biff.RowRecord[] rowprops = fromSheet.getRowProperties(); for (int i = 0; i < rowprops.length; i++) { RowRecord rr = toSheet.getRowRecord(rowprops[i].getRowNumber()); XFRecord format = rowprops[i].hasDefaultFormat() ? formatRecords.getXFRecord(rowprops[i].getXFIndex()) : null; rr.setRowDetails(rowprops[i].getRowHeight(), rowprops[i].matchesDefaultFontHeight(), rowprops[i].isCollapsed(), rowprops[i].getOutlineLevel(), rowprops[i].getGroupStart(), format); numRows = Math.max(numRows, rowprops[i].getRowNumber() + 1); } } catch (RowsExceededException e) { // Handle the rows exceeded exception - this cannot occur since // the sheet we are copying from will have a valid number of rows Assert.verify(false); } // Copy the headers and footers // sheetWriter.setHeader(new HeaderRecord(si.getHeader())); // sheetWriter.setFooter(new FooterRecord(si.getFooter())); // Copy the page breaks int[] rowbreaks = fromSheet.getRowPageBreaks(); if (rowbreaks != null) { for (int i = 0; i < rowbreaks.length; i++) { rowBreaks.add(new Integer(rowbreaks[i])); } } int[] columnbreaks = fromSheet.getColumnPageBreaks(); if (columnbreaks != null) { for (int i = 0; i < columnbreaks.length; i++) { columnBreaks.add(new Integer(columnbreaks[i])); } } // Copy the charts sheetWriter.setCharts(fromSheet.getCharts()); // Copy the drawings DrawingGroupObject[] dr = fromSheet.getDrawings(); for (int i = 0 ; i < dr.length ; i++) { if (dr[i] instanceof jxl.biff.drawing.Drawing) { WritableImage wi = new WritableImage (dr[i], toSheet.getWorkbook().getDrawingGroup()); drawings.add(wi); images.add(wi); } else if (dr[i] instanceof jxl.biff.drawing.Comment) { jxl.biff.drawing.Comment c = new jxl.biff.drawing.Comment(dr[i], toSheet.getWorkbook().getDrawingGroup(), workbookSettings); drawings.add(c); // Set up the reference on the cell value CellValue cv = (CellValue) toSheet.getWritableCell(c.getColumn(), c.getRow()); Assert.verify(cv.getCellFeatures() != null); cv.getWritableCellFeatures().setCommentDrawing(c); } else if (dr[i] instanceof jxl.biff.drawing.Button) { jxl.biff.drawing.Button b = new jxl.biff.drawing.Button (dr[i], toSheet.getWorkbook().getDrawingGroup(), workbookSettings); drawings.add(b); } else if (dr[i] instanceof jxl.biff.drawing.ComboBox) { jxl.biff.drawing.ComboBox cb = new jxl.biff.drawing.ComboBox (dr[i], toSheet.getWorkbook().getDrawingGroup(), workbookSettings); drawings.add(cb); } else if (dr[i] instanceof jxl.biff.drawing.CheckBox) { jxl.biff.drawing.CheckBox cb = new jxl.biff.drawing.CheckBox (dr[i], toSheet.getWorkbook().getDrawingGroup(), workbookSettings); drawings.add(cb); } } // Copy the data validations DataValidation rdv = fromSheet.getDataValidation(); if (rdv != null) { dataValidation = new DataValidation(rdv, toSheet.getWorkbook(), toSheet.getWorkbook(), workbookSettings); int objid = dataValidation.getComboBoxObjectId(); if (objid != 0) { comboBox = (ComboBox) drawings.get(objid); } } // Copy the conditional formats ConditionalFormat[] cf = fromSheet.getConditionalFormats(); if (cf.length > 0) { for (int i = 0; i < cf.length ; i++) { conditionalFormats.add(cf[i]); } } // Get the autofilter autoFilter = fromSheet.getAutoFilter(); // Copy the workspace options sheetWriter.setWorkspaceOptions(fromSheet.getWorkspaceOptions()); // Set a flag to indicate if it contains a chart only if (fromSheet.getSheetBof().isChart()) { chartOnly = true; sheetWriter.setChartOnly(); } // Copy the environment specific print record if (fromSheet.getPLS() != null) { if (fromSheet.getWorkbookBof().isBiff7()) { logger.warn("Cannot copy Biff7 print settings record - ignoring"); } else { plsRecord = new PLSRecord(fromSheet.getPLS()); } } // Copy the button property set if (fromSheet.getButtonPropertySet() != null) { buttonPropertySet = new ButtonPropertySetRecord (fromSheet.getButtonPropertySet()); } // Copy the outline levels maxRowOutlineLevel = fromSheet.getMaxRowOutlineLevel(); maxColumnOutlineLevel = fromSheet.getMaxColumnOutlineLevel(); } /** * Copies a sheet from a read-only version to the writable version. * Performs shallow copies */ public void copyWritableSheet() { shallowCopyCells(); /* // Copy the column formats Iterator cfit = fromWritableSheet.columnFormats.iterator(); while (cfit.hasNext()) { ColumnInfoRecord cv = new ColumnInfoRecord ((ColumnInfoRecord) cfit.next()); columnFormats.add(cv); } // Copy the merged cells Range[] merged = fromWritableSheet.getMergedCells(); for (int i = 0; i < merged.length; i++) { mergedCells.add(new SheetRangeImpl((SheetRangeImpl)merged[i], this)); } // Copy the row properties try { RowRecord[] copyRows = fromWritableSheet.rows; RowRecord row = null; for (int i = 0; i < copyRows.length ; i++) { row = copyRows[i]; if (row != null && (!row.isDefaultHeight() || row.isCollapsed())) { RowRecord rr = getRowRecord(i); rr.setRowDetails(row.getRowHeight(), row.matchesDefaultFontHeight(), row.isCollapsed(), row.getStyle()); } } } catch (RowsExceededException e) { // Handle the rows exceeded exception - this cannot occur since // the sheet we are copying from will have a valid number of rows Assert.verify(false); } // Copy the horizontal page breaks rowBreaks = new ArrayList(fromWritableSheet.rowBreaks); // Copy the vertical page breaks columnBreaks = new ArrayList(fromWritableSheet.columnBreaks); // Copy the data validations DataValidation rdv = fromWritableSheet.dataValidation; if (rdv != null) { dataValidation = new DataValidation(rdv, workbook, workbook, workbookSettings); } // Copy the charts sheetWriter.setCharts(fromWritableSheet.getCharts()); // Copy the drawings DrawingGroupObject[] dr = si.getDrawings(); for (int i = 0 ; i < dr.length ; i++) { if (dr[i] instanceof jxl.biff.drawing.Drawing) { WritableImage wi = new WritableImage(dr[i], workbook.getDrawingGroup()); drawings.add(wi); images.add(wi); } // Not necessary to copy the comments, as they will be handled by // the deep copy of the individual cells } // Copy the workspace options sheetWriter.setWorkspaceOptions(fromWritableSheet.getWorkspaceOptions()); // Copy the environment specific print record if (fromWritableSheet.plsRecord != null) { plsRecord = new PLSRecord(fromWritableSheet.plsRecord); } // Copy the button property set if (fromWritableSheet.buttonPropertySet != null) { buttonPropertySet = new ButtonPropertySetRecord (fromWritableSheet.buttonPropertySet); } */ } /** * Imports a sheet from a different workbook, doing a deep copy */ public void importSheet() { xfRecords = new HashMap(); fonts = new HashMap(); formats = new HashMap(); deepCopyCells(); // Copy the column info records jxl.read.biff.ColumnInfoRecord[] readCirs = fromSheet.getColumnInfos(); for (int i = 0 ; i < readCirs.length; i++) { jxl.read.biff.ColumnInfoRecord rcir = readCirs[i]; for (int j = rcir.getStartColumn(); j <= rcir.getEndColumn() ; j++) { ColumnInfoRecord cir = new ColumnInfoRecord(rcir, j); int xfIndex = cir.getXfIndex(); XFRecord cf = (WritableCellFormat) xfRecords.get(new Integer(xfIndex)); if (cf == null) { CellFormat readFormat = fromSheet.getColumnView(j).getFormat(); WritableCellFormat wcf = copyCellFormat(readFormat); } cir.setCellFormat(cf); cir.setHidden(rcir.getHidden()); columnFormats.add(cir); } } // Copy the hyperlinks Hyperlink[] hls = fromSheet.getHyperlinks(); for (int i = 0 ; i < hls.length; i++) { WritableHyperlink hr = new WritableHyperlink (hls[i], toSheet); hyperlinks.add(hr); } // Copy the merged cells Range[] merged = fromSheet.getMergedCells(); for (int i = 0; i < merged.length; i++) { mergedCells.add(new SheetRangeImpl((SheetRangeImpl)merged[i], toSheet)); } // Copy the row properties try { jxl.read.biff.RowRecord[] rowprops = fromSheet.getRowProperties(); for (int i = 0; i < rowprops.length; i++) { RowRecord rr = toSheet.getRowRecord(rowprops[i].getRowNumber()); XFRecord format = null; jxl.read.biff.RowRecord rowrec = rowprops[i]; if (rowrec.hasDefaultFormat()) { format = (WritableCellFormat) xfRecords.get(new Integer(rowrec.getXFIndex())); if (format == null) { int rownum = rowrec.getRowNumber(); CellFormat readFormat = fromSheet.getRowView(rownum).getFormat(); WritableCellFormat wcf = copyCellFormat(readFormat); } } rr.setRowDetails(rowrec.getRowHeight(), rowrec.matchesDefaultFontHeight(), rowrec.isCollapsed(), rowrec.getOutlineLevel(), rowrec.getGroupStart(), format); numRows = Math.max(numRows, rowprops[i].getRowNumber() + 1); } } catch (RowsExceededException e) { // Handle the rows exceeded exception - this cannot occur since // the sheet we are copying from will have a valid number of rows Assert.verify(false); } // Copy the headers and footers // sheetWriter.setHeader(new HeaderRecord(si.getHeader())); // sheetWriter.setFooter(new FooterRecord(si.getFooter())); // Copy the page breaks int[] rowbreaks = fromSheet.getRowPageBreaks(); if (rowbreaks != null) { for (int i = 0; i < rowbreaks.length; i++) { rowBreaks.add(new Integer(rowbreaks[i])); } } int[] columnbreaks = fromSheet.getColumnPageBreaks(); if (columnbreaks != null) { for (int i = 0; i < columnbreaks.length; i++) { columnBreaks.add(new Integer(columnbreaks[i])); } } // Copy the charts Chart[] fromCharts = fromSheet.getCharts(); if (fromCharts != null && fromCharts.length > 0) { logger.warn("Importing of charts is not supported"); /* sheetWriter.setCharts(fromSheet.getCharts()); IndexMapping xfMapping = new IndexMapping(200); for (Iterator i = xfRecords.keySet().iterator(); i.hasNext();) { Integer key = (Integer) i.next(); XFRecord xfmapping = (XFRecord) xfRecords.get(key); xfMapping.setMapping(key.intValue(), xfmapping.getXFIndex()); } IndexMapping fontMapping = new IndexMapping(200); for (Iterator i = fonts.keySet().iterator(); i.hasNext();) { Integer key = (Integer) i.next(); Integer fontmap = (Integer) fonts.get(key); fontMapping.setMapping(key.intValue(), fontmap.intValue()); } IndexMapping formatMapping = new IndexMapping(200); for (Iterator i = formats.keySet().iterator(); i.hasNext();) { Integer key = (Integer) i.next(); Integer formatmap = (Integer) formats.get(key); formatMapping.setMapping(key.intValue(), formatmap.intValue()); } // Now reuse the rationalization feature on each chart to // handle the new fonts for (int i = 0; i < fromCharts.length ; i++) { fromCharts[i].rationalize(xfMapping, fontMapping, formatMapping); } */ } // Copy the drawings DrawingGroupObject[] dr = fromSheet.getDrawings(); // Make sure the destination workbook has a drawing group // created in it if (dr.length > 0 && toSheet.getWorkbook().getDrawingGroup() == null) { toSheet.getWorkbook().createDrawingGroup(); } for (int i = 0 ; i < dr.length ; i++) { if (dr[i] instanceof jxl.biff.drawing.Drawing) { WritableImage wi = new WritableImage (dr[i].getX(), dr[i].getY(), dr[i].getWidth(), dr[i].getHeight(), dr[i].getImageData()); toSheet.getWorkbook().addDrawing(wi); drawings.add(wi); images.add(wi); } else if (dr[i] instanceof jxl.biff.drawing.Comment) { jxl.biff.drawing.Comment c = new jxl.biff.drawing.Comment(dr[i], toSheet.getWorkbook().getDrawingGroup(), workbookSettings); drawings.add(c); // Set up the reference on the cell value CellValue cv = (CellValue) toSheet.getWritableCell(c.getColumn(), c.getRow()); Assert.verify(cv.getCellFeatures() != null); cv.getWritableCellFeatures().setCommentDrawing(c); } else if (dr[i] instanceof jxl.biff.drawing.Button) { jxl.biff.drawing.Button b = new jxl.biff.drawing.Button (dr[i], toSheet.getWorkbook().getDrawingGroup(), workbookSettings); drawings.add(b); } else if (dr[i] instanceof jxl.biff.drawing.ComboBox) { jxl.biff.drawing.ComboBox cb = new jxl.biff.drawing.ComboBox (dr[i], toSheet.getWorkbook().getDrawingGroup(), workbookSettings); drawings.add(cb); } } // Copy the data validations DataValidation rdv = fromSheet.getDataValidation(); if (rdv != null) { dataValidation = new DataValidation(rdv, toSheet.getWorkbook(), toSheet.getWorkbook(), workbookSettings); int objid = dataValidation.getComboBoxObjectId(); if (objid != 0) { comboBox = (ComboBox) drawings.get(objid); } } // Copy the workspace options sheetWriter.setWorkspaceOptions(fromSheet.getWorkspaceOptions()); // Set a flag to indicate if it contains a chart only if (fromSheet.getSheetBof().isChart()) { chartOnly = true; sheetWriter.setChartOnly(); } // Copy the environment specific print record if (fromSheet.getPLS() != null) { if (fromSheet.getWorkbookBof().isBiff7()) { logger.warn("Cannot copy Biff7 print settings record - ignoring"); } else { plsRecord = new PLSRecord(fromSheet.getPLS()); } } // Copy the button property set if (fromSheet.getButtonPropertySet() != null) { buttonPropertySet = new ButtonPropertySetRecord (fromSheet.getButtonPropertySet()); } importNames(); // Copy the outline levels maxRowOutlineLevel = fromSheet.getMaxRowOutlineLevel(); maxColumnOutlineLevel = fromSheet.getMaxColumnOutlineLevel(); } /** * Performs a shallow copy of the specified cell */ private WritableCell shallowCopyCell(Cell cell) { CellType ct = cell.getType(); WritableCell newCell = null; if (ct == CellType.LABEL) { newCell = new Label((LabelCell) cell); } else if (ct == CellType.NUMBER) { newCell = new Number((NumberCell) cell); } else if (ct == CellType.DATE) { newCell = new DateTime((DateCell) cell); } else if (ct == CellType.BOOLEAN) { newCell = new Boolean((BooleanCell) cell); } else if (ct == CellType.NUMBER_FORMULA) { newCell = new ReadNumberFormulaRecord((FormulaData) cell); } else if (ct == CellType.STRING_FORMULA) { newCell = new ReadStringFormulaRecord((FormulaData) cell); } else if( ct == CellType.BOOLEAN_FORMULA) { newCell = new ReadBooleanFormulaRecord((FormulaData) cell); } else if (ct == CellType.DATE_FORMULA) { newCell = new ReadDateFormulaRecord((FormulaData) cell); } else if(ct == CellType.FORMULA_ERROR) { newCell = new ReadErrorFormulaRecord((FormulaData) cell); } else if (ct == CellType.EMPTY) { if (cell.getCellFormat() != null) { // It is a blank cell, rather than an empty cell, so // it may have formatting information, so // it must be copied newCell = new Blank(cell); } } return newCell; } /** * Performs a deep copy of the specified cell, handling the cell format * * @param cell the cell to copy */ private WritableCell deepCopyCell(Cell cell) { WritableCell c = shallowCopyCell(cell); if (c == null) { return c; } if (c instanceof ReadFormulaRecord) { ReadFormulaRecord rfr = (ReadFormulaRecord) c; boolean crossSheetReference = !rfr.handleImportedCellReferences (fromSheet.getWorkbook(), fromSheet.getWorkbook(), workbookSettings); if (crossSheetReference) { try { logger.warn("Formula " + rfr.getFormula() + " in cell " + CellReferenceHelper.getCellReference(cell.getColumn(), cell.getRow()) + " cannot be imported because it references another " + " sheet from the source workbook"); } catch (FormulaException e) { logger.warn("Formula in cell " + CellReferenceHelper.getCellReference(cell.getColumn(), cell.getRow()) + " cannot be imported: " + e.getMessage()); } // Create a new error formula and add it instead c = new Formula(cell.getColumn(), cell.getRow(), "\"ERROR\""); } } // Copy the cell format CellFormat cf = c.getCellFormat(); int index = ( (XFRecord) cf).getXFIndex(); WritableCellFormat wcf = (WritableCellFormat) xfRecords.get(new Integer(index)); if (wcf == null) { wcf = copyCellFormat(cf); } c.setCellFormat(wcf); return c; } /** * Perform a shallow copy of the cells from the specified sheet into this one */ void shallowCopyCells() { // Copy the cells int cells = fromSheet.getRows(); Cell[] row = null; Cell cell = null; for (int i = 0; i < cells; i++) { row = fromSheet.getRow(i); for (int j = 0; j < row.length; j++) { cell = row[j]; WritableCell c = shallowCopyCell(cell); // Encase the calls to addCell in a try-catch block // These should not generate any errors, because we are // copying from an existing spreadsheet. In the event of // errors, catch the exception and then bomb out with an // assertion try { if (c != null) { toSheet.addCell(c); // Cell.setCellFeatures short circuits when the cell is copied, // so make sure the copy logic handles the validated cells if (c.getCellFeatures() != null && c.getCellFeatures().hasDataValidation()) { validatedCells.add(c); } } } catch (WriteException e) { Assert.verify(false); } } } numRows = toSheet.getRows(); } /** * Perform a deep copy of the cells from the specified sheet into this one */ void deepCopyCells() { // Copy the cells int cells = fromSheet.getRows(); Cell[] row = null; Cell cell = null; for (int i = 0; i < cells; i++) { row = fromSheet.getRow(i); for (int j = 0; j < row.length; j++) { cell = row[j]; WritableCell c = deepCopyCell(cell); // Encase the calls to addCell in a try-catch block // These should not generate any errors, because we are // copying from an existing spreadsheet. In the event of // errors, catch the exception and then bomb out with an // assertion try { if (c != null) { toSheet.addCell(c); // Cell.setCellFeatures short circuits when the cell is copied, // so make sure the copy logic handles the validated cells if (c.getCellFeatures() != null & c.getCellFeatures().hasDataValidation()) { validatedCells.add(c); } } } catch (WriteException e) { Assert.verify(false); } } } } /** * Returns an initialized copy of the cell format * * @param cf the cell format to copy * @return a deep copy of the cell format */ private WritableCellFormat copyCellFormat(CellFormat cf) { try { // just do a deep copy of the cell format for now. This will create // a copy of the format and font also - in the future this may // need to be sorted out XFRecord xfr = (XFRecord) cf; WritableCellFormat f = new WritableCellFormat(xfr); formatRecords.addStyle(f); // Maintain the local list of formats int xfIndex = xfr.getXFIndex(); xfRecords.put(new Integer(xfIndex), f); int fontIndex = xfr.getFontIndex(); fonts.put(new Integer(fontIndex), new Integer(f.getFontIndex())); int formatIndex = xfr.getFormatRecord(); formats.put(new Integer(formatIndex), new Integer(f.getFormatRecord())); return f; } catch (NumFormatRecordsException e) { logger.warn("Maximum number of format records exceeded. Using " + "default format."); return WritableWorkbook.NORMAL_STYLE; } } /** * Imports any names defined on the source sheet to the destination workbook */ private void importNames() { WorkbookParser fromWorkbook = (WorkbookParser) fromSheet.getWorkbook(); WritableWorkbook toWorkbook = toSheet.getWorkbook(); int fromSheetIndex = fromWorkbook.getIndex(fromSheet); NameRecord[] nameRecords = fromWorkbook.getNameRecords(); String[] names = toWorkbook.getRangeNames(); for (int i = 0 ; i < nameRecords.length ;i++) { NameRecord.NameRange[] nameRanges = nameRecords[i].getRanges(); for (int j = 0; j < nameRanges.length; j++) { int nameSheetIndex = fromWorkbook.getExternalSheetIndex (nameRanges[j].getExternalSheet()); if (fromSheetIndex == nameSheetIndex) { String name = nameRecords[i].getName(); if (Arrays.binarySearch(names, name) < 0) { toWorkbook.addNameArea(name, toSheet, nameRanges[j].getFirstColumn(), nameRanges[j].getFirstRow(), nameRanges[j].getLastColumn(), nameRanges[j].getLastRow()); } else { logger.warn("Named range " + name + " is already present in the destination workbook"); } } } } } /** * Gets the number of rows - allows for the case where formatting has * been applied to rows, even though the row has no data * * @return the number of rows */ int getRows() { return numRows; } /** * Accessor for the maximum column outline level * * @return the maximum column outline level, or 0 if no outlines/groups */ public int getMaxColumnOutlineLevel() { return maxColumnOutlineLevel; } /** * Accessor for the maximum row outline level * * @return the maximum row outline level, or 0 if no outlines/groups */ public int getMaxRowOutlineLevel() { return maxRowOutlineLevel; } } jexcelapi/src/jxl/write/biff/DSFRecord.java0000750000175000017500000000306511207000610020745 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Stores a flag which indicates whether the file is a double stream * file. For files written by JExcelAPI, this FALSE */ class DSFRecord extends WritableRecordData { /** * The data to be written to the binary file */ private byte[] data; /** * Constructor */ public DSFRecord() { super(Type.DSF); // Hard code the fact that this is most assuredly not a double // stream file data = new byte[] {0,0}; } /** * The binary data to be written out * * @return the binary data */ public byte[] getData() { return data; } } jexcelapi/src/jxl/write/biff/DBCellRecord.java0000750000175000017500000000576111207000610021423 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import java.util.ArrayList; import java.util.Iterator; import jxl.biff.IntegerHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Indexes the first row record of the block and each individual cell. * This is invoked by the sheets write process */ class DBCellRecord extends WritableRecordData { /** * The file position of the first Row record in this block */ private int rowPos; /** * The position of the start of the next cell after the first row. This * is used as the offset for the cell positions */ private int cellOffset; /** * The list of all cell positions in this block */ private ArrayList cellRowPositions; /** * The position of this record in the file. Vital for calculating offsets */ private int position; /** * Constructor * * @param rp the position of this row */ public DBCellRecord(int rp) { super(Type.DBCELL); rowPos = rp; cellRowPositions = new ArrayList(10); } /** * Sets the offset of this cell record within the sheet stream * * @param pos the offset */ void setCellOffset(int pos) { cellOffset = pos; } /** * Adds a cell * * @param pos */ void addCellRowPosition(int pos) { cellRowPositions.add(new Integer(pos)); } /** * Sets the position of this cell within the sheet stream * * @param pos the position */ void setPosition(int pos) { position = pos; } /** * Gets the binary data for this cell record * * @return the binary data */ protected byte[] getData() { byte[] data = new byte[4 + 2 * cellRowPositions.size()]; // Set the offset to the first row IntegerHelper.getFourBytes(position - rowPos, data, 0); // Now add in all the cell offsets int pos = 4; int lastCellPos = cellOffset; Iterator i = cellRowPositions.iterator(); while (i.hasNext()) { int cellPos = ((Integer) i.next()).intValue(); IntegerHelper.getTwoBytes(cellPos - lastCellPos, data, pos); lastCellPos = cellPos; pos += 2; } return data; } } jexcelapi/src/jxl/write/biff/RowsExceededException.java0000750000175000017500000000230611207000610023427 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; /** * Exception thrown when attempting to add a row to a spreadsheet which * has already reached the maximum amount */ public class RowsExceededException extends JxlWriteException { /** * Constructor */ public RowsExceededException() { super(maxRowsExceeded); } } jexcelapi/src/jxl/write/biff/#ColumnInfoRecord.java#0000750000175000017500000002075211207000610022512 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.FormattingRecords; import jxl.biff.IndexMapping; import jxl.biff.IntegerHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; import jxl.biff.XFRecord; /** * Describes the column formatting for a particular column */ class ColumnInfoRecord extends WritableRecordData { /** * The binary data */ private byte[] data; /** * The column number which this format applies to */ private int column; /** * The style for the column */ private XFRecord style; /** * The index for the style of this column */ private int xfIndex; /** * The width of the column in 1/256 of a character */ private int width; /** * Flag to indicate the hidden status of this column */ private boolean hidden; /** * The column's outline level */ private int outlineLevel; /** * Column collapsed flag */ private boolean collapsed; /** * Constructor used when setting column information from the user * API * * @param w the width of the column in characters * @param col the column to format * @param xf the style for the column */ public ColumnInfoRecord(int col, int w, XFRecord xf) { super(Type.COLINFO); column = col; width = w; style = xf; xfIndex = style.getXFIndex(); hidden = false; } /** * Copy constructor used when copying from sheet to sheet within the * same workbook * * @param the record to copy */ public ColumnInfoRecord(ColumnInfoRecord cir) { super(Type.COLINFO); column = cir.column; width = cir.width; style = cir.style; xfIndex = cir.xfIndex; hidden = cir.hidden; outlineLevel = cir.outlineLevel; collapsed = cir.collapsed; } /** * Constructor used when copying an existing spreadsheet * * @param col the column number * @param cir the column info record read in * @param fr the format records */ public ColumnInfoRecord(jxl.read.biff.ColumnInfoRecord cir, int col, FormattingRecords fr) { super(Type.COLINFO); column = col; width = cir.getWidth(); xfIndex = cir.getXFIndex(); style = fr.getXFRecord(xfIndex); outlineLevel = cir.getOutlineLevel(); collapsed = cir.getCollapsed(); } /** * Constructor used when importing a sheet from another * spreadsheet * * @param col the column number * @param cir the column info record read in */ public ColumnInfoRecord(jxl.read.biff.ColumnInfoRecord cir, int col) { super(Type.COLINFO); column = col; width = cir.getWidth(); xfIndex = cir.getXFIndex(); outlineLevel = cir.getOutlineLevel(); collapsed = cir.getCollapsed(); } /** * Gets the column this format applies to * * @return the column which is formatted */ public int getColumn() { return column; } /** * Increments the column. Called when inserting a new column into * the sheet */ public void incrementColumn() { column++; } /** * Decrements the column. Called when removing a column from * the sheet */ public void decrementColumn() { column--; } /** * Accessor for the width * * @return the width */ int getWidth() { return width; } /** * Sets the width. Used when autosizing columns * * @param w the new width */ void setWidth(int w) { width = w; } /** * Gets the binary data to be written to the output file * * @return the data to write to file */ public byte[] getData() { data = new byte[0x0c]; IntegerHelper.getTwoBytes(column, data, 0); IntegerHelper.getTwoBytes(column, data, 2); IntegerHelper.getTwoBytes(width, data, 4); IntegerHelper.getTwoBytes(xfIndex, data, 6); // int options = 0x2; int options = 0x6 | (outlineLevel << 8); if (hidden) { options |= 0x1; } outlineLevel = ((options & 0x700) / 0x100); if (collapsed) { options |= 0x1000; } IntegerHelper.getTwoBytes(options, data, 8); // IntegerHelper.getTwoBytes(2, data, 10); return data; } /** * Gets the cell format associated with this column info record * * @return the cell format for this column */ public XFRecord getCellFormat() { return style; } /** * Sets the cell format. Used when importing spreadsheets * * @param xfr the xf record */ public void setCellFormat(XFRecord xfr) { style = xfr; } /** * Accessor for the xf index, used when importing from another spreadsheet * * @return the xf index */ public int getXfIndex() { return xfIndex; } /** * Rationalizes the sheets xf index mapping * @param xfmapping the index mapping */ void rationalize(IndexMapping xfmapping) { xfIndex = xfmapping.getNewIndex(xfIndex); } /** * Sets this column to be hidden (or otherwise) * * @param h TRUE if the column is to be hidden, FALSE otherwise */ void setHidden(boolean h) { hidden = h; } /** * Accessor for the hidden flag * * @return TRUE if this column is hidden, FALSE otherwise */ boolean getHidden() { return hidden; } /** * Standard equals method * * @return TRUE if these objects are equal, FALSE otherwise */ public boolean equals(Object o) { if (o == this) { return true; } if (!(o instanceof ColumnInfoRecord)) { return false; } ColumnInfoRecord cir = (ColumnInfoRecord) o; if (column != cir.column || xfIndex != cir.xfIndex || width != cir.width || hidden != cir.hidden || outlineLevel != cir.outlineLevel || collapsed != cir.collapsed) { return false; } if ((style == null && cir.style != null) || (style != null && cir.style == null)) { return false; } return style.equals(cir.style); } /** * Standard hashCode method * * @return the hashCode */ public int hashCode() { int hashValue = 137; int oddPrimeNumber = 79; hashValue = hashValue * oddPrimeNumber + column; hashValue = hashValue * oddPrimeNumber + xfIndex; hashValue = hashValue * oddPrimeNumber + width; hashValue = hashValue * oddPrimeNumber + (hidden ? 1:0); if (style != null) { hashValue ^= style.hashCode(); ?? } return hashValue; } /** * Accessor for the column's outline level * * @return the column's outline level */ public int getOutlineLevel() { return outlineLevel; } /** * Accessor for whether the column is collapsed * * @return the column's collapsed state */ public boolean getCollapsed() { return collapsed; } /** * Increments the column's outline level. This is how groups are made * as well */ public void incrementOutlineLevel() { outlineLevel++; } /** * Decrements the column's outline level. This removes it from a * grouping level. If * all outline levels are gone the uncollapse the column. */ public void decrementOutlineLevel() { if (0 < outlineLevel) { outlineLevel--; } if (0==outlineLevel) { collapsed = false; } } /** * Sets the column's outline level * * @param level the column's outline level */ public void setOutlineLevel(int level) { outlineLevel = level; } /** * Sets the column's collapsed state * * @param value the column's collapsed state */ public void setCollapsed(boolean value) { collapsed = value; } } jexcelapi/src/jxl/write/biff/RefModeRecord.java0000750000175000017500000000265211207000610021653 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Stores the reference style option from the options dialog box */ class RefModeRecord extends WritableRecordData { /** * Constructor */ public RefModeRecord() { super(Type.REFMODE); } /** * Gets the binary data for output to file * * @return the binary data */ public byte[] getData() { byte[] data = new byte[2]; // Hard code in the style A1 for now data[0] = 0x1; return data; } } jexcelapi/src/jxl/write/biff/WritableSheetCopier.java0000750000175000017500000004015411234322655023116 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2006 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import java.util.Arrays; import java.util.ArrayList; import java.util.HashMap; import java.util.TreeSet; import java.util.Iterator; import jxl.common.Assert; import jxl.common.Logger; import jxl.BooleanCell; import jxl.Cell; import jxl.CellType; import jxl.CellView; import jxl.DateCell; import jxl.HeaderFooter; import jxl.Hyperlink; import jxl.Image; import jxl.LabelCell; import jxl.NumberCell; import jxl.Range; import jxl.Sheet; import jxl.SheetSettings; import jxl.WorkbookSettings; import jxl.biff.AutoFilter; import jxl.biff.CellReferenceHelper; import jxl.biff.ConditionalFormat; import jxl.biff.DataValidation; import jxl.biff.FormattingRecords; import jxl.biff.FormulaData; import jxl.biff.IndexMapping; import jxl.biff.NumFormatRecordsException; import jxl.biff.SheetRangeImpl; import jxl.biff.WorkspaceInformationRecord; import jxl.biff.XFRecord; import jxl.biff.drawing.Chart; import jxl.biff.drawing.ComboBox; import jxl.biff.drawing.Drawing; import jxl.biff.drawing.DrawingGroupObject; import jxl.format.CellFormat; import jxl.biff.formula.FormulaException; import jxl.read.biff.SheetImpl; import jxl.read.biff.NameRecord; import jxl.read.biff.WorkbookParser; import jxl.write.Blank; import jxl.write.Boolean; import jxl.write.DateTime; import jxl.write.Formula; import jxl.write.Label; import jxl.write.Number; import jxl.write.WritableCell; import jxl.write.WritableCellFormat; import jxl.write.WritableFont; import jxl.write.WritableHyperlink; import jxl.write.WritableImage; import jxl.write.WritableSheet; import jxl.write.WritableWorkbook; import jxl.write.WriteException; /** * A transient utility object used to copy sheets. This * functionality has been farmed out to a different class * in order to reduce the bloat of the WritableSheetImpl */ class WritableSheetCopier { private static Logger logger = Logger.getLogger(SheetCopier.class); private WritableSheetImpl fromSheet; private WritableSheetImpl toSheet; private WorkbookSettings workbookSettings; // Objects used by the sheet private TreeSet fromColumnFormats; private TreeSet toColumnFormats; private MergedCells fromMergedCells; private MergedCells toMergedCells; private RowRecord[] fromRows; private ArrayList fromRowBreaks; private ArrayList fromColumnBreaks; private ArrayList toRowBreaks; private ArrayList toColumnBreaks; private DataValidation fromDataValidation; private DataValidation toDataValidation; private SheetWriter sheetWriter; private ArrayList fromDrawings; private ArrayList toDrawings; private ArrayList toImages; private WorkspaceInformationRecord fromWorkspaceOptions; private PLSRecord fromPLSRecord; private PLSRecord toPLSRecord; private ButtonPropertySetRecord fromButtonPropertySet; private ButtonPropertySetRecord toButtonPropertySet; private ArrayList fromHyperlinks; private ArrayList toHyperlinks; private ArrayList validatedCells; private int numRows; private int maxRowOutlineLevel; private int maxColumnOutlineLevel; private boolean chartOnly; private FormattingRecords formatRecords; // Objects used to maintain state during the copy process private HashMap xfRecords; private HashMap fonts; private HashMap formats; public WritableSheetCopier(WritableSheet f, WritableSheet t) { fromSheet = (WritableSheetImpl) f; toSheet = (WritableSheetImpl) t; workbookSettings = toSheet.getWorkbook().getSettings(); chartOnly = false; } void setColumnFormats(TreeSet fcf, TreeSet tcf) { fromColumnFormats = fcf; toColumnFormats = tcf; } void setMergedCells(MergedCells fmc, MergedCells tmc) { fromMergedCells = fmc; toMergedCells = tmc; } void setRows(RowRecord[] r) { fromRows = r; } void setValidatedCells(ArrayList vc) { validatedCells = vc; } void setRowBreaks(ArrayList frb, ArrayList trb) { fromRowBreaks = frb; toRowBreaks = trb; } void setColumnBreaks(ArrayList fcb, ArrayList tcb) { fromColumnBreaks = fcb; toColumnBreaks = tcb; } void setDrawings(ArrayList fd, ArrayList td, ArrayList ti) { fromDrawings = fd; toDrawings = td; toImages = ti; } void setHyperlinks(ArrayList fh, ArrayList th) { fromHyperlinks = fh; toHyperlinks = th; } void setWorkspaceOptions(WorkspaceInformationRecord wir) { fromWorkspaceOptions = wir; } void setDataValidation(DataValidation dv) { fromDataValidation = dv; } void setPLSRecord(PLSRecord plsr) { fromPLSRecord = plsr; } void setButtonPropertySetRecord(ButtonPropertySetRecord bpsr) { fromButtonPropertySet = bpsr; } void setSheetWriter(SheetWriter sw) { sheetWriter = sw; } DataValidation getDataValidation() { return toDataValidation; } PLSRecord getPLSRecord() { return toPLSRecord; } boolean isChartOnly() { return chartOnly; } ButtonPropertySetRecord getButtonPropertySet() { return toButtonPropertySet; } /** * Copies a sheet from a read-only version to the writable version. * Performs shallow copies */ public void copySheet() { shallowCopyCells(); // Copy the column formats Iterator cfit = fromColumnFormats.iterator(); while (cfit.hasNext()) { ColumnInfoRecord cv = new ColumnInfoRecord ((ColumnInfoRecord) cfit.next()); toColumnFormats.add(cv); } // Copy the merged cells Range[] merged = fromMergedCells.getMergedCells(); for (int i = 0; i < merged.length; i++) { toMergedCells.add(new SheetRangeImpl((SheetRangeImpl)merged[i], toSheet)); } try { RowRecord row = null; RowRecord newRow = null; for (int i = 0; i < fromRows.length ; i++) { row = fromRows[i]; if (row != null && (!row.isDefaultHeight() || row.isCollapsed())) { newRow = toSheet.getRowRecord(i); newRow.setRowDetails(row.getRowHeight(), row.matchesDefaultFontHeight(), row.isCollapsed(), row.getOutlineLevel(), row.getGroupStart(), row.getStyle()); } } } catch (RowsExceededException e) { // Handle the rows exceeded exception - this cannot occur since // the sheet we are copying from will have a valid number of rows Assert.verify(false); } // Copy the horizontal page breaks toRowBreaks = new ArrayList(fromRowBreaks); // Copy the vertical page breaks toColumnBreaks = new ArrayList(fromColumnBreaks); // Copy the data validations if (fromDataValidation != null) { toDataValidation = new DataValidation (fromDataValidation, toSheet.getWorkbook(), toSheet.getWorkbook(), toSheet.getWorkbook().getSettings()); } // Copy the charts sheetWriter.setCharts(fromSheet.getCharts()); // Copy the drawings for (Iterator i = fromDrawings.iterator(); i.hasNext(); ) { Object o = i.next(); if (o instanceof jxl.biff.drawing.Drawing) { WritableImage wi = new WritableImage ((jxl.biff.drawing.Drawing) o, toSheet.getWorkbook().getDrawingGroup()); toDrawings.add(wi); toImages.add(wi); } // Not necessary to copy the comments, as they will be handled by // the deep copy of the individual cells } // Copy the workspace options sheetWriter.setWorkspaceOptions(fromWorkspaceOptions); // Copy the environment specific print record if (fromPLSRecord != null) { toPLSRecord = new PLSRecord(fromPLSRecord); } // Copy the button property set if (fromButtonPropertySet != null) { toButtonPropertySet = new ButtonPropertySetRecord(fromButtonPropertySet); } // Copy the hyperlinks for (Iterator i = fromHyperlinks.iterator(); i.hasNext();) { WritableHyperlink hr = new WritableHyperlink ((WritableHyperlink) i.next(), toSheet); toHyperlinks.add(hr); } } /** * Performs a shallow copy of the specified cell */ private WritableCell shallowCopyCell(Cell cell) { CellType ct = cell.getType(); WritableCell newCell = null; if (ct == CellType.LABEL) { newCell = new Label((LabelCell) cell); } else if (ct == CellType.NUMBER) { newCell = new Number((NumberCell) cell); } else if (ct == CellType.DATE) { newCell = new DateTime((DateCell) cell); } else if (ct == CellType.BOOLEAN) { newCell = new Boolean((BooleanCell) cell); } else if (ct == CellType.NUMBER_FORMULA) { newCell = new ReadNumberFormulaRecord((FormulaData) cell); } else if (ct == CellType.STRING_FORMULA) { newCell = new ReadStringFormulaRecord((FormulaData) cell); } else if( ct == CellType.BOOLEAN_FORMULA) { newCell = new ReadBooleanFormulaRecord((FormulaData) cell); } else if (ct == CellType.DATE_FORMULA) { newCell = new ReadDateFormulaRecord((FormulaData) cell); } else if(ct == CellType.FORMULA_ERROR) { newCell = new ReadErrorFormulaRecord((FormulaData) cell); } else if (ct == CellType.EMPTY) { if (cell.getCellFormat() != null) { // It is a blank cell, rather than an empty cell, so // it may have formatting information, so // it must be copied newCell = new Blank(cell); } } return newCell; } /** * Performs a deep copy of the specified cell, handling the cell format * * @param cell the cell to copy */ private WritableCell deepCopyCell(Cell cell) { WritableCell c = shallowCopyCell(cell); if (c == null) { return c; } if (c instanceof ReadFormulaRecord) { ReadFormulaRecord rfr = (ReadFormulaRecord) c; boolean crossSheetReference = !rfr.handleImportedCellReferences (fromSheet.getWorkbook(), fromSheet.getWorkbook(), workbookSettings); if (crossSheetReference) { try { logger.warn("Formula " + rfr.getFormula() + " in cell " + CellReferenceHelper.getCellReference(cell.getColumn(), cell.getRow()) + " cannot be imported because it references another " + " sheet from the source workbook"); } catch (FormulaException e) { logger.warn("Formula in cell " + CellReferenceHelper.getCellReference(cell.getColumn(), cell.getRow()) + " cannot be imported: " + e.getMessage()); } // Create a new error formula and add it instead c = new Formula(cell.getColumn(), cell.getRow(), "\"ERROR\""); } } // Copy the cell format CellFormat cf = c.getCellFormat(); int index = ( (XFRecord) cf).getXFIndex(); WritableCellFormat wcf = (WritableCellFormat) xfRecords.get(new Integer(index)); if (wcf == null) { wcf = copyCellFormat(cf); } c.setCellFormat(wcf); return c; } /** * Perform a shallow copy of the cells from the specified sheet into this one */ void shallowCopyCells() { // Copy the cells int cells = fromSheet.getRows(); Cell[] row = null; Cell cell = null; for (int i = 0; i < cells; i++) { row = fromSheet.getRow(i); for (int j = 0; j < row.length; j++) { cell = row[j]; WritableCell c = shallowCopyCell(cell); // Encase the calls to addCell in a try-catch block // These should not generate any errors, because we are // copying from an existing spreadsheet. In the event of // errors, catch the exception and then bomb out with an // assertion try { if (c != null) { toSheet.addCell(c); // Cell.setCellFeatures short circuits when the cell is copied, // so make sure the copy logic handles the validated cells if (c.getCellFeatures() != null & c.getCellFeatures().hasDataValidation()) { validatedCells.add(c); } } } catch (WriteException e) { Assert.verify(false); } } } numRows = toSheet.getRows(); } /** * Perform a deep copy of the cells from the specified sheet into this one */ void deepCopyCells() { // Copy the cells int cells = fromSheet.getRows(); Cell[] row = null; Cell cell = null; for (int i = 0; i < cells; i++) { row = fromSheet.getRow(i); for (int j = 0; j < row.length; j++) { cell = row[j]; WritableCell c = deepCopyCell(cell); // Encase the calls to addCell in a try-catch block // These should not generate any errors, because we are // copying from an existing spreadsheet. In the event of // errors, catch the exception and then bomb out with an // assertion try { if (c != null) { toSheet.addCell(c); // Cell.setCellFeatures short circuits when the cell is copied, // so make sure the copy logic handles the validated cells if (c.getCellFeatures() != null & c.getCellFeatures().hasDataValidation()) { validatedCells.add(c); } } } catch (WriteException e) { Assert.verify(false); } } } } /** * Returns an initialized copy of the cell format * * @param cf the cell format to copy * @return a deep copy of the cell format */ private WritableCellFormat copyCellFormat(CellFormat cf) { try { // just do a deep copy of the cell format for now. This will create // a copy of the format and font also - in the future this may // need to be sorted out XFRecord xfr = (XFRecord) cf; WritableCellFormat f = new WritableCellFormat(xfr); formatRecords.addStyle(f); // Maintain the local list of formats int xfIndex = xfr.getXFIndex(); xfRecords.put(new Integer(xfIndex), f); int fontIndex = xfr.getFontIndex(); fonts.put(new Integer(fontIndex), new Integer(f.getFontIndex())); int formatIndex = xfr.getFormatRecord(); formats.put(new Integer(formatIndex), new Integer(f.getFormatRecord())); return f; } catch (NumFormatRecordsException e) { logger.warn("Maximum number of format records exceeded. Using " + "default format."); return WritableWorkbook.NORMAL_STYLE; } } /** * Accessor for the maximum column outline level * * @return the maximum column outline level, or 0 if no outlines/groups */ public int getMaxColumnOutlineLevel() { return maxColumnOutlineLevel; } /** * Accessor for the maximum row outline level * * @return the maximum row outline level, or 0 if no outlines/groups */ public int getMaxRowOutlineLevel() { return maxRowOutlineLevel; } } jexcelapi/src/jxl/write/biff/HyperlinkRecord.java0000750000175000017500000007416511207000610022307 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import java.io.File; import java.net.URL; import java.net.MalformedURLException; import java.util.ArrayList; import jxl.common.Assert; import jxl.common.Logger; import jxl.CellType; import jxl.Hyperlink; import jxl.Range; import jxl.WorkbookSettings; import jxl.biff.CellReferenceHelper; import jxl.biff.IntegerHelper; import jxl.biff.SheetRangeImpl; import jxl.biff.StringHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; import jxl.write.Label; import jxl.write.WritableHyperlink; import jxl.write.WritableCell; import jxl.write.WritableSheet; /** * A hyperlink */ public class HyperlinkRecord extends WritableRecordData { /** * The logger */ private static Logger logger = Logger.getLogger(HyperlinkRecord.class); /** * The first row */ private int firstRow; /** * The last row */ private int lastRow; /** * The first column */ private int firstColumn; /** * The last column */ private int lastColumn; /** * The URL referred to by this hyperlink */ private URL url; /** * The local file referred to by this hyperlink */ private File file; /** * The location in this workbook referred to by this hyperlink */ private String location; /** * The cell contents of the cell which activate this hyperlink */ private String contents; /** * The type of this hyperlink */ private LinkType linkType; /** * The data for this hyperlink */ private byte[] data; /** * The range of this hyperlink. When creating a hyperlink, this will * be null until the hyperlink is added to the sheet */ private Range range; /** * The sheet containing this hyperlink */ private WritableSheet sheet; /** * Indicates whether this record has been modified since it was copied */ private boolean modified; /** * The excel type of hyperlink */ private static class LinkType {}; private static final LinkType urlLink = new LinkType(); private static final LinkType fileLink = new LinkType(); private static final LinkType uncLink = new LinkType(); private static final LinkType workbookLink = new LinkType(); private static final LinkType unknown = new LinkType(); /** * Constructs this object from the readable spreadsheet * * @param hl the hyperlink from the read spreadsheet */ protected HyperlinkRecord(Hyperlink h, WritableSheet s) { super(Type.HLINK); if (h instanceof jxl.read.biff.HyperlinkRecord) { copyReadHyperlink(h, s); } else { copyWritableHyperlink(h, s); } } /** * Copies a hyperlink read in from a read only sheet */ private void copyReadHyperlink(Hyperlink h, WritableSheet s) { jxl.read.biff.HyperlinkRecord hl = (jxl.read.biff.HyperlinkRecord) h; data = hl.getRecord().getData(); sheet = s; // Populate this hyperlink with the copied data firstRow = hl.getRow(); firstColumn = hl.getColumn(); lastRow = hl.getLastRow(); lastColumn = hl.getLastColumn(); range = new SheetRangeImpl(s, firstColumn, firstRow, lastColumn, lastRow); linkType = unknown; if (hl.isFile()) { linkType = fileLink; file = hl.getFile(); } else if (hl.isURL()) { linkType = urlLink; url = hl.getURL(); } else if (hl.isLocation()) { linkType = workbookLink; location = hl.getLocation(); } modified = false; } /** * Copies a hyperlink read in from a writable sheet. * Used when copying writable sheets * * @param hl the hyperlink from the read spreadsheet */ private void copyWritableHyperlink(Hyperlink hl, WritableSheet s) { HyperlinkRecord h = (HyperlinkRecord) hl; firstRow = h.firstRow; lastRow = h.lastRow; firstColumn = h.firstColumn; lastColumn = h.lastColumn; if (h.url != null) { try { url = new URL(h.url.toString()); } catch (MalformedURLException e) { // should never get a malformed url as a result url.toString() Assert.verify(false); } } if (h.file != null) { file = new File(h.file.getPath()); } location = h.location; contents = h.contents; linkType = h.linkType; modified = true; sheet = s; range = new SheetRangeImpl(s, firstColumn, firstRow, lastColumn, lastRow); } /** * Constructs a URL hyperlink to a range of cells * * @param col the column containing this hyperlink * @param row the row containing this hyperlink * @param lastcol the last column which activates this hyperlink * @param lastrow the last row which activates this hyperlink * @param url the hyperlink * @param desc the description */ protected HyperlinkRecord(int col, int row, int lastcol, int lastrow, URL url, String desc) { super(Type.HLINK); firstColumn = col; firstRow = row; lastColumn = Math.max(firstColumn, lastcol); lastRow = Math.max(firstRow, lastrow); this.url = url; contents = desc; linkType = urlLink; modified = true; } /** * Constructs a File hyperlink to a range of cells * * @param col the column containing this hyperlink * @param row the row containing this hyperlink * @param lastcol the last column which activates this hyperlink * @param lastrow the last row which activates this hyperlink * @param file the hyperlink * @param desc the description */ protected HyperlinkRecord(int col, int row, int lastcol, int lastrow, File file, String desc) { super(Type.HLINK); firstColumn = col; firstRow = row; lastColumn = Math.max(firstColumn, lastcol); lastRow = Math.max(firstRow, lastrow); contents = desc; this.file = file; if (file.getPath().startsWith("\\\\")) { linkType = uncLink; } else { linkType = fileLink; } modified = true; } /** * Constructs a hyperlink to some cells within this workbook * * @param col the column containing this hyperlink * @param row the row containing this hyperlink * @param lastcol the last column which activates this hyperlink * @param lastrow the last row which activates this hyperlink * @param desc the contents of the cell which describe this hyperlink * @param sheet the sheet containing the cells to be linked to * @param destcol the column number of the first destination linked cell * @param destrow the row number of the first destination linked cell * @param lastdestcol the column number of the last destination linked cell * @param lastdestrow the row number of the last destination linked cell */ protected HyperlinkRecord(int col, int row, int lastcol, int lastrow, String desc, WritableSheet s, int destcol, int destrow, int lastdestcol, int lastdestrow) { super(Type.HLINK); firstColumn = col; firstRow = row; lastColumn = Math.max(firstColumn, lastcol); lastRow = Math.max(firstRow, lastrow); setLocation(s, destcol, destrow, lastdestcol, lastdestrow); contents = desc; linkType = workbookLink; modified = true; } /** * Determines whether this is a hyperlink to a file * * @return TRUE if this is a hyperlink to a file, FALSE otherwise */ public boolean isFile() { return linkType == fileLink; } /** * Determines whether this is a hyperlink to a UNC * * @return TRUE if this is a hyperlink to a UNC, FALSE otherwise */ public boolean isUNC() { return linkType == uncLink; } /** * Determines whether this is a hyperlink to a web resource * * @return TRUE if this is a URL */ public boolean isURL() { return linkType == urlLink; } /** * Determines whether this is a hyperlink to a location in this workbook * * @return TRUE if this is a link to an internal location */ public boolean isLocation() { return linkType == workbookLink; } /** * Returns the row number of the top left cell * * @return the row number of this cell */ public int getRow() { return firstRow; } /** * Returns the column number of the top left cell * * @return the column number of this cell */ public int getColumn() { return firstColumn; } /** * Returns the row number of the bottom right cell * * @return the row number of this cell */ public int getLastRow() { return lastRow; } /** * Returns the column number of the bottom right cell * * @return the column number of this cell */ public int getLastColumn() { return lastColumn; } /** * Gets the URL referenced by this Hyperlink * * @return the URL, or NULL if this hyperlink is not a URL */ public URL getURL() { return url; } /** * Returns the local file eferenced by this Hyperlink * * @return the file, or NULL if this hyperlink is not a file */ public File getFile() { return file; } /** * Gets the binary data to be written to the output file * * @return the data to write to file */ public byte[] getData() { if (!modified) { return data; } // Build up the jxl.common.data byte[] commonData = new byte[32]; // Set the range of cells this hyperlink applies to IntegerHelper.getTwoBytes(firstRow, commonData, 0); IntegerHelper.getTwoBytes(lastRow, commonData, 2); IntegerHelper.getTwoBytes(firstColumn, commonData, 4); IntegerHelper.getTwoBytes(lastColumn, commonData, 6); // Some inexplicable byte sequence commonData[8] = (byte) 0xd0; commonData[9] = (byte) 0xc9; commonData[10] = (byte) 0xea; commonData[11] = (byte) 0x79; commonData[12] = (byte) 0xf9; commonData[13] = (byte) 0xba; commonData[14] = (byte) 0xce; commonData[15] = (byte) 0x11; commonData[16] = (byte) 0x8c; commonData[17] = (byte) 0x82; commonData[18] = (byte) 0x0; commonData[19] = (byte) 0xaa; commonData[20] = (byte) 0x0; commonData[21] = (byte) 0x4b; commonData[22] = (byte) 0xa9; commonData[23] = (byte) 0x0b; commonData[24] = (byte) 0x2; commonData[25] = (byte) 0x0; commonData[26] = (byte) 0x0; commonData[27] = (byte) 0x0; // Set up the option flags to indicate the type of this URL. There // is no description int optionFlags = 0; if (isURL()) { optionFlags = 3; if (contents != null) { optionFlags |= 0x14; } } else if (isFile()) { optionFlags = 1; if (contents != null) { optionFlags |= 0x14; } } else if (isLocation()) { optionFlags = 8; } else if (isUNC()) { optionFlags = 259; } IntegerHelper.getFourBytes(optionFlags, commonData, 28); if (isURL()) { data = getURLData(commonData); } else if (isFile()) { data = getFileData(commonData); } else if (isLocation()) { data = getLocationData(commonData); } else if (isUNC()) { data = getUNCData(commonData); } return data; } /** * A standard toString method * * @return the contents of this object as a string */ public String toString() { if (isFile()) { return file.toString(); } else if (isURL()) { return url.toString(); } else if (isUNC()) { return file.toString(); } else { return ""; } } /** * Gets the range of cells which activate this hyperlink * The get sheet index methods will all return -1, because the * cells will all be present on the same sheet * * @return the range of cells which activate the hyperlink or NULL * if this hyperlink has not been added to the sheet */ public Range getRange() { return range; } /** * Sets the URL of this hyperlink * * @param url the url */ public void setURL(URL url) { URL prevurl = this.url; linkType = urlLink; file = null; location = null; contents = null; this.url = url; modified = true; if (sheet == null) { // hyperlink has not been added to the sheet yet, so simply return return; } // Change the label on the sheet if it was a string representation of the // URL WritableCell wc = sheet.getWritableCell(firstColumn, firstRow); if (wc.getType() == CellType.LABEL) { Label l = (Label) wc; String prevurlString = prevurl.toString(); String prevurlString2 = ""; if (prevurlString.charAt(prevurlString.length() - 1) == '/' || prevurlString.charAt(prevurlString.length() - 1) == '\\') { prevurlString2 = prevurlString.substring(0, prevurlString.length() - 1); } if (l.getString().equals(prevurlString) || l.getString().equals(prevurlString2)) { l.setString(url.toString()); } } } /** * Sets the file activated by this hyperlink * * @param file the file */ public void setFile(File file) { linkType = fileLink; url = null; location = null; contents = null; this.file = file; modified = true; if (sheet == null) { // hyperlink has not been added to the sheet yet, so simply return return; } // Change the label on the sheet WritableCell wc = sheet.getWritableCell(firstColumn, firstRow); Assert.verify(wc.getType() == CellType.LABEL); Label l = (Label) wc; l.setString(file.toString()); } /** * Sets the location of the cells to be linked to within this workbook * * @param desc the label describing the link * @param sheet the sheet containing the cells to be linked to * @param destcol the column number of the first destination linked cell * @param destrow the row number of the first destination linked cell * @param lastdestcol the column number of the last destination linked cell * @param lastdestrow the row number of the last destination linked cell */ protected void setLocation(String desc, WritableSheet sheet, int destcol, int destrow, int lastdestcol, int lastdestrow) { linkType = workbookLink; url = null; file = null; modified = true; contents = desc; setLocation(sheet, destcol, destrow, lastdestcol, lastdestrow); if (sheet == null) { // hyperlink has not been added to the sheet yet, so simply return return; } // Change the label on the sheet WritableCell wc = sheet.getWritableCell(firstColumn, firstRow); Assert.verify(wc.getType() == CellType.LABEL); Label l = (Label) wc; l.setString(desc); } /** * Initializes the location from the data passed in * * @param sheet the sheet containing the cells to be linked to * @param destcol the column number of the first destination linked cell * @param destrow the row number of the first destination linked cell * @param lastdestcol the column number of the last destination linked cell * @param lastdestrow the row number of the last destination linked cell */ private void setLocation(WritableSheet sheet, int destcol, int destrow, int lastdestcol, int lastdestrow) { StringBuffer sb = new StringBuffer(); sb.append('\''); if (sheet.getName().indexOf('\'') == -1) { sb.append(sheet.getName()); } else { // sb.append(sheet.getName().replaceAll("'", "''")); // Can't use replaceAll as it is only 1.4 compatible, so have to // do this the tedious way String sheetName = sheet.getName(); int pos = 0 ; int nextPos = sheetName.indexOf('\'', pos); while (nextPos != -1 && pos < sheetName.length()) { sb.append(sheetName.substring(pos, nextPos)); sb.append("''"); pos = nextPos + 1; nextPos = sheetName.indexOf('\'', pos); } sb.append(sheetName.substring(pos)); } sb.append('\''); sb.append('!'); lastdestcol = Math.max(destcol, lastdestcol); lastdestrow = Math.max(destrow, lastdestrow); CellReferenceHelper.getCellReference(destcol, destrow, sb); sb.append(':'); CellReferenceHelper.getCellReference(lastdestcol, lastdestrow, sb); location = sb.toString(); } /** * A row has been inserted, so adjust the range objects accordingly * * @param r the row which has been inserted */ void insertRow(int r) { // This will not be called unless the hyperlink has been added to the // sheet Assert.verify(sheet != null && range != null); if (r > lastRow) { return; } if (r <= firstRow) { firstRow++; modified = true; } if (r <= lastRow) { lastRow++; modified = true; } if (modified) { range = new SheetRangeImpl(sheet, firstColumn, firstRow, lastColumn, lastRow); } } /** * A column has been inserted, so adjust the range objects accordingly * * @param c the column which has been inserted */ void insertColumn(int c) { // This will not be called unless the hyperlink has been added to the // sheet Assert.verify(sheet != null && range != null); if (c > lastColumn) { return; } if (c <= firstColumn) { firstColumn++; modified = true; } if (c <= lastColumn) { lastColumn++; modified = true; } if (modified) { range = new SheetRangeImpl(sheet, firstColumn, firstRow, lastColumn, lastRow); } } /** * A row has been removed, so adjust the range objects accordingly * * @param r the row which has been inserted */ void removeRow(int r) { // This will not be called unless the hyperlink has been added to the // sheet Assert.verify(sheet != null && range != null); if (r > lastRow) { return; } if (r < firstRow) { firstRow--; modified = true; } if (r < lastRow) { lastRow--; modified = true; } if (modified) { Assert.verify(range != null); range = new SheetRangeImpl(sheet, firstColumn, firstRow, lastColumn, lastRow); } } /** * A column has been removed, so adjust the range objects accordingly * * @param c the column which has been removed */ void removeColumn(int c) { // This will not be called unless the hyperlink has been added to the // sheet Assert.verify(sheet != null && range != null); if (c > lastColumn) { return; } if (c < firstColumn) { firstColumn--; modified = true; } if (c < lastColumn) { lastColumn--; modified = true; } if (modified) { Assert.verify(range != null); range = new SheetRangeImpl(sheet, firstColumn, firstRow, lastColumn, lastRow); } } /** * Gets the hyperlink stream specific to a URL link * * @param cd the data jxl.common.for all types of hyperlink * @return the raw data for a URL hyperlink */ private byte[] getURLData(byte[] cd) { String urlString = url.toString(); int dataLength = cd.length + 20 + (urlString.length() + 1)* 2; if (contents != null) { dataLength += 4 + (contents.length() + 1) * 2; } byte[] d = new byte[dataLength]; System.arraycopy(cd, 0, d, 0, cd.length); int urlPos = cd.length; if (contents != null) { IntegerHelper.getFourBytes(contents.length() + 1, d, urlPos); StringHelper.getUnicodeBytes(contents, d, urlPos + 4); urlPos += (contents.length() + 1) * 2 + 4; } // Inexplicable byte sequence d[urlPos] = (byte) 0xe0; d[urlPos+1] = (byte) 0xc9; d[urlPos+2] = (byte) 0xea; d[urlPos+3] = (byte) 0x79; d[urlPos+4] = (byte) 0xf9; d[urlPos+5] = (byte) 0xba; d[urlPos+6] = (byte) 0xce; d[urlPos+7] = (byte) 0x11; d[urlPos+8] = (byte) 0x8c; d[urlPos+9] = (byte) 0x82; d[urlPos+10] = (byte) 0x0; d[urlPos+11] = (byte) 0xaa; d[urlPos+12] = (byte) 0x0; d[urlPos+13] = (byte) 0x4b; d[urlPos+14] = (byte) 0xa9; d[urlPos+15] = (byte) 0x0b; // Number of characters in the url, including a zero trailing character IntegerHelper.getFourBytes((urlString.length() + 1)*2, d, urlPos+16); // Put the url into the data string StringHelper.getUnicodeBytes(urlString, d, urlPos+20); return d; } /** * Gets the hyperlink stream specific to a URL link * * @param cd the data jxl.common.for all types of hyperlink * @return the raw data for a URL hyperlink */ private byte[] getUNCData(byte[] cd) { String uncString = file.getPath(); byte[] d = new byte[cd.length + uncString.length() * 2 + 2 + 4]; System.arraycopy(cd, 0, d, 0, cd.length); int urlPos = cd.length; // The length of the unc string, including zero terminator int length = uncString.length() + 1; IntegerHelper.getFourBytes(length, d, urlPos); // Place the string into the stream StringHelper.getUnicodeBytes(uncString, d, urlPos + 4); return d; } /** * Gets the hyperlink stream specific to a local file link * * @param cd the data jxl.common.for all types of hyperlink * @return the raw data for a URL hyperlink */ private byte[] getFileData(byte[] cd) { // Build up the directory hierarchy in reverse order ArrayList path = new ArrayList(); ArrayList shortFileName = new ArrayList(); path.add(file.getName()); shortFileName.add(getShortName(file.getName())); File parent = file.getParentFile(); while (parent != null) { path.add(parent.getName()); shortFileName.add(getShortName(parent.getName())); parent = parent.getParentFile(); } // Deduce the up directory level count and remove the directory from // the path int upLevelCount = 0; int pos = path.size() - 1; boolean upDir = true; while (upDir) { String s = (String) path.get(pos); if (s.equals("..")) { upLevelCount++; path.remove(pos); shortFileName.remove(pos); } else { upDir = false; } pos--; } StringBuffer filePathSB = new StringBuffer(); StringBuffer shortFilePathSB = new StringBuffer(); if (file.getPath().charAt(1)==':') { char driveLetter = file.getPath().charAt(0); if (driveLetter != 'C' && driveLetter != 'c') { filePathSB.append(driveLetter); filePathSB.append(':'); shortFilePathSB.append(driveLetter); shortFilePathSB.append(':'); } } for (int i = path.size() - 1; i >= 0 ; i--) { filePathSB.append((String)path.get(i)); shortFilePathSB.append((String)shortFileName.get(i)); if (i != 0) { filePathSB.append("\\"); shortFilePathSB.append("\\"); } } String filePath = filePathSB.toString(); String shortFilePath = shortFilePathSB.toString(); int dataLength = cd.length + 4 + (shortFilePath.length() + 1) + // short file name 16 + // inexplicable byte sequence 2 + // up directory level count 8 + (filePath.length() + 1) * 2 + // long file name 24; // inexplicable byte sequence if (contents != null) { dataLength += 4 + (contents.length() + 1) * 2; } // Copy across the jxl.common.data into the new array byte[] d = new byte[dataLength]; System.arraycopy(cd, 0, d, 0, cd.length); int filePos = cd.length; // Add in the description text if (contents != null) { IntegerHelper.getFourBytes(contents.length() + 1, d, filePos); StringHelper.getUnicodeBytes(contents, d, filePos + 4); filePos += (contents.length() + 1) * 2 + 4; } int curPos = filePos; // Inexplicable byte sequence d[curPos] = (byte) 0x03; d[curPos+1] = (byte) 0x03; d[curPos+2] = (byte) 0x0; d[curPos+3] = (byte) 0x0; d[curPos+4] = (byte) 0x0; d[curPos+5] = (byte) 0x0; d[curPos+6] = (byte) 0x0; d[curPos+7] = (byte) 0x0; d[curPos+8] = (byte) 0xc0; d[curPos+9] = (byte) 0x0; d[curPos+10] = (byte) 0x0; d[curPos+11] = (byte) 0x0; d[curPos+12] = (byte) 0x0; d[curPos+13] = (byte) 0x0; d[curPos+14] = (byte) 0x0; d[curPos+15] = (byte) 0x46; curPos += 16; // The directory up level count IntegerHelper.getTwoBytes(upLevelCount, d, curPos); curPos += 2; // The number of bytes in the short file name, including zero terminator IntegerHelper.getFourBytes((shortFilePath.length() + 1), d, curPos); // The short file name StringHelper.getBytes(shortFilePath, d, curPos+4); curPos += 4 + (shortFilePath.length() + 1); // Inexplicable byte sequence d[curPos] = (byte) 0xff; d[curPos+1] = (byte) 0xff; d[curPos+2] = (byte) 0xad; d[curPos+3] = (byte) 0xde; d[curPos+4] = (byte) 0x0; d[curPos+5] = (byte) 0x0; d[curPos+6] = (byte) 0x0; d[curPos+7] = (byte) 0x0; d[curPos+8] = (byte) 0x0; d[curPos+9] = (byte) 0x0; d[curPos+10] = (byte) 0x0; d[curPos+11] = (byte) 0x0; d[curPos+12] = (byte) 0x0; d[curPos+13] = (byte) 0x0; d[curPos+14] = (byte) 0x0; d[curPos+15] = (byte) 0x0; d[curPos+16] = (byte) 0x0; d[curPos+17] = (byte) 0x0; d[curPos+18] = (byte) 0x0; d[curPos+19] = (byte) 0x0; d[curPos+20] = (byte) 0x0; d[curPos+21] = (byte) 0x0; d[curPos+22] = (byte) 0x0; d[curPos+23] = (byte) 0x0; curPos += 24; // Size of the long file name data in bytes, including inexplicable data // fields int size = 6 + filePath.length() * 2; IntegerHelper.getFourBytes(size, d, curPos); curPos += 4; // The number of bytes in the long file name // NOT including zero terminator IntegerHelper.getFourBytes((filePath.length()) * 2, d, curPos); curPos += 4; // Inexplicable bytes d[curPos] = (byte) 0x3; d[curPos+1] = (byte) 0x0; curPos += 2; // The long file name StringHelper.getUnicodeBytes(filePath, d, curPos); curPos += (filePath.length() + 1) * 2; /* curPos += 24; int nameLength = filePath.length() * 2; // Size of the file link IntegerHelper.getFourBytes(nameLength+6, d, curPos); // Number of characters IntegerHelper.getFourBytes(nameLength, d, curPos+4); // Inexplicable byte sequence d[curPos+8] = 0x03; // The long file name StringHelper.getUnicodeBytes(filePath, d, curPos+10); */ return d; } /** * Gets the DOS short file name in 8.3 format of the name passed in * * @param s the name * @return the dos short name */ private String getShortName(String s) { int sep = s.indexOf('.'); String prefix = null; String suffix = null; if (sep == -1) { prefix = s; suffix=""; } else { prefix = s.substring(0,sep); suffix = s.substring(sep+1); } if (prefix.length() > 8) { prefix = prefix.substring(0, 6) + "~" + (prefix.length() - 8); prefix = prefix.substring(0, 8); } suffix = suffix.substring(0,Math.min(3, suffix.length())); if (suffix.length() > 0) { return prefix + '.' + suffix; } else { return prefix; } } /** * Gets the hyperlink stream specific to a location link * * @param cd the data jxl.common.for all types of hyperlink * @return the raw data for a URL hyperlink */ private byte[] getLocationData(byte[] cd) { byte[] d = new byte[cd.length + 4 + (location.length() + 1)* 2]; System.arraycopy(cd, 0, d, 0, cd.length); int locPos = cd.length; // The number of chars in the location string, plus a 0 terminator IntegerHelper.getFourBytes(location.length() + 1, d, locPos); // Get the location StringHelper.getUnicodeBytes(location, d, locPos+4); return d; } /** * Initializes the range when this hyperlink is added to the sheet * * @param s the sheet containing this hyperlink */ void initialize(WritableSheet s) { sheet = s; range = new SheetRangeImpl(s, firstColumn, firstRow, lastColumn, lastRow); } /** * Called by the worksheet. Gets the string contents to put into the cell * containing this hyperlink * * @return the string contents for the hyperlink cell */ String getContents() { return contents; } /** * Sets the description * * @param desc the description */ protected void setContents(String desc) { contents = desc; modified = true; } } jexcelapi/src/jxl/write/biff/Styles.java0000750000175000017500000001242011207000610020450 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2004 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.common.Logger; import jxl.biff.XFRecord; import jxl.write.DateFormat; import jxl.write.DateFormats; import jxl.write.NumberFormats; import jxl.write.WritableCellFormat; import jxl.write.WritableFont; import jxl.write.WritableWorkbook; /** * A structure containing the styles used by this workbook. This is used * to enforce thread safety by tying the default styles to a workbook * instance rather than by initializing them statically */ class Styles { /** * The logger */ private static Logger logger = Logger.getLogger(Styles.class); /** * The default font for Cell formats */ private WritableFont arial10pt; /** * The font used for hyperlinks */ private WritableFont hyperlinkFont; /** * The default style for cells */ private WritableCellFormat normalStyle; /** * The style used for hyperlinks */ private WritableCellFormat hyperlinkStyle; /** * A cell format used to hide the cell contents */ private WritableCellFormat hiddenStyle; /** * A cell format used for the default date format */ private WritableCellFormat defaultDateFormat; /** * Constructor */ public Styles() { arial10pt = null; hyperlinkFont = null; normalStyle = null; hyperlinkStyle = null; hiddenStyle = null; } private synchronized void initNormalStyle() { normalStyle = new WritableCellFormat(getArial10Pt(), NumberFormats.DEFAULT); normalStyle.setFont(getArial10Pt()); } public WritableCellFormat getNormalStyle() { if (normalStyle == null) { initNormalStyle(); } return normalStyle; } private synchronized void initHiddenStyle() { hiddenStyle = new WritableCellFormat (getArial10Pt(), new DateFormat(";;;")); } public WritableCellFormat getHiddenStyle() { if (hiddenStyle == null) { initHiddenStyle(); } return hiddenStyle; } private synchronized void initHyperlinkStyle() { hyperlinkStyle = new WritableCellFormat(getHyperlinkFont(), NumberFormats.DEFAULT); } public WritableCellFormat getHyperlinkStyle() { if (hyperlinkStyle == null) { initHyperlinkStyle(); } return hyperlinkStyle; } private synchronized void initArial10Pt() { arial10pt = new WritableFont(WritableWorkbook.ARIAL_10_PT); } public WritableFont getArial10Pt() { if (arial10pt == null) { initArial10Pt(); } return arial10pt; } private synchronized void initHyperlinkFont() { hyperlinkFont = new WritableFont(WritableWorkbook.HYPERLINK_FONT); } public WritableFont getHyperlinkFont() { if (hyperlinkFont == null) { initHyperlinkFont(); } return hyperlinkFont; } private synchronized void initDefaultDateFormat() { defaultDateFormat = new WritableCellFormat(DateFormats.DEFAULT); } public WritableCellFormat getDefaultDateFormat() { if (defaultDateFormat == null) { initDefaultDateFormat(); } return defaultDateFormat; } /** * Gets the thread safe version of the cell format passed in. If the * format is already thread safe (ie. it doesn't use a statically initialized * format or font) then the same object is simply returned * This object is already tied to a workbook instance, so no synchronisation * is necesasry * * @param wf a format to verify * @return the thread safe format */ public XFRecord getFormat(XFRecord wf) { XFRecord format = wf; // Check to see if the format is one of the shared Workbook defaults. If // so, then get hold of the Workbook's specific instance if (format == WritableWorkbook.NORMAL_STYLE) { format = getNormalStyle(); } else if (format == WritableWorkbook.HYPERLINK_STYLE) { format = getHyperlinkStyle(); } else if (format == WritableWorkbook.HIDDEN_STYLE) { format = getHiddenStyle(); } else if (format == DateRecord.defaultDateFormat) { format = getDefaultDateFormat(); } // Do the same with the statically shared fonts if (format.getFont() == WritableWorkbook.ARIAL_10_PT) { format.setFont(getArial10Pt()); } else if (format.getFont() == WritableWorkbook.HYPERLINK_FONT) { format.setFont(getHyperlinkFont()); } return format; } } jexcelapi/src/jxl/write/biff/ReadDateFormulaRecord.java0000750000175000017500000000375711207000610023340 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2004 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import java.text.DateFormat; import java.util.Date; import jxl.DateFormulaCell; import jxl.biff.FormulaData; /** * Class for read number formula records */ class ReadDateFormulaRecord extends ReadFormulaRecord implements DateFormulaCell { /** * Constructor * * @param f */ public ReadDateFormulaRecord(FormulaData f) { super(f); } /** * Gets the Date contents for this cell. * * @return the cell contents */ public Date getDate() { return ( (DateFormulaCell) getReadFormula()).getDate(); } /** * Indicates whether the date value contained in this cell refers to a date, * or merely a time * * @return TRUE if the value refers to a time */ public boolean isTime() { return ( (DateFormulaCell) getReadFormula()).isTime(); } /** * Gets the DateFormat used to format this cell. This is the java * equivalent of the Excel format * * @return the DateFormat used to format the cell */ public DateFormat getDateFormat() { return ( (DateFormulaCell) getReadFormula()).getDateFormat(); } } jexcelapi/src/jxl/write/biff/FooterRecord.java0000750000175000017500000000411211207000610021561 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.IntegerHelper; import jxl.biff.StringHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Places a string at the bottom of each page when the file is printed. * JExcelApi sets this to be blank */ class FooterRecord extends WritableRecordData { /** * The binary data */ private byte[] data; /** * The footer string */ private String footer; /** * Consructor * * @param s the footer */ public FooterRecord(String s) { super(Type.FOOTER); footer = s; } /** * Consructor invoked when copying a sheets * * @param fr the read footer record */ public FooterRecord(FooterRecord fr) { super(Type.FOOTER); footer = fr.footer; } /** * Gets the binary data to write to the output file * * @return the binary data */ public byte[] getData() { if (footer == null || footer.length() == 0) { data = new byte[0]; return data; } data = new byte[footer.length() * 2 + 3]; IntegerHelper.getTwoBytes(footer.length(), data, 0); data[2] = (byte) 0x1; StringHelper.getUnicodeBytes(footer, data, 3); return data; } } jexcelapi/src/jxl/write/biff/StringRecord.java0000750000175000017500000000327211207000610021577 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.IntegerHelper; import jxl.biff.StringHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Stores the string result of a formula calculation. This record * occurs immediately after the formula */ class StringRecord extends WritableRecordData { /** * The string value */ private String value; /** * Constructor */ public StringRecord(String val) { super(Type.STRING); value = val; } /** * The binary data to be written out * * @return the binary data */ public byte[] getData() { byte[] data = new byte[value.length() * 2 + 3]; IntegerHelper.getTwoBytes(value.length(), data, 0); data[2] = 0x01; // unicode StringHelper.getUnicodeBytes(value, data, 3); return data; } } jexcelapi/src/jxl/write/biff/ExternalNameRecord.java0000750000175000017500000000364611207000610022721 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.common.Logger; import jxl.biff.StringHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * An external sheet record, used to maintain integrity when formulas * are copied from read databases */ class ExternalNameRecord extends WritableRecordData { /** * The logger */ Logger logger = Logger.getLogger(ExternalNameRecord.class); /** * The name of the addin */ private String name; /** * Constructor used for writable workbooks */ public ExternalNameRecord(String n) { super(Type.EXTERNNAME); name = n; } /** * Gets the binary data for output to file * * @return the binary data */ public byte[] getData() { byte[] data = new byte[name.length() * 2 + 12]; data[6] = (byte) name.length(); data[7] = 0x1; StringHelper.getUnicodeBytes(name, data, 8); int pos = 8 + name.length() * 2; data[pos] = 0x2; data[pos+1] = 0x0; data[pos+2] = 0x1c; data[pos+3] = 0x17; return data; } } jexcelapi/src/jxl/write/biff/ExternalSheetRecord.java0000750000175000017500000001247411207000610023110 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import java.util.ArrayList; import java.util.Iterator; import jxl.biff.IntegerHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * An external sheet record, used to maintain integrity when formulas * are copied from read databases */ class ExternalSheetRecord extends WritableRecordData { /** * The underlying external sheet data */ private byte[] data; /** * The list of XTI structures */ private ArrayList xtis; /** * An XTI structure */ private static class XTI { int supbookIndex; int firstTab; int lastTab; XTI(int s, int f, int l) { supbookIndex = s; firstTab = f; lastTab = l; } void sheetInserted(int index) { if (firstTab >= index) { firstTab++; } if (lastTab >= index) { lastTab++; } } void sheetRemoved(int index) { if (firstTab == index) { firstTab = 0; } if (lastTab == index) { lastTab = 0; } if (firstTab > index) { firstTab--; } if (lastTab > index) { lastTab--; } } } /** * Constructor * * @param esf the external sheet record to copy */ public ExternalSheetRecord(jxl.read.biff.ExternalSheetRecord esf) { super(Type.EXTERNSHEET); xtis = new ArrayList(esf.getNumRecords()); XTI xti = null; for (int i = 0 ; i < esf.getNumRecords(); i++) { xti = new XTI(esf.getSupbookIndex(i), esf.getFirstTabIndex(i), esf.getLastTabIndex(i)); xtis.add(xti); } } /** * Constructor used for writable workbooks */ public ExternalSheetRecord() { super(Type.EXTERNSHEET); xtis = new ArrayList(); } /** * Gets the extern sheet index for the specified parameters, creating * a new xti record if necessary * @param supbookind the internal supbook reference * @param sheetind the sheet index */ int getIndex(int supbookind, int sheetind) { Iterator i = xtis.iterator(); XTI xti = null; boolean found = false; int pos = 0; while (i.hasNext() && !found) { xti = (XTI) i.next(); if (xti.supbookIndex == supbookind && xti.firstTab == sheetind) { found = true; } else { pos++; } } if (!found) { xti = new XTI(supbookind, sheetind, sheetind); xtis.add(xti); pos = xtis.size() - 1; } return pos; } /** * Gets the binary data for output to file * * @return the binary data */ public byte[] getData() { byte[] data = new byte[2 + xtis.size() * 6]; int pos = 0; IntegerHelper.getTwoBytes(xtis.size(), data, 0); pos += 2; Iterator i = xtis.iterator(); XTI xti = null; while (i.hasNext()) { xti = (XTI) i.next(); IntegerHelper.getTwoBytes(xti.supbookIndex, data, pos); IntegerHelper.getTwoBytes(xti.firstTab, data, pos+2); IntegerHelper.getTwoBytes(xti.lastTab, data, pos+4); pos +=6 ; } return data; } /** * Gets the supbook index for the specified external sheet * * @param the index of the supbook record * @return the supbook index */ public int getSupbookIndex(int index) { return ((XTI) xtis.get(index)).supbookIndex; } /** * Gets the first tab index for the specified external sheet * * @param the index of the supbook record * @return the first tab index */ public int getFirstTabIndex(int index) { return ((XTI) xtis.get(index)).firstTab; } /** * Gets the last tab index for the specified external sheet * * @param the index of the supbook record * @return the last tab index */ public int getLastTabIndex(int index) { return ((XTI) xtis.get(index)).lastTab; } /** * Called when a sheet has been inserted via the API * @param the position of the insertion */ void sheetInserted(int index) { XTI xti = null; for (Iterator i = xtis.iterator(); i.hasNext() ; ) { xti = (XTI) i.next(); xti.sheetInserted(index); } } /** * Called when a sheet has been removed via the API * @param the position of the insertion */ void sheetRemoved(int index) { XTI xti = null; for (Iterator i = xtis.iterator(); i.hasNext() ; ) { xti = (XTI) i.next(); xti.sheetRemoved(index); } } } jexcelapi/src/jxl/write/biff/FormulaRecord.java0000750000175000017500000002450011207000610021733 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.common.Assert; import jxl.common.Logger; import jxl.CellReferenceHelper; import jxl.CellType; import jxl.Sheet; import jxl.WorkbookSettings; import jxl.biff.FormattingRecords; import jxl.biff.FormulaData; import jxl.biff.IntegerHelper; import jxl.biff.Type; import jxl.biff.WorkbookMethods; import jxl.biff.formula.ExternalSheet; import jxl.biff.formula.FormulaException; import jxl.biff.formula.FormulaParser; import jxl.format.CellFormat; import jxl.write.WritableCell; /** * A formula record. Parses the string passed in to deduce the set of * formula records */ public class FormulaRecord extends CellValue implements FormulaData { /** * The logger */ private static Logger logger = Logger.getLogger(FormulaRecord.class); /** * The formula to parse */ private String formulaToParse; /** * The formula parser */ private FormulaParser parser; /** * The parsed formula string */ private String formulaString; /** * The parsed formula bytes */ private byte[] formulaBytes; /** * The location where this formula was copied from. It is used subsequently * to adjust relative cell references */ private CellValue copiedFrom; /** * Constructor * * @param f the formula to copy */ public FormulaRecord(int c, int r, String f) { super(Type.FORMULA2, c, r); formulaToParse = f; copiedFrom = null; } /** * Constructor * * @param f the formula to copy */ public FormulaRecord(int c, int r, String f, CellFormat st) { super(Type.FORMULA, c, r, st); formulaToParse = f; copiedFrom = null; } /** * Copy constructor for writable formulas * * @param c the column * @param r the row * @param fr the record to copy */ protected FormulaRecord(int c, int r, FormulaRecord fr) { super(Type.FORMULA, c, r, fr); copiedFrom = fr; formulaBytes = new byte[fr.formulaBytes.length]; System.arraycopy(fr.formulaBytes, 0, formulaBytes, 0, formulaBytes.length); } /** * Copy constructor for formulas read in - invoked from writable formulas * * @param c the column * @param r the row * @param rfr the formula data to copy */ protected FormulaRecord(int c, int r, ReadFormulaRecord rfr) { super(Type.FORMULA, c, r, rfr); try { copiedFrom = rfr; formulaBytes = rfr.getFormulaBytes(); } catch (FormulaException e) { // Fail silently logger.error("", e); } } /** * Initializes the string and the formula bytes. In order to get * access to the workbook settings, the object is not initialized until * it is added to the sheet * * @param ws the workbook settings * @param es the external sheet * @param nt the name table */ private void initialize(WorkbookSettings ws, ExternalSheet es, WorkbookMethods nt) { if (copiedFrom != null) { initializeCopiedFormula(ws, es, nt); return; } parser = new FormulaParser(formulaToParse, es, nt, ws); try { parser.parse(); formulaString = parser.getFormula(); formulaBytes = parser.getBytes(); } catch (FormulaException e) { logger.warn (e.getMessage() + " when parsing formula " + formulaToParse + " in cell " + getSheet().getName() + "!" + CellReferenceHelper.getCellReference(getColumn(), getRow())); try { // try again, with an error formula formulaToParse = "ERROR(1)"; parser = new FormulaParser(formulaToParse, es, nt, ws); parser.parse(); formulaString = parser.getFormula(); formulaBytes = parser.getBytes(); } catch (FormulaException e2) { // fail silently logger.error("",e2); } } } /** * This formula was copied from a formula already present in the writable * workbook. Requires special handling to sort out the cell references * @param ws the workbook settings * @param es the external sheet * @param nt the name table */ private void initializeCopiedFormula(WorkbookSettings ws, ExternalSheet es, WorkbookMethods nt) { try { parser = new FormulaParser(formulaBytes, this, es, nt, ws); parser.parse(); parser.adjustRelativeCellReferences (getColumn() - copiedFrom.getColumn(), getRow() - copiedFrom.getRow()); formulaString = parser.getFormula(); formulaBytes = parser.getBytes(); } catch (FormulaException e) { try { // try again, with an error formula formulaToParse = "ERROR(1)"; parser = new FormulaParser(formulaToParse, es, nt, ws); parser.parse(); formulaString = parser.getFormula(); formulaBytes = parser.getBytes(); } catch (FormulaException e2) { // fail silently logger.error("", e2); } } } /** * Called when the cell is added to the worksheet. Overrides the * method in the base class in order to get a handle to the * WorkbookSettings so that this formula may be initialized * * @param fr the formatting records * @param ss the shared strings used within the workbook * @param s the sheet this is being added to */ void setCellDetails(FormattingRecords fr, SharedStrings ss, WritableSheetImpl s) { super.setCellDetails(fr, ss, s); initialize(s.getWorkbookSettings(), s.getWorkbook(), s.getWorkbook()); s.getWorkbook().addRCIRCell(this); } /** * Gets the binary data for output to file * * @return the binary data */ public byte[] getData() { byte[] celldata = super.getData(); byte[] formulaData = getFormulaData(); byte[] data = new byte[formulaData.length + celldata.length]; System.arraycopy(celldata, 0, data, 0, celldata.length); System.arraycopy(formulaData, 0, data, celldata.length, formulaData.length); return data; } /** * Returns the content type of this cell * * @return the content type for this cell */ public CellType getType() { return CellType.ERROR; } /** * Quick and dirty function to return the contents of this cell as a string. * For more complex manipulation of the contents, it is necessary to cast * this interface to correct subinterface * * @return the contents of this cell as a string */ public String getContents() { return formulaString; } /** * Gets the raw bytes for the formula. This will include the * parsed tokens array * * @return the raw record data */ public byte[] getFormulaData() { byte[] data = new byte[formulaBytes.length + 16]; System.arraycopy(formulaBytes, 0, data, 16, formulaBytes.length); data[6] = (byte) 0x10; data[7] = (byte) 0x40; data[12] = (byte) 0xe0; data[13] = (byte) 0xfc; // Set the recalculate on load bit data[8] |= 0x02; // Set the length of the rpn array IntegerHelper.getTwoBytes(formulaBytes.length, data, 14); return data; } /** * A dummy implementation to keep the compiler quiet. This object needs * to be instantiated from ReadFormulaRecord * * @param col the column which the new cell will occupy * @param row the row which the new cell will occupy * @return NOTHING */ public WritableCell copyTo(int col, int row) { Assert.verify(false); return null; } /** * Called when a column is inserted on the specified sheet. Notifies all * RCIR cells of this change. The default implementation here does nothing * * @param s the sheet on which the column was inserted * @param sheetIndex the sheet index on which the column was inserted * @param col the column number which was inserted */ void columnInserted(Sheet s, int sheetIndex, int col) { parser.columnInserted(sheetIndex, col, s == getSheet()); formulaBytes = parser.getBytes(); } /** * Called when a column is removed on the specified sheet. Notifies all * RCIR cells of this change. The default implementation here does nothing * * @param s the sheet on which the column was inserted * @param sheetIndex the sheet index on which the column was inserted * @param col the column number which was inserted */ void columnRemoved(Sheet s, int sheetIndex, int col) { parser.columnRemoved(sheetIndex, col, s == getSheet()); formulaBytes = parser.getBytes(); } /** * Called when a row is inserted on the specified sheet. Notifies all * RCIR cells of this change. The default implementation here does nothing * * @param s the sheet on which the column was inserted * @param sheetIndex the sheet index on which the column was inserted * @param row the column number which was inserted */ void rowInserted(Sheet s, int sheetIndex, int row) { parser.rowInserted(sheetIndex, row, s == getSheet()); formulaBytes = parser.getBytes(); } /** * Called when a row is inserted on the specified sheet. Notifies all * RCIR cells of this change. The default implementation here does nothing * * @param s the sheet on which the row was removed * @param sheetIndex the sheet index on which the column was removed * @param row the column number which was removed */ void rowRemoved(Sheet s, int sheetIndex, int row) { parser.rowRemoved(sheetIndex, row, s == getSheet()); formulaBytes = parser.getBytes(); } } jexcelapi/src/jxl/write/biff/SaveRecalcRecord.java0000750000175000017500000000317611207000610022344 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Stores the recalculate before save flag as set in the options dialog box */ class SaveRecalcRecord extends WritableRecordData { /** * The binary data for output to file */ private byte[] data; /** * The recalculate before save flag */ private boolean recalc; /** * Constructor * * @param r recalculate flag */ public SaveRecalcRecord(boolean r) { super(Type.SAVERECALC); recalc = r; data = new byte[2]; if (recalc) { data[0] = 1; } } /** * Gets the binary data for output to file * * @return the binary data */ public byte[] getData() { return data; } } jexcelapi/src/jxl/write/biff/WindowProtectRecord.java0000750000175000017500000000323011207000610023133 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.IntegerHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Stores an option from the Protect Workbook dialog box */ class WindowProtectRecord extends WritableRecordData { /** * Protect flag */ private boolean protection; /** * The binary data */ private byte[] data; /** * Constructor * * @param prot the protect flag */ public WindowProtectRecord(boolean prot) { super(Type.WINDOWPROTECT); protection = prot; data = new byte[2]; if (protection) { IntegerHelper.getTwoBytes(1, data, 0); } } /** * Gets the binary data for output to file * * @return the binary data */ public byte[] getData() { return data; } } jexcelapi/src/jxl/write/biff/FileDataOutput.java0000750000175000017500000000644611207000610022072 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2007 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import java.io.OutputStream; import java.io.IOException; import java.io.File; import java.io.RandomAccessFile; import jxl.common.Logger; /** * Used to generate the excel biff data using a temporary file. This * class wraps a RandomAccessFile */ class FileDataOutput implements ExcelDataOutput { // The logger private static Logger logger = Logger.getLogger(FileDataOutput.class); /** * The temporary file */ private File temporaryFile; /** * The excel data */ private RandomAccessFile data; /** * Constructor * * @param tmpdir the temporary directory used to write files. If this is * NULL then the sytem temporary directory will be used */ public FileDataOutput(File tmpdir) throws IOException { temporaryFile = File.createTempFile("jxl",".tmp", tmpdir); temporaryFile.deleteOnExit(); data = new RandomAccessFile(temporaryFile, "rw"); } /** * Writes the bytes to the end of the array, growing the array * as needs dictate * * @param d the data to write to the end of the array */ public void write(byte[] bytes) throws IOException { data.write(bytes); } /** * Gets the current position within the file * * @return the position within the file */ public int getPosition() throws IOException { // As all excel data structures are four bytes anyway, it's ok to // truncate the long to an int return (int) data.getFilePointer(); } /** * Sets the data at the specified position to the contents of the array * * @param pos the position to alter * @param newdata the data to modify */ public void setData(byte[] newdata, int pos) throws IOException { long curpos = data.getFilePointer(); data.seek(pos); data.write(newdata); data.seek(curpos); } /** * Writes the data to the output stream */ public void writeData(OutputStream out) throws IOException { byte[] buffer = new byte[1024]; int length = 0; data.seek(0); while ((length = data.read(buffer)) != -1) { out.write(buffer, 0, length); } } /** * Called when the final compound file has been written */ public void close() throws IOException { data.close(); // Explicitly delete the temporary file, since sometimes it is the case // that a single process may be generating multiple different excel files temporaryFile.delete(); } } jexcelapi/src/jxl/write/biff/#!ediff-merge!7!!#3588tQu#0000750000175000017500000002720011207000610022107 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.BuiltInName; import jxl.biff.IntegerHelper; import jxl.biff.StringHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * A name record. Simply takes the binary data from the name * record read in */ class NameRecord extends WritableRecordData { /** * The binary data for output to file */ private byte[] data; /** * The name */ private String name; /** * The built in name */ private BuiltInName builtInName; /** * The index into the name table */ private int index; /** * The 0-based index sheet reference for a record name * 0 is for a global reference */ private int sheetRef = 0; /** * A nested class to hold range information */ class NameRange { private int columnFirst; private int rowFirst; private int columnLast; private int rowLast; private int externalSheet; NameRange(jxl.read.biff.NameRecord.NameRange nr) { columnFirst = nr.getFirstColumn(); rowFirst = nr.getFirstRow(); columnLast = nr.getLastColumn(); rowLast = nr.getLastRow(); externalSheet = nr.getExternalSheet(); } /** * Create a new range for the name record. */ NameRange(int extSheet, int theStartRow, int theEndRow, int theStartCol, int theEndCol) { columnFirst = theStartCol; rowFirst = theStartRow; columnLast = theEndCol; rowLast = theEndRow; externalSheet = extSheet; } int getFirstColumn() {return columnFirst;} int getFirstRow() {return rowFirst;} int getLastColumn() {return columnLast;} int getLastRow() {return rowLast;} int getExternalSheet() { return externalSheet;} byte[] getData() { byte[] d = new byte[10]; // Sheet index IntegerHelper.getTwoBytes(externalSheet, d, 0); // Starting row IntegerHelper.getTwoBytes(rowFirst, d, 2); // End row IntegerHelper.getTwoBytes(rowLast, d, 4); // Start column IntegerHelper.getTwoBytes(columnFirst & 0xff, d, 6); // End columns IntegerHelper.getTwoBytes(columnLast & 0xff, d, 8); return d; } } /** * The ranges covered by this name */ private NameRange[] ranges; // Constants which refer to the parse tokens after the string private static final int cellReference = 0x3a; private static final int areaReference = 0x3b; private static final int subExpression = 0x29; private static final int union = 0x10; /** * Constructor - used when copying sheets * * @param index the index into the name table */ public NameRecord(jxl.read.biff.NameRecord sr, int ind) { super(Type.NAME); data = sr.getData(); name = sr.getName(); sheetRef = sr.getSheetRef(); index = ind; // Copy the ranges jxl.read.biff.NameRecord.NameRange[] r = sr.getRanges(); ranges = new NameRange[r.length]; for (int i = 0 ; i < ranges.length ; i++) { ranges[i] = new NameRange(r[i]); } } /** * Create a new name record with the given information. * * @param theName Name to be created. * @param theIndex Index of this name. * @param extSheet External sheet index this name refers to. * @param theStartRow First row this name refers to. * @param theEndRow Last row this name refers to. * @param theStartCol First column this name refers to. * @param theEndCol Last column this name refers to. * @param global TRUE if this is a global name */ NameRecord(String theName, int theIndex, int extSheet, int theStartRow, int theEndRow, int theStartCol, int theEndCol, boolean global) { super(Type.NAME); name = theName; index = theIndex; sheetRef = global ? 0 : index+1; // 0 indicates a global name, otherwise // the 1-based index of the sheet ranges = new NameRange[1]; ranges[0] = new NameRange(extSheet, theStartRow, theEndRow, theStartCol, theEndCol); } /** * Create a new name record with the given information. * * @param theName Name to be created. * @param theIndex Index of this name. * @param extSheet External sheet index this name refers to. * @param theStartRow First row this name refers to. * @param theEndRow Last row this name refers to. * @param theStartCol First column this name refers to. * @param theEndCol Last column this name refers to. * @param global TRUE if this is a global name */ NameRecord(BuiltInName theName, int theIndex, int extSheet, int theStartRow, int theEndRow, int theStartCol, int theEndCol, boolean global) { super(Type.NAME); builtInName = theName; index = theIndex; sheetRef = global ? 0 : index + 1; // 0 indicates a global name, otherwise // the 1-based index of the sheet ranges = new NameRange[1]; ranges[0] = new NameRange(extSheet, theStartRow, theEndRow, theStartCol, theEndCol); } /** * Create a new name record with the given information for 2-range entities. * * @param theName Name to be created. * @param theIndex Index of this name. * @param extSheet External sheet index this name refers to. * @param theStartRow First row this name refers to. * @param theEndRow Last row this name refers to. * @param theStartCol First column this name refers to. * @param theEndCol Last column this name refers to. * @param theStartRow2 First row this name refers to (2nd instance). * @param theEndRow2 Last row this name refers to (2nd instance). * @param theStartCol2 First column this name refers to (2nd instance). * @param theEndCol2 Last column this name refers to (2nd instance). * @param global TRUE if this is a global name */ NameRecord(BuiltInName theName, int theIndex, int extSheet, int theStartRow, int theEndRow, int theStartCol, int theEndCol, int theStartRow2, int theEndRow2, int theStartCol2, int theEndCol2, boolean global) { super(Type.NAME); builtInName = theName; index = theIndex; sheetRef = global ? 0 : index + 1; // 0 indicates a global name, otherwise // the 1-based index of the sheet ranges = new NameRange[2]; ranges[0] = new NameRange(extSheet, theStartRow, theEndRow, theStartCol, theEndCol); ranges[1] = new NameRange(extSheet, theStartRow2, theEndRow2, theStartCol2, theEndCol2); } /** * Gets the binary data for output to file * * @return the binary data */ public byte[] getData() { if (data != null) { // this is a copy return data; } final int NAME_HEADER_LENGTH = 15; final byte AREA_RANGE_LENGTH = 11; final byte AREA_REFERENCE = 0x3b; int detailLength; if (ranges.length > 1) { detailLength = (ranges.length * AREA_RANGE_LENGTH) + 4; } else { detailLength = AREA_RANGE_LENGTH; } int length = NAME_HEADER_LENGTH + detailLength; length += builtInName != null ? 1 : name.length(); data = new byte[length]; <<<<<<< variant A <<<<<<< variant A >>>>>>> variant B ======= end <<<<<<< variant A >>>>>>> variant B ======= end >>>>>>> variant B ======= end // Options int options = 0; if (builtInName != null) { options |= 0x20; } IntegerHelper.getTwoBytes(options, data, 0); // Keyboard shortcut data[2] = 0; // Length of the name in chars if (builtInName != null) { data[3] = (byte) 0x1; } else { data[3] = (byte) name.length(); } // Size of the definitions IntegerHelper.getTwoBytes(detailLength, data, 4); // Sheet index IntegerHelper.getTwoBytes(sheetRef, data, 6); IntegerHelper.getTwoBytes(sheetRef, data, 8); // Byte 10-13 are optional lengths [0,0,0,0] // Byte 14 is length of name which is not used. // The name if (builtInName != null) { data[15] = (byte) builtInName.getValue(); } else { StringHelper.getBytes(name, data, 15); } // The actual range definition. int pos = builtInName != null ? 16 : name.length() + 15; // If there are multiple ranges for the name, we must specify a subExpression type // rather than areaReference and then put out multiple areaReference entries with an end byte. if (ranges.length > 1) { data[pos++] = subExpression; // Length of remaining bytes excluding itself IntegerHelper.getTwoBytes(detailLength - 3, data, pos); pos += 2; byte[] rd; for (int i = 0 ; i < ranges.length ; i++) { data[pos++] = areaReference; rd = ranges[i].getData(); System.arraycopy(rd, 0, data, pos, rd.length); pos += rd.length; } data[pos] = 0x10; } else { // Range format - area data[pos] = areaReference; // The range data byte[] rd = ranges[0].getData(); System.arraycopy(rd, 0, data, pos+1, rd.length); } return data; } /** * Accessor for the name * * @return the name */ public String getName() { return name; } /** * Accessor for the index of this name in the name table * * @return the index of this name in the name table */ public int getIndex() { return index; } /** * The 0-based index sheet reference for a record name * 0 is for a global reference * * @return the sheet reference for name formula */ public int getSheetRef() { return sheetRef; } /** * Set the index sheet reference for a record name * 0 is for a global reference * */ public void setSheetRef(int i) { sheetRef = i; IntegerHelper.getTwoBytes(sheetRef, data, 8); } /** * Gets the array of ranges for this name * @return the ranges */ public NameRange[] getRanges() { return ranges; } } jexcelapi/src/jxl/write/biff/WritableFormattingRecords.java0000750000175000017500000001544311207000610024323 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.common.Assert; import jxl.biff.Fonts; import jxl.biff.FormattingRecords; import jxl.biff.NumFormatRecordsException; import jxl.write.NumberFormats; import jxl.write.WritableCellFormat; /** * Handles the Format and XF record indexing. The writable subclass * instantiates the predetermined list of XF records and formats * present in every Excel Workbook */ public class WritableFormattingRecords extends FormattingRecords { /** * The statically defined normal style */ public static WritableCellFormat normalStyle; /** * Constructor. Instantiates the prerequisite list of formats and * styles required by all Excel workbooks * * @param f the list of Fonts * @param styles the list of style clones */ public WritableFormattingRecords(Fonts f, Styles styles) { super(f); try { // Hard code all the styles StyleXFRecord sxf = new StyleXFRecord (styles.getArial10Pt(),NumberFormats.DEFAULT); sxf.setLocked(true); addStyle(sxf); sxf = new StyleXFRecord(getFonts().getFont(1),NumberFormats.DEFAULT); sxf.setLocked(true); sxf.setCellOptions(0xf400); addStyle(sxf); sxf = new StyleXFRecord(getFonts().getFont(1),NumberFormats.DEFAULT); sxf.setLocked(true); sxf.setCellOptions(0xf400); addStyle(sxf); sxf = new StyleXFRecord(getFonts().getFont(1),NumberFormats.DEFAULT); sxf.setLocked(true); sxf.setCellOptions(0xf400); addStyle(sxf); sxf = new StyleXFRecord(getFonts().getFont(2),NumberFormats.DEFAULT); sxf.setLocked(true); sxf.setCellOptions(0xf400); addStyle(sxf); sxf = new StyleXFRecord(getFonts().getFont(3),NumberFormats.DEFAULT); sxf.setLocked(true); sxf.setCellOptions(0xf400); addStyle(sxf); sxf = new StyleXFRecord(styles.getArial10Pt(), NumberFormats.DEFAULT); sxf.setLocked(true); sxf.setCellOptions(0xf400); addStyle(sxf); sxf = new StyleXFRecord(styles.getArial10Pt(), NumberFormats.DEFAULT); sxf.setLocked(true); sxf.setCellOptions(0xf400); addStyle(sxf); sxf = new StyleXFRecord(styles.getArial10Pt(), NumberFormats.DEFAULT); sxf.setLocked(true); sxf.setCellOptions(0xf400); addStyle(sxf); sxf = new StyleXFRecord(styles.getArial10Pt(), NumberFormats.DEFAULT); sxf.setLocked(true); sxf.setCellOptions(0xf400); addStyle(sxf); sxf = new StyleXFRecord(styles.getArial10Pt(), NumberFormats.DEFAULT); sxf.setLocked(true); sxf.setCellOptions(0xf400); addStyle(sxf); sxf = new StyleXFRecord(styles.getArial10Pt(), NumberFormats.DEFAULT); sxf.setLocked(true); sxf.setCellOptions(0xf400); addStyle(sxf); sxf = new StyleXFRecord(styles.getArial10Pt(), NumberFormats.DEFAULT); sxf.setLocked(true); sxf.setCellOptions(0xf400); addStyle(sxf); sxf = new StyleXFRecord(styles.getArial10Pt(), NumberFormats.DEFAULT); sxf.setLocked(true); sxf.setCellOptions(0xf400); addStyle(sxf); sxf = new StyleXFRecord(styles.getArial10Pt(), NumberFormats.DEFAULT); sxf.setLocked(true); sxf.setCellOptions(0xf400); addStyle(sxf); // That's the end of the built ins. Write the normal style // cell XF here addStyle(styles.getNormalStyle()); // Continue with "user defined" styles sxf = new StyleXFRecord(getFonts().getFont(1), NumberFormats.FORMAT7); sxf.setLocked(true); sxf.setCellOptions(0xf800); addStyle(sxf); sxf = new StyleXFRecord(getFonts().getFont(1), NumberFormats.FORMAT5); sxf.setLocked(true); sxf.setCellOptions(0xf800); addStyle(sxf); sxf = new StyleXFRecord(getFonts().getFont(1), NumberFormats.FORMAT8); sxf.setLocked(true); sxf.setCellOptions(0xf800); addStyle(sxf); sxf = new StyleXFRecord(getFonts().getFont(1), NumberFormats.FORMAT6); sxf.setLocked(true); sxf.setCellOptions(0xf800); addStyle(sxf); sxf = new StyleXFRecord(getFonts().getFont(1), NumberFormats.PERCENT_INTEGER); sxf.setLocked(true); sxf.setCellOptions(0xf800); addStyle(sxf); // Hard code in the pre-defined number formats for now /* FormatRecord fr = new FormatRecord ("\"$\"#,##0_);\\(\"$\"#,##0\\)",5); addFormat(fr); fr = new FormatRecord ("\"$\"#,##0_);[Red]\\(\"$\"#,##0\\)", 6); addFormat(fr); fr = new FormatRecord ("\"$\"#,##0.00_);\\(\"$\"#,##0.00\\)", 7); addFormat(fr); fr = new FormatRecord ("\"$\"#,##0.00_);[Red]\\(\"$\"#,##0.00\\)", 8); addFormat(fr); fr = new FormatRecord ("_(\"$\"* #,##0_);_(\"$\"* \\(#,##0\\);_(\"$\"* \"-\"_);_(@_)", 0x2a); // outputFile.write(fr); fr = new FormatRecord ("_(* #,##0_);_(* \\(#,##0\\);_(* \"-\"_);_(@_)", 0x2e); // outputFile.write(fr); fr = new FormatRecord ("_(\"$\"* #,##0.00_);_(\"$\"* \\(#,##0.00\\);_(\"$\"* \"-\"??_);_(@_)", 0x2c); // outputFile.write(fr); fr = new FormatRecord ("_(* #,##0.00_);_(* \\(#,##0.00\\);_(* \"-\"??_);_(@_)", 0x2b); // outputFile.write(fr); */ } catch (NumFormatRecordsException e) { // This should not happen yet, since we are just creating the file. // Bomb out Assert.verify(false, e.getMessage()); } } } jexcelapi/src/jxl/write/biff/VerticalCentreRecord.java0000750000175000017500000000321011207000610023233 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Indicates whether the centre vertically on page option has been * set from the options dialog box */ class VerticalCentreRecord extends WritableRecordData { /** * The binary data for output to file */ private byte[] data; /** * The centre flag */ private boolean centre; /** * Constructor * * @param ce the centre flag */ public VerticalCentreRecord(boolean ce) { super(Type.VCENTER); centre = ce; data = new byte[2]; if (centre) { data[0] = 1; } } /** * Gets the data for output to file * * @return the binary data */ public byte[] getData() { return data; } } jexcelapi/src/jxl/write/biff/#TemplateRecord.java#0000750000175000017500000000272211207000610022211 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2009 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Record which indicates whether or not this file is a template (Usually saved with .xlt file name extension) * should be refreshed when the workbook is loaded */ class TemplateRecord extends WritableRecordData { /** * Constructor * * @param template flag */ public TemplateRecord() { super(Type.TEMPLATE); } /** * Gets the binary data for output to file * * @return the binary data */ public byte[] getData() { return new byte[0]; } } jexcelapi/src/jxl/write/biff/IndexRecord.java0000750000175000017500000000527211207000610021402 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.Type; import jxl.biff.IntegerHelper; import jxl.biff.WritableRecordData; /** * Index into the cell rows in an worksheet */ class IndexRecord extends WritableRecordData { /** * The binary data */ private byte[] data; /** * The numbe of rows served by this index record */ private int rows; /** * The position of the BOF record in the excel output stream */ private int bofPosition; /** * The number of blocks needed to hold all the rows */ private int blocks; /** * The position of the current 'pointer' within the byte array */ private int dataPos; /** * Constructor * * @param pos the position of the BOF record * @param bl the number of blocks * @param r the number of rows */ public IndexRecord(int pos, int r, int bl) { super(Type.INDEX); bofPosition = pos; rows = r; blocks = bl; // Allocate the amount of bytes required to hold all the blocks data = new byte[16 + 4 * blocks]; dataPos = 16; } /** * Gets the binary data for output. This writes out an empty data block, and * the information is filled in later on when the information becomes * available * * @return the binary data */ protected byte[] getData() { IntegerHelper.getFourBytes(rows, data, 8); return data; } /** * Adds another index record into the array * * @param pos the position in the output file */ void addBlockPosition(int pos) { IntegerHelper.getFourBytes(pos - bofPosition, data, dataPos); dataPos += 4; } /** * Sets the position of the data start. This happens to be the position * of the DEFCOLWIDTH record */ void setDataStartPosition(int pos) { IntegerHelper.getFourBytes(pos - bofPosition, data, 12); } } jexcelapi/src/jxl/write/biff/MarginRecord.java0000750000175000017500000000276411207000610021553 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.DoubleHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Record which specifies a margin value */ abstract class MarginRecord extends WritableRecordData { /** * The margin */ private double margin; /** * Constructor */ public MarginRecord(Type t, double v) { super(t); margin = v; } /** * Gets the binary data for output to file * * @return the binary data */ public byte[] getData() { byte[] data = new byte[8]; DoubleHelper.getIEEEBytes(margin, data, 0); return data; } } jexcelapi/src/jxl/write/biff/ExcelDataOutput.java0000750000175000017500000000362011207000610022242 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2007 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import java.io.OutputStream; import java.io.IOException; /** * Interface to abstract away an in-memory output or a temporary file * output. Used by the File object */ interface ExcelDataOutput { /** * Appends the bytes to the end of the output * * @param d the data to write to the end of the array */ public void write(byte[] bytes) throws IOException; /** * Gets the current position within the file * * @return the position within the file */ public int getPosition() throws IOException; /** * Sets the data at the specified position to the contents of the array * * @param pos the position to alter * @param newdata the data to modify */ public void setData(byte[] newdata, int pos) throws IOException; /** * Writes the data to the output stream */ public void writeData(OutputStream out) throws IOException; /** * Called when the final compound file has been written */ public void close() throws IOException; } jexcelapi/src/jxl/write/biff/DefaultColumnWidth.java0000750000175000017500000000315011207000610022727 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.IntegerHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * The default column width for a workbook */ class DefaultColumnWidth extends WritableRecordData { /** * The default column width */ private int width; /** * The binary data */ private byte[] data; /** * Constructor * * @param w the default column width */ public DefaultColumnWidth(int w) { super(Type.DEFCOLWIDTH); width = w; data = new byte[2]; IntegerHelper.getTwoBytes(width, data, 0); } /** * Gets the binary data for writing to the stream * * @return the binary data */ protected byte[] getData() { return data; } } jexcelapi/src/jxl/write/biff/HideobjRecord.java0000750000175000017500000000340011207000610021666 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.IntegerHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Stores options selected in the Options dialog box * * =2 if the Hide All option is turned on * =1 if the Show Placeholders option is turned on * =0 if the Show All option is turned on */ class HideobjRecord extends WritableRecordData { /** * Hide object mode */ private int hidemode; /** * The binary data */ private byte[] data; /** * Constructor * * @param newHideMode the hide all flag */ public HideobjRecord(int newHideMode) { super(Type.HIDEOBJ); hidemode = newHideMode; data = new byte[2]; IntegerHelper.getTwoBytes(hidemode, data, 0); } /** * Gets the binary data for output to file * * @return the binary data */ public byte[] getData() { return data; } } jexcelapi/src/jxl/write/biff/ReadErrorFormulaRecord.java0000750000175000017500000000717711207000610023554 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2004 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.common.Logger; import jxl.ErrorFormulaCell; import jxl.biff.FormulaData; import jxl.biff.IntegerHelper; import jxl.biff.formula.FormulaErrorCode; import jxl.biff.formula.FormulaException; import jxl.biff.formula.FormulaParser; /** * Class for read number formula records */ class ReadErrorFormulaRecord extends ReadFormulaRecord implements ErrorFormulaCell { // The logger private static Logger logger = Logger.getLogger(ReadErrorFormulaRecord.class); /** * Constructor * * @param f */ public ReadErrorFormulaRecord(FormulaData f) { super(f); } /** * Gets the error code for this cell. * * @return the cell contents */ public int getErrorCode() { return ( (ErrorFormulaCell) getReadFormula()).getErrorCode(); } /** * Error formula specific exception handling. Can't really create * a formula (as it will look for a cell of that name, so just * create a STRING record containing the contents * * @return the bodged data */ protected byte[] handleFormulaException() { byte[] expressiondata = null; byte[] celldata = super.getCellData(); int errorCode = getErrorCode(); String formulaString = null; if (errorCode == FormulaErrorCode.DIV0.getCode()) { formulaString = "1/0"; } else if (errorCode == FormulaErrorCode.VALUE.getCode()) { formulaString = "\"\"/0"; } else if (errorCode == FormulaErrorCode.REF.getCode()) { formulaString = "\"#REF!\""; } else { formulaString = "\"ERROR\""; } // Generate an appropriate dummy formula WritableWorkbookImpl w = getSheet().getWorkbook(); FormulaParser parser = new FormulaParser(formulaString, w, w, w.getSettings()); // Get the bytes for the dummy formula try { parser.parse(); } catch(FormulaException e2) { logger.warn(e2.getMessage()); } byte[] formulaBytes = parser.getBytes(); expressiondata = new byte[formulaBytes.length + 16]; IntegerHelper.getTwoBytes(formulaBytes.length, expressiondata, 14); System.arraycopy(formulaBytes, 0, expressiondata, 16, formulaBytes.length); // Set the recalculate on load bit expressiondata[8] |= 0x02; byte[] data = new byte[celldata.length + expressiondata.length]; System.arraycopy(celldata, 0, data, 0, celldata.length); System.arraycopy(expressiondata, 0, data, celldata.length, expressiondata.length); // Set the type bits to indicate an error data[6] = 2; data[12] = -1; data[13] = -1; // Set the error code data[8] = (byte) errorCode; return data; } } jexcelapi/src/jxl/write/biff/NineteenFourRecord.java0000750000175000017500000000344011207000610022727 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.IntegerHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * A record which indicates whether or the 1904 date system is * in use */ class NineteenFourRecord extends WritableRecordData { /** * Flag which indicates whether the 1904 date system is being used */ private boolean nineteenFourDate; /** * The binary data for output to file */ private byte[] data; /** * Constructor * * @param oldDate flag indicating whether the 1904 date system is in use */ public NineteenFourRecord(boolean oldDate) { super(Type.NINETEENFOUR); nineteenFourDate = oldDate; data = new byte[2]; if (nineteenFourDate) { IntegerHelper.getTwoBytes(1, data, 0); } } /** * The binary data for output to file * @return the binary data */ public byte[] getData() { return data; } } jexcelapi/src/jxl/write/biff/SharedStrings.java0000750000175000017500000001201011207000610021740 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; /** * The list of available shared strings. This class contains * the labels used for the entire spreadsheet */ class SharedStrings { /** * All the strings in the spreadsheet, keyed on the string itself */ private HashMap strings; /** * Contains the same strings, held in a list */ private ArrayList stringList; /** * The total occurrence of strings in the workbook */ private int totalOccurrences; /** * Constructor */ public SharedStrings() { strings = new HashMap(100); stringList = new ArrayList(100); totalOccurrences = 0; } /** * Gets the index for the string passed in. If the string is already * present, then returns the index of that string, otherwise * creates a new key-index mapping * * @param s the string whose index we want * @return the index of the string */ public int getIndex(String s) { Integer i = (Integer) strings.get(s); if (i == null) { i = new Integer(strings.size()); strings.put(s, i); stringList.add(s); } totalOccurrences++; return i.intValue(); } /** * Gets the string at the specified index * * @param i the index of the string * @return the string at the specified index */ public String get(int i) { return (String) stringList.get(i); } /** * Writes out the shared string table * * @param outputFile the binary output file * @exception IOException */ public void write(File outputFile) throws IOException { // Thanks to Guenther for contributing the ExtSST implementation portion // of this method int charsLeft = 0; String curString = null; SSTRecord sst = new SSTRecord(totalOccurrences, stringList.size()); ExtendedSSTRecord extsst = new ExtendedSSTRecord(stringList.size()); int bucketSize = extsst.getNumberOfStringsPerBucket(); Iterator i = stringList.iterator(); int stringIndex = 0; while (i.hasNext() && charsLeft == 0) { curString = (String) i.next(); // offset + header bytes int relativePosition = sst.getOffset() + 4; charsLeft = sst.add(curString); if ((stringIndex % bucketSize) == 0) { extsst.addString(outputFile.getPos(), relativePosition); } stringIndex++; } outputFile.write(sst); if (charsLeft != 0 || i.hasNext()) { // Add the remainder of the string to the continue record SSTContinueRecord cont = createContinueRecord(curString, charsLeft, outputFile); // Carry on looping through the array until all the strings are done while (i.hasNext()) { curString = (String) i.next(); int relativePosition = cont.getOffset() + 4; charsLeft = cont.add(curString); if ((stringIndex % bucketSize) == 0) { extsst.addString(outputFile.getPos(), relativePosition); } stringIndex++; if (charsLeft != 0) { outputFile.write(cont); cont = createContinueRecord(curString, charsLeft, outputFile); } } outputFile.write(cont); } outputFile.write(extsst); } /** * Creates and returns a continue record using the left over bits and * pieces */ private SSTContinueRecord createContinueRecord (String curString, int charsLeft, File outputFile) throws IOException { // Set up the remainder of the string in the continue record SSTContinueRecord cont = null; while (charsLeft != 0) { cont = new SSTContinueRecord(); if (charsLeft == curString.length() || curString.length() == 0) { charsLeft = cont.setFirstString(curString, true); } else { charsLeft = cont.setFirstString (curString.substring(curString.length() - charsLeft), false); } if (charsLeft != 0) { outputFile.write(cont); cont = new SSTContinueRecord(); } } return cont; } } jexcelapi/src/jxl/write/biff/MergedCellsRecord.java0000750000175000017500000000450511207000610022517 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import java.util.ArrayList; import jxl.Cell; import jxl.Range; import jxl.biff.IntegerHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * A number record. This is stored as 8 bytes, as opposed to the * 4 byte RK record */ public class MergedCellsRecord extends WritableRecordData { /** * The ranges of all the cells which are merged on this sheet */ private ArrayList ranges; /** * Constructs a merged cell record * * @param ws the sheet containing the merged cells */ protected MergedCellsRecord(ArrayList mc) { super(Type.MERGEDCELLS); ranges = mc; } /** * Gets the raw data for output to file * * @return the data to write to file */ public byte[] getData() { byte[] data = new byte[ranges.size() * 8 + 2]; // Set the number of ranges IntegerHelper.getTwoBytes(ranges.size(), data, 0); int pos = 2; Range range = null; for (int i = 0; i < ranges.size() ; i++) { range = (Range) ranges.get(i); // Set the various cell records Cell tl = range.getTopLeft(); Cell br = range.getBottomRight(); IntegerHelper.getTwoBytes(tl.getRow(), data, pos); IntegerHelper.getTwoBytes(br.getRow(), data, pos+2); IntegerHelper.getTwoBytes(tl.getColumn(), data, pos+4); IntegerHelper.getTwoBytes(br.getColumn(), data, pos+6); pos += 8; } return data; } } jexcelapi/src/jxl/write/biff/VerticalPageBreaksRecord.java0000750000175000017500000000363711207000610024034 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.IntegerHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Contains the list of explicit horizontal page breaks on the current sheet */ class VerticalPageBreaksRecord extends WritableRecordData { /** * The row breaks */ private int[] columnBreaks; /** * Constructor * * @param break the row breaks */ public VerticalPageBreaksRecord(int[] breaks) { super(Type.VERTICALPAGEBREAKS); columnBreaks = breaks; } /** * Gets the binary data to write to the output file * * @return the binary data */ public byte[] getData() { byte[] data = new byte[columnBreaks.length * 6 + 2]; // The number of breaks on the list IntegerHelper.getTwoBytes(columnBreaks.length, data, 0); int pos = 2; for (int i = 0; i < columnBreaks.length; i++) { IntegerHelper.getTwoBytes(columnBreaks[i], data, pos); IntegerHelper.getTwoBytes(0xff, data, pos+4); pos += 6; } return data; } } jexcelapi/src/jxl/write/biff/CodepageRecord.java0000750000175000017500000000301411207000610022032 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Stores the default character set in operation when the workbook was * saved */ class CodepageRecord extends WritableRecordData { /** * The binary data */ private byte[] data; /** * Constructor */ public CodepageRecord() { super(Type.CODEPAGE); // Hard code inthe ANSI character set for Microsoft data = new byte[] {(byte) 0xe4, (byte) 0x4}; } /** * Retrieves the data for output to binary file * * @return the data to be written */ public byte[] getData() { return data; } } jexcelapi/src/jxl/write/biff/DefaultRowHeightRecord.java0000750000175000017500000000364311207000610023540 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.IntegerHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * The default row height for cells in the workbook */ class DefaultRowHeightRecord extends WritableRecordData { /** * The binary data */ private byte[] data; /** * The default row height */ private int rowHeight; /** * Indicates whether or not the default row height has been changed */ private boolean changed; /** * Constructor * * @param height the default row height * @param ch TRUE if the default value has been changed, false * otherwise */ public DefaultRowHeightRecord(int h, boolean ch) { super(Type.DEFAULTROWHEIGHT); data = new byte[4]; rowHeight = h; changed = ch; } /** * Gets the binary data for writing to the output stream * * @return the binary data */ public byte[] getData() { if (changed) { data[0] |= 0x1; } IntegerHelper.getTwoBytes(rowHeight, data, 2); return data; } } jexcelapi/src/jxl/write/biff/CopyAdditionalPropertySetsException.java0000750000175000017500000000232411207000610026355 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; /** * Exception thrown when attempting to copy a workbook which contains * additional property sets */ public class CopyAdditionalPropertySetsException extends JxlWriteException { /** * Constructor */ public CopyAdditionalPropertySetsException() { super(copyPropertySets); } } jexcelapi/src/jxl/write/biff/ProtectRecord.java0000750000175000017500000000321211207000610021743 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.IntegerHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * The protection state for a sheet or workbook */ class ProtectRecord extends WritableRecordData { /** * The protection state */ private boolean protection; /** * The binary data */ private byte[] data; /** * Constructor * * @param prot the protection state */ public ProtectRecord(boolean prot) { super(Type.PROTECT); protection = prot; data = new byte[2]; if (protection) { IntegerHelper.getTwoBytes(1, data, 0); } } /** * Gets the binary data for output to file * * @return the binary data */ public byte[] getData() { return data; } } jexcelapi/src/jxl/write/biff/GuttersRecord.java0000750000175000017500000000533511207000610021770 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.IntegerHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Record which contains the size of the row and column gutters. These are * all set to zero by default */ class GuttersRecord extends WritableRecordData { /** * The binary data */ private byte[] data; /** * The rowGutter */ private int rowGutter; /** * The column gutter */ private int colGutter; /** * The maximum outline level for the row gutter */ private int maxRowOutline; /** * The maximum row outline level for the column gutter */ private int maxColumnOutline; /** * Constructor */ public GuttersRecord() { super(Type.GUTS); } /** * Gets the binary data for output * * @return the binary data */ public byte[] getData() { data = new byte[8]; IntegerHelper.getTwoBytes(rowGutter, data, 0); IntegerHelper.getTwoBytes(colGutter, data, 2); IntegerHelper.getTwoBytes(maxRowOutline, data, 4); IntegerHelper.getTwoBytes(maxColumnOutline, data, 6); return data; } /** * Accessor for the maximum row outline * * @return the maximum row outline */ public int getMaxRowOutline() { return maxRowOutline; } /** * Sets the maximum row outline * * @param value the maximum row outline */ public void setMaxRowOutline(int value) { maxRowOutline = value; rowGutter = 1 + 14 * value; } /** * Accessor for the maximum column outline * * @return the maximum column outline */ public int getMaxColumnOutline() { return maxColumnOutline; } /** * Sets the maximum column outline * * @param value the maximum row outline */ public void setMaxColumnOutline(int value) { maxColumnOutline = value; colGutter = 1 + 14 * value; } } jexcelapi/src/jxl/write/biff/WritableSheetImpl.java0000750000175000017500000022373111263327606022605 0ustar drazzibdrazzib/********************************************************************** * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import java.io.IOException; import java.util.ArrayList; import java.util.Comparator; import java.util.Iterator; import java.util.TreeSet; import java.util.regex.Pattern; import jxl.common.Assert; import jxl.common.Logger; import jxl.BooleanCell; import jxl.Cell; import jxl.CellFeatures; import jxl.CellReferenceHelper; import jxl.CellType; import jxl.CellView; import jxl.DateCell; import jxl.HeaderFooter; import jxl.Hyperlink; import jxl.Image; import jxl.LabelCell; import jxl.NumberCell; import jxl.Range; import jxl.Sheet; import jxl.SheetSettings; import jxl.WorkbookSettings; import jxl.biff.AutoFilter; import jxl.biff.BuiltInName; import jxl.biff.CellFinder; import jxl.biff.ConditionalFormat; import jxl.biff.DataValidation; import jxl.biff.DVParser; import jxl.biff.EmptyCell; import jxl.biff.FormattingRecords; import jxl.biff.FormulaData; import jxl.biff.IndexMapping; import jxl.biff.NumFormatRecordsException; import jxl.biff.SheetRangeImpl; import jxl.biff.WorkspaceInformationRecord; import jxl.biff.XFRecord; import jxl.biff.drawing.Chart; import jxl.biff.drawing.ComboBox; import jxl.biff.drawing.Drawing; import jxl.biff.drawing.DrawingGroupObject; import jxl.format.CellFormat; import jxl.format.Font; import jxl.format.PageOrientation; import jxl.format.PaperSize; import jxl.write.Blank; import jxl.write.Boolean; import jxl.write.DateTime; import jxl.write.Label; import jxl.write.Number; import jxl.write.WritableCell; import jxl.write.WritableCellFeatures; import jxl.write.WritableCellFormat; import jxl.write.WritableFont; import jxl.write.WritableHyperlink; import jxl.write.WritableImage; import jxl.write.WritableSheet; import jxl.write.WritableWorkbook; import jxl.write.WriteException; /** * A writable sheet. This class contains implementation of all the * writable sheet methods which may be invoke by the API */ class WritableSheetImpl implements WritableSheet { /** * The logger */ private static Logger logger = Logger.getLogger(WritableSheetImpl.class); /** * The name of this sheet */ private String name; /** * A handle to the output file which the binary data is written to */ private File outputFile; /** * The rows within this sheet */ private RowRecord[] rows; /** * A handle to workbook format records */ private FormattingRecords formatRecords; /** * A handle to the shared strings used by this workbook */ private SharedStrings sharedStrings; /** * The list of non-default column formats */ private TreeSet columnFormats; /** * The list of autosized columns */ private TreeSet autosizedColumns; /** * The list of hyperlinks */ private ArrayList hyperlinks; /** * The list of merged ranged */ private MergedCells mergedCells; /** * A number of rows. This is a count of the maximum row number + 1 */ private int numRows; /** * The number of columns. This is a count of the maximum column number + 1 */ private int numColumns; /** * The environment specific print record, copied from the read spreadsheet */ private PLSRecord plsRecord; /** * The buttons property set */ private ButtonPropertySetRecord buttonPropertySet; /** * A flag indicating that this sheet is a chart only */ private boolean chartOnly; /** * The data validations on this page. Used to store data validations * from a read sheet */ private DataValidation dataValidation; /** * Array of row page breaks */ private ArrayList rowBreaks; /** * Array of column page breaks */ private ArrayList columnBreaks; /** * The drawings on this sheet */ private ArrayList drawings; /** * The images on this sheet. This is a subset of the drawings list */ private ArrayList images; /** * The conditional formats on this sheet */ private ArrayList conditionalFormats; /** * The autofilter */ private AutoFilter autoFilter; /** * The writable cells on this sheet which may have validation added * to them */ private ArrayList validatedCells; /** * The combo box object used for list validations on this sheet */ private ComboBox comboBox; /** * Drawings modified flag. Set to true if the drawings list has * been modified */ private boolean drawingsModified; /** * The maximum row outline level */ private int maxRowOutlineLevel; /** * The maximum column outline level */ private int maxColumnOutlineLevel; /** * The settings for this sheet */ private SheetSettings settings; /** * The sheet writer engine */ private SheetWriter sheetWriter; /** * The settings for the workbook */ private WorkbookSettings workbookSettings; /** * The workbook */ private WritableWorkbookImpl workbook; /** * The amount by which to grow the rows array */ private final static int rowGrowSize = 10; /** * The maximum number of rows excel allows in a worksheet */ private final static int numRowsPerSheet = 65536; /** * The maximum number of characters permissible for a sheet name */ private final static int maxSheetNameLength = 31; /** * The illegal characters for a sheet name */ private final static char[] illegalSheetNameCharacters = new char[] {'*', ':', '?', '\\'}; /** * The supported file types */ private static final String[] imageTypes = new String[] {"png"}; /** * The comparator for column info record */ private static class ColumnInfoComparator implements Comparator { /** * Equals method * * @param o the object to compare * @return TRUE if equal, FALSE otherwise */ public boolean equals(Object o) { return o == this; } /** * Comparison function for to ColumnInfoRecords * * @param o2 first object to compare * @param o1 second object to compare * @return the result of the comparison */ public int compare(Object o1, Object o2) { if (o1 == o2) { return 0; } Assert.verify(o1 instanceof ColumnInfoRecord); Assert.verify(o2 instanceof ColumnInfoRecord); ColumnInfoRecord ci1 = (ColumnInfoRecord) o1; ColumnInfoRecord ci2 = (ColumnInfoRecord) o2; return ci1.getColumn() - ci2.getColumn(); } } /** * Constructor * * @param fr the formatting records used by the workbook * @param of the output file to write the binary data * @param f the fonts used by the workbook * @param n the name of this sheet * @param ss the shared strings used by the workbook * @param ws the workbook settings */ public WritableSheetImpl(String n, File of, FormattingRecords fr, SharedStrings ss, WorkbookSettings ws, WritableWorkbookImpl ww) { name = validateName(n); outputFile = of; rows = new RowRecord[0]; numRows = 0; numColumns = 0; chartOnly = false; workbook = ww; formatRecords = fr; sharedStrings = ss; workbookSettings = ws; drawingsModified = false; columnFormats = new TreeSet(new ColumnInfoComparator()); autosizedColumns = new TreeSet(); hyperlinks = new ArrayList(); mergedCells = new MergedCells(this); rowBreaks = new ArrayList(); columnBreaks = new ArrayList(); drawings = new ArrayList(); images = new ArrayList(); conditionalFormats = new ArrayList(); validatedCells = new ArrayList(); settings = new SheetSettings(this); sheetWriter = new SheetWriter(outputFile, this, workbookSettings); } /** * Returns the cell for the specified location eg. "A4", using the * CellReferenceHelper * * @param loc the cell reference * @return the cell at the specified co-ordinates */ public Cell getCell(String loc) { return getCell(CellReferenceHelper.getColumn(loc), CellReferenceHelper.getRow(loc)); } /** * Returns the cell specified at this row and at this column * * @param column the column number * @param row the row number * @return the cell at the specified co-ordinates */ public Cell getCell(int column, int row) { return getWritableCell(column, row); } /** * Returns the cell for the specified location eg. "A4". Note that this * method is identical to calling getCell(CellReferenceHelper.getColumn(loc), * CellReferenceHelper.getRow(loc)) and its implicit performance * overhead for string parsing. As such,this method should therefore * be used sparingly * * @param loc the cell reference * @return the cell at the specified co-ordinates */ public WritableCell getWritableCell(String loc) { return getWritableCell(CellReferenceHelper.getColumn(loc), CellReferenceHelper.getRow(loc)); } /** * Returns the cell specified at this row and at this column * * @param column the column number * @param row the row number * @return the cell at the specified co-ordinates */ public WritableCell getWritableCell(int column, int row) { WritableCell c = null; if (row < rows.length && rows[row] != null) { c = rows[row].getCell(column); } if (c == null) { c = new EmptyCell(column, row); } return c; } /** * Returns the number of rows in this sheet * * @return the number of rows in this sheet */ public int getRows() { return numRows; } /** * Returns the number of columns in this sheet * * @return the number of columns in this sheet */ public int getColumns() { return numColumns; } /** * Gets the cell whose contents match the string passed in. * If no match is found, then null is returned. The search is performed * on a row by row basis, so the lower the row number, the more * efficiently the algorithm will perform * * @param contents the string to match * @return the Cell whose contents match the paramter, null if not found */ public Cell findCell(String contents) { CellFinder cellFinder = new CellFinder(this); return cellFinder.findCell(contents); } /** * Gets the cell whose contents match the string passed in. * If no match is found, then null is returned. The search is performed * on a row by row basis, so the lower the row number, the more * efficiently the algorithm will perform * * @param contents the string to match * @param firstCol the first column within the range * @param firstRow the first row of the range * @param lastCol the last column within the range * @param lastRow the last row within the range * @param reverse indicates whether to perform a reverse search or not * @return the Cell whose contents match the parameter, null if not found */ public Cell findCell(String contents, int firstCol, int firstRow, int lastCol, int lastRow, boolean reverse) { CellFinder cellFinder = new CellFinder(this); return cellFinder.findCell(contents, firstCol, firstRow, lastCol, lastRow, reverse); } /** * Gets the cell whose contents match the regular expressionstring passed in. * If no match is found, then null is returned. The search is performed * on a row by row basis, so the lower the row number, the more * efficiently the algorithm will perform * * @param pattern the regular expression string to match * @param firstCol the first column within the range * @param firstRow the first row of the range * @param lastRow the last row within the range * @param lastCol the last column within the ranage * @param reverse indicates whether to perform a reverse search or not * @return the Cell whose contents match the parameter, null if not found */ public Cell findCell(Pattern pattern, int firstCol, int firstRow, int lastCol, int lastRow, boolean reverse) { CellFinder cellFinder = new CellFinder(this); return cellFinder.findCell(pattern, firstCol, firstRow, lastCol, lastRow, reverse); } /** * Gets the cell whose contents match the string passed in. * If no match is found, then null is returned. The search is performed * on a row by row basis, so the lower the row number, the more * efficiently the algorithm will perform. This method differs * from the findCell methods in that only cells with labels are * queried - all numerical cells are ignored. This should therefore * improve performance. * * @param contents the string to match * @return the Cell whose contents match the paramter, null if not found */ public LabelCell findLabelCell(String contents) { CellFinder cellFinder = new CellFinder(this); return cellFinder.findLabelCell(contents); } /** * Gets all the cells on the specified row * * @param row the rows whose cells are to be returned * @return the cells on the given row */ public Cell[] getRow(int row) { // Find the last non-null cell boolean found = false; int col = numColumns - 1; while (col >= 0 && !found) { if (getCell(col, row).getType() != CellType.EMPTY) { found = true; } else { col--; } } // Only create entries for non-empty cells Cell[] cells = new Cell[col+1]; for (int i = 0; i <= col; i++) { cells[i] = getCell(i, row); } return cells; } /** * Gets all the cells on the specified column * * @param col the column whose cells are to be returned * @return the cells on the specified column */ public Cell[] getColumn(int col) { // Find the last non-null cell boolean found = false; int row = numRows - 1; while (row >= 0 && !found) { if (getCell(col, row).getType() != CellType.EMPTY) { found = true; } else { row--; } } // Only create entries for non-empty cells Cell[] cells = new Cell[row+1]; for (int i = 0; i <= row; i++) { cells[i] = getCell(col, i); } return cells; } /** * Gets the name of this sheet * * @return the name of the sheet */ public String getName() { return name; } /** * Inserts a blank row into this spreadsheet. If the row is out of range * of the rows in the sheet, then no action is taken * * @param row the row to insert */ public void insertRow(int row) { if (row < 0 || row >= numRows) { return; } // Create a new array to hold the new rows. Grow it if need be RowRecord[] oldRows = rows; if (numRows == rows.length) { rows = new RowRecord[oldRows.length + rowGrowSize]; } else { rows = new RowRecord[oldRows.length]; } // Copy in everything up to the new row System.arraycopy(oldRows, 0, rows, 0, row); // Copy in the remaining rows System.arraycopy(oldRows, row, rows, row+1, numRows - row); // Increment all the internal row number by one for (int i = row+1; i <= numRows; i++) { if (rows[i] != null) { rows[i].incrementRow(); } } // Adjust any hyperlinks HyperlinkRecord hr = null; Iterator i = hyperlinks.iterator(); while (i.hasNext()) { hr = (HyperlinkRecord) i.next(); hr.insertRow(row); } // Adjust any data validations if (dataValidation != null) { dataValidation.insertRow(row); } if (validatedCells != null && validatedCells.size() > 0) { for (Iterator vci = validatedCells.iterator(); vci.hasNext();) { CellValue cv = (CellValue) vci.next(); CellFeatures cf = cv.getCellFeatures(); if (cf.getDVParser() != null) { cf.getDVParser().insertRow(row); } } } // Adjust any merged cells mergedCells.insertRow(row); // Adjust any page breaks ArrayList newRowBreaks = new ArrayList(); Iterator ri = rowBreaks.iterator(); while (ri.hasNext()) { int val = ( (Integer) ri.next()).intValue(); if (val >= row) { val++; } newRowBreaks.add(new Integer(val)); } rowBreaks = newRowBreaks; // Adjust any conditional formats for (Iterator cfit = conditionalFormats.iterator(); cfit.hasNext() ;) { ConditionalFormat cf = (ConditionalFormat) cfit.next(); cf.insertRow(row); } // Handle interested cell references on the main workbook if (workbookSettings.getFormulaAdjust()) { workbook.rowInserted(this, row); } // Adjust the maximum row record numRows++; } /** * Inserts a blank column into this spreadsheet. If the column is out of * range of the columns in the sheet, then no action is taken. If the * max column on the sheet has been reached, then the last column entry * gets dropped * * @param col the column to insert */ public void insertColumn(int col) { if (col < 0 || col >= numColumns) { return; } // Iterate through all the row records adding in the column for (int i = 0 ; i < numRows ; i++) { if (rows[i] != null) { rows[i].insertColumn(col); } } // Adjust any hyperlinks HyperlinkRecord hr = null; Iterator i = hyperlinks.iterator(); while (i.hasNext()) { hr = (HyperlinkRecord) i.next(); hr.insertColumn(col); } // Iterate through the column views, incrementing the column number i = columnFormats.iterator(); while (i.hasNext()) { ColumnInfoRecord cir = (ColumnInfoRecord) i.next(); if (cir.getColumn() >= col) { cir.incrementColumn(); } } // Iterate through the autosized columns, incrementing the column number if (autosizedColumns.size() > 0) { TreeSet newAutosized = new TreeSet(); i = autosizedColumns.iterator(); while (i.hasNext()) { Integer colnumber = (Integer) i.next(); if (colnumber.intValue() >= col) { newAutosized.add(new Integer(colnumber.intValue() + 1)); } else { newAutosized.add(colnumber); } } autosizedColumns = newAutosized; } // Handle any data validations if (dataValidation != null) { dataValidation.insertColumn(col); } if (validatedCells != null && validatedCells.size() > 0) { for (Iterator vci = validatedCells.iterator(); vci.hasNext();) { CellValue cv = (CellValue) vci.next(); CellFeatures cf = cv.getCellFeatures(); if (cf.getDVParser() != null) { cf.getDVParser().insertColumn(col); } } } // Adjust any merged cells mergedCells.insertColumn(col); // Adjust any page breaks ArrayList newColumnBreaks = new ArrayList(); Iterator ri = columnBreaks.iterator(); while (ri.hasNext()) { int val = ( (Integer) ri.next()).intValue(); if (val >= col) { val++; } newColumnBreaks.add(new Integer(val)); } columnBreaks = newColumnBreaks; // Adjust any conditional formats for (Iterator cfit = conditionalFormats.iterator(); cfit.hasNext() ;) { ConditionalFormat cf = (ConditionalFormat) cfit.next(); cf.insertColumn(col); } // Handle interested cell references on the main workbook if (workbookSettings.getFormulaAdjust()) { workbook.columnInserted(this, col); } numColumns++; } /** * Removes a column from this spreadsheet. If the column is out of range * of the columns in the sheet, then no action is taken * * @param col the column to remove */ public void removeColumn(int col) { if (col < 0 || col >= numColumns) { return; } // Iterate through all the row records removing the column for (int i = 0 ; i < numRows ; i++) { if (rows[i] != null) { rows[i].removeColumn(col); } } // Adjust any hyperlinks HyperlinkRecord hr = null; Iterator i = hyperlinks.iterator(); while (i.hasNext()) { hr = (HyperlinkRecord) i.next(); if (hr.getColumn() == col && hr.getLastColumn() == col) { // The row with the hyperlink on has been removed, so get // rid of it from the list i.remove(); } else { hr.removeColumn(col); } } // Adjust any data validations if (dataValidation != null) { dataValidation.removeColumn(col); } if (validatedCells != null && validatedCells.size() > 0) { for (Iterator vci = validatedCells.iterator(); vci.hasNext();) { CellValue cv = (CellValue) vci.next(); CellFeatures cf = cv.getCellFeatures(); if (cf.getDVParser() != null) { cf.getDVParser().removeColumn(col); } } } // Adjust any merged cells mergedCells.removeColumn(col); // Adjust any page breaks ArrayList newColumnBreaks = new ArrayList(); Iterator ri = columnBreaks.iterator(); while (ri.hasNext()) { int val = ( (Integer) ri.next()).intValue(); if (val != col) { if (val > col) { val--; } newColumnBreaks.add(new Integer(val)); } } columnBreaks = newColumnBreaks; // Iterate through the column views, decrementing the column number i = columnFormats.iterator(); ColumnInfoRecord removeColumn = null; while (i.hasNext()) { ColumnInfoRecord cir = (ColumnInfoRecord) i.next(); if (cir.getColumn() == col) { removeColumn = cir; } else if (cir.getColumn() > col) { cir.decrementColumn(); } } if (removeColumn != null) { columnFormats.remove(removeColumn); } // Iterate through the autosized columns, decrementing the column number if (autosizedColumns.size() > 0) { TreeSet newAutosized = new TreeSet(); i = autosizedColumns.iterator(); while (i.hasNext()) { Integer colnumber = (Integer) i.next(); if (colnumber.intValue() == col) { // do nothing } else if (colnumber.intValue() > col) { newAutosized.add(new Integer(colnumber.intValue() - 1)); } else { newAutosized.add(colnumber); } } autosizedColumns = newAutosized; } // Adjust any conditional formats for (Iterator cfit = conditionalFormats.iterator(); cfit.hasNext() ;) { ConditionalFormat cf = (ConditionalFormat) cfit.next(); cf.removeColumn(col); } // Handle interested cell references on the main workbook if (workbookSettings.getFormulaAdjust()) { workbook.columnRemoved(this, col); } numColumns--; } /** * Removes a row from this spreadsheet. If the row is out of * range of the columns in the sheet, then no action is taken * * @param row the row to remove */ public void removeRow(int row) { if (row < 0 || row >= numRows) { // Call rowRemoved anyway, to adjust the named cells if (workbookSettings.getFormulaAdjust()) { workbook.rowRemoved(this, row); } return; } // Create a new array to hold the new rows. Grow it if need be RowRecord[] oldRows = rows; rows = new RowRecord[oldRows.length]; // Copy in everything up to the row to be removed System.arraycopy(oldRows, 0, rows, 0, row); // Copy in the remaining rows System.arraycopy(oldRows, row + 1, rows, row, numRows - (row + 1)); // Decrement all the internal row numbers by one for (int i = row; i < numRows; i++) { if (rows[i] != null) { rows[i].decrementRow(); } } // Adjust any hyperlinks HyperlinkRecord hr = null; Iterator i = hyperlinks.iterator(); while (i.hasNext()) { hr = (HyperlinkRecord) i.next(); if (hr.getRow() == row && hr.getLastRow() == row) { // The row with the hyperlink on has been removed, so get // rid of it from the list i.remove(); } else { hr.removeRow(row); } } // Adjust any data validations if (dataValidation != null) { dataValidation.removeRow(row); } if (validatedCells != null && validatedCells.size() > 0) { for (Iterator vci = validatedCells.iterator(); vci.hasNext();) { CellValue cv = (CellValue) vci.next(); CellFeatures cf = cv.getCellFeatures(); if (cf.getDVParser() != null) { cf.getDVParser().removeRow(row); } } } // Adjust any merged cells mergedCells.removeRow(row); // Adjust any page breaks ArrayList newRowBreaks = new ArrayList(); Iterator ri = rowBreaks.iterator(); while (ri.hasNext()) { int val = ( (Integer) ri.next()).intValue(); if (val != row) { if (val > row) { val--; } newRowBreaks.add(new Integer(val)); } } rowBreaks = newRowBreaks; // Adjust any conditional formats for (Iterator cfit = conditionalFormats.iterator(); cfit.hasNext() ;) { ConditionalFormat cf = (ConditionalFormat) cfit.next(); cf.removeRow(row); } // Handle interested cell references on the main workbook if (workbookSettings.getFormulaAdjust()) { workbook.rowRemoved(this, row); } // Adjust any drawings /* if (drawings != null) { for (Iterator drawingIt = drawings.iterator() ; drawingIt.hasNext() ; ) { DrawingGroupObject dgo = (DrawingGroupObject) drawingIt.next(); dgo.removeRow(row); } } */ // Adjust the maximum row record numRows--; } /** * Adds the cell to this sheet. If the cell has already been added to * this sheet or another sheet, a WriteException is thrown. If the * position to be occupied by this cell is already taken, the incumbent * cell is replaced. * The cell is then marked as referenced, and its formatting information * registered with the list of formatting records updated if necessary * The RowsExceededException may be caught if client code wishes to * explicitly trap the case where too many rows have been written * to the current sheet. If this behaviour is not desired, it is * sufficient simply to handle the WriteException, since this is a base * class of RowsExceededException * * @exception WriteException * @exception RowsExceededException * @param cell the cell to add */ public void addCell(WritableCell cell) throws WriteException, RowsExceededException { if (cell.getType() == CellType.EMPTY) { if (cell != null && cell.getCellFormat() == null) { // return if it's a blank cell with no particular cell formatting // information return; } } CellValue cv = (CellValue) cell; if (cv.isReferenced()) { throw new JxlWriteException(JxlWriteException.cellReferenced); } int row = cell.getRow(); RowRecord rowrec = getRowRecord(row); CellValue curcell = rowrec.getCell(cv.getColumn()); boolean curSharedValidation = (curcell != null && curcell.getCellFeatures() != null && curcell.getCellFeatures().getDVParser() != null && curcell.getCellFeatures().getDVParser().extendedCellsValidation()); // Check for shared data validations, but only if the cell being added // has a data validation if (cell.getCellFeatures() != null && cell.getCellFeatures().hasDataValidation() && curSharedValidation) { DVParser dvp = curcell.getCellFeatures().getDVParser(); logger.warn("Cannot add cell at " + CellReferenceHelper.getCellReference(cv) + " because it is part of the shared cell validation group " + CellReferenceHelper.getCellReference(dvp.getFirstColumn(), dvp.getFirstRow()) + "-" + CellReferenceHelper.getCellReference(dvp.getLastColumn(), dvp.getLastRow())); return; } // Apply any shared validation from the current cell to this cell if (curSharedValidation) { WritableCellFeatures wcf = cell.getWritableCellFeatures(); if (wcf == null) { wcf = new WritableCellFeatures(); cell.setCellFeatures(wcf); } wcf.shareDataValidation(curcell.getCellFeatures()); } rowrec.addCell(cv); // Adjust the max rows and max columns accordingly numRows = Math.max(row+1, numRows); numColumns = Math.max(numColumns, rowrec.getMaxColumn()); // Indicate this cell is now part of a worksheet, so that it can't be // added anywhere else cv.setCellDetails(formatRecords, sharedStrings, this); } /** * Gets the row record at the specified row number, growing the * array as needs dictate * * @param row the row number we are interested in * @return the row record at the specified row * @exception RowsExceededException */ RowRecord getRowRecord(int row) throws RowsExceededException { if (row >= numRowsPerSheet) { throw new RowsExceededException(); } // Grow the array of rows if needs be // Thanks to Brendan for spotting the flaw in merely adding on the // grow size if (row >= rows.length) { RowRecord[] oldRows = rows; rows = new RowRecord[Math.max(oldRows.length + rowGrowSize, row+1)]; System.arraycopy(oldRows, 0, rows, 0, oldRows.length); oldRows = null; } RowRecord rowrec = rows[row]; if (rowrec == null) { rowrec = new RowRecord(row, this); rows[row] = rowrec; } return rowrec; } /** * Gets the row record for the specified row * * @param r the row * @return the row record */ RowRecord getRowInfo(int r) { if (r < 0 || r > rows.length) { return null; } return rows[r]; } /** * Gets the column info record for the specified column * * @param c the column * @return the column record */ ColumnInfoRecord getColumnInfo(int c) { Iterator i = columnFormats.iterator(); ColumnInfoRecord cir = null; boolean stop = false; while (i.hasNext() && !stop) { cir = (ColumnInfoRecord) i.next(); if (cir.getColumn() >= c) { stop = true; } } if (!stop) { return null; } return cir.getColumn() == c ? cir : null; } /** * Sets the name of this worksheet * * @param n the name of this sheet */ public void setName(String n) { name = n; } /** * Sets the hidden status of this sheet * * @param h the hiden flag * @deprecated Use the settings bean instead */ public void setHidden(boolean h) { settings.setHidden(h); } /** * Indicates whether or not this sheet is protected * * @param prot protected flag * @deprecated Use the settings bean instead */ public void setProtected(boolean prot) { settings.setProtected(prot); } /** * Sets this sheet as selected * @deprecated Use the settings bean */ public void setSelected() { settings.setSelected(); } /** * Retrieves the hidden status of this sheet * * @return TRUE if hidden, FALSE otherwise * @deprecated Use the sheet settings bean instead */ public boolean isHidden() { return settings.isHidden(); } /** * Sets the width (in characters) for a particular column in this sheet * * @param col the column whose width to set * @param width the width of the column in characters */ public void setColumnView(int col, int width) { CellView cv = new CellView(); cv.setSize(width * 256); setColumnView(col, cv); } /** * Sets the width (in characters) and format options for a * particular column in this sheet * * @param col the column to set * @param width the width in characters * @param format the formt details for the column */ public void setColumnView(int col, int width, CellFormat format) { CellView cv = new CellView(); cv.setSize(width * 256); cv.setFormat(format); setColumnView(col, cv); } /** * Sets the view for this column * * @param col the column on which to set the view * @param view the view to set */ public void setColumnView(int col, CellView view) { XFRecord xfr = (XFRecord) view.getFormat(); if (xfr == null) { Styles styles = getWorkbook().getStyles(); xfr = styles.getNormalStyle(); } try { if (!xfr.isInitialized()) { formatRecords.addStyle(xfr); } int width = view.depUsed() ? view.getDimension() * 256 : view.getSize(); if (view.isAutosize()) { autosizedColumns.add(new Integer(col)); } ColumnInfoRecord cir = new ColumnInfoRecord(col, width, xfr); if (view.isHidden()) { cir.setHidden(true); } if (!columnFormats.contains(cir)) { columnFormats.add(cir); } else { columnFormats.remove(cir); columnFormats.add(cir); } } catch (NumFormatRecordsException e) { logger.warn("Maximum number of format records exceeded. Using " + "default format."); ColumnInfoRecord cir = new ColumnInfoRecord (col, view.getDimension()*256, WritableWorkbook.NORMAL_STYLE); if (!columnFormats.contains(cir)) { columnFormats.add(cir); } } } /** * Sets the height of the specified row, as well as its collapse status * * @param row the row to be formatted * @param height the row height in 1/20ths of a point * @exception RowsExceededException * @deprecated use the override which takes a CellView object */ public void setRowView(int row, int height) throws RowsExceededException { CellView cv = new CellView(); cv.setSize(height); cv.setHidden(false); setRowView(row, cv); } /** * Sets the height of the specified row, as well as its collapse status * * @param row the row to be formatted * @param collapsed indicates whether the row is collapsed * @exception jxl.write.biff.RowsExceededException * @deprecated use the override which takes a CellView object */ public void setRowView(int row, boolean collapsed) throws RowsExceededException { CellView cv = new CellView(); cv.setHidden(collapsed); setRowView(row, cv); } /** * Sets the height of the specified row, as well as its collapse status * * @param row the row to be formatted * @param height the row height in 1/20th of a point * @param collapsed indicates whether the row is collapsed * @param zeroHeight indicates that the row has zero height * @exception RowsExceededException * @deprecated use the override which takes a CellView object */ public void setRowView(int row, int height, boolean collapsed) throws RowsExceededException { CellView cv = new CellView(); cv.setSize(height); cv.setHidden(collapsed); setRowView(row, cv); } /** * Sets the view for this column * * @param row the column on which to set the view * @param view the view to set * @exception RowsExceededException */ public void setRowView(int row, CellView view) throws RowsExceededException { RowRecord rowrec = getRowRecord(row); XFRecord xfr = (XFRecord) view.getFormat(); try { if (xfr != null) { if (!xfr.isInitialized()) { formatRecords.addStyle(xfr); } } } catch (NumFormatRecordsException e) { logger.warn("Maximum number of format records exceeded. Using " + "default format."); xfr = null; } rowrec.setRowDetails(view.getSize(), false, view.isHidden(), 0, false, xfr); numRows = Math.max(numRows, row + 1); } /** * Writes out this sheet. This functionality is delegated off to the * SheetWriter class in order to reduce the bloated nature of this source * file * * @exception IOException */ public void write() throws IOException { boolean dmod = drawingsModified; if (workbook.getDrawingGroup() != null) { dmod |= workbook.getDrawingGroup().hasDrawingsOmitted(); } if (autosizedColumns.size() > 0) { autosizeColumns(); } sheetWriter.setWriteData(rows, rowBreaks, columnBreaks, hyperlinks, mergedCells, columnFormats, maxRowOutlineLevel, maxColumnOutlineLevel); sheetWriter.setDimensions(getRows(), getColumns()); sheetWriter.setSettings(settings); sheetWriter.setPLS(plsRecord); sheetWriter.setDrawings(drawings, dmod); sheetWriter.setButtonPropertySet(buttonPropertySet); sheetWriter.setDataValidation(dataValidation, validatedCells); sheetWriter.setConditionalFormats(conditionalFormats); sheetWriter.setAutoFilter(autoFilter); sheetWriter.write(); } /** * Copies the specified sheet, row by row and cell by cell * * @param s the sheet to copy */ void copy(Sheet s) { // Copy the settings settings = new SheetSettings(s.getSettings(), this); SheetCopier si = new SheetCopier(s, this); si.setColumnFormats(columnFormats); si.setFormatRecords(formatRecords); si.setHyperlinks(hyperlinks); si.setMergedCells(mergedCells); si.setRowBreaks(rowBreaks); si.setColumnBreaks(columnBreaks); si.setSheetWriter(sheetWriter); si.setDrawings(drawings); si.setImages(images); si.setConditionalFormats(conditionalFormats); si.setValidatedCells(validatedCells); si.copySheet(); dataValidation = si.getDataValidation(); comboBox = si.getComboBox(); plsRecord = si.getPLSRecord(); chartOnly = si.isChartOnly(); buttonPropertySet = si.getButtonPropertySet(); numRows = si.getRows(); autoFilter = si.getAutoFilter(); maxRowOutlineLevel = si.getMaxRowOutlineLevel(); maxColumnOutlineLevel = si.getMaxColumnOutlineLevel(); } /** * Copies the specified sheet, row by row and cell by cell * * @param s the sheet to copy */ void copy(WritableSheet s) { settings = new SheetSettings(s.getSettings(), this); WritableSheetImpl si = (WritableSheetImpl) s; WritableSheetCopier sc = new WritableSheetCopier(s, this); sc.setColumnFormats(si.columnFormats, columnFormats); sc.setMergedCells(si.mergedCells, mergedCells); sc.setRows(si.rows); sc.setRowBreaks(si.rowBreaks, rowBreaks); sc.setColumnBreaks(si.columnBreaks, columnBreaks); sc.setDataValidation(si.dataValidation); sc.setSheetWriter(sheetWriter); sc.setDrawings(si.drawings, drawings, images); sc.setWorkspaceOptions(si.getWorkspaceOptions()); sc.setPLSRecord(si.plsRecord); sc.setButtonPropertySetRecord(si.buttonPropertySet); sc.setHyperlinks(si.hyperlinks, hyperlinks); sc.setValidatedCells(validatedCells); sc.copySheet(); dataValidation = sc.getDataValidation(); plsRecord = sc.getPLSRecord(); buttonPropertySet = sc.getButtonPropertySet(); } /** * Gets the header. Called when copying sheets * * @return the page header */ final HeaderRecord getHeader() { return sheetWriter.getHeader(); } /** * Gets the footer. Called when copying sheets * * @return the page footer */ final FooterRecord getFooter() { return sheetWriter.getFooter(); } /** * Determines whether the sheet is protected * * @return whether or not the sheet is protected * @deprecated Use the SheetSettings bean instead */ public boolean isProtected() { return settings.isProtected(); } /** * Gets the hyperlinks on this sheet * * @return an array of hyperlinks */ public Hyperlink[] getHyperlinks() { Hyperlink[] hl = new Hyperlink[hyperlinks.size()]; for (int i = 0; i < hyperlinks.size(); i++) { hl[i] = (Hyperlink) hyperlinks.get(i); } return hl; } /** * Gets the cells which have been merged on this sheet * * @return an array of range objects */ public Range[] getMergedCells() { return mergedCells.getMergedCells(); } /** * Gets the writable hyperlinks on this sheet * * @return an array of hyperlinks */ public WritableHyperlink[] getWritableHyperlinks() { WritableHyperlink[] hl = new WritableHyperlink[hyperlinks.size()]; for (int i = 0; i < hyperlinks.size(); i++) { hl[i] = (WritableHyperlink) hyperlinks.get(i); } return hl; } /** * Removes the specified hyperlink. Note that if you merely set the * cell contents to be an Empty cell, then the cells containing the * hyperlink will still be active. The contents of the cell which * activate the hyperlink are removed. * The hyperlink passed in must be a hyperlink retrieved using the * getHyperlinks method * * @param h the hyperlink to remove. * @param preserveLabel if TRUE preserves the label contents, if FALSE * removes them */ public void removeHyperlink(WritableHyperlink h) { removeHyperlink(h, false); } /** * Removes the specified hyperlink. Note that if you merely set the * cell contents to be an Empty cell, then the cells containing the * hyperlink will still be active. * If the preserveLabel field is set, the cell contents of the * hyperlink are preserved, although the hyperlink is deactivated. If * this value is FALSE, the cell contents are removed * The hyperlink passed in must be a hyperlink retrieved using the * getHyperlinks method * * @param h the hyperlink to remove. * @param preserveLabel if TRUE preserves the label contents, if FALSE * removes them */ public void removeHyperlink(WritableHyperlink h, boolean preserveLabel) { // Remove the hyperlink hyperlinks.remove(hyperlinks.indexOf(h)); if (!preserveLabel) { // Set the cell contents for the hyperlink - including any formatting // information - to be empty Assert.verify(rows.length > h.getRow() && rows[h.getRow()] != null); rows[h.getRow()].removeCell(h.getColumn()); } } /** * Adds the specified hyperlink * * @param the hyperlink * @exception WriteException * @exception RowsExceededException */ public void addHyperlink(WritableHyperlink h) throws WriteException, RowsExceededException { // First set the label on the sheet Cell c = getCell(h.getColumn(), h.getRow()); String contents = null; if (h.isFile() || h.isUNC()) { String cnts = ( (HyperlinkRecord) h).getContents(); if (cnts == null) { contents = h.getFile().getPath(); } else { contents = cnts; } } else if (h.isURL()) { String cnts = ( (HyperlinkRecord) h).getContents(); if (cnts == null) { contents = h.getURL().toString(); } else { contents=cnts; } } else if (h.isLocation()) { contents = ( (HyperlinkRecord) h).getContents(); } // If the cell type is a label, then preserve the cell contents // and most of the format (apart from the font) // otherwise overwrite the cell content and the format with the contents // and the standard hyperlink format if (c.getType() == CellType.LABEL) { Label l = (Label) c; l.setString(contents); WritableCellFormat wcf = new WritableCellFormat(l.getCellFormat()); ( (XFRecord) wcf).setFont(WritableWorkbook.HYPERLINK_FONT); l.setCellFormat(wcf); } else { Label l = new Label(h.getColumn(), h.getRow(), contents, WritableWorkbook.HYPERLINK_STYLE); addCell(l); } // Set all other cells within range to be empty for (int i = h.getRow(); i <= h.getLastRow(); i++) { for (int j = h.getColumn(); j <= h.getLastColumn(); j++) { if (i != h.getRow() && j != h.getColumn()) { // Set the cell to be empty if (rows.length < h.getLastColumn() && rows[i] != null) { rows[i].removeCell(j); } } } } ((HyperlinkRecord) h).initialize(this); hyperlinks.add(h); } /** * Merges the specified cells. Any clashes or intersections between * merged cells are resolved when the spreadsheet is written out * * @param col1 the column number of the top left cell * @param row1 the row number of the top left cell * @param col2 the column number of the bottom right cell * @param row2 the row number of the bottom right cell * @return the Range object representing the merged cells * @exception jxl.write..WriteException * @exception jxl.write.biff.RowsExceededException */ public Range mergeCells(int col1, int row1, int col2, int row2) throws WriteException, RowsExceededException { // First check that the cells make sense if (col2 < col1 || row2 < row1) { logger.warn("Cannot merge cells - top left and bottom right "+ "incorrectly specified"); } // Make sure the spreadsheet is up to size if (col2 >= numColumns || row2 >= numRows) { addCell(new Blank(col2, row2)); } SheetRangeImpl range = new SheetRangeImpl(this, col1, row1, col2, row2); mergedCells.add(range); return range; } /** * Sets a row grouping * * @param row1 the first row of the group * @param row2 the last row of the group * @param collapsed should the group be collapsed? * @exception WriteException * @exception RowsExceededException */ public void setRowGroup(int row1, int row2, boolean collapsed) throws WriteException, RowsExceededException { if (row2 < row1) { logger.warn("Cannot merge cells - top and bottom rows incorrectly " + "specified"); } for (int i = row1; i <= row2; i++) { RowRecord row = getRowRecord(i); numRows = Math.max(i+1, numRows); row.incrementOutlineLevel(); row.setCollapsed(collapsed); maxRowOutlineLevel = Math.max(maxRowOutlineLevel, row.getOutlineLevel()); } } /** * Unsets a row grouping * * @param row1 the first row to unset * @param row2 the last row to unset * @exception WriteException * @exception RowsExceededException */ public void unsetRowGroup(int row1, int row2) throws WriteException, RowsExceededException { if (row2 < row1) { logger.warn("Cannot merge cells - top and bottom rows incorrectly " + "specified"); } // Make sure the spreadsheet is up to size if (row2 >= numRows) { logger.warn("" + row2 + " is greater than the sheet bounds"); row2 = numRows - 1; } for (int i = row1; i <= row2; i++) { rows[i].decrementOutlineLevel(); } // Recalculate the max outline level maxRowOutlineLevel = 0; for (int i = rows.length; i-- > 0; ) { maxRowOutlineLevel = Math.max(maxRowOutlineLevel, rows[i].getOutlineLevel()); } } /** * Sets a column grouping * * @param col1 the first column of the group * @param col2 the last column of the group * @param collapsed should the group be collapsed? * @exception WriteException * @exception RowsExceededException */ public void setColumnGroup(int col1, int col2, boolean collapsed) throws WriteException, RowsExceededException { if (col2 < col1) { logger.warn("Cannot merge cells - top and bottom rows incorrectly " + "specified"); } for (int i = col1; i <= col2; i++) { ColumnInfoRecord cir = getColumnInfo(i); // Create the column info record if not present using a default // cell view if (cir == null) { setColumnView(i, new CellView()); cir = getColumnInfo(i); } cir.incrementOutlineLevel(); cir.setCollapsed(collapsed); maxColumnOutlineLevel = Math.max(maxColumnOutlineLevel, cir.getOutlineLevel()); } } /** * Unsets a column grouping * * @param col1 the first column to unset * @param col2 the last column to unset * @exception WriteException * @exception RowsExceededException */ public void unsetColumnGroup(int col1, int col2) throws WriteException, RowsExceededException { if (col2 < col1) { logger.warn("Cannot merge cells - top and bottom rows incorrectly " + "specified"); } for (int i = col1; i <= col2; i++) { ColumnInfoRecord cir = getColumnInfo(i); cir.decrementOutlineLevel(); } // Recalculate the max outline level maxColumnOutlineLevel = 0; for (Iterator it = columnFormats.iterator(); it.hasNext(); ) { ColumnInfoRecord cir = (ColumnInfoRecord)it.next(); maxColumnOutlineLevel = Math.max(maxColumnOutlineLevel, cir.getOutlineLevel()); } } /** * Unmerges the specified cells. The Range passed in should be one that * has been previously returned as a result of the getMergedCells method * * @param r the range of cells to unmerge */ public void unmergeCells(Range r) { mergedCells.unmergeCells(r); } /** * Sets the header for this page * * @param l the print header to print on the left side * @param c the print header to print in the centre * @param r the print header to print on the right hand side * @deprecated Use the sheet settings bean */ public void setHeader(String l, String c, String r) { HeaderFooter header = new HeaderFooter(); header.getLeft().append(l); header.getCentre().append(c); header.getRight().append(r); settings.setHeader(header); } /** * Sets the footer for this page * * @param l the print header to print on the left side * @param c the print header to print in the centre * @param r the print header to print on the right hand side * @deprecated Use the sheet settings bean */ public void setFooter(String l, String c, String r) { HeaderFooter footer = new HeaderFooter(); footer.getLeft().append(l); footer.getCentre().append(c); footer.getRight().append(r); settings.setFooter(footer); } /** * Sets the page setup details * * @param p the page orientation * @deprecated Use the SheetSettings bean */ public void setPageSetup(PageOrientation p) { settings.setOrientation(p); } /** * Sets the page setup details * * @param p the page orientation * @param hm the header margin, in inches * @param fm the footer margin, in inches * @deprecated Use the SheetSettings bean */ public void setPageSetup(PageOrientation p, double hm, double fm) { settings.setOrientation(p); settings.setHeaderMargin(hm); settings.setFooterMargin(fm); } /** * Sets the page setup details * * @param p the page orientation * @param ps the paper size * @param hm the header margin, in inches * @param fm the footer margin, in inches * @deprecated Use the SheetSettings bean */ public void setPageSetup(PageOrientation p, PaperSize ps, double hm, double fm) { settings.setPaperSize(ps); settings.setOrientation(p); settings.setHeaderMargin(hm); settings.setFooterMargin(fm); } /** * Gets the settings for this sheet * * @return the page settings bean */ public SheetSettings getSettings() { return settings; } /** * Gets the workbook settings */ WorkbookSettings getWorkbookSettings() { return workbookSettings; } /** * Forces a page break at the specified row * * @param row the row to break at */ public void addRowPageBreak(int row) { // First check that the row is not already present Iterator i = rowBreaks.iterator(); boolean found = false; while (i.hasNext() && !found) { if (( (Integer) i.next()).intValue() == row) { found = true; } } if (!found) { rowBreaks.add(new Integer(row)); } } /** * Forces a page break at the specified column * * @param col the column to break at */ public void addColumnPageBreak(int col) { // First check that the row is not already present Iterator i = columnBreaks.iterator(); boolean found = false; while (i.hasNext() && !found) { if (( (Integer) i.next()).intValue() == col) { found = true; } } if (!found) { columnBreaks.add(new Integer(col)); } } /** * Accessor for the charts. Used when copying * * @return the charts on this sheet */ Chart[] getCharts() { return sheetWriter.getCharts(); } /** * Accessor for the drawings. Used when copying * * @return the drawings on this sheet */ private DrawingGroupObject[] getDrawings() { DrawingGroupObject[] dr = new DrawingGroupObject[drawings.size()]; dr = (DrawingGroupObject[]) drawings.toArray(dr); return dr; } /** * Check all the merged cells for borders. Although in an OO sense the * logic should belong in this class, in order to reduce the bloated * nature of the source code for this object this logic has been delegated * to the SheetWriter */ void checkMergedBorders() { sheetWriter.setWriteData(rows, rowBreaks, columnBreaks, hyperlinks, mergedCells, columnFormats, maxRowOutlineLevel, maxColumnOutlineLevel); sheetWriter.setDimensions(getRows(), getColumns()); sheetWriter.checkMergedBorders(); } /** * Accessor for the workspace options * * @return the workspace options */ private WorkspaceInformationRecord getWorkspaceOptions() { return sheetWriter.getWorkspaceOptions(); } /** * Rationalizes the sheets xf index mapping * @param xfMapping the index mapping for XFRecords * @param fontMapping the index mapping for fonts * @param formatMapping the index mapping for formats */ void rationalize(IndexMapping xfMapping, IndexMapping fontMapping, IndexMapping formatMapping) { // Rationalize the column formats for (Iterator i = columnFormats.iterator() ; i.hasNext() ;) { ColumnInfoRecord cir = (ColumnInfoRecord) i.next(); cir.rationalize(xfMapping); } // Rationalize the row formats for (int i = 0; i < rows.length ; i++) { if (rows[i] != null) { rows[i].rationalize(xfMapping); } } // Rationalize any data that appears on the charts Chart[] charts = getCharts(); for (int c = 0; c < charts.length; c++) { charts[c].rationalize(xfMapping, fontMapping, formatMapping); } } /** * Accessor for the workbook * @return the workbook */ WritableWorkbookImpl getWorkbook() { return workbook; } /** * Gets the column format for the specified column * * @param col the column number * @return the column format, or NULL if the column has no specific format * @deprecated Use getColumnView instead */ public CellFormat getColumnFormat(int col) { return getColumnView(col).getFormat(); } /** * Gets the column width for the specified column * * @param col the column number * @return the column width, or the default width if the column has no * specified format * @deprecated Use getColumnView instead */ public int getColumnWidth(int col) { return getColumnView(col).getDimension(); } /** * Gets the column width for the specified column * * @param row the column number * @return the row height, or the default height if the column has no * specified format * @deprecated Use getRowView instead */ public int getRowHeight(int row) { return getRowView(row).getDimension(); } /** * Accessor for the chart only method * * @return TRUE if this is a chart only, FALSE otherwise */ boolean isChartOnly() { return chartOnly; } /** * Gets the row view for the specified row * * @param col the row number * @return the row format, or the default format if no override is specified */ public CellView getRowView(int row) { CellView cv = new CellView(); try { RowRecord rr = getRowRecord(row); if (rr == null || rr.isDefaultHeight()) { cv.setDimension(settings.getDefaultRowHeight()); cv.setSize(settings.getDefaultRowHeight()); } else if (rr.isCollapsed()) { cv.setHidden(true); } else { cv.setDimension(rr.getRowHeight()); cv.setSize(rr.getRowHeight()); } return cv; } catch (RowsExceededException e) { // Simple return the default cv.setDimension(settings.getDefaultRowHeight()); cv.setSize(settings.getDefaultRowHeight()); return cv; } } /** * Gets the column width for the specified column * * @param col the column number * @return the column format, or the default format if no override is specified */ public CellView getColumnView(int col) { ColumnInfoRecord cir = getColumnInfo(col); CellView cv = new CellView(); if (cir != null) { cv.setDimension(cir.getWidth()/256); cv.setSize(cir.getWidth()); cv.setHidden(cir.getHidden()); cv.setFormat(cir.getCellFormat()); } else { cv.setDimension(settings.getDefaultColumnWidth()/256); cv.setSize(settings.getDefaultColumnWidth() * 256); } return cv; } /** * Adds an image to this sheet * * @param image the image to add */ public void addImage(WritableImage image) { boolean supported = false; java.io.File imageFile = image.getImageFile(); String fileType = "?"; if (imageFile != null) { String fileName = imageFile.getName(); int fileTypeIndex = fileName.lastIndexOf('.'); fileType = fileTypeIndex != -1 ? fileName.substring(fileTypeIndex+1) : ""; for (int i = 0 ; i < imageTypes.length && !supported ; i++) { if (fileType.equalsIgnoreCase(imageTypes[i])) { supported = true; } } } else { supported = true; } if (supported) { workbook.addDrawing(image); drawings.add(image); images.add(image); } else { StringBuffer message = new StringBuffer("Image type "); message.append(fileType); message.append(" not supported. Supported types are "); message.append(imageTypes[0]); for (int i = 1 ; i < imageTypes.length ; i++) { message.append(", "); message.append(imageTypes[i]); } logger.warn(message.toString()); } } /** * Gets the number of images on this sheet * * @return the number of images on this sheet */ public int getNumberOfImages() { return images.size(); } /** * Accessor for a particular image on this sheet * * @param i the 0-based image index number * @return the image with the specified index number */ public WritableImage getImage(int i) { return (WritableImage) images.get(i); } /** * Accessor for a particular image on this sheet * * @param i the 0-based image index number * @return the image with the specified index number */ public Image getDrawing(int i) { return (Image) images.get(i); } /** * Removes the specified image from this sheet. The image passed in * must be the same instance as that retrieved from a getImage call * * @param wi the image to remove */ public void removeImage(WritableImage wi) { drawings.remove(wi); images.remove(wi); drawingsModified = true; workbook.removeDrawing(wi); } /** * Validates the sheet name */ private String validateName(String n) { if (n.length() > maxSheetNameLength) { logger.warn("Sheet name " + n + " too long - truncating"); n = n.substring(0, maxSheetNameLength); } if (n.charAt(0) == '\'') { logger.warn("Sheet naming cannot start with \' - removing"); n = n.substring(1); } for (int i = 0 ; i < illegalSheetNameCharacters.length ; i++) { String newname = n.replace(illegalSheetNameCharacters[i], '@'); if (n != newname) { logger.warn(illegalSheetNameCharacters[i] + " is not a valid character within a sheet name - replacing"); } n = newname; } return n; } /** * Adds a drawing to the list - typically used for comments * * @param the drawing to add */ void addDrawing(DrawingGroupObject o) { drawings.add(o); Assert.verify(!(o instanceof Drawing)); } /** * Removes a drawing to the list - typically used for comments * * @param the drawing to add */ void removeDrawing(DrawingGroupObject o) { int origSize = drawings.size(); drawings.remove(o); int newSize = drawings.size(); drawingsModified = true; Assert.verify(newSize == origSize -1); } /** * Removes the data validation for the specified cell. Called from * CellValue in response to a cell being replaced * * @param cv the cell being removed */ void removeDataValidation(CellValue cv) { if (dataValidation != null) { dataValidation.removeDataValidation(cv.getColumn(), cv.getRow()); } if (validatedCells != null) { boolean result = validatedCells.remove(cv); if (!result) { logger.warn("Could not remove validated cell " + CellReferenceHelper.getCellReference(cv)); } } } /** * Accessor for the page breaks on this sheet * * @return the page breaks on this sheet */ public int[] getRowPageBreaks() { int[] rb = new int[rowBreaks.size()]; int pos = 0; for (Iterator i = rowBreaks.iterator(); i.hasNext() ; pos++) { rb[pos] = ( (Integer) i.next()).intValue(); } return rb; } /** * Accessor for the page breaks on this sheet * * @return the page breaks on this sheet */ public int[] getColumnPageBreaks() { int[] rb = new int[columnBreaks.size()]; int pos = 0; for (Iterator i = columnBreaks.iterator(); i.hasNext() ; pos++) { rb[pos] = ( (Integer) i.next()).intValue(); } return rb; } /** * Flags the added cell as having data validation * * @param cell the cell with data validation */ void addValidationCell(CellValue cv) { validatedCells.add(cv); } /** * Accessor for the combo box object used for list data validations on this * sheet * * @return the combo box */ ComboBox getComboBox() { return comboBox; } /** * Sets the combo box object used for list validations on this sheet * * @param cb the combo box */ void setComboBox(ComboBox cb) { comboBox = cb; } /** * Gets the data validation. Retrieved by CellValue when copying sheets */ public DataValidation getDataValidation() { return dataValidation; } /** * Performs the column autosizing */ private void autosizeColumns() { Iterator i = autosizedColumns.iterator(); while (i.hasNext()) { Integer col = (Integer) i.next(); autosizeColumn(col.intValue()); } } /** * Autosizes the specified column * * @param col the column to autosize */ private void autosizeColumn(int col) { int maxWidth = 0; ColumnInfoRecord cir = getColumnInfo(col); Font columnFont = cir.getCellFormat().getFont(); Font defaultFont = WritableWorkbook.NORMAL_STYLE.getFont(); for (int i = 0 ; i < numRows; i++) { Cell cell = null; if (rows[i] != null) { cell = rows[i].getCell(col); } if (cell != null) { String contents = cell.getContents(); Font font = cell.getCellFormat().getFont(); Font activeFont = font.equals(defaultFont) ? columnFont : font; int pointSize = activeFont.getPointSize(); int numChars = contents.length(); if (activeFont.isItalic() || activeFont.getBoldWeight() > 400) // magic value for normal bold { numChars += 2; } int points = numChars * pointSize; maxWidth = Math.max(maxWidth, points * 256); } } cir.setWidth((int) (maxWidth / defaultFont.getPointSize())); } /** * Imports a sheet from a different workbook * * @param s the sheet to import */ void importSheet(Sheet s) { // Copy the settings settings = new SheetSettings(s.getSettings(), this); SheetCopier si = new SheetCopier(s, this); si.setColumnFormats(columnFormats); si.setFormatRecords(formatRecords); si.setHyperlinks(hyperlinks); si.setMergedCells(mergedCells); si.setRowBreaks(rowBreaks); si.setColumnBreaks(columnBreaks); si.setSheetWriter(sheetWriter); si.setDrawings(drawings); si.setImages(images); si.setValidatedCells(validatedCells); si.importSheet(); dataValidation = si.getDataValidation(); comboBox = si.getComboBox(); plsRecord = si.getPLSRecord(); chartOnly = si.isChartOnly(); buttonPropertySet = si.getButtonPropertySet(); numRows = si.getRows(); maxRowOutlineLevel = si.getMaxRowOutlineLevel(); maxColumnOutlineLevel = si.getMaxColumnOutlineLevel(); } /** * Extend the data validation contained in the specified cell across and * downwards * * @param c the number of cells accross to apply this data validation * @param r the number of cells downwards to apply this data validation */ public void applySharedDataValidation(WritableCell c, int extraCols, int extraRows) throws WriteException { // Check that the cell being applied has a data validation if (c.getWritableCellFeatures() == null || !c.getWritableCellFeatures().hasDataValidation()) { logger.warn("Cannot extend data validation for " + CellReferenceHelper.getCellReference(c.getColumn(), c.getRow()) + " as it has no data validation"); return; } // Check that none of the other cells in the range have any // cell validations int startColumn = c.getColumn(); int startRow = c.getRow(); int endRow = Math.min(numRows - 1, startRow + extraRows); for (int y = startRow; y <= endRow; y++) { if (rows[y] != null) { int endCol = Math.min(rows[y].getMaxColumn() -1, startColumn + extraCols); for (int x = startColumn; x <= endCol; x++) { // Ignore the first cell if (x == startColumn && y == startRow) { continue; // continue statements - they're no better than gotos } WritableCell c2 = rows[y].getCell(x); // Check that the target cell does not have any data validation if (c2 != null && c2.getWritableCellFeatures() != null && c2.getWritableCellFeatures().hasDataValidation()) { logger.warn("Cannot apply data validation from " + CellReferenceHelper.getCellReference(startColumn, startRow) + " to " + CellReferenceHelper.getCellReference (startColumn + extraCols, startRow + extraRows) + " as cell " + CellReferenceHelper.getCellReference(x, y) + " already has a data validation"); return; } } } } // Extend the range on the source data validation WritableCellFeatures sourceDataValidation = c.getWritableCellFeatures(); sourceDataValidation.getDVParser().extendCellValidation(extraCols, extraRows); // Go through all the additional cells and add the data validation cell for (int y = startRow; y <= startRow + extraRows; y++) { RowRecord rowrec = getRowRecord(y); // create the row if it doesn't exist for (int x = startColumn; x <= startColumn + extraCols; x++) { // Ignore the first cell if (x == startColumn && y == startRow) { continue; // continue statements - they're no better than gotos } WritableCell c2 = rowrec.getCell(x); // Check that the target cell does not have any data validation if (c2 == null) { Blank b = new Blank(x, y); WritableCellFeatures validation = new WritableCellFeatures(); validation.shareDataValidation(sourceDataValidation); b.setCellFeatures(validation); addCell(b); } else { // add the shared data validation to the existing cell WritableCellFeatures validation = c2.getWritableCellFeatures(); if (validation != null) { validation.shareDataValidation(sourceDataValidation); } else { validation = new WritableCellFeatures(); validation.shareDataValidation(sourceDataValidation); c2.setCellFeatures(validation); } } } } } /** * Remove the shared data validation from multiple cells. The cell passed * in is the top left cell. The data validation is removed from this * cell and all cells which share the same validation. * * @param cell the top left cell containing the shared data validation */ public void removeSharedDataValidation(WritableCell cell) throws WriteException { WritableCellFeatures wcf = cell.getWritableCellFeatures(); if (wcf == null || !wcf.hasDataValidation()) { return; } DVParser dvp = wcf.getDVParser(); // If the cell is not part of an extended validation, then simply call // the atomic remove validation from the cell features if (!dvp.extendedCellsValidation()) { wcf.removeDataValidation(); return; } // Check that the cell validation being removed is in the top left of the // validated area if (dvp.extendedCellsValidation()) { if (cell.getColumn() != dvp.getFirstColumn() || cell.getRow() != dvp.getFirstRow()) { logger.warn("Cannot remove data validation from " + CellReferenceHelper.getCellReference(dvp.getFirstColumn(), dvp.getFirstRow()) + "-" + CellReferenceHelper.getCellReference(dvp.getLastColumn(), dvp.getLastRow()) + " because the selected cell " + CellReferenceHelper.getCellReference(cell) + " is not the top left cell in the range"); return; } } for (int y = dvp.getFirstRow(); y <= dvp.getLastRow(); y++) { for (int x = dvp.getFirstColumn(); x <= dvp.getLastColumn(); x++) { CellValue c2 = (CellValue) rows[y].getCell(x); // It's possible that some cells in the shared data range might // be null eg. in the event of an insertRow or insertColumn if (c2 != null) { c2.getWritableCellFeatures().removeSharedDataValidation(); c2.removeCellFeatures(); } } } // Remove this shared validation from any data validations that were // copied in if (dataValidation != null) { dataValidation.removeSharedDataValidation(dvp.getFirstColumn(), dvp.getFirstRow(), dvp.getLastColumn(), dvp.getLastRow()); } } } jexcelapi/src/jxl/write/biff/NameRecord.java0000750000175000017500000004073311207000610021214 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.common.Logger; import jxl.biff.BuiltInName; import jxl.biff.IntegerHelper; import jxl.biff.StringHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * A name record. Simply takes the binary data from the name * record read in */ class NameRecord extends WritableRecordData { // The logger private static Logger logger = Logger.getLogger(NameRecord.class); /** * The binary data for output to file */ private byte[] data; /** * The name */ private String name; /** * The built in name */ private BuiltInName builtInName; /** * The index into the name table */ private int index; /** * The 0-based index sheet reference for a record name * 0 is for a global reference */ private int sheetRef = 0; /** * Modified flag */ private boolean modified; /** * A nested class to hold range information */ static class NameRange { private int columnFirst; private int rowFirst; private int columnLast; private int rowLast; private int externalSheet; NameRange(jxl.read.biff.NameRecord.NameRange nr) { columnFirst = nr.getFirstColumn(); rowFirst = nr.getFirstRow(); columnLast = nr.getLastColumn(); rowLast = nr.getLastRow(); externalSheet = nr.getExternalSheet(); } /** * Create a new range for the name record. */ NameRange(int extSheet, int theStartRow, int theEndRow, int theStartCol, int theEndCol) { columnFirst = theStartCol; rowFirst = theStartRow; columnLast = theEndCol; rowLast = theEndRow; externalSheet = extSheet; } int getFirstColumn() {return columnFirst;} int getFirstRow() {return rowFirst;} int getLastColumn() {return columnLast;} int getLastRow() {return rowLast;} int getExternalSheet() { return externalSheet;} void incrementFirstRow() { rowFirst++ ; } void incrementLastRow() { rowLast++ ; } void decrementFirstRow() { rowFirst-- ; } void decrementLastRow() { rowLast-- ; } void incrementFirstColumn() { columnFirst++ ; } void incrementLastColumn() { columnLast++ ; } void decrementFirstColumn() { columnFirst-- ; } void decrementLastColumn() { columnLast-- ; } byte[] getData() { byte[] d = new byte[10]; // Sheet index IntegerHelper.getTwoBytes(externalSheet, d, 0); // Starting row IntegerHelper.getTwoBytes(rowFirst, d, 2); // End row IntegerHelper.getTwoBytes(rowLast, d, 4); // Start column IntegerHelper.getTwoBytes(columnFirst & 0xff, d, 6); // End columns IntegerHelper.getTwoBytes(columnLast & 0xff, d, 8); return d; } } /** * The ranges covered by this name */ private NameRange[] ranges; // Constants which refer to the parse tokens after the string private static final int cellReference = 0x3a; private static final int areaReference = 0x3b; private static final int subExpression = 0x29; private static final int union = 0x10; // An empty range private static final NameRange EMPTY_RANGE = new NameRange(0,0,0,0,0); /** * Constructor - used when copying sheets * * @param index the index into the name table */ public NameRecord(jxl.read.biff.NameRecord sr, int ind) { super(Type.NAME); data = sr.getData(); name = sr.getName(); sheetRef = sr.getSheetRef(); index = ind; modified = false; // Copy the ranges jxl.read.biff.NameRecord.NameRange[] r = sr.getRanges(); ranges = new NameRange[r.length]; for (int i = 0 ; i < ranges.length ; i++) { ranges[i] = new NameRange(r[i]); } } /** * Create a new name record with the given information. * * @param theName Name to be created. * @param theIndex Index of this name. * @param extSheet External sheet index this name refers to. * @param theStartRow First row this name refers to. * @param theEndRow Last row this name refers to. * @param theStartCol First column this name refers to. * @param theEndCol Last column this name refers to. * @param global TRUE if this is a global name */ NameRecord(String theName, int theIndex, int extSheet, int theStartRow, int theEndRow, int theStartCol, int theEndCol, boolean global) { super(Type.NAME); name = theName; index = theIndex; sheetRef = global ? 0 : index+1; // 0 indicates a global name, otherwise // the 1-based index of the sheet ranges = new NameRange[1]; ranges[0] = new NameRange(extSheet, theStartRow, theEndRow, theStartCol, theEndCol); modified = true; } /** * Create a new name record with the given information. * * @param theName Name to be created. * @param theIndex Index of this name. * @param extSheet External sheet index this name refers to. * @param theStartRow First row this name refers to. * @param theEndRow Last row this name refers to. * @param theStartCol First column this name refers to. * @param theEndCol Last column this name refers to. * @param global TRUE if this is a global name */ NameRecord(BuiltInName theName, int theIndex, int extSheet, int theStartRow, int theEndRow, int theStartCol, int theEndCol, boolean global) { super(Type.NAME); builtInName = theName; index = theIndex; sheetRef = global ? 0 : index + 1; // 0 indicates a global name, otherwise // the 1-based index of the sheet ranges = new NameRange[1]; ranges[0] = new NameRange(extSheet, theStartRow, theEndRow, theStartCol, theEndCol); } /** * Create a new name record with the given information for 2-range entities. * * @param theName Name to be created. * @param theIndex Index of this name. * @param extSheet External sheet index this name refers to. * @param theStartRow First row this name refers to. * @param theEndRow Last row this name refers to. * @param theStartCol First column this name refers to. * @param theEndCol Last column this name refers to. * @param theStartRow2 First row this name refers to (2nd instance). * @param theEndRow2 Last row this name refers to (2nd instance). * @param theStartCol2 First column this name refers to (2nd instance). * @param theEndCol2 Last column this name refers to (2nd instance). * @param global TRUE if this is a global name */ NameRecord(BuiltInName theName, int theIndex, int extSheet, int theStartRow, int theEndRow, int theStartCol, int theEndCol, int theStartRow2, int theEndRow2, int theStartCol2, int theEndCol2, boolean global) { super(Type.NAME); builtInName = theName; index = theIndex; sheetRef = global ? 0 : index + 1; // 0 indicates a global name, otherwise // the 1-based index of the sheet ranges = new NameRange[2]; ranges[0] = new NameRange(extSheet, theStartRow, theEndRow, theStartCol, theEndCol); ranges[1] = new NameRange(extSheet, theStartRow2, theEndRow2, theStartCol2, theEndCol2); } /** * Gets the binary data for output to file * * @return the binary data */ public byte[] getData() { if (data != null && !modified) { // this is a copy return data; } final int NAME_HEADER_LENGTH = 15; final byte AREA_RANGE_LENGTH = 11; final byte AREA_REFERENCE = 0x3b; int detailLength; if (ranges.length > 1) { detailLength = (ranges.length * AREA_RANGE_LENGTH) + 4; } else { detailLength = AREA_RANGE_LENGTH; } int length = NAME_HEADER_LENGTH + detailLength; length += builtInName != null ? 1 : name.length(); data = new byte[length]; // Options int options = 0; if (builtInName != null) { options |= 0x20; } IntegerHelper.getTwoBytes(options, data, 0); // Keyboard shortcut data[2] = 0; // Length of the name in chars if (builtInName != null) { data[3] = (byte) 0x1; } else { data[3] = (byte) name.length(); } // Size of the definitions IntegerHelper.getTwoBytes(detailLength, data, 4); // Sheet index IntegerHelper.getTwoBytes(sheetRef, data, 6); IntegerHelper.getTwoBytes(sheetRef, data, 8); // Byte 10-13 are optional lengths [0,0,0,0] // Byte 14 is length of name which is not used. // The name if (builtInName != null) { data[15] = (byte) builtInName.getValue(); } else { StringHelper.getBytes(name, data, 15); } // The actual range definition. int pos = builtInName != null ? 16 : name.length() + 15; // If there are multiple ranges for the name, we must specify a // subExpression type rather than areaReference and then put out // multiple areaReference entries with an end byte. if (ranges.length > 1) { data[pos++] = subExpression; // Length of remaining bytes excluding itself IntegerHelper.getTwoBytes(detailLength - 3, data, pos); pos += 2; byte[] rd; for (int i = 0 ; i < ranges.length ; i++) { data[pos++] = areaReference; rd = ranges[i].getData(); System.arraycopy(rd, 0, data, pos, rd.length); pos += rd.length; } data[pos] = 0x10; } else { // Range format - area data[pos] = areaReference; // The range data byte[] rd = ranges[0].getData(); System.arraycopy(rd, 0, data, pos+1, rd.length); } return data; } /** * Accessor for the name * * @return the name */ public String getName() { return name; } /** * Accessor for the index of this name in the name table * * @return the index of this name in the name table */ public int getIndex() { return index; } /** * The 0-based index sheet reference for a record name * 0 is for a global reference * * @return the sheet reference for name formula */ public int getSheetRef() { return sheetRef; } /** * Set the index sheet reference for a record name * 0 is for a global reference * */ public void setSheetRef(int i) { sheetRef = i; IntegerHelper.getTwoBytes(sheetRef, data, 8); } /** * Gets the array of ranges for this name * @return the ranges */ public NameRange[] getRanges() { return ranges; } /** * Called when a row is inserted on the * * @param sheetIndex the sheet index on which the column was inserted * @param row the column number which was inserted */ void rowInserted(int sheetIndex, int row) { for (int i = 0 ; i < ranges.length ; i++) { if (sheetIndex != ranges[i].getExternalSheet()) { continue; // shame on me - this is no better than a goto } if (row <= ranges[i].getFirstRow()) { ranges[i].incrementFirstRow(); modified = true; } if (row <= ranges[i].getLastRow()) { ranges[i].incrementLastRow(); modified = true; } } } /** * Called when a row is removed on the worksheet * * @param sheetIndex the sheet index on which the column was inserted * @param row the column number which was inserted * @reeturn TRUE if the name is to be removed entirely, FALSE otherwise */ boolean rowRemoved(int sheetIndex, int row) { for (int i = 0 ; i < ranges.length ; i++) { if (sheetIndex != ranges[i].getExternalSheet()) { continue; // shame on me - this is no better than a goto } if (row == ranges[i].getFirstRow() && row == ranges[i].getLastRow()) { // remove the range ranges[i] = EMPTY_RANGE; } if (row < ranges[i].getFirstRow() && row > 0) { ranges[i].decrementFirstRow(); modified = true; } if (row <= ranges[i].getLastRow()) { ranges[i].decrementLastRow(); modified = true; } } // If all ranges are empty, then remove the name int emptyRanges = 0; for (int i = 0 ; i < ranges.length; i++) { if (ranges[i] == EMPTY_RANGE) { emptyRanges++; } } if (emptyRanges == ranges.length) { return true; } // otherwise just remove the empty ones NameRange[] newRanges = new NameRange[ranges.length - emptyRanges]; for (int i = 0 ; i < ranges.length ; i++) { if (ranges[i] != EMPTY_RANGE) { newRanges[i] = ranges[i]; } } ranges = newRanges; return false; } /** * Called when a row is removed on the worksheet * * @param sheetIndex the sheet index on which the column was inserted * @param row the column number which was inserted * @reeturn TRUE if the name is to be removed entirely, FALSE otherwise */ boolean columnRemoved(int sheetIndex, int col) { for (int i = 0 ; i < ranges.length ; i++) { if (sheetIndex != ranges[i].getExternalSheet()) { continue; // shame on me - this is no better than a goto } if (col == ranges[i].getFirstColumn() && col == ranges[i].getLastColumn()) { // remove the range ranges[i] = EMPTY_RANGE; } if (col < ranges[i].getFirstColumn() && col > 0) { ranges[i].decrementFirstColumn(); modified = true; } if (col <= ranges[i].getLastColumn()) { ranges[i].decrementLastColumn(); modified = true; } } // If all ranges are empty, then remove the name int emptyRanges = 0; for (int i = 0 ; i < ranges.length; i++) { if (ranges[i] == EMPTY_RANGE) { emptyRanges++; } } if (emptyRanges == ranges.length) { return true; } // otherwise just remove the empty ones NameRange[] newRanges = new NameRange[ranges.length - emptyRanges]; for (int i = 0 ; i < ranges.length ; i++) { if (ranges[i] != EMPTY_RANGE) { newRanges[i] = ranges[i]; } } ranges = newRanges; return false; } /** * Called when a row is inserted on the * * @param sheetIndex the sheet index on which the column was inserted * @param col the column number which was inserted */ void columnInserted(int sheetIndex, int col) { for (int i = 0 ; i < ranges.length ; i++) { if (sheetIndex != ranges[i].getExternalSheet()) { continue; // shame on me - this is no better than a goto } if (col <= ranges[i].getFirstColumn()) { ranges[i].incrementFirstColumn(); modified = true; } if (col <= ranges[i].getLastColumn()) { ranges[i].incrementLastColumn(); modified = true; } } } } jexcelapi/src/jxl/write/biff/BOFRecord.java0000750000175000017500000000605311207000610020737 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Record to indicate the beginning of a new stream in the Compound * File */ class BOFRecord extends WritableRecordData { /** * The data to write to the file */ private byte[] data; // Dummy types for constructor overloading private static class WorkbookGlobalsBOF{}; private static class SheetBOF{}; public final static WorkbookGlobalsBOF workbookGlobals = new WorkbookGlobalsBOF(); public final static SheetBOF sheet = new SheetBOF(); /** * Constructor for generating a workbook globals BOF record * * @param dummy - a dummy argument for overloading purposes */ public BOFRecord(WorkbookGlobalsBOF dummy) { super(Type.BOF); // Create the data as biff 8 format with a substream type of // workbook globals data = new byte[] {(byte) 0x0, (byte) 0x6, (byte) 0x5, // substream type (byte) 0x0, // substream type (byte) 0xf2, // rupBuild (byte) 0x15, // rupBuild (byte) 0xcc, // rupYear (byte) 0x07, // rupYear (byte) 0x0, // bfh (byte) 0x0, // bfh (byte) 0x0, // bfh (byte) 0x0, // bfh (byte) 0x6, // sfo (byte) 0x0, // sfo, (byte) 0x0, // sfo (byte) 0x0 // sfo }; } /** * Constructor for generating a sheet BOF record * * @param dummy - a dummy argument for overloading purposes */ public BOFRecord(SheetBOF dummy) { super(Type.BOF); // Create the data as biff 8 format with a substream type of // worksheet data = new byte[] {(byte) 0x0, (byte) 0x6, (byte) 0x10, // substream type (byte) 0x0, // substream type (byte) 0xf2, // rupBuild (byte) 0x15, // rupBuild (byte) 0xcc, // rupYear (byte) 0x07, // rupYear (byte) 0x0, // bfh (byte) 0x0, // bfh (byte) 0x0, // bfh (byte) 0x0, // bfh (byte) 0x6, // sfo (byte) 0x0, // sfo, (byte) 0x0, // sfo (byte) 0x0 // sfo }; } /** * Gets the data for writing to the output file * * @return the binary data for writing */ public byte[] getData() { return data; } } jexcelapi/src/jxl/write/biff/WritableWorkbookImpl.java0000750000175000017500000014605511207000610023312 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import jxl.common.Assert; import jxl.common.Logger; import jxl.Range; import jxl.Sheet; import jxl.Workbook; import jxl.WorkbookSettings; import jxl.biff.BuiltInName; import jxl.biff.CellReferenceHelper; import jxl.biff.CountryCode; import jxl.biff.Fonts; import jxl.biff.FormattingRecords; import jxl.biff.IndexMapping; import jxl.biff.IntegerHelper; import jxl.biff.RangeImpl; import jxl.biff.WorkbookMethods; import jxl.biff.XCTRecord; import jxl.biff.drawing.Drawing; import jxl.biff.drawing.DrawingGroup; import jxl.biff.drawing.DrawingGroupObject; import jxl.biff.drawing.Origin; import jxl.biff.formula.ExternalSheet; import jxl.format.Colour; import jxl.format.RGB; import jxl.read.biff.WorkbookParser; import jxl.write.WritableCell; import jxl.write.WritableSheet; import jxl.write.WritableWorkbook; /** * A writable workbook */ public class WritableWorkbookImpl extends WritableWorkbook implements ExternalSheet, WorkbookMethods { /** * The logger */ private static Logger logger = Logger.getLogger(WritableWorkbookImpl.class); /** * The list of formats available within this workbook */ private FormattingRecords formatRecords; /** * The output file to write the workbook to */ private File outputFile; /** * The list of sheets within this workbook */ private ArrayList sheets; /** * The list of fonts available within this workbook */ private Fonts fonts; /** * The list of external sheets, used by cell references in formulas */ private ExternalSheetRecord externSheet; /** * The supbook records */ private ArrayList supbooks; /** * The name records */ private ArrayList names; /** * A lookup hash map of the name records */ private HashMap nameRecords; /** * The shared strings used by this workbook */ private SharedStrings sharedStrings; /** * Indicates whether or not the output stream should be closed. This * depends on whether this Workbook was created with an output stream, * or a flat file (flat file closes the stream */ private boolean closeStream; /** * The workbook protection flag */ private boolean wbProtected; /** * The settings for the workbook */ private WorkbookSettings settings; /** * The list of cells for the entire workbook which need to be updated * following a row/column insert or remove */ private ArrayList rcirCells; /** * The drawing group */ private DrawingGroup drawingGroup; /** * The jxl.common.workbook styles */ private Styles styles; /** * Contains macros flag */ private boolean containsMacros; /** * The buttons property set */ private ButtonPropertySetRecord buttonPropertySet; /** * The country record, initialised when copying a workbook */ private CountryRecord countryRecord; // synchronizer object for static unitiatialization private static Object SYNCHRONIZER = new Object(); /** * The names of any add in functions */ private String[] addInFunctionNames; /** * The XCT records */ private XCTRecord[] xctRecords; /** * Constructor. Writes the workbook direct to the existing output stream * * @exception IOException * @param os the output stream * @param cs TRUE if the workbook should close the output stream, FALSE * @param ws the configuration for this workbook * otherwise */ public WritableWorkbookImpl(OutputStream os, boolean cs, WorkbookSettings ws) throws IOException { super(); outputFile = new File(os, ws, null); sheets = new ArrayList(); sharedStrings = new SharedStrings(); nameRecords = new HashMap(); closeStream = cs; wbProtected = false; containsMacros = false; settings = ws; rcirCells = new ArrayList(); styles = new Styles(); // Reset the statically declared styles. These are no longer needed // because the Styles class will intercept all calls within // CellValue.setCellDetails and if it detects a standard format, then it // will return a clone. In short, the static cell values will // never get initialized anyway. Still, just to be extra sure... synchronized(SYNCHRONIZER) { WritableWorkbook.ARIAL_10_PT.uninitialize(); WritableWorkbook.HYPERLINK_FONT.uninitialize(); WritableWorkbook.NORMAL_STYLE.uninitialize(); WritableWorkbook.HYPERLINK_STYLE.uninitialize(); WritableWorkbook.HIDDEN_STYLE.uninitialize(); DateRecord.defaultDateFormat.uninitialize(); } WritableFonts wf = new WritableFonts(this); fonts = wf; WritableFormattingRecords wfr = new WritableFormattingRecords(fonts, styles); formatRecords = wfr; } /** * A pseudo copy constructor. Takes the handles to the font and formatting * records * * @exception IOException * @param w the workbook to copy * @param os the output stream to write the data to * @param cs TRUE if the workbook should close the output stream, FALSE * @param ws the configuration for this workbook */ public WritableWorkbookImpl(OutputStream os, Workbook w, boolean cs, WorkbookSettings ws) throws IOException { super(); WorkbookParser wp = (WorkbookParser) w; // Reset the statically declared styles. These are no longer needed // because the Styles class will intercept all calls within // CellValue.setCellDetails and if it detects a standard format, then it // will return a clone. In short, the static cell values will // never get initialized anyway. Still, just to be extra sure... synchronized(SYNCHRONIZER) { WritableWorkbook.ARIAL_10_PT.uninitialize(); WritableWorkbook.HYPERLINK_FONT.uninitialize(); WritableWorkbook.NORMAL_STYLE.uninitialize(); WritableWorkbook.HYPERLINK_STYLE.uninitialize(); WritableWorkbook.HIDDEN_STYLE.uninitialize(); DateRecord.defaultDateFormat.uninitialize(); } closeStream = cs; sheets = new ArrayList(); sharedStrings = new SharedStrings(); nameRecords = new HashMap(); fonts = wp.getFonts(); formatRecords = wp.getFormattingRecords(); wbProtected = false; settings = ws; rcirCells = new ArrayList(); styles = new Styles(); outputFile = new File(os, ws, wp.getCompoundFile()); containsMacros = false; if (!ws.getPropertySetsDisabled()) { containsMacros = wp.containsMacros(); } // Copy the country settings if (wp.getCountryRecord() != null) { countryRecord = new CountryRecord(wp.getCountryRecord()); } // Copy any add in functions addInFunctionNames = wp.getAddInFunctionNames(); // Copy XCT records xctRecords = wp.getXCTRecords(); // Copy any external sheets if (wp.getExternalSheetRecord() != null) { externSheet = new ExternalSheetRecord(wp.getExternalSheetRecord()); // Get the associated supbooks jxl.read.biff.SupbookRecord[] readsr = wp.getSupbookRecords(); supbooks = new ArrayList(readsr.length); for (int i = 0; i < readsr.length; i++) { jxl.read.biff.SupbookRecord readSupbook = readsr[i]; if (readSupbook.getType() == readSupbook.INTERNAL || readSupbook.getType() == readSupbook.EXTERNAL) { supbooks.add(new SupbookRecord(readSupbook, settings)); } else { if (readSupbook.getType() != readSupbook.ADDIN) { logger.warn("unsupported supbook type - ignoring"); } } } } // Copy any drawings. These must be present before we try and copy // the images from the read workbook if (wp.getDrawingGroup() != null) { drawingGroup = new DrawingGroup(wp.getDrawingGroup()); } // Copy the property set references if (containsMacros && wp.getButtonPropertySet() != null) { buttonPropertySet = new ButtonPropertySetRecord (wp.getButtonPropertySet()); } // Copy any names if (!settings.getNamesDisabled()) { jxl.read.biff.NameRecord[] na = wp.getNameRecords(); names = new ArrayList(na.length); for (int i = 0; i < na.length; i++) { if (na[i].isBiff8()) { NameRecord n = new NameRecord(na[i], i); names.add(n); String name = n.getName(); nameRecords.put(name, n); } else { logger.warn("Cannot copy Biff7 name records - ignoring"); } } } copyWorkbook(w); // The copy process may have caused some critical fields in the // read drawing group to change. Make sure these updates are reflected // in the writable drawing group if (drawingGroup != null) { drawingGroup.updateData(wp.getDrawingGroup()); } } /** * Gets the sheets within this workbook. Use of this method for * large worksheets can cause performance problems. * * @return an array of the individual sheets */ public WritableSheet[] getSheets() { WritableSheet[] sheetArray = new WritableSheet[getNumberOfSheets()]; for (int i = 0 ; i < getNumberOfSheets() ; i++) { sheetArray[i] = getSheet(i); } return sheetArray; } /** * Gets the sheet names * * @return an array of strings containing the sheet names */ public String[] getSheetNames() { String[] sheetNames = new String[getNumberOfSheets()]; for (int i = 0 ; i < sheetNames.length ; i++) { sheetNames[i] = getSheet(i).getName(); } return sheetNames; } /** * Interface method from WorkbookMethods - gets the specified * sheet within this workbook * * @param index the zero based index of the required sheet * @return The sheet specified by the index */ public Sheet getReadSheet(int index) { return getSheet(index); } /** * Gets the specified sheet within this workbook * * @param index the zero based index of the reQuired sheet * @return The sheet specified by the index */ public WritableSheet getSheet(int index) { return (WritableSheet) sheets.get(index); } /** * Gets the sheet with the specified name from within this workbook * * @param name the sheet name * @return The sheet with the specified name, or null if it is not found */ public WritableSheet getSheet(String name) { // Iterate through the boundsheet records boolean found = false; Iterator i = sheets.iterator(); WritableSheet s = null; while (i.hasNext() && !found) { s = (WritableSheet) i.next(); if (s.getName().equals(name)) { found = true; } } return found ? s : null; } /** * Returns the number of sheets in this workbook * * @return the number of sheets in this workbook */ public int getNumberOfSheets() { return sheets.size(); } /** * Closes this workbook, and frees makes any memory allocated available * for garbage collection * * @exception IOException * @exception JxlWriteException */ public void close() throws IOException, JxlWriteException { outputFile.close(closeStream); } /** * Sets a new output file. This allows the smae workbook to be * written to various different output files without having to * read in any templates again * * @param fileName the file name * @exception IOException */ public void setOutputFile(java.io.File fileName) throws IOException { FileOutputStream fos = new FileOutputStream(fileName); outputFile.setOutputFile(fos); } /** * The internal method implementation for creating new sheets * * @param name * @param index * @param handleRefs flag indicating whether or not to handle external * sheet references * @return */ private WritableSheet createSheet(String name, int index, boolean handleRefs) { WritableSheet w = new WritableSheetImpl(name, outputFile, formatRecords, sharedStrings, settings, this); int pos = index; if (index <= 0) { pos = 0; sheets.add(0, w); } else if (index > sheets.size()) { pos = sheets.size(); sheets.add(w); } else { sheets.add(index, w); } if (handleRefs && externSheet != null) { externSheet.sheetInserted(pos); } if (supbooks != null && supbooks.size() > 0) { SupbookRecord supbook = (SupbookRecord) supbooks.get(0); if (supbook.getType() == SupbookRecord.INTERNAL) { supbook.adjustInternal(sheets.size()); } } return w; } /** * Creates a new sheet within the workbook, at the specified position. * The new sheet is inserted at the specified position, or prepended/appended * to the list of sheets if the index specified is somehow inappropriate * * @param name the name of the new sheet * @param index the index at which to add the sheet * @return the created sheet */ public WritableSheet createSheet(String name, int index) { return createSheet(name, index, true); } /** * Removes a sheet from this workbook, the other sheets indices being * altered accordingly. If the sheet referenced by the index * does not exist, then no action is taken. * * @param index the index of the sheet to remove */ public void removeSheet(int index) { int pos = index; if (index <= 0) { pos = 0; sheets.remove(0); } else if (index >= sheets.size()) { pos = sheets.size() - 1; sheets.remove(sheets.size() - 1); } else { sheets.remove(index); } if (externSheet != null) { externSheet.sheetRemoved(pos); } if (supbooks != null && supbooks.size() > 0) { SupbookRecord supbook = (SupbookRecord) supbooks.get(0); if (supbook.getType() == SupbookRecord.INTERNAL) { supbook.adjustInternal(sheets.size()); } } if (names != null && names.size() > 0) { for (int i=0; i< names.size();i++) { NameRecord n = (NameRecord) names.get(i); int oldRef = n.getSheetRef(); if(oldRef == (pos+1)) { n.setSheetRef(0); // make a global name reference } else if (oldRef > (pos+1)) { if(oldRef < 1) { oldRef = 1; } n.setSheetRef(oldRef-1); // move one sheet } } } } /** * Moves the specified sheet within this workbook to another index * position. * * @param fromIndex the zero based index of the reQuired sheet * @param toIndex the zero based index of the reQuired sheet * @return the sheet that has been moved */ public WritableSheet moveSheet(int fromIndex, int toIndex) { // Handle dodgy index fromIndex = Math.max(fromIndex, 0); fromIndex = Math.min(fromIndex, sheets.size() - 1); toIndex = Math.max(toIndex, 0); toIndex = Math.min(toIndex, sheets.size() - 1); WritableSheet sheet= (WritableSheet)sheets.remove(fromIndex); sheets.add(toIndex, sheet); return sheet; } /** * Writes out this sheet to the output file. First it writes out * the standard workbook information required by excel, before calling * the write method on each sheet individually * * @exception IOException */ public void write() throws IOException { // Perform some preliminary sheet check before we start writing out // the workbook WritableSheetImpl wsi = null; for (int i = 0; i < getNumberOfSheets(); i++) { wsi = (WritableSheetImpl) getSheet(i); // Check the merged records. This has to be done before the // globals are written out because some more XF formats might be created wsi.checkMergedBorders(); // Check to see if there are any predefined names Range range = wsi.getSettings().getPrintArea(); if (range != null) { addNameArea(BuiltInName.PRINT_AREA, wsi, range.getTopLeft().getColumn(), range.getTopLeft().getRow(), range.getBottomRight().getColumn(), range.getBottomRight().getRow(), false); } // Check to see if print titles by row were set Range rangeR = wsi.getSettings().getPrintTitlesRow(); Range rangeC = wsi.getSettings().getPrintTitlesCol(); if (rangeR != null && rangeC != null) { addNameArea(BuiltInName.PRINT_TITLES, wsi, rangeR.getTopLeft().getColumn(), rangeR.getTopLeft().getRow(), rangeR.getBottomRight().getColumn(), rangeR.getBottomRight().getRow(), rangeC.getTopLeft().getColumn(), rangeC.getTopLeft().getRow(), rangeC.getBottomRight().getColumn(), rangeC.getBottomRight().getRow(), false); } // Check to see if print titles by row were set else if (rangeR != null) { addNameArea(BuiltInName.PRINT_TITLES, wsi, rangeR.getTopLeft().getColumn(), rangeR.getTopLeft().getRow(), rangeR.getBottomRight().getColumn(), rangeR.getBottomRight().getRow(), false); } // Check to see if print titles by column were set else if (rangeC != null) { addNameArea(BuiltInName.PRINT_TITLES, wsi, rangeC.getTopLeft().getColumn(), rangeC.getTopLeft().getRow(), rangeC.getBottomRight().getColumn(), rangeC.getBottomRight().getRow(), false); } } // Rationalize all the XF and number formats if (!settings.getRationalizationDisabled()) { rationalize(); } // Write the workbook globals BOFRecord bof = new BOFRecord(BOFRecord.workbookGlobals); outputFile.write(bof); // Must immediatly follow the BOF record if (settings.getTemplate()) { // Only write record if we are a template TemplateRecord trec= new TemplateRecord(); outputFile.write(trec); } InterfaceHeaderRecord ihr = new InterfaceHeaderRecord(); outputFile.write(ihr); MMSRecord mms = new MMSRecord(0,0); outputFile.write(mms); InterfaceEndRecord ier = new InterfaceEndRecord(); outputFile.write(ier); WriteAccessRecord wr = new WriteAccessRecord(settings.getWriteAccess()); outputFile.write(wr); CodepageRecord cp = new CodepageRecord(); outputFile.write(cp); DSFRecord dsf = new DSFRecord(); outputFile.write(dsf); if (settings.getExcel9File()) { // Only write record if we are a template // We are not excel 2000, should we still set the flag Excel9FileRecord e9rec= new Excel9FileRecord(); outputFile.write(e9rec); } TabIdRecord tabid = new TabIdRecord(getNumberOfSheets()); outputFile.write(tabid); if (containsMacros) { ObjProjRecord objproj = new ObjProjRecord(); outputFile.write(objproj); } if (buttonPropertySet != null) { outputFile.write(buttonPropertySet); } FunctionGroupCountRecord fgcr = new FunctionGroupCountRecord(); outputFile.write(fgcr); // do not support password protected workbooks WindowProtectRecord wpr = new WindowProtectRecord (settings.getWindowProtected()); outputFile.write(wpr); ProtectRecord pr = new ProtectRecord(wbProtected); outputFile.write(pr); PasswordRecord pw = new PasswordRecord(null); outputFile.write(pw); Prot4RevRecord p4r = new Prot4RevRecord(false); outputFile.write(p4r); Prot4RevPassRecord p4rp = new Prot4RevPassRecord(); outputFile.write(p4rp); // If no sheet is identified as being selected, then select // the first one boolean sheetSelected = false; WritableSheetImpl wsheet = null; int selectedSheetIndex = 0; for (int i = 0 ; i < getNumberOfSheets() && !sheetSelected ; i++) { wsheet = (WritableSheetImpl) getSheet(i); if (wsheet.getSettings().isSelected()) { sheetSelected = true; selectedSheetIndex = i; } } if (!sheetSelected) { wsheet = (WritableSheetImpl) getSheet(0); wsheet.getSettings().setSelected(true); selectedSheetIndex = 0; } Window1Record w1r = new Window1Record(selectedSheetIndex); outputFile.write(w1r); BackupRecord bkr = new BackupRecord(false); outputFile.write(bkr); HideobjRecord ho = new HideobjRecord(settings.getHideobj()); outputFile.write(ho); NineteenFourRecord nf = new NineteenFourRecord(false); outputFile.write(nf); PrecisionRecord pc = new PrecisionRecord(false); outputFile.write(pc); RefreshAllRecord rar = new RefreshAllRecord(settings.getRefreshAll()); outputFile.write(rar); BookboolRecord bb = new BookboolRecord(true); outputFile.write(bb); // Write out all the fonts used fonts.write(outputFile); // Write out the cell formats used within this workbook formatRecords.write(outputFile); // Write out the palette, if it exists if (formatRecords.getPalette() != null) { outputFile.write(formatRecords.getPalette()); } // Write out the uses elfs record UsesElfsRecord uer = new UsesElfsRecord(); outputFile.write(uer); // Write out the boundsheet records. Keep a handle to each one's // position so we can write in the stream offset later int[] boundsheetPos = new int[getNumberOfSheets()]; Sheet sheet = null; for (int i = 0; i < getNumberOfSheets(); i++) { boundsheetPos[i] = outputFile.getPos(); sheet = getSheet(i); BoundsheetRecord br = new BoundsheetRecord(sheet.getName()); if (sheet.getSettings().isHidden()) { br.setHidden(); } if ( ( (WritableSheetImpl) sheets.get(i)).isChartOnly()) { br.setChartOnly(); } outputFile.write(br); } if (countryRecord == null) { CountryCode lang = CountryCode.getCountryCode(settings.getExcelDisplayLanguage()); if (lang == CountryCode.UNKNOWN) { logger.warn("Unknown country code " + settings.getExcelDisplayLanguage() + " using " + CountryCode.USA.getCode()); lang = CountryCode.USA; } CountryCode region = CountryCode.getCountryCode(settings.getExcelRegionalSettings()); countryRecord = new CountryRecord(lang, region); if (region == CountryCode.UNKNOWN) { logger.warn("Unknown country code " + settings.getExcelDisplayLanguage() + " using " + CountryCode.UK.getCode()); region = CountryCode.UK; } } outputFile.write(countryRecord); // Write out the names of any add in functions if (addInFunctionNames != null && addInFunctionNames.length > 0) { // Write out the supbook record // SupbookRecord supbook = new SupbookRecord(); // outputFile.write(supbook); for (int i = 0 ; i < addInFunctionNames.length; i++) { ExternalNameRecord enr = new ExternalNameRecord(addInFunctionNames[i]); outputFile.write(enr); } } if (xctRecords != null) { for (int i = 0 ; i < xctRecords.length; i++) { outputFile.write(xctRecords[i]); } } // Write out the external sheet record, if it exists if (externSheet != null) { //Write out all the supbook records for (int i = 0; i < supbooks.size() ; i++) { SupbookRecord supbook = (SupbookRecord) supbooks.get(i); outputFile.write(supbook); } outputFile.write(externSheet); } // Write out the names, if any exists if (names != null) { for (int i = 0 ; i < names.size() ; i++) { NameRecord n = (NameRecord) names.get(i); outputFile.write(n); } } // Write out the mso drawing group, if it exists if (drawingGroup != null) { drawingGroup.write(outputFile); } sharedStrings.write(outputFile); EOFRecord eof = new EOFRecord(); outputFile.write(eof); // Write out the sheets for (int i = 0; i < getNumberOfSheets(); i++) { // first go back and modify the offset we wrote out for the // boundsheet record outputFile.setData (IntegerHelper.getFourBytes(outputFile.getPos()), boundsheetPos[i] + 4); wsheet = (WritableSheetImpl) getSheet(i); wsheet.write(); } } /** * Produces a writable copy of the workbook passed in by * creating copies of each sheet in the specified workbook and adding * them to its own record * * @param w the workbook to copy */ private void copyWorkbook(Workbook w) { int numSheets = w.getNumberOfSheets(); wbProtected = w.isProtected(); Sheet s = null; WritableSheetImpl ws = null; for (int i = 0 ; i < numSheets; i++) { s = w.getSheet(i); ws = (WritableSheetImpl) createSheet(s.getName(),i, false); ws.copy(s); } } /** * Copies the specified sheet and places it at the index * specified by the parameter * * @param s the index of the sheet to copy * @param name the name of the new sheet * @param index the position of the new sheet */ public void copySheet(int s, String name, int index) { WritableSheet sheet = getSheet(s); WritableSheetImpl ws = (WritableSheetImpl) createSheet(name, index); ws.copy(sheet); } /** * Copies the specified sheet and places it at the index * specified by the parameter * * @param s the name of the sheet to copy * @param name the name of the new sheet * @param index the position of the new sheet */ public void copySheet(String s, String name, int index) { WritableSheet sheet = getSheet(s); WritableSheetImpl ws = (WritableSheetImpl) createSheet(name, index); ws.copy(sheet); } /** * Indicates whether or not this workbook is protected * * @param prot protected flag */ public void setProtected(boolean prot) { wbProtected = prot; } /** * Rationalizes the cell formats, and then passes the resultant XF index * mappings to each sheet in turn */ private void rationalize() { IndexMapping fontMapping = formatRecords.rationalizeFonts(); IndexMapping formatMapping = formatRecords.rationalizeDisplayFormats(); IndexMapping xfMapping = formatRecords.rationalize(fontMapping, formatMapping); WritableSheetImpl wsi = null; for (int i = 0; i < sheets.size(); i++) { wsi = (WritableSheetImpl) sheets.get(i); wsi.rationalize(xfMapping, fontMapping, formatMapping); } } /** * Gets the internal sheet index for a sheet name * * @param name the sheet name * @return the internal sheet index */ private int getInternalSheetIndex(String name) { int index = -1; String[] names = getSheetNames(); for (int i = 0 ; i < names.length; i++) { if (name.equals(names[i])) { index = i; break; } } return index; } /** * Gets the name of the external sheet specified by the index * * @param index the external sheet index * @return the name of the external sheet */ public String getExternalSheetName(int index) { int supbookIndex = externSheet.getSupbookIndex(index); SupbookRecord sr = (SupbookRecord) supbooks.get(supbookIndex); int firstTab = externSheet.getFirstTabIndex(index); if (sr.getType() == SupbookRecord.INTERNAL) { // It's an internal reference - get the name from the sheets list WritableSheet ws = getSheet(firstTab); return ws.getName(); } else if (sr.getType() == SupbookRecord.EXTERNAL) { String name = sr.getFileName() + sr.getSheetName(firstTab); return name; } // An unknown supbook - return unkown logger.warn("Unknown Supbook 1"); return "[UNKNOWN]"; } /** * Gets the name of the last external sheet specified by the index * * @param index the external sheet index * @return the name of the external sheet */ public String getLastExternalSheetName(int index) { int supbookIndex = externSheet.getSupbookIndex(index); SupbookRecord sr = (SupbookRecord) supbooks.get(supbookIndex); int lastTab = externSheet.getLastTabIndex(index); if (sr.getType() == SupbookRecord.INTERNAL) { // It's an internal reference - get the name from the sheets list WritableSheet ws = getSheet(lastTab); return ws.getName(); } else if (sr.getType() == SupbookRecord.EXTERNAL) { Assert.verify(false); } // An unknown supbook - return unkown logger.warn("Unknown Supbook 2"); return "[UNKNOWN]"; } /** * Parsing of formulas is only supported for a subset of the available * biff version, so we need to test to see if this version is acceptable * * @return the BOF record, which */ public jxl.read.biff.BOFRecord getWorkbookBof() { return null; } /** * Gets the index of the external sheet for the name * * @param sheetName * @return the sheet index of the external sheet index */ public int getExternalSheetIndex(int index) { if (externSheet == null) { return index; } Assert.verify(externSheet != null); int firstTab = externSheet.getFirstTabIndex(index); return firstTab; } /** * Gets the index of the external sheet for the name * * @param sheetName * @return the sheet index of the external sheet index */ public int getLastExternalSheetIndex(int index) { if (externSheet == null) { return index; } Assert.verify(externSheet != null); int lastTab = externSheet.getLastTabIndex(index); return lastTab; } /** * Gets the external sheet index for the sheet name * * @param sheetName * @return the sheet index or -1 if the sheet could not be found */ public int getExternalSheetIndex(String sheetName) { if (externSheet == null) { externSheet = new ExternalSheetRecord(); supbooks = new ArrayList(); supbooks.add(new SupbookRecord(getNumberOfSheets(), settings)); } // Iterate through the sheets records boolean found = false; Iterator i = sheets.iterator(); int sheetpos = 0; WritableSheetImpl s = null; while (i.hasNext() && !found) { s = (WritableSheetImpl) i.next(); if (s.getName().equals(sheetName)) { found = true; } else { sheetpos++; } } if (found) { // Check that the supbook record at position zero is internal and // contains all the sheets SupbookRecord supbook = (SupbookRecord) supbooks.get(0); if (supbook.getType() != SupbookRecord.INTERNAL || supbook.getNumberOfSheets() != getNumberOfSheets()) { logger.warn("Cannot find sheet " + sheetName + " in supbook record"); } return externSheet.getIndex(0, sheetpos); } // Check for square brackets int closeSquareBracketsIndex = sheetName.lastIndexOf(']'); int openSquareBracketsIndex = sheetName.lastIndexOf('['); if (closeSquareBracketsIndex == -1 || openSquareBracketsIndex == -1) { logger.warn("Square brackets"); return -1; } String worksheetName = sheetName.substring(closeSquareBracketsIndex+1); String workbookName = sheetName.substring(openSquareBracketsIndex+1, closeSquareBracketsIndex); String path = sheetName.substring(0, openSquareBracketsIndex); String fileName = path + workbookName; boolean supbookFound = false; SupbookRecord externalSupbook = null; int supbookIndex = -1; for (int ind = 0; ind < supbooks.size() && !supbookFound ; ind++) { externalSupbook = (SupbookRecord) supbooks.get(ind); if (externalSupbook.getType() == SupbookRecord.EXTERNAL && externalSupbook.getFileName().equals(fileName)) { supbookFound = true; supbookIndex = ind; } } if (!supbookFound) { externalSupbook = new SupbookRecord(fileName, settings); supbookIndex = supbooks.size(); supbooks.add(externalSupbook); } int sheetIndex = externalSupbook.getSheetIndex(worksheetName); return externSheet.getIndex(supbookIndex, sheetIndex); } /** * Gets the last external sheet index for the sheet name * @param sheetName * @return the sheet index or -1 if the sheet could not be found */ public int getLastExternalSheetIndex(String sheetName) { if (externSheet == null) { externSheet = new ExternalSheetRecord(); supbooks = new ArrayList(); supbooks.add(new SupbookRecord(getNumberOfSheets(), settings)); } // Iterate through the sheets records boolean found = false; Iterator i = sheets.iterator(); int sheetpos = 0; WritableSheetImpl s = null; while (i.hasNext() && !found) { s = (WritableSheetImpl) i.next(); if (s.getName().equals(sheetName)) { found = true; } else { sheetpos++; } } if (!found) { return -1; } // Check that the supbook record at position zero is internal and contains // all the sheets SupbookRecord supbook = (SupbookRecord) supbooks.get(0); Assert.verify(supbook.getType() == SupbookRecord.INTERNAL && supbook.getNumberOfSheets() == getNumberOfSheets()); return externSheet.getIndex(0, sheetpos); } /** * Sets the RGB value for the specified colour for this workbook * * @param c the colour whose RGB value is to be overwritten * @param r the red portion to set (0-255) * @param g the green portion to set (0-255) * @param b the blue portion to set (0-255) */ public void setColourRGB(Colour c, int r, int g, int b) { formatRecords.setColourRGB(c,r,g,b); } /** * Accessor for the RGB value for the specified colour * * @return the RGB for the specified colour */ public RGB getColourRGB(Colour c) { return formatRecords.getColourRGB(c); } /** * Gets the name at the specified index * * @param index the index into the name table * @return the name of the cell */ public String getName(int index) { Assert.verify(index >= 0 && index < names.size()); NameRecord n = (NameRecord) names.get(index); return n.getName(); } /** * Gets the index of the name record for the name * * @param name * @return the index in the name table */ public int getNameIndex(String name) { NameRecord nr = (NameRecord) nameRecords.get(name); return nr != null ? nr.getIndex() : -1; } /** * Adds a cell to workbook wide range of cells which need adjustment * following a row/column insert or remove * * @param f the cell to add to the list */ void addRCIRCell(CellValue cv) { rcirCells.add(cv); } /** * Called when a column is inserted on the specified sheet. Notifies all * RCIR cells of this change * * @param s the sheet on which the column was inserted * @param col the column number which was inserted */ void columnInserted(WritableSheetImpl s, int col) { int externalSheetIndex = getExternalSheetIndex(s.getName()); for (Iterator i = rcirCells.iterator() ; i.hasNext() ;) { CellValue cv = (CellValue) i.next(); cv.columnInserted(s, externalSheetIndex, col); } // Adjust any named cells if (names != null) { for (Iterator i = names.iterator(); i.hasNext() ;) { NameRecord nameRecord = (NameRecord) i.next(); nameRecord.columnInserted(externalSheetIndex, col); } } } /** * Called when a column is removed on the specified sheet. Notifies all * RCIR cells of this change * * @param s the sheet on which the column was removed * @param col the column number which was removed */ void columnRemoved(WritableSheetImpl s, int col) { int externalSheetIndex = getExternalSheetIndex(s.getName()); for (Iterator i = rcirCells.iterator() ; i.hasNext() ;) { CellValue cv = (CellValue) i.next(); cv.columnRemoved(s, externalSheetIndex, col); } // Adjust any named cells ArrayList removedNames = new ArrayList(); if (names != null) { for (Iterator i = names.iterator(); i.hasNext() ;) { NameRecord nameRecord = (NameRecord) i.next(); boolean removeName = nameRecord.columnRemoved(externalSheetIndex, col); if (removeName) { removedNames.add(nameRecord); } } // Remove any names which have been deleted for (Iterator i = removedNames.iterator(); i.hasNext() ;) { NameRecord nameRecord = (NameRecord) i.next(); boolean removed = names.remove(nameRecord); Assert.verify(removed, "Could not remove name " + nameRecord.getName()); } } } /** * Called when a row is inserted on the specified sheet. Notifies all * RCIR cells of this change * * @param s the sheet on which the row was inserted * @param row the row number which was inserted */ void rowInserted(WritableSheetImpl s, int row) { int externalSheetIndex = getExternalSheetIndex(s.getName()); // Adjust the row infos for (Iterator i = rcirCells.iterator() ; i.hasNext() ;) { CellValue cv = (CellValue) i.next(); cv.rowInserted(s, externalSheetIndex, row); } // Adjust any named cells if (names != null) { for (Iterator i = names.iterator(); i.hasNext() ;) { NameRecord nameRecord = (NameRecord) i.next(); nameRecord.rowInserted(externalSheetIndex, row); } } } /** * Called when a row is removed on the specified sheet. Notifies all * RCIR cells of this change * * @param s the sheet on which the row was removed * @param row the row number which was removed */ void rowRemoved(WritableSheetImpl s, int row) { int externalSheetIndex = getExternalSheetIndex(s.getName()); for (Iterator i = rcirCells.iterator() ; i.hasNext() ;) { CellValue cv = (CellValue) i.next(); cv.rowRemoved(s, externalSheetIndex, row); } // Adjust any named cells ArrayList removedNames = new ArrayList(); if (names != null) { for (Iterator i = names.iterator(); i.hasNext() ;) { NameRecord nameRecord = (NameRecord) i.next(); boolean removeName = nameRecord.rowRemoved(externalSheetIndex, row); if (removeName) { removedNames.add(nameRecord); } } // Remove any names which have been deleted for (Iterator i = removedNames.iterator(); i.hasNext() ;) { NameRecord nameRecord = (NameRecord) i.next(); boolean removed = names.remove(nameRecord); Assert.verify(removed, "Could not remove name " + nameRecord.getName()); } } } /** * Gets the named cell from this workbook. If the name refers to a * range of cells, then the cell on the top left is returned. If * the name cannot be found, null is returned * * @param the name of the cell/range to search for * @return the cell in the top left of the range if found, NULL * otherwise */ public WritableCell findCellByName(String name) { NameRecord nr = (NameRecord) nameRecords.get(name); if (nr == null) { return null; } NameRecord.NameRange[] ranges = nr.getRanges(); // Go and retrieve the first cell in the first range int sheetIndex = getExternalSheetIndex(ranges[0].getExternalSheet()); WritableSheet s = getSheet(sheetIndex); WritableCell cell = s.getWritableCell(ranges[0].getFirstColumn(), ranges[0].getFirstRow()); return cell; } /** * Gets the named range from this workbook. The Range object returns * contains all the cells from the top left to the bottom right * of the range. * If the named range comprises an adjacent range, * the Range[] will contain one object; for non-adjacent * ranges, it is necessary to return an array of length greater than * one. * If the named range contains a single cell, the top left and * bottom right cell will be the same cell * * @param the name of the cell/range to search for * @return the range of cells */ public Range[] findByName(String name) { NameRecord nr = (NameRecord) nameRecords.get(name); if (nr == null) { return null; } NameRecord.NameRange[] ranges = nr.getRanges(); Range[] cellRanges = new Range[ranges.length]; for (int i = 0; i < ranges.length ; i++) { cellRanges[i] = new RangeImpl (this, getExternalSheetIndex(ranges[i].getExternalSheet()), ranges[i].getFirstColumn(), ranges[i].getFirstRow(), getLastExternalSheetIndex(ranges[i].getExternalSheet()), ranges[i].getLastColumn(), ranges[i].getLastRow()); } return cellRanges; } /** * Adds a drawing to this workbook * * @param d the drawing to add */ void addDrawing(DrawingGroupObject d) { if (drawingGroup == null) { drawingGroup = new DrawingGroup(Origin.WRITE); } drawingGroup.add(d); } /** * Removes a drawing from this workbook * * @param d the drawing to remove */ void removeDrawing(Drawing d) { Assert.verify(drawingGroup != null); drawingGroup.remove(d); } /** * Accessor for the drawing group * * @return the drawing group */ DrawingGroup getDrawingGroup() { return drawingGroup; } /** * Create a drawing group for this workbook - used when importing sheets * which contain drawings, but this workbook doesn't. * We can't subsume this into the getDrawingGroup() method because the * null-ness of the return value is used elsewhere to determine the * origin of the workbook */ DrawingGroup createDrawingGroup() { if (drawingGroup == null) { drawingGroup = new DrawingGroup(Origin.WRITE); } return drawingGroup; } /** * Gets the named ranges * * @return the list of named cells within the workbook */ public String[] getRangeNames() { if (names == null) { return new String[0]; } String[] n = new String[names.size()]; for (int i = 0 ; i < names.size() ; i++) { NameRecord nr = (NameRecord) names.get(i); n[i] = nr.getName(); } return n; } /** * Removes the specified named range from the workbook * * @param name the name to remove */ public void removeRangeName(String name) { int pos = 0; boolean found = false; for (Iterator i = names.iterator(); i.hasNext() && !found ;) { NameRecord nr = (NameRecord) i.next(); if (nr.getName().equals(name)) { found = true; } else { pos++; } } // Remove the name from the list of names and the associated hashmap // of names (used to retrieve the name index). If the name cannot // be found, a warning is displayed if (found) { names.remove(pos); if (nameRecords.remove(name) == null) { logger.warn("Could not remove " + name + " from index lookups"); } } } /** * Accessor for the jxl.common.styles * * @return the standard styles for this workbook */ Styles getStyles() { return styles; } /** * Add new named area to this workbook with the given information. * * @param name name to be created. * @param sheet sheet containing the name * @param firstCol first column this name refers to. * @param firstRow first row this name refers to. * @param lastCol last column this name refers to. * @param lastRow last row this name refers to. */ public void addNameArea(String name, WritableSheet sheet, int firstCol, int firstRow, int lastCol, int lastRow) { addNameArea(name, sheet, firstCol, firstRow, lastCol, lastRow, true); } /** * Add new named area to this workbook with the given information. * * @param name name to be created. * @param sheet sheet containing the name * @param firstCol first column this name refers to. * @param firstRow first row this name refers to. * @param lastCol last column this name refers to. * @param lastRow last row this name refers to. * @param global TRUE if this is a global name, FALSE if this is tied to * the sheet */ void addNameArea(String name, WritableSheet sheet, int firstCol, int firstRow, int lastCol, int lastRow, boolean global) { if (names == null) { names = new ArrayList(); } int externalSheetIndex = getExternalSheetIndex(sheet.getName()); // Create a new name record. NameRecord nr = new NameRecord(name, names.size(), externalSheetIndex, firstRow, lastRow, firstCol, lastCol, global); // Add new name to name array. names.add(nr); // Add new name to name hash table. nameRecords.put(name, nr); } /** * Add new named area to this workbook with the given information. * * @param name name to be created. * @param sheet sheet containing the name * @param firstCol first column this name refers to. * @param firstRow first row this name refers to. * @param lastCol last column this name refers to. * @param lastRow last row this name refers to. * @param global TRUE if this is a global name, FALSE if this is tied to * the sheet */ void addNameArea(BuiltInName name, WritableSheet sheet, int firstCol, int firstRow, int lastCol, int lastRow, boolean global) { if (names == null) { names = new ArrayList(); } int index = getInternalSheetIndex(sheet.getName()); int externalSheetIndex = getExternalSheetIndex(sheet.getName()); // Create a new name record. NameRecord nr = new NameRecord(name, index, externalSheetIndex, firstRow, lastRow, firstCol, lastCol, global); // Add new name to name array. names.add(nr); // Add new name to name hash table. nameRecords.put(name, nr); } /** * Add new named area to this workbook with the given information. * * @param name name to be created. * @param sheet sheet containing the name * @param firstCol first column this name refers to. * @param firstRow first row this name refers to. * @param lastCol last column this name refers to. * @param lastRow last row this name refers to. * @param firstCol2 first column this name refers to. * @param firstRow2 first row this name refers to. * @param lastCol2 last column this name refers to. * @param lastRow2 last row this name refers to. * @param global TRUE if this is a global name, FALSE if this is tied to * the sheet */ void addNameArea(BuiltInName name, WritableSheet sheet, int firstCol, int firstRow, int lastCol, int lastRow, int firstCol2, int firstRow2, int lastCol2, int lastRow2, boolean global) { if (names == null) { names = new ArrayList(); } int index = getInternalSheetIndex(sheet.getName()); int externalSheetIndex = getExternalSheetIndex(sheet.getName()); // Create a new name record. NameRecord nr = new NameRecord(name, index, externalSheetIndex, firstRow2, lastRow2, firstCol2, lastCol2, firstRow, lastRow, firstCol, lastCol, global); // Add new name to name array. names.add(nr); // Add new name to name hash table. nameRecords.put(name, nr); } /** * Accessor for the workbook settings */ WorkbookSettings getSettings() { return settings; } /** * Returns the cell for the specified location eg. "Sheet1!A4". * This is identical to using the CellReferenceHelper with its * associated performance overheads, consequently it should * be use sparingly * * @param loc the cell to retrieve * @return the cell at the specified location */ public WritableCell getWritableCell(String loc) { WritableSheet s = getSheet(CellReferenceHelper.getSheet(loc)); return s.getWritableCell(loc); } /** * Imports a sheet from a different workbook. Does a deep copy on all * elements within that sheet * * @param name the name of the new sheet * @param index the position for the new sheet within this workbook * @param sheet the sheet (from another workbook) to merge into this one * @return the new sheet */ public WritableSheet importSheet(String name, int index, Sheet sheet) { WritableSheet ws = createSheet(name, index); ((WritableSheetImpl) ws).importSheet(sheet); return ws; } } jexcelapi/src/jxl/write/biff/PrecisionRecord.java0000750000175000017500000000327011207000610022262 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.IntegerHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Stores the Precision As Displayed option from the dialog box */ class PrecisionRecord extends WritableRecordData { /** * The precision as displayed flag */ private boolean asDisplayed; /** * The binary data */ private byte[] data; /** * Constructor * * @param disp the precision as displayed flag */ public PrecisionRecord(boolean disp) { super(Type.PRECISION); asDisplayed = disp; data = new byte[2]; if (!asDisplayed) { IntegerHelper.getTwoBytes(1, data, 0); } } /** * Gets the binary data for output to file * * @return the binary data */ public byte[] getData() { return data; } } jexcelapi/src/jxl/write/biff/SortRecord.java0000750000175000017500000000674411207000610021267 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 200r Andrew Khan, Al Mantei * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.StringHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Record which specifies sort dialog box values */ class SortRecord extends WritableRecordData { private String column1Name; private String column2Name; private String column3Name; private boolean sortColumns; private boolean sortKey1Desc; private boolean sortKey2Desc; private boolean sortKey3Desc; private boolean sortCaseSensitive; /** * Constructor * * @param a Sort Column 1 Name * @param b Sort Column 2 Name * @param c Sort Column 3 Name * @param sc Sort Columns * @param sk1d Sort Key 1 Descending * @param sk2d Sort Key 2 Descending * @param sk3d Sort Key 3 Descending * @param scs Sort Case Sensitive */ public SortRecord(String a, String b, String c, boolean sc, boolean sk1d, boolean sk2d, boolean sk3d, boolean scs) { super(Type.SORT); column1Name = a; column2Name = b; column3Name = c; sortColumns = sc; sortKey1Desc = sk1d; sortKey2Desc = sk2d; sortKey3Desc = sk3d; sortCaseSensitive = scs; } /** * Gets the binary data for output to file * * @return the binary data */ public byte[] getData() { int byteCount = 5 + (column1Name.length() * 2) + 1; if (column2Name.length() > 0) byteCount += (column2Name.length() * 2) + 1; if (column3Name.length() > 0) byteCount += (column3Name.length() * 2) + 1; byte[] data = new byte[byteCount + 1]; // there is supposed to be an extra "unused" byte at the end int optionFlag = 0; if (sortColumns) optionFlag = optionFlag | 0x01; if (sortKey1Desc) optionFlag = optionFlag | 0x02; if (sortKey2Desc) optionFlag = optionFlag | 0x04; if (sortKey3Desc) optionFlag = optionFlag | 0x08; if (sortCaseSensitive) optionFlag = optionFlag | 0x10; data[0] = (byte) optionFlag; // data[1] is an index for sorting by a list - not implemented data[2] = (byte) column1Name.length(); data[3] = (byte) column2Name.length(); data[4] = (byte) column3Name.length(); // always write the headings in unicode data[5] = 0x01; StringHelper.getUnicodeBytes(column1Name, data, 6); int curPos = 6 + (column1Name.length() * 2); if (column2Name.length() > 0) { data[curPos++] = 0x01; StringHelper.getUnicodeBytes(column2Name, data, curPos); curPos += column2Name.length() * 2; } if (column3Name.length() > 0) { data[curPos++] = 0x01; StringHelper.getUnicodeBytes(column3Name, data, curPos); curPos += column3Name.length() * 2; } return data; } } jexcelapi/src/jxl/write/biff/ReadFormulaRecord.java0000750000175000017500000003230211207000610022526 0ustar drazzibdrazzib/************************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.common.Assert; import jxl.common.Logger; import jxl.CellReferenceHelper; import jxl.CellType; import jxl.FormulaCell; import jxl.Sheet; import jxl.WorkbookSettings; import jxl.biff.FormattingRecords; import jxl.biff.FormulaData; import jxl.biff.IntegerHelper; import jxl.biff.Type; import jxl.biff.WorkbookMethods; import jxl.biff.formula.ExternalSheet; import jxl.biff.formula.FormulaException; import jxl.biff.formula.FormulaParser; import jxl.write.WritableCell; /** * A formula record. This is invoked when copying a formula from a * read only spreadsheet * This method implements the FormulaData interface to allow the copying * of writable sheets */ class ReadFormulaRecord extends CellValue implements FormulaData { /** * The logger */ private static Logger logger = Logger.getLogger(ReadFormulaRecord.class); /** * The underlying formula from the read sheet */ private FormulaData formula; /** * The formula parser */ private FormulaParser parser; /** * Constructor * * @param f the formula to copy */ protected ReadFormulaRecord(FormulaData f) { super(Type.FORMULA, f); formula = f; } protected final byte[] getCellData() { return super.getData(); } /** * An exception has occurred, so produce some appropriate dummy * cell contents. This may be overridden by subclasses * if they require specific handling * * @return the bodged data */ protected byte[] handleFormulaException() { byte[] expressiondata = null; byte[] celldata = super.getData(); // Generate an appropriate dummy formula WritableWorkbookImpl w = getSheet().getWorkbook(); parser = new FormulaParser(getContents(), w, w, w.getSettings()); // Get the bytes for the dummy formula try { parser.parse(); } catch(FormulaException e2) { logger.warn(e2.getMessage()); parser = new FormulaParser("\"ERROR\"", w, w, w.getSettings()); try {parser.parse();} catch(FormulaException e3) {Assert.verify(false);} } byte[] formulaBytes = parser.getBytes(); expressiondata = new byte[formulaBytes.length + 16]; IntegerHelper.getTwoBytes(formulaBytes.length, expressiondata, 14); System.arraycopy(formulaBytes, 0, expressiondata, 16, formulaBytes.length); // Set the recalculate on load bit expressiondata[8] |= 0x02; byte[] data = new byte[celldata.length + expressiondata.length]; System.arraycopy(celldata, 0, data, 0, celldata.length); System.arraycopy(expressiondata, 0, data, celldata.length, expressiondata.length); return data; } /** * Gets the binary data for output to file * * @return the binary data */ public byte[] getData() { // Take the superclass cell data to take into account cell // rationalization byte[] celldata = super.getData(); byte[] expressiondata = null; try { if (parser == null) { expressiondata = formula.getFormulaData(); } else { byte[] formulaBytes = parser.getBytes(); expressiondata = new byte[formulaBytes.length + 16]; IntegerHelper.getTwoBytes(formulaBytes.length, expressiondata, 14); System.arraycopy(formulaBytes, 0, expressiondata, 16, formulaBytes.length); } // Set the recalculate on load bit expressiondata[8] |= 0x02; byte[] data = new byte[celldata.length + expressiondata.length]; System.arraycopy(celldata, 0, data, 0, celldata.length); System.arraycopy(expressiondata, 0, data, celldata.length, expressiondata.length); return data; } catch (FormulaException e) { // Something has gone wrong trying to read the formula data eg. it // might be unsupported biff7 data logger.warn (CellReferenceHelper.getCellReference(getColumn(), getRow()) + " " + e.getMessage()); return handleFormulaException(); } } /** * Returns the content type of this cell * * @return the content type for this cell */ public CellType getType() { return formula.getType(); } /** * Quick and dirty function to return the contents of this cell as a string. * * @return the contents of this cell as a string */ public String getContents() { return formula.getContents(); } /** * Gets the raw bytes for the formula. This will include the * parsed tokens array. Used when copying spreadsheets * * @return the raw record data */ public byte[] getFormulaData() throws FormulaException { byte[] d = formula.getFormulaData(); byte[] data = new byte[d.length]; System.arraycopy(d, 0, data, 0, d.length); // Set the recalculate on load bit data[8] |= 0x02; return data; } /** * Gets the formula bytes * * @return the formula bytes */ public byte[] getFormulaBytes() throws FormulaException { // If the formula has been parsed, then get the parsed bytes if (parser != null) { return parser.getBytes(); } // otherwise get the bytes from the original formula byte[] readFormulaData = getFormulaData(); byte[] formulaBytes = new byte[readFormulaData.length - 16]; System.arraycopy(readFormulaData, 16, formulaBytes, 0, formulaBytes.length); return formulaBytes; } /** * Implementation of the deep copy function * * @param col the column which the new cell will occupy * @param row the row which the new cell will occupy * @return a copy of this cell, which can then be added to the sheet */ public WritableCell copyTo(int col, int row) { return new FormulaRecord(col, row, this); } /** * Overrides the method in the base class to add this to the Workbook's * list of maintained formulas * * @param fr the formatting records * @param ss the shared strings used within the workbook * @param s the sheet this is being added to */ void setCellDetails(FormattingRecords fr, SharedStrings ss, WritableSheetImpl s) { super.setCellDetails(fr, ss, s); s.getWorkbook().addRCIRCell(this); } /** * Called when a column is inserted on the specified sheet. Notifies all * RCIR cells of this change. The default implementation here does nothing * * @param s the sheet on which the column was inserted * @param sheetIndex the sheet index on which the column was inserted * @param col the column number which was inserted */ void columnInserted(Sheet s, int sheetIndex, int col) { try { if (parser == null) { byte[] formulaData = formula.getFormulaData(); byte[] formulaBytes = new byte[formulaData.length - 16]; System.arraycopy(formulaData, 16, formulaBytes, 0, formulaBytes.length); parser = new FormulaParser(formulaBytes, this, getSheet().getWorkbook(), getSheet().getWorkbook(), getSheet().getWorkbookSettings()); parser.parse(); } parser.columnInserted(sheetIndex, col, s == getSheet()); } catch (FormulaException e) { logger.warn("cannot insert column within formula: " + e.getMessage()); } } /** * Called when a column is removed on the specified sheet. Notifies all * RCIR cells of this change. The default implementation here does nothing * * @param s the sheet on which the column was inserted * @param sheetIndex the sheet index on which the column was inserted * @param col the column number which was inserted */ void columnRemoved(Sheet s, int sheetIndex, int col) { try { if (parser == null) { byte[] formulaData = formula.getFormulaData(); byte[] formulaBytes = new byte[formulaData.length - 16]; System.arraycopy(formulaData, 16, formulaBytes, 0, formulaBytes.length); parser = new FormulaParser(formulaBytes, this, getSheet().getWorkbook(), getSheet().getWorkbook(), getSheet().getWorkbookSettings()); parser.parse(); } parser.columnRemoved(sheetIndex, col, s == getSheet()); } catch (FormulaException e) { logger.warn("cannot remove column within formula: " + e.getMessage()); } } /** * Called when a row is inserted on the specified sheet. Notifies all * RCIR cells of this change. The default implementation here does nothing * * @param s the sheet on which the column was inserted * @param sheetIndex the sheet index on which the column was inserted * @param row the column number which was inserted */ void rowInserted(Sheet s, int sheetIndex, int row) { try { if (parser == null) { byte[] formulaData = formula.getFormulaData(); byte[] formulaBytes = new byte[formulaData.length - 16]; System.arraycopy(formulaData, 16, formulaBytes, 0, formulaBytes.length); parser = new FormulaParser(formulaBytes, this, getSheet().getWorkbook(), getSheet().getWorkbook(), getSheet().getWorkbookSettings()); parser.parse(); } parser.rowInserted(sheetIndex, row, s == getSheet()); } catch (FormulaException e) { logger.warn("cannot insert row within formula: " + e.getMessage()); } } /** * Called when a row is inserted on the specified sheet. Notifies all * RCIR cells of this change. The default implementation here does nothing * * @param s the sheet on which the row was removed * @param sheetIndex the sheet index on which the column was removed * @param row the column number which was removed */ void rowRemoved(Sheet s, int sheetIndex, int row) { try { if (parser == null) { byte[] formulaData = formula.getFormulaData(); byte[] formulaBytes = new byte[formulaData.length - 16]; System.arraycopy(formulaData, 16, formulaBytes, 0, formulaBytes.length); parser = new FormulaParser(formulaBytes, this, getSheet().getWorkbook(), getSheet().getWorkbook(), getSheet().getWorkbookSettings()); parser.parse(); } parser.rowRemoved(sheetIndex, row, s == getSheet()); } catch (FormulaException e) { logger.warn("cannot remove row within formula: " + e.getMessage()); } } /** * Accessor for the read formula * * @return the read formula */ protected FormulaData getReadFormula() { return formula; } /** * Accessor for the read formula * * @return the read formula */ public String getFormula() throws FormulaException { return ( (FormulaCell) formula).getFormula(); } /** * If this formula was on an imported sheet, check that * cell references to another sheet are warned appropriately * * @return TRUE if this formula was able to be imported, FALSE otherwise */ public boolean handleImportedCellReferences(ExternalSheet es, WorkbookMethods mt, WorkbookSettings ws) { try { if (parser == null) { byte[] formulaData = formula.getFormulaData(); byte[] formulaBytes = new byte[formulaData.length - 16]; System.arraycopy(formulaData, 16, formulaBytes, 0, formulaBytes.length); parser = new FormulaParser(formulaBytes, this, es, mt, ws); parser.parse(); } return parser.handleImportedCellReferences(); } catch (FormulaException e) { logger.warn("cannot import formula: " + e.getMessage()); return false; } } } jexcelapi/src/jxl/write/biff/InterfaceEndRecord.java0000750000175000017500000000255611207000610022664 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.Type; import jxl.biff.WritableRecordData; /** * Marks the end of the user interface section of the Book stream. * It has no data field */ class InterfaceEndRecord extends WritableRecordData { /** * Consructor */ public InterfaceEndRecord() { super(Type.INTERFACEEND); } /** * Gets the binary data for output * * @return the binary data */ public byte[] getData() { return new byte[0]; } } jexcelapi/src/jxl/write/biff/MulRKRecord.java0000750000175000017500000000612111207000610021317 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import java.util.List; import jxl.biff.IntegerHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; import jxl.write.Number; /** * Contains an array of RK numbers */ class MulRKRecord extends WritableRecordData { /** * The row containing these numbers */ private int row; /** * The first column these rk number occur on */ private int colFirst; /** * The last column these rk number occur on */ private int colLast; /** * The array of rk numbers */ private int[] rknumbers; /** * The array of xf indices */ private int[] xfIndices; /** * Constructs the rk numbers from the integer cells * * @param numbers A list of jxl.write.Number objects */ public MulRKRecord(List numbers) { super(Type.MULRK); row = ((Number)numbers.get(0)).getRow(); colFirst = ((Number)numbers.get(0)).getColumn(); colLast = colFirst + numbers.size() - 1; rknumbers = new int[numbers.size()]; xfIndices = new int[numbers.size()]; for (int i = 0; i < numbers.size(); i++) { rknumbers[i] = (int) ((Number)numbers.get(i)).getValue(); xfIndices[i] = ( (CellValue) numbers.get(i)).getXFIndex(); } } /** * Gets the binary data for output to file * * @return the binary data */ public byte[] getData() { byte[] data = new byte[rknumbers.length * 6 + 6]; // Set up the row and the first column IntegerHelper.getTwoBytes(row, data, 0); IntegerHelper.getTwoBytes(colFirst, data, 2); // Add all the rk numbers int pos = 4; int rkValue = 0; byte[] rkBytes = new byte[4]; for (int i = 0; i < rknumbers.length; i++) { IntegerHelper.getTwoBytes(xfIndices[i], data, pos); // To represent an int as an Excel RK value, we have to // undergo some outrageous jiggery pokery, as follows: // Gets the bit representation of the number rkValue = rknumbers[i] << 2; // Set the integer bit rkValue |= 0x2; IntegerHelper.getFourBytes(rkValue, data, pos+2); pos+=6; } // Write the number of rk numbers in this record IntegerHelper.getTwoBytes(colLast, data, pos); return data; } } jexcelapi/src/jxl/write/biff/WritableFonts.java0000750000175000017500000000314311207000610021752 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.Fonts; import jxl.write.WritableFont; /** * A container for the list of fonts used in this workbook The writable * subclass instantiates the predetermined list of fonts available to * users of the writable API */ public class WritableFonts extends Fonts { /** * Constructor. Creates the predetermined list of fonts */ public WritableFonts(WritableWorkbookImpl w) { super(); addFont(w.getStyles().getArial10Pt()); // Create the default fonts WritableFont f = new WritableFont(WritableFont.ARIAL); addFont(f); f = new WritableFont(WritableFont.ARIAL); addFont(f); f = new WritableFont(WritableFont.ARIAL); addFont(f); } } jexcelapi/src/jxl/write/biff/BottomMarginRecord.java0000750000175000017500000000214611207000610022732 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.Type; /** * The settings for the left margin */ class BottomMarginRecord extends MarginRecord { BottomMarginRecord(double v) { super(Type.BOTTOMMARGIN, v); } } jexcelapi/src/jxl/write/biff/DateFormatRecord.java0000750000175000017500000000253011207000610022353 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.biff.FormatRecord; /** * A class which contains a date format */ public class DateFormatRecord extends FormatRecord { /** * Constructor * * @param fmt the date format */ protected DateFormatRecord(String fmt) { super(); // Do the replacements in the format string String fs = fmt; fs = replace(fs, "a", "AM/PM"); fs = replace(fs, "S", "0"); setFormatString(fs); } } jexcelapi/src/jxl/write/biff/BooleanRecord.java0000750000175000017500000000704111207000610021706 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write.biff; import jxl.BooleanCell; import jxl.CellType; import jxl.biff.Type; import jxl.format.CellFormat; /** * A boolean cell's last calculated value */ public abstract class BooleanRecord extends CellValue { /** * The boolean value of this cell. If this cell represents an error, * this will be false */ private boolean value; /** * Constructor invoked by the user API * * @param c the column * @param r the row * @param val the value */ protected BooleanRecord(int c, int r, boolean val) { super(Type.BOOLERR, c, r); value = val; } /** * Overloaded constructor invoked from the API, which takes a cell * format * * @param c the column * @param r the row * @param val the value * @param st the cell format */ protected BooleanRecord(int c, int r, boolean val, CellFormat st) { super(Type.BOOLERR, c, r, st); value = val; } /** * Constructor used when copying a workbook * * @param nc the number to copy */ protected BooleanRecord(BooleanCell nc) { super(Type.BOOLERR, nc); value = nc.getValue(); } /** * Copy constructor * * @param c the column * @param r the row * @param br the record to copy */ protected BooleanRecord(int c, int r, BooleanRecord br) { super(Type.BOOLERR, c, r, br); value = br.value; } /** * Interface method which Gets the boolean value stored in this cell. If * this cell contains an error, then returns FALSE. Always query this cell * type using the accessor method isError() prior to calling this method * * @return TRUE if this cell contains TRUE, FALSE if it contains FALSE or * an error code */ public boolean getValue() { return value; } /** * Returns the numerical value as a string * * @return The numerical value of the formula as a string */ public String getContents() { // return Boolean.toString(value) - only available in 1.4 or later return (new Boolean(value)).toString(); } /** * Returns the cell type * * @return The cell type */ public CellType getType() { return CellType.BOOLEAN; } /** * Sets the value * * @param val the boolean value */ protected void setValue(boolean val) { value = val; } /** * Gets the binary data for output to file * * @return the binary data */ public byte[] getData() { byte[] celldata = super.getData(); byte[] data = new byte[celldata.length + 2]; System.arraycopy(celldata, 0, data, 0, celldata.length); if (value) { data[celldata.length] = 1; } return data; } } jexcelapi/src/jxl/write/DateTime.java0000750000175000017500000001133211207000610017754 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2001 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write; import java.util.Date; import jxl.DateCell; import jxl.format.CellFormat; import jxl.write.biff.DateRecord; /** * A Date which may be created on the fly by a user application and added to a * spreadsheet * * NOTE: By default, all dates will have local timezone information added to * their UTC value. If this is not desired (eg. if the date entered * represents an interval eg. 9.83s for the 100m world record, then use * the overloaded constructor which indicate that the date passed in was * created under the GMT timezone. It is important that when the date * was created, an instruction like * Calendar.setTimeZone(TimeZone.getTimeZone("GMT")) * was made prior to that */ public class DateTime extends DateRecord implements WritableCell, DateCell { /** * Instance variable for dummy variable overload */ public static final GMTDate GMT = new GMTDate(); /** * Constructor. The date will be displayed with date and time components * using the default date format * * @param c the column * @param r the row * @param d the date */ public DateTime(int c, int r, Date d) { super(c, r, d); } /** * Constructor, which adjusts the specified date to take timezone * considerations into account. The date passed in will be displayed with * date and time components using the default date format * * @param c the column * @param r the row * @param d the date * @param a dummy overload */ public DateTime(int c, int r, Date d, GMTDate a) { super(c, r, d, a); } /** * Constructor which takes the format for this cell * * @param c the column * @param r the row * @param st the format * @param d the date */ public DateTime(int c, int r, Date d, CellFormat st) { super(c, r, d, st); } /** * Constructor, which adjusts the specified date to take timezone * considerations into account * * @param c the column * @param r the row * @param d the date * @param st the cell format * @param a the cummy overload */ public DateTime(int c, int r, Date d, CellFormat st, GMTDate a) { super(c, r, d, st, a); } /** * Constructor which takes the format for the cell and an indicator * as to whether this cell is a full date time or purely just a time * eg. if the spreadsheet is to contain the world record for 100m, then the * value would be 9.83s, which would be indicated as just a time * * @param c the column * @param r the row * @param st the style * @param tim flag indicating that this represents a time * @param d the date */ public DateTime(int c, int r, Date d, CellFormat st, boolean tim) { super(c, r, d, st, tim); } /** * A constructor called by the worksheet when creating a writable version * of a spreadsheet that has been read in * * @param dc the date to copy */ public DateTime(DateCell dc) { super(dc); } /** * Copy constructor used for deep copying * * @param col the column * @param row the row * @param dt the date to copy */ protected DateTime(int col, int row, DateTime dt) { super(col, row, dt); } /** * Sets the date for this cell * * @param d the date */ public void setDate(Date d) { super.setDate(d); } /** * Sets the date for this cell, performing the necessary timezone adjustments * * @param d the date * @param a the dummy overload */ public void setDate(Date d, GMTDate a) { super.setDate(d, a); } /** * Implementation of the deep copy function * * @param col the column which the new cell will occupy * @param row the row which the new cell will occupy * @return a copy of this cell, which can then be added to the sheet */ public WritableCell copyTo(int col, int row) { return new DateTime(col, row, this); } } jexcelapi/src/jxl/write/WritableCell.java0000750000175000017500000000371011207000610020632 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write; import jxl.Cell; import jxl.format.CellFormat; /** * The interface for all writable cells */ public interface WritableCell extends Cell { /** * Sets the cell format for this cell * * @param cf the cell format */ public void setCellFormat(CellFormat cf); /** * A deep copy. The returned cell still needs to be added to the sheet. * By not automatically adding the cell to the sheet, the client program * may change certain attributes, such as the value or the format * * @param col the column which the new cell will occupy * @param row the row which the new cell will occupy * @return a copy of this cell, which can then be added to the sheet */ public WritableCell copyTo(int col, int row); /** * Accessor for the cell features * * @return the cell features or NULL if this cell doesn't have any */ public WritableCellFeatures getWritableCellFeatures(); /** * Sets the cell features * * @param cf the cell features */ public void setCellFeatures(WritableCellFeatures cf); } jexcelapi/src/jxl/write/WritableImage.java20000750000175000017500000001120611207000610021056 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write; import java.io.File; import jxl.biff.drawing.Drawing; import jxl.biff.drawing.DrawingGroupObject; import jxl.biff.drawing.DrawingGroup; /** * Allows an image to be created, or an existing image to be manipulated * Note that co-ordinates and dimensions are given in cells, so that if for * example the width or height of a cell which the image spans is altered, * the image will have a correspondign distortion */ public class WritableImage extends Drawing { /** * Constructor * * @param x the column number at which to position the image * @param y the row number at which to position the image * @param width the number of columns cells which the image spans * @param height the number of rows which the image spans * @param image the source image file */ public WritableImage(double x, double y, double width, double height, File image) { super(x, y, width, height, image); } /** * Constructor * * @param x the column number at which to position the image * @param y the row number at which to position the image * @param width the number of columns cells which the image spans * @param height the number of rows which the image spans * @param image the image data */ public WritableImage(double x, double y, double width, double height, byte[] imageData) { super(x, y, width, height, imageData); } /** * Constructor, used when copying sheets * * @param d the image to copy */ public WritableImage(DrawingGroupObject d, DrawingGroup dg) { super(d, dg); } /** * Accessor for the image position * * @return the column number at which the image is positioned */ public double getColumn() { return super.getX(); } /** * Accessor for the image position * * @param c the column number at which the image should be positioned */ public void setColumn(double c) { super.setX(c); } /** * Accessor for the image position * * @return the row number at which the image is positions */ public double getRow() { return super.getY(); } /** * Accessor for the image position * * @param c the row number at which the image should be positioned */ public void setRow(double c) { super.setY(c); } /** * Accessor for the image dimensions * * @return the number of columns this image spans */ public double getWidth() { return super.getWidth(); } /** * Accessor for the image dimensions * Note that the actual size of the rendered image will depend on the * width of the columns it spans * * @param c the number of columns which this image spans */ public void setWidth(double c) { super.setWidth(c); } /** * Accessor for the image dimensions * * @return the number of rows which this image spans */ public double getHeight() { return super.getHeight(); } /** * Accessor for the image dimensions * Note that the actual size of the rendered image will depend on the * height of the rows it spans * * @param c the number of rows which this image should span */ public void setHeight(double c) { super.setHeight(c); } /** * Accessor for the image file * * @return the file which the image references */ public File getImageFile() { return super.getImageFile(); } /** * Accessor for the image data * * @return the image data */ public byte[] getImageData() { return super.getImageData(); } } jexcelapi/src/jxl/write/Font.java0000750000175000017500000001307011207000610017167 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write; import jxl.format.Colour; import jxl.format.ScriptStyle; import jxl.format.UnderlineStyle; /** * A class which is instantiated when the user application wishes to specify * the font for a particular cell * * @deprecated Renamed to writable font */ public class Font extends WritableFont { /** * Objects created with this font name will be rendered within Excel as ARIAL * fonts * @deprecated */ public static final FontName ARIAL = WritableFont.ARIAL; /** * Objects created with this font name will be rendered within Excel as TIMES * fonts * @deprecated */ public static final FontName TIMES = WritableFont.TIMES; // The bold styles /** * Indicates that this font should not be presented as bold * @deprecated */ public static final BoldStyle NO_BOLD = WritableFont.NO_BOLD; /** * Indicates that this font should be presented in a BOLD style * @deprecated */ public static final BoldStyle BOLD = WritableFont.BOLD; // The underline styles /** * @deprecated */ public static final UnderlineStyle NO_UNDERLINE = UnderlineStyle.NO_UNDERLINE; /** * @deprecated */ public static final UnderlineStyle SINGLE = UnderlineStyle.SINGLE; /** * @deprecated */ public static final UnderlineStyle DOUBLE = UnderlineStyle.DOUBLE; /** * @deprecated */ public static final UnderlineStyle SINGLE_ACCOUNTING = UnderlineStyle.SINGLE_ACCOUNTING; /** * @deprecated */ public static final UnderlineStyle DOUBLE_ACCOUNTING = UnderlineStyle.DOUBLE_ACCOUNTING; // The script styles public static final ScriptStyle NORMAL_SCRIPT = ScriptStyle.NORMAL_SCRIPT; public static final ScriptStyle SUPERSCRIPT = ScriptStyle.SUPERSCRIPT; public static final ScriptStyle SUBSCRIPT = ScriptStyle.SUBSCRIPT; /** * Creates a default font, vanilla font of the specified face and with * default point size. * * @param fn the font name * @deprecated Use jxl.write.WritableFont */ public Font(FontName fn) { super(fn); } /** * Constructs of font of the specified face and of size given by the * specified point size * * @param ps the point size * @param fn the font name * @deprecated use jxl.write.WritableFont */ public Font(FontName fn, int ps) { super(fn, ps); } /** * Creates a font of the specified face, point size and bold style * * @param ps the point size * @param bs the bold style * @param fn the font name * @deprecated use jxl.write.WritableFont */ public Font(FontName fn, int ps, BoldStyle bs) { super(fn, ps, bs); } /** * Creates a font of the specified face, point size, bold weight and * italicised option. * * @param ps the point size * @param bs the bold style * @param italic italic flag * @param fn the font name * @deprecated use jxl.write.WritableFont */ public Font(FontName fn, int ps, BoldStyle bs, boolean italic) { super(fn, ps, bs, italic); } /** * Creates a font of the specified face, point size, bold weight, * italicisation and underline style * * @param ps the point size * @param bs the bold style * @param us underscore flag * @param fn font name * @param it italic flag * @deprecated use jxl.write.WritableFont */ public Font(FontName fn, int ps, BoldStyle bs, boolean it, UnderlineStyle us) { super(fn, ps, bs, it, us); } /** * Creates a font of the specified face, point size, bold style, * italicisation, underline style and colour * * @param ps the point size * @param bs the bold style * @param us the underline style * @param fn the font name * @param it italic flag * @param c the colour * @deprecated use jxl.write.WritableFont */ public Font(FontName fn, int ps, BoldStyle bs, boolean it, UnderlineStyle us, Colour c) { super(fn, ps, bs, it, us, c); } /** * Creates a font of the specified face, point size, bold style, * italicisation, underline style, colour, and script * style (superscript/subscript) * * @param ps the point size * @param bs the bold style * @param us the underline style * @param fn the font name * @param it the italic flag * @param c the colour * @param ss the script style * @deprecated use jxl.write.WritableFont */ public Font(FontName fn, int ps, BoldStyle bs, boolean it, UnderlineStyle us, Colour c, ScriptStyle ss) { super(fn, ps, bs, it, us, c, ss); } } jexcelapi/src/jxl/write/VerticalAlignment.java0000750000175000017500000000234011207000610021667 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write; /** * Enumeration type which describes the vertical alignment of data within a cell * * @deprecated Repackaged as jxl.format.VerticalAlignment */ public final class VerticalAlignment extends jxl.format.VerticalAlignment { /** * Constructor */ private VerticalAlignment() { super(0, null); } } jexcelapi/src/jxl/write/DateFormats.java0000750000175000017500000001220711207000610020473 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write; import jxl.biff.DisplayFormat; /** * Static class which contains Excels predefined Date formats */ public final class DateFormats { /** * Inner class which holds the format index */ private static class BuiltInFormat implements DisplayFormat { /** * The index of this date format */ private int index; /** * The excel format */ private String formatString; /** * Constructor * * @param i the index * @param s the format string */ public BuiltInFormat(int i, String s) { index = i; formatString = s; } /** * Gets the format index * * @return the format index */ public int getFormatIndex() { return index; } /** * Interface method which determines whether the index has been set. For * built ins this is always true * * @return TRUE, since this is a built in format */ public boolean isInitialized() { return true; } /** * Initialize this format with the specified position. Since this is a * built in format, this is always initialized, so this method body for * this is empty * * @param pos the position in the array */ public void initialize(int pos) { } /** * Determines whether this format is a built in format * * @return TRUE, since this is a built in format */ public boolean isBuiltIn() { return true; } /** * Accesses the excel format string which is applied to the cell * Note that this is the string that excel uses, and not the java * equivalent * * @return the cell format string */ public String getFormatString() { return formatString; } /** * Standard equals method * * @param o the object to compare * @return TRUE if the two objects are equal, FALSE otherwise */ public boolean equals(Object o) { if (o == this) { return true; } if (!(o instanceof BuiltInFormat)) { return false; } BuiltInFormat bif = (BuiltInFormat) o; return index == bif.index; } /** * Hash code implementation * * @return the hash code */ public int hashCode() { return index; } } // The available built in date formats /** * The default format. This is equivalent to a date format of "M/d/yy" */ public static final DisplayFormat FORMAT1 = new BuiltInFormat(0x0e, "M/d/yy"); /** * The default format. This is equivalent to a date format of "M/d/yy" */ public static final DisplayFormat DEFAULT = FORMAT1; /** * Equivalent to a date format of "d-MMM-yy" */ public static final DisplayFormat FORMAT2 = new BuiltInFormat(0xf, "d-MMM-yy"); /** * Equivalent to a date format of "d-MMM" */ public static final DisplayFormat FORMAT3 = new BuiltInFormat(0x10, "d-MMM"); /** * Equivalent to a date format of "MMM-yy" */ public static final DisplayFormat FORMAT4 = new BuiltInFormat(0x11, "MMM-yy"); /** * Equivalent to a date format of "h:mm a" */ public static final DisplayFormat FORMAT5 = new BuiltInFormat(0x12, "h:mm a"); /** * Equivalent to a date format of "h:mm:ss a" */ public static final DisplayFormat FORMAT6 = new BuiltInFormat(0x13, "h:mm:ss a"); /** * Equivalent to a date format of "H:mm" */ public static final DisplayFormat FORMAT7 = new BuiltInFormat(0x14, "H:mm"); /** * Equivalent to a date format of "H:mm:ss" */ public static final DisplayFormat FORMAT8 = new BuiltInFormat(0x15, "H:mm:ss"); /** * Equivalent to a date format of "M/d/yy H:mm" */ public static final DisplayFormat FORMAT9 = new BuiltInFormat(0x16, "M/d/yy H:mm"); /** * Equivalent to a date format of "mm:ss" */ public static final DisplayFormat FORMAT10 = new BuiltInFormat(0x2d, "mm:ss"); /** * Equivalent to a date format of "H:mm:ss" */ public static final DisplayFormat FORMAT11 = new BuiltInFormat(0x2e, "H:mm:ss"); /** * Equivalent to a date format of "mm:ss.S" */ public static final DisplayFormat FORMAT12 = new BuiltInFormat(0x2f, "H:mm:ss"); } jexcelapi/src/jxl/write/Alignment.java0000750000175000017500000000237711207000610020207 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.write; /** * Enumeration class which contains the various alignments for data within a * cell * * @deprecated Repackaged as jxl.Alignment. This version is retained * for backwards compatibility */ public final class Alignment extends jxl.format.Alignment { /** * Private constructor */ private Alignment() { super(0, null); } } jexcelapi/src/jxl/demo/0000750000175000017500000000000011270605332015220 5ustar drazzibdrazzibjexcelapi/src/jxl/demo/Write.java0000750000175000017500000015422511263330666017200 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2001 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.demo; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.Locale; import java.util.TimeZone; import jxl.CellReferenceHelper; import jxl.CellView; import jxl.HeaderFooter; import jxl.Range; import jxl.Workbook; import jxl.WorkbookSettings; import jxl.format.Alignment; import jxl.format.Border; import jxl.format.BorderLineStyle; import jxl.format.Colour; import jxl.format.Orientation; import jxl.format.PageOrder; import jxl.format.PageOrientation; import jxl.format.PaperSize; import jxl.format.ScriptStyle; import jxl.format.UnderlineStyle; import jxl.write.Blank; import jxl.write.Boolean; import jxl.write.DateFormat; import jxl.write.DateFormats; import jxl.write.DateTime; import jxl.write.Formula; import jxl.write.Label; import jxl.write.Number; import jxl.write.NumberFormat; import jxl.write.NumberFormats; import jxl.write.WritableCellFeatures; import jxl.write.WritableCellFormat; import jxl.write.WritableFont; import jxl.write.WritableHyperlink; import jxl.write.WritableImage; import jxl.write.WritableSheet; import jxl.write.WritableWorkbook; import jxl.write.WriteException; /** * Demo class which writes a spreadsheet. This demo illustrates most of the * features of the JExcelAPI, such as text, numbers, fonts, number formats and * date formats */ public class Write { /** * The filename */ private String filename; /** * The workbook */ private WritableWorkbook workbook; /** * Constructor * * @param fn */ public Write(String fn) { filename = fn; } /** * Uses the JExcelAPI to create a spreadsheet * * @exception IOException * @exception WriteException */ public void write() throws IOException, WriteException { WorkbookSettings ws = new WorkbookSettings(); ws.setLocale(new Locale("en", "EN")); workbook = Workbook.createWorkbook(new File(filename), ws); WritableSheet s2 = workbook.createSheet("Number Formats", 0); WritableSheet s3 = workbook.createSheet("Date Formats", 1); WritableSheet s1 = workbook.createSheet("Label Formats", 2); WritableSheet s4 = workbook.createSheet("Borders", 3); WritableSheet s5 = workbook.createSheet("Labels", 4); WritableSheet s6 = workbook.createSheet("Formulas", 5); WritableSheet s7 = workbook.createSheet("Images", 6); // WritableSheet s8 = workbook.createSheet // ("'Illegal chars in name !*%^?': which exceeds max name length",7); // Modify the colour palette to bright red for the lime colour workbook.setColourRGB(Colour.LIME, 0xff, 0, 0); // Add a named range to the workbook workbook.addNameArea("namedrange", s4, 1, 11, 5, 14); workbook.addNameArea("validation_range", s1, 4, 65, 9, 65); workbook.addNameArea("formulavalue", s6, 1, 45, 1, 45); // Add a print area to the "Labels" sheet s5.getSettings().setPrintArea(4,4,15,35); writeLabelFormatSheet(s1); writeNumberFormatSheet(s2); writeDateFormatSheet(s3); writeBordersSheet(s4); writeLabelsSheet(s5); writeFormulaSheet(s6); writeImageSheet(s7); workbook.write(); workbook.close(); } /** * Writes out a sheet containing the various numerical formats * * @param s */ private void writeNumberFormatSheet(WritableSheet s) throws WriteException { WritableCellFormat wrappedText = new WritableCellFormat (WritableWorkbook.ARIAL_10_PT); wrappedText.setWrap(true); s.setColumnView(0,20); s.setColumnView(4,20); s.setColumnView(5,20); s.setColumnView(6,20); // Floats Label l = new Label(0,0,"+/- Pi - default format", wrappedText); s.addCell(l); Number n = new Number(1,0,3.1415926535); s.addCell(n); n = new Number(2,0,-3.1415926535); s.addCell(n); l = new Label(0,1,"+/- Pi - integer format", wrappedText); s.addCell(l); WritableCellFormat cf1 = new WritableCellFormat(NumberFormats.INTEGER); n = new Number(1,1,3.1415926535,cf1); s.addCell(n); n = new Number(2,1,-3.1415926535, cf1); s.addCell(n); l = new Label(0,2,"+/- Pi - float 2dps", wrappedText); s.addCell(l); WritableCellFormat cf2 = new WritableCellFormat(NumberFormats.FLOAT); n = new Number(1,2,3.1415926535,cf2); s.addCell(n); n = new Number(2,2,-3.1415926535, cf2); s.addCell(n); l = new Label(0,3,"+/- Pi - custom 3dps", wrappedText); s.addCell(l); NumberFormat dp3 = new NumberFormat("#.###"); WritableCellFormat dp3cell = new WritableCellFormat(dp3); n = new Number(1,3,3.1415926535,dp3cell); s.addCell(n); n = new Number(2,3,-3.1415926535, dp3cell); s.addCell(n); l = new Label(0,4,"+/- Pi - custom &3.14", wrappedText); s.addCell(l); NumberFormat pounddp2 = new NumberFormat("&#.00"); WritableCellFormat pounddp2cell = new WritableCellFormat(pounddp2); n = new Number(1,4,3.1415926535,pounddp2cell); s.addCell(n); n = new Number(2,4,-3.1415926535, pounddp2cell); s.addCell(n); l = new Label(0,5,"+/- Pi - custom Text #.### Text", wrappedText); s.addCell(l); NumberFormat textdp4 = new NumberFormat("Text#.####Text"); WritableCellFormat textdp4cell = new WritableCellFormat(textdp4); n = new Number(1,5,3.1415926535, textdp4cell); s.addCell(n); n = new Number(2,5,-3.1415926535, textdp4cell); s.addCell(n); // Integers l = new Label(4,0,"+/- Bilko default format"); s.addCell(l); n = new Number(5, 0, 15042699); s.addCell(n); n = new Number(6, 0, -15042699); s.addCell(n); l = new Label(4,1,"+/- Bilko float format"); s.addCell(l); WritableCellFormat cfi1 = new WritableCellFormat(NumberFormats.FLOAT); n = new Number(5, 1, 15042699, cfi1); s.addCell(n); n = new Number(6, 1, -15042699, cfi1); s.addCell(n); l = new Label(4,2,"+/- Thousands separator"); s.addCell(l); WritableCellFormat cfi2 = new WritableCellFormat (NumberFormats.THOUSANDS_INTEGER); n = new Number(5, 2, 15042699,cfi2 ); s.addCell(n); n = new Number(6, 2, -15042699, cfi2); s.addCell(n); l = new Label(4,3,"+/- Accounting red - added 0.01"); s.addCell(l); WritableCellFormat cfi3 = new WritableCellFormat (NumberFormats.ACCOUNTING_RED_FLOAT); n = new Number(5, 3, 15042699.01, cfi3); s.addCell(n); n = new Number(6, 3, -15042699.01, cfi3); s.addCell(n); l = new Label(4,4,"+/- Percent"); s.addCell(l); WritableCellFormat cfi4 = new WritableCellFormat (NumberFormats.PERCENT_INTEGER); n = new Number(5, 4, 15042699, cfi4); s.addCell(n); n = new Number(6, 4, -15042699, cfi4); s.addCell(n); l = new Label(4,5,"+/- Exponential - 2dps"); s.addCell(l); WritableCellFormat cfi5 = new WritableCellFormat (NumberFormats.EXPONENTIAL); n = new Number(5, 5, 15042699, cfi5); s.addCell(n); n = new Number(6, 5, -15042699, cfi5); s.addCell(n); l = new Label(4,6,"+/- Custom exponentional - 3dps", wrappedText); s.addCell(l); NumberFormat edp3 = new NumberFormat("0.000E0"); WritableCellFormat edp3Cell = new WritableCellFormat(edp3); n = new Number(5,6,15042699,edp3Cell); s.addCell(n); n = new Number(6,6,-15042699,edp3Cell); s.addCell(n); l = new Label(4, 7, "Custom neg brackets", wrappedText); s.addCell(l); NumberFormat negbracks = new NumberFormat("#,##0;(#,##0)"); WritableCellFormat negbrackscell = new WritableCellFormat(negbracks); n = new Number(5,7, 15042699, negbrackscell); s.addCell(n); n = new Number(6,7, -15042699, negbrackscell); s.addCell(n); l = new Label(4, 8, "Custom neg brackets 2", wrappedText); s.addCell(l); NumberFormat negbracks2 = new NumberFormat("#,##0;(#,##0)a"); WritableCellFormat negbrackscell2 = new WritableCellFormat(negbracks2); n = new Number(5,8, 15042699, negbrackscell2); s.addCell(n); n = new Number(6,8, -15042699, negbrackscell2); s.addCell(n); l = new Label(4, 9, "Custom percent", wrappedText); s.addCell(l); NumberFormat cuspercent = new NumberFormat("0.0%"); WritableCellFormat cuspercentf = new WritableCellFormat(cuspercent); n = new Number(5, 9, 3.14159265, cuspercentf); s.addCell(n); // Booleans l = new Label(0,10, "Boolean - TRUE"); s.addCell(l); Boolean b = new Boolean(1,10, true); s.addCell(b); l = new Label(0,11, "Boolean - FALSE"); s.addCell(l); b = new Boolean(1,11,false); s.addCell(b); l = new Label(0, 12, "A hidden cell->"); s.addCell(l); n = new Number(1, 12, 17, WritableWorkbook.HIDDEN_STYLE); s.addCell(n); // Currencies l = new Label(4, 19, "Currency formats"); s.addCell(l); l = new Label(4, 21, "UK Pound"); s.addCell(l); NumberFormat poundCurrency = new NumberFormat(NumberFormat.CURRENCY_POUND + " #,###.00", NumberFormat.COMPLEX_FORMAT); WritableCellFormat poundFormat = new WritableCellFormat(poundCurrency); n = new Number(5, 21, 12345, poundFormat); s.addCell(n); l = new Label(4, 22, "Euro 1"); s.addCell(l); NumberFormat euroPrefixCurrency = new NumberFormat(NumberFormat.CURRENCY_EURO_PREFIX + " #,###.00", NumberFormat.COMPLEX_FORMAT); WritableCellFormat euroPrefixFormat = new WritableCellFormat(euroPrefixCurrency); n = new Number(5, 22, 12345, euroPrefixFormat); s.addCell(n); l = new Label(4, 23, "Euro 2"); s.addCell(l); NumberFormat euroSuffixCurrency = new NumberFormat("#,###.00" + NumberFormat.CURRENCY_EURO_SUFFIX, NumberFormat.COMPLEX_FORMAT); WritableCellFormat euroSuffixFormat = new WritableCellFormat(euroSuffixCurrency); n = new Number(5, 23, 12345, euroSuffixFormat); s.addCell(n); l = new Label(4, 24, "Dollar"); s.addCell(l); NumberFormat dollarCurrency = new NumberFormat(NumberFormat.CURRENCY_DOLLAR + " #,###.00", NumberFormat.COMPLEX_FORMAT); WritableCellFormat dollarFormat = new WritableCellFormat(dollarCurrency); n = new Number(5, 24, 12345, dollarFormat); s.addCell(n); l = new Label(4, 25, "Japanese Yen"); s.addCell(l); NumberFormat japaneseYenCurrency = new NumberFormat(NumberFormat.CURRENCY_JAPANESE_YEN + " #,###.00", NumberFormat.COMPLEX_FORMAT); WritableCellFormat japaneseYenFormat = new WritableCellFormat(japaneseYenCurrency); n = new Number(5, 25, 12345, japaneseYenFormat); s.addCell(n); l = new Label(4, 30, "Fraction formats"); s.addCell(l); l = new Label(4,32, "One digit fraction format", wrappedText); s.addCell(l); WritableCellFormat fraction1digitformat = new WritableCellFormat(NumberFormats.FRACTION_ONE_DIGIT); n = new Number(5, 32, 3.18279, fraction1digitformat); s.addCell(n); l = new Label(4,33, "Two digit fraction format", wrappedText); s.addCell(l); WritableCellFormat fraction2digitformat = new WritableCellFormat(NumberFormats.FRACTION_TWO_DIGITS); n = new Number(5, 33, 3.18279, fraction2digitformat); s.addCell(n); l = new Label(4,34, "Three digit fraction format (improper)", wrappedText); s.addCell(l); NumberFormat fraction3digit1 = new NumberFormat(NumberFormat.FRACTION_THREE_DIGITS, NumberFormat.COMPLEX_FORMAT); WritableCellFormat fraction3digitformat1 = new WritableCellFormat(fraction3digit1); n = new Number(5, 34, 3.18927, fraction3digitformat1); s.addCell(n); l = new Label(4,35, "Three digit fraction format (proper)", wrappedText); s.addCell(l); NumberFormat fraction3digit2 = new NumberFormat("# " + NumberFormat.FRACTION_THREE_DIGITS, NumberFormat.COMPLEX_FORMAT); WritableCellFormat fraction3digitformat2 = new WritableCellFormat(fraction3digit2); n = new Number(5, 35, 3.18927, fraction3digitformat2); s.addCell(n); // Lots of numbers for (int row = 0; row < 100; row++) { for (int col = 8; col < 108; col++) { n = new Number(col, row, col+row); s.addCell(n); } } // Lots of numbers for (int row = 101; row < 3000; row++) { for (int col = 0; col < 25; col++) { n = new Number(col, row, col+row); s.addCell(n); } } } /** * Adds cells to the specified sheet which test the various date formats * * @param s */ private void writeDateFormatSheet(WritableSheet s) throws WriteException { WritableCellFormat wrappedText = new WritableCellFormat (WritableWorkbook.ARIAL_10_PT); wrappedText.setWrap(true); s.setColumnView(0, 20); s.setColumnView(2, 20); s.setColumnView(3, 20); s.setColumnView(4, 20); s.getSettings().setFitWidth(2); s.getSettings().setFitHeight(2); Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT")); c.set(1975, 4, 31, 15, 21, 45); c.set(Calendar.MILLISECOND, 660); Date date = c.getTime(); c.set(1900, 0, 1, 0, 0, 0); c.set(Calendar.MILLISECOND, 0); Date date2 = c.getTime(); c.set(1970, 0, 1, 0, 0, 0); Date date3 = c.getTime(); c.set(1918, 10, 11, 11, 0, 0); Date date4 = c.getTime(); c.set(1900, 0, 2, 0, 0, 0); Date date5 = c.getTime(); c.set(1901, 0, 1, 0, 0, 0); Date date6 = c.getTime(); c.set(1900, 4, 31, 0, 0, 0); Date date7 = c.getTime(); c.set(1900, 1, 1, 0, 0, 0); Date date8 = c.getTime(); c.set(1900, 0, 31, 0, 0, 0); Date date9 = c.getTime(); c.set(1900, 2, 1, 0, 0, 0); Date date10 = c.getTime(); c.set(1900, 1, 27, 0, 0, 0); Date date11 = c.getTime(); c.set(1900, 1, 28, 0, 0, 0); Date date12 = c.getTime(); c.set(1980, 5, 31, 12, 0, 0); Date date13 = c.getTime(); c.set(1066, 9, 14, 0, 0, 0); Date date14 = c.getTime(); // Built in date formats SimpleDateFormat sdf = new SimpleDateFormat("dd MMM yyyy HH:mm:ss.SSS"); sdf.setTimeZone(TimeZone.getTimeZone("GMT")); Label l = new Label(0,0,"All dates are " + sdf.format(date), wrappedText); s.addCell(l); l = new Label(0,1,"Built in formats", wrappedText); s.addCell(l); l = new Label(2, 1, "Custom formats"); s.addCell(l); WritableCellFormat cf1 = new WritableCellFormat(DateFormats.FORMAT1); DateTime dt = new DateTime(0,2,date, cf1, DateTime.GMT); s.addCell(dt); cf1 = new WritableCellFormat(DateFormats.FORMAT2); dt = new DateTime(0,3,date, cf1,DateTime.GMT); s.addCell(dt); cf1 = new WritableCellFormat(DateFormats.FORMAT3); dt = new DateTime(0,4,date, cf1); s.addCell(dt); cf1 = new WritableCellFormat(DateFormats.FORMAT4); dt = new DateTime(0,5,date, cf1); s.addCell(dt); cf1 = new WritableCellFormat(DateFormats.FORMAT5); dt = new DateTime(0,6,date, cf1); s.addCell(dt); cf1 = new WritableCellFormat(DateFormats.FORMAT6); dt = new DateTime(0,7,date, cf1); s.addCell(dt); cf1 = new WritableCellFormat(DateFormats.FORMAT7); dt = new DateTime(0,8,date, cf1, DateTime.GMT); s.addCell(dt); cf1 = new WritableCellFormat(DateFormats.FORMAT8); dt = new DateTime(0,9,date, cf1, DateTime.GMT); s.addCell(dt); cf1 = new WritableCellFormat(DateFormats.FORMAT9); dt = new DateTime(0,10,date, cf1, DateTime.GMT); s.addCell(dt); cf1 = new WritableCellFormat(DateFormats.FORMAT10); dt = new DateTime(0,11,date, cf1, DateTime.GMT); s.addCell(dt); cf1 = new WritableCellFormat(DateFormats.FORMAT11); dt = new DateTime(0,12,date, cf1, DateTime.GMT); s.addCell(dt); cf1 = new WritableCellFormat(DateFormats.FORMAT12); dt = new DateTime(0,13,date, cf1, DateTime.GMT); s.addCell(dt); // Custom formats DateFormat df = new DateFormat("dd MM yyyy"); cf1 = new WritableCellFormat(df); l = new Label(2, 2, "dd MM yyyy"); s.addCell(l); dt = new DateTime(3, 2, date, cf1, DateTime.GMT); s.addCell(dt); df = new DateFormat("dd MMM yyyy"); cf1 = new WritableCellFormat(df); l = new Label(2, 3, "dd MMM yyyy"); s.addCell(l); dt = new DateTime(3, 3, date, cf1, DateTime.GMT); s.addCell(dt); df = new DateFormat("hh:mm"); cf1 = new WritableCellFormat(df); l = new Label(2, 4, "hh:mm"); s.addCell(l); dt = new DateTime(3, 4, date, cf1, DateTime.GMT); s.addCell(dt); df = new DateFormat("hh:mm:ss"); cf1 = new WritableCellFormat(df); l = new Label(2, 5, "hh:mm:ss"); s.addCell(l); dt = new DateTime(3, 5, date, cf1, DateTime.GMT); s.addCell(dt); df = new DateFormat("H:mm:ss a"); cf1 = new WritableCellFormat(df); l = new Label(2, 5, "H:mm:ss a"); s.addCell(l); dt = new DateTime(3, 5, date, cf1, DateTime.GMT); s.addCell(dt); dt = new DateTime(4, 5, date13, cf1, DateTime.GMT); s.addCell(dt); df = new DateFormat("mm:ss.SSS"); cf1 = new WritableCellFormat(df); l = new Label(2, 6, "mm:ss.SSS"); s.addCell(l); dt = new DateTime(3, 6, date, cf1, DateTime.GMT); s.addCell(dt); df = new DateFormat("hh:mm:ss a"); cf1 = new WritableCellFormat(df); l = new Label(2, 7, "hh:mm:ss a"); s.addCell(l); dt = new DateTime(4, 7, date13, cf1, DateTime.GMT); s.addCell(dt); // Check out the zero date ie. 1 Jan 1900 l = new Label(0,16,"Zero date " + sdf.format(date2), wrappedText); s.addCell(l); cf1 = new WritableCellFormat(DateFormats.FORMAT9); dt = new DateTime(0,17,date2, cf1, DateTime.GMT); s.addCell(dt); // Check out the zero date + 1 ie. 2 Jan 1900 l = new Label(3,16,"Zero date + 1 " + sdf.format(date5), wrappedText); s.addCell(l); cf1 = new WritableCellFormat(DateFormats.FORMAT9); dt = new DateTime(3,17,date5, cf1, DateTime.GMT); s.addCell(dt); // Check out the 1 Jan 1901 l = new Label(3,19, sdf.format(date6), wrappedText); s.addCell(l); cf1 = new WritableCellFormat(DateFormats.FORMAT9); dt = new DateTime(3,20,date6, cf1, DateTime.GMT); s.addCell(dt); // Check out the 31 May 1900 l = new Label(3,22, sdf.format(date7), wrappedText); s.addCell(l); cf1 = new WritableCellFormat(DateFormats.FORMAT9); dt = new DateTime(3,23, date7, cf1, DateTime.GMT); s.addCell(dt); // Check out 1 Feb 1900 l = new Label(3,25, sdf.format(date8), wrappedText); s.addCell(l); cf1 = new WritableCellFormat(DateFormats.FORMAT9); dt = new DateTime(3,26, date8, cf1, DateTime.GMT); s.addCell(dt); // Check out 31 Jan 1900 l = new Label(3,28, sdf.format(date9), wrappedText); s.addCell(l); cf1 = new WritableCellFormat(DateFormats.FORMAT9); dt = new DateTime(3,29, date9, cf1, DateTime.GMT); s.addCell(dt); // Check out 31 Jan 1900 l = new Label(3,28, sdf.format(date9), wrappedText); s.addCell(l); cf1 = new WritableCellFormat(DateFormats.FORMAT9); dt = new DateTime(3,29, date9, cf1, DateTime.GMT); s.addCell(dt); // Check out 1 Mar 1900 l = new Label(3,31, sdf.format(date10), wrappedText); s.addCell(l); cf1 = new WritableCellFormat(DateFormats.FORMAT9); dt = new DateTime(3,32, date10, cf1, DateTime.GMT); s.addCell(dt); // Check out 27 Feb 1900 l = new Label(3,34, sdf.format(date11), wrappedText); s.addCell(l); cf1 = new WritableCellFormat(DateFormats.FORMAT9); dt = new DateTime(3,35, date11, cf1, DateTime.GMT); s.addCell(dt); // Check out 28 Feb 1900 l = new Label(3,37, sdf.format(date12), wrappedText); s.addCell(l); cf1 = new WritableCellFormat(DateFormats.FORMAT9); dt = new DateTime(3,38, date12, cf1, DateTime.GMT); s.addCell(dt); // Check out the zero date ie. 1 Jan 1970 l = new Label(0,19,"Zero UTC date " + sdf.format(date3), wrappedText); s.addCell(l); cf1 = new WritableCellFormat(DateFormats.FORMAT9); dt = new DateTime(0,20,date3, cf1, DateTime.GMT); s.addCell(dt); // Check out the WWI armistice day ie. 11 am, Nov 11, 1918 l = new Label(0,22,"Armistice date " + sdf.format(date4), wrappedText); s.addCell(l); cf1 = new WritableCellFormat(DateFormats.FORMAT9); dt = new DateTime(0,23,date4, cf1, DateTime.GMT); s.addCell(dt); // Check out the Battle of Hastings date Oct 14th, 1066 l = new Label(0,25, "Battle of Hastings " + sdf.format(date14), wrappedText); s.addCell(l); cf1 = new WritableCellFormat(DateFormats.FORMAT2); dt = new DateTime(0, 26, date14, cf1, DateTime.GMT); s.addCell(dt); } /** * Adds cells to the specified sheet which test the various label formatting * styles, such as different fonts, different sizes and bold, underline etc. * * @param s1 */ private void writeLabelFormatSheet(WritableSheet s1) throws WriteException { s1.setColumnView(0, 60); Label lr = new Label(0,0, "Arial Fonts"); s1.addCell(lr); lr = new Label(1,0, "10pt"); s1.addCell(lr); lr = new Label(2, 0, "Normal"); s1.addCell(lr); lr = new Label(3, 0, "12pt"); s1.addCell(lr); WritableFont arial12pt = new WritableFont(WritableFont.ARIAL, 12); WritableCellFormat arial12format = new WritableCellFormat(arial12pt); arial12format.setWrap(true); lr = new Label(4, 0, "Normal", arial12format); s1.addCell(lr); WritableFont arial10ptBold = new WritableFont (WritableFont.ARIAL, 10, WritableFont.BOLD); WritableCellFormat arial10BoldFormat = new WritableCellFormat (arial10ptBold); lr = new Label(2, 2, "BOLD", arial10BoldFormat); s1.addCell(lr); WritableFont arial12ptBold = new WritableFont (WritableFont.ARIAL, 12, WritableFont.BOLD); WritableCellFormat arial12BoldFormat = new WritableCellFormat (arial12ptBold); lr = new Label(4, 2, "BOLD", arial12BoldFormat); s1.addCell(lr); WritableFont arial10ptItalic = new WritableFont (WritableFont.ARIAL, 10, WritableFont.NO_BOLD, true); WritableCellFormat arial10ItalicFormat = new WritableCellFormat (arial10ptItalic); lr = new Label(2, 4, "Italic", arial10ItalicFormat); s1.addCell(lr); WritableFont arial12ptItalic = new WritableFont (WritableFont.ARIAL, 12, WritableFont.NO_BOLD, true); WritableCellFormat arial12ptItalicFormat = new WritableCellFormat (arial12ptItalic); lr = new Label(4, 4, "Italic", arial12ptItalicFormat); s1.addCell(lr); WritableFont times10pt = new WritableFont(WritableFont.TIMES, 10); WritableCellFormat times10format = new WritableCellFormat(times10pt); lr = new Label(0, 7, "Times Fonts", times10format); s1.addCell(lr); lr = new Label(1, 7, "10pt", times10format); s1.addCell(lr); lr = new Label(2, 7, "Normal", times10format); s1.addCell(lr); lr = new Label(3, 7, "12pt", times10format); s1.addCell(lr); WritableFont times12pt = new WritableFont(WritableFont.TIMES, 12); WritableCellFormat times12format = new WritableCellFormat(times12pt); lr = new Label(4, 7, "Normal", times12format); s1.addCell(lr); WritableFont times10ptBold = new WritableFont (WritableFont.TIMES, 10, WritableFont.BOLD); WritableCellFormat times10BoldFormat = new WritableCellFormat (times10ptBold); lr = new Label(2, 9, "BOLD", times10BoldFormat); s1.addCell(lr); WritableFont times12ptBold = new WritableFont (WritableFont.TIMES, 12, WritableFont.BOLD); WritableCellFormat times12BoldFormat = new WritableCellFormat (times12ptBold); lr = new Label(4, 9, "BOLD", times12BoldFormat); s1.addCell(lr); // The underline styles s1.setColumnView(6, 22); s1.setColumnView(7, 22); s1.setColumnView(8, 22); s1.setColumnView(9, 22); lr = new Label(0, 11, "Underlining"); s1.addCell(lr); WritableFont arial10ptUnderline = new WritableFont (WritableFont.ARIAL, WritableFont.DEFAULT_POINT_SIZE, WritableFont.NO_BOLD, false, UnderlineStyle.SINGLE); WritableCellFormat arialUnderline = new WritableCellFormat (arial10ptUnderline); lr = new Label(6,11, "Underline", arialUnderline); s1.addCell(lr); WritableFont arial10ptDoubleUnderline = new WritableFont (WritableFont.ARIAL, WritableFont.DEFAULT_POINT_SIZE, WritableFont.NO_BOLD, false, UnderlineStyle.DOUBLE); WritableCellFormat arialDoubleUnderline = new WritableCellFormat (arial10ptDoubleUnderline); lr = new Label(7,11, "Double Underline", arialDoubleUnderline); s1.addCell(lr); WritableFont arial10ptSingleAcc = new WritableFont (WritableFont.ARIAL, WritableFont.DEFAULT_POINT_SIZE, WritableFont.NO_BOLD, false, UnderlineStyle.SINGLE_ACCOUNTING); WritableCellFormat arialSingleAcc = new WritableCellFormat (arial10ptSingleAcc); lr = new Label(8,11, "Single Accounting Underline", arialSingleAcc); s1.addCell(lr); WritableFont arial10ptDoubleAcc = new WritableFont (WritableFont.ARIAL, WritableFont.DEFAULT_POINT_SIZE, WritableFont.NO_BOLD, false, UnderlineStyle.DOUBLE_ACCOUNTING); WritableCellFormat arialDoubleAcc = new WritableCellFormat (arial10ptDoubleAcc); lr = new Label(9,11, "Double Accounting Underline", arialDoubleAcc); s1.addCell(lr); WritableFont times14ptBoldUnderline = new WritableFont (WritableFont.TIMES, 14, WritableFont.BOLD, false, UnderlineStyle.SINGLE); WritableCellFormat timesBoldUnderline = new WritableCellFormat (times14ptBoldUnderline); lr = new Label(6,12, "Times 14 Bold Underline", timesBoldUnderline); s1.addCell(lr); WritableFont arial18ptBoldItalicUnderline = new WritableFont (WritableFont.ARIAL, 18, WritableFont.BOLD, true, UnderlineStyle.SINGLE); WritableCellFormat arialBoldItalicUnderline = new WritableCellFormat (arial18ptBoldItalicUnderline); lr = new Label(6,13, "Arial 18 Bold Italic Underline", arialBoldItalicUnderline); s1.addCell(lr); lr = new Label(0, 15, "Script styles"); s1.addCell(lr); WritableFont superscript = new WritableFont (WritableFont.ARIAL, WritableFont.DEFAULT_POINT_SIZE, WritableFont.NO_BOLD, false, UnderlineStyle.NO_UNDERLINE, Colour.BLACK, ScriptStyle.SUPERSCRIPT); WritableCellFormat superscriptFormat = new WritableCellFormat (superscript); lr = new Label(1,15, "superscript", superscriptFormat); s1.addCell(lr); WritableFont subscript = new WritableFont (WritableFont.ARIAL, WritableFont.DEFAULT_POINT_SIZE, WritableFont.NO_BOLD, false, UnderlineStyle.NO_UNDERLINE, Colour.BLACK, ScriptStyle.SUBSCRIPT); WritableCellFormat subscriptFormat = new WritableCellFormat (subscript); lr = new Label(2,15, "subscript", subscriptFormat); s1.addCell(lr); lr = new Label(0, 17, "Colours"); s1.addCell(lr); WritableFont red = new WritableFont(WritableFont.ARIAL, WritableFont.DEFAULT_POINT_SIZE, WritableFont.NO_BOLD, false, UnderlineStyle.NO_UNDERLINE, Colour.RED); WritableCellFormat redFormat = new WritableCellFormat(red); lr = new Label(2, 17, "Red", redFormat); s1.addCell(lr); WritableFont blue = new WritableFont(WritableFont.ARIAL, WritableFont.DEFAULT_POINT_SIZE, WritableFont.NO_BOLD, false, UnderlineStyle.NO_UNDERLINE, Colour.BLUE); WritableCellFormat blueFormat = new WritableCellFormat(blue); lr = new Label(2, 18, "Blue", blueFormat); s1.addCell(lr); WritableFont lime = new WritableFont(WritableFont.ARIAL); lime.setColour(Colour.LIME); WritableCellFormat limeFormat = new WritableCellFormat(lime); limeFormat.setWrap(true); lr = new Label(4, 18, "Modified palette - was lime, now red", limeFormat); s1.addCell(lr); WritableCellFormat greyBackground = new WritableCellFormat(); greyBackground.setWrap(true); greyBackground.setBackground(Colour.GRAY_50); lr = new Label(2, 19, "Grey background", greyBackground); s1.addCell(lr); WritableFont yellow = new WritableFont(WritableFont.ARIAL, WritableFont.DEFAULT_POINT_SIZE, WritableFont.NO_BOLD, false, UnderlineStyle.NO_UNDERLINE, Colour.YELLOW); WritableCellFormat yellowOnBlue = new WritableCellFormat(yellow); yellowOnBlue.setWrap(true); yellowOnBlue.setBackground(Colour.BLUE); lr = new Label(2, 20, "Blue background, yellow foreground", yellowOnBlue); s1.addCell(lr); WritableCellFormat yellowOnBlack = new WritableCellFormat(yellow); yellowOnBlack.setWrap(true); yellowOnBlack.setBackground(Colour.PALETTE_BLACK); lr = new Label(3, 20, "Black background, yellow foreground", yellowOnBlack); s1.addCell(lr); lr = new Label(0, 22, "Null label"); s1.addCell(lr); lr = new Label(2, 22, null); s1.addCell(lr); lr = new Label(0, 24, "A very long label, more than 255 characters\012" + "Rejoice O shores\012" + "Sing O bells\012" + "But I with mournful tread\012" + "Walk the deck my captain lies\012" + "Fallen cold and dead\012"+ "Summer surprised, coming over the Starnbergersee\012" + "With a shower of rain. We stopped in the Colonnade\012" + "A very long label, more than 255 characters\012" + "Rejoice O shores\012" + "Sing O bells\012" + "But I with mournful tread\012" + "Walk the deck my captain lies\012" + "Fallen cold and dead\012"+ "Summer surprised, coming over the Starnbergersee\012" + "With a shower of rain. We stopped in the Colonnade\012" + "A very long label, more than 255 characters\012" + "Rejoice O shores\012" + "Sing O bells\012" + "But I with mournful tread\012" + "Walk the deck my captain lies\012" + "Fallen cold and dead\012"+ "Summer surprised, coming over the Starnbergersee\012" + "With a shower of rain. We stopped in the Colonnade\012" + "A very long label, more than 255 characters\012" + "Rejoice O shores\012" + "Sing O bells\012" + "But I with mournful tread\012" + "Walk the deck my captain lies\012" + "Fallen cold and dead\012"+ "Summer surprised, coming over the Starnbergersee\012" + "With a shower of rain. We stopped in the Colonnade\012" + "And sat and drank coffee an talked for an hour\012", arial12format); s1.addCell(lr); WritableCellFormat vertical = new WritableCellFormat(); vertical.setOrientation(Orientation.VERTICAL); lr = new Label(0, 26, "Vertical orientation", vertical); s1.addCell(lr); WritableCellFormat plus_90 = new WritableCellFormat(); plus_90.setOrientation(Orientation.PLUS_90); lr = new Label(1, 26, "Plus 90", plus_90); s1.addCell(lr); WritableCellFormat minus_90 = new WritableCellFormat(); minus_90.setOrientation(Orientation.MINUS_90); lr = new Label(2, 26, "Minus 90", minus_90); s1.addCell(lr); lr = new Label(0, 28, "Modified row height"); s1.addCell(lr); s1.setRowView(28, 24*20); lr = new Label(0, 29, "Collapsed row"); s1.addCell(lr); s1.setRowView(29, true); // Write hyperlinks try { Label l = new Label(0, 30, "Hyperlink to home page"); s1.addCell(l); URL url = new URL("http://www.andykhan.com/jexcelapi"); WritableHyperlink wh = new WritableHyperlink(0, 30, 8, 31, url); s1.addHyperlink(wh); // The below hyperlink clashes with above WritableHyperlink wh2 = new WritableHyperlink(7, 30, 9, 31, url); s1.addHyperlink(wh2); l = new Label(4, 2, "File hyperlink to documentation"); s1.addCell(l); File file = new File("../jexcelapi/docs/index.html"); wh = new WritableHyperlink(0, 32, 8, 32, file, "JExcelApi Documentation"); s1.addHyperlink(wh); // Add a hyperlink to another cell on this sheet wh = new WritableHyperlink(0, 34, 8, 34, "Link to another cell", s1, 0, 180, 1, 181); s1.addHyperlink(wh); file = new File("\\\\localhost\\file.txt"); wh = new WritableHyperlink(0, 36, 8, 36, file); s1.addHyperlink(wh); // Add a very long hyperlink url = new URL("http://www.amazon.co.uk/exec/obidos/ASIN/0571058086"+ "/qid=1099836249/sr=1-3/ref=sr_1_11_3/202-6017285-1620664"); wh = new WritableHyperlink(0, 38, 0, 38, url); s1.addHyperlink(wh); } catch (MalformedURLException e) { System.err.println(e.toString()); } // Write out some merged cells Label l = new Label(5, 35, "Merged cells", timesBoldUnderline); s1.mergeCells(5, 35, 8, 37); s1.addCell(l); l = new Label(5, 38, "More merged cells"); s1.addCell(l); Range r = s1.mergeCells(5, 38, 8, 41); s1.insertRow(40); s1.removeRow(39); s1.unmergeCells(r); // Merge cells and centre across them WritableCellFormat wcf = new WritableCellFormat(); wcf.setAlignment(Alignment.CENTRE); l = new Label(5, 42, "Centred across merged cells", wcf); s1.addCell(l); s1.mergeCells(5, 42, 10, 42); wcf = new WritableCellFormat(); wcf.setBorder(Border.ALL, BorderLineStyle.THIN); wcf.setBackground(Colour.GRAY_25); l = new Label(3, 44, "Merged with border", wcf); s1.addCell(l); s1.mergeCells(3, 44, 4, 46); // Clash some ranges - the second range will not be added // Also merge some cells with two data items in the - the second data // item will not be merged /* l = new Label(5, 16, "merged cells"); s1.addCell(l); Label l5 = new Label(7, 17, "this label won't appear"); s1.addCell(l5); s1.mergeCells(5, 16, 8, 18); s1.mergeCells(5, 19, 6, 24); s1.mergeCells(6, 18, 10, 19); */ WritableFont courier10ptFont = new WritableFont(WritableFont.COURIER, 10); WritableCellFormat courier10pt = new WritableCellFormat(courier10ptFont); l = new Label(0, 49, "Courier fonts", courier10pt); s1.addCell(l); WritableFont tahoma12ptFont = new WritableFont(WritableFont.TAHOMA, 12); WritableCellFormat tahoma12pt = new WritableCellFormat(tahoma12ptFont); l = new Label(0, 50, "Tahoma fonts", tahoma12pt); s1.addCell(l); WritableFont.FontName wingdingsFont = WritableFont.createFont("Wingdings 2"); WritableFont wingdings210ptFont = new WritableFont(wingdingsFont, 10); WritableCellFormat wingdings210pt = new WritableCellFormat (wingdings210ptFont); l = new Label(0,51, "Bespoke Windgdings 2", wingdings210pt); s1.addCell(l); WritableCellFormat shrinkToFit = new WritableCellFormat(times12pt); shrinkToFit.setShrinkToFit(true); l = new Label(3,53, "Shrunk to fit", shrinkToFit); s1.addCell(l); l = new Label(3,55, "Some long wrapped text in a merged cell", arial12format); s1.addCell(l); s1.mergeCells(3,55,4,55); l = new Label(0, 57, "A cell with a comment"); WritableCellFeatures cellFeatures = new WritableCellFeatures(); cellFeatures.setComment("the cell comment"); l.setCellFeatures(cellFeatures); s1.addCell(l); l = new Label(0, 59, "A cell with a long comment"); cellFeatures = new WritableCellFeatures(); cellFeatures.setComment("a very long cell comment indeed that won't " + "fit inside a standard comment box, so a " + "larger comment box is used instead", 5, 6); l.setCellFeatures(cellFeatures); s1.addCell(l); WritableCellFormat indented = new WritableCellFormat(times12pt); indented.setIndentation(4); l = new Label(0, 61, "Some indented text", indented); s1.addCell(l); l = new Label(0, 63, "Data validation: list"); s1.addCell(l); Blank b = new Blank(1,63); cellFeatures = new WritableCellFeatures(); ArrayList al = new ArrayList(); al.add("bagpuss"); al.add("clangers"); al.add("ivor the engine"); al.add("noggin the nog"); cellFeatures.setDataValidationList(al); b.setCellFeatures(cellFeatures); s1.addCell(b); l = new Label(0, 64, "Data validation: number > 4.5"); s1.addCell(l); b = new Blank(1,64); cellFeatures = new WritableCellFeatures(); cellFeatures.setNumberValidation(4.5, WritableCellFeatures.GREATER_THAN); b.setCellFeatures(cellFeatures); s1.addCell(b); l = new Label(0, 65, "Data validation: named range"); s1.addCell(l); l = new Label(4, 65, "tiger"); s1.addCell(l); l = new Label(5, 65, "sword"); s1.addCell(l); l = new Label(6, 65, "honour"); s1.addCell(l); l = new Label(7, 65, "company"); s1.addCell(l); l = new Label(8, 65, "victory"); s1.addCell(l); l = new Label(9, 65, "fortress"); s1.addCell(l); b = new Blank(1,65); cellFeatures = new WritableCellFeatures(); cellFeatures.setDataValidationRange("validation_range"); b.setCellFeatures(cellFeatures); s1.addCell(b); // Set the row grouping s1.setRowGroup(39, 45, false); // s1.setRowGroup(72, 74, true); l = new Label(0, 66, "Block of cells B67-F71 with data validation"); s1.addCell(l); al = new ArrayList(); al.add("Achilles"); al.add("Agamemnon"); al.add("Hector"); al.add("Odysseus"); al.add("Patroclus"); al.add("Nestor"); b = new Blank(1, 66); cellFeatures = new WritableCellFeatures(); cellFeatures.setDataValidationList(al); b.setCellFeatures(cellFeatures); s1.addCell(b); s1.applySharedDataValidation(b, 4,4); cellFeatures = new WritableCellFeatures(); cellFeatures.setDataValidationRange(""); l = new Label(0, 71, "Read only cell using empty data validation"); l.setCellFeatures(cellFeatures); s1.addCell(l); // Set the row grouping s1.setRowGroup(39, 45, false); // s1.setRowGroup(72, 74, true); } /** * Adds cells to the specified sheet which test the various border * styles * * @param s */ private void writeBordersSheet(WritableSheet s) throws WriteException { s.getSettings().setProtected(true); s.setColumnView(1, 15); s.setColumnView(2, 15); s.setColumnView(4, 15); WritableCellFormat thickLeft = new WritableCellFormat(); thickLeft.setBorder(Border.LEFT, BorderLineStyle.THICK); Label lr = new Label(1,0, "Thick left", thickLeft); s.addCell(lr); WritableCellFormat dashedRight = new WritableCellFormat(); dashedRight.setBorder(Border.RIGHT, BorderLineStyle.DASHED); lr = new Label(2, 0, "Dashed right", dashedRight); s.addCell(lr); WritableCellFormat doubleTop = new WritableCellFormat(); doubleTop.setBorder(Border.TOP, BorderLineStyle.DOUBLE); lr = new Label(1, 2, "Double top", doubleTop); s.addCell(lr); WritableCellFormat hairBottom = new WritableCellFormat(); hairBottom.setBorder(Border.BOTTOM, BorderLineStyle.HAIR); lr = new Label(2, 2, "Hair bottom", hairBottom); s.addCell(lr); WritableCellFormat allThin = new WritableCellFormat(); allThin.setBorder(Border.ALL, BorderLineStyle.THIN); lr = new Label(4, 2, "All thin", allThin); s.addCell(lr); WritableCellFormat twoBorders = new WritableCellFormat(); twoBorders.setBorder(Border.TOP, BorderLineStyle.THICK); twoBorders.setBorder(Border.LEFT, BorderLineStyle.THICK); lr = new Label(6,2, "Two borders", twoBorders); s.addCell(lr); // Create a cell in the middle of nowhere (out of the grow region) lr = new Label(20, 20, "Dislocated cell - after a page break"); s.addCell(lr); // Set the orientation and the margins s.getSettings().setPaperSize(PaperSize.A3); s.getSettings().setOrientation(PageOrientation.LANDSCAPE); s.getSettings().setPageOrder(PageOrder.DOWN_THEN_RIGHT); s.getSettings().setHeaderMargin(2); s.getSettings().setFooterMargin(2); s.getSettings().setTopMargin(3); s.getSettings().setBottomMargin(3); // Add a header and footera HeaderFooter header = new HeaderFooter(); header.getCentre().append("Page Header"); s.getSettings().setHeader(header); HeaderFooter footer = new HeaderFooter(); footer.getRight().append("page "); footer.getRight().appendPageNumber(); s.getSettings().setFooter(footer); // Add a page break and insert a couple of rows s.addRowPageBreak(18); s.insertRow(17); s.insertRow(17); s.removeRow(17); // Add a page break off the screen s.addRowPageBreak(30); // Add a hidden column lr = new Label(10, 1, "Hidden column"); s.addCell(lr); lr = new Label(3, 8, "Hidden row"); s.addCell(lr); s.setRowView(8, true); WritableCellFormat allThickRed = new WritableCellFormat(); allThickRed.setBorder(Border.ALL, BorderLineStyle.THICK, Colour.RED); lr = new Label(1, 5, "All thick red", allThickRed); s.addCell(lr); WritableCellFormat topBottomBlue = new WritableCellFormat(); topBottomBlue.setBorder(Border.TOP, BorderLineStyle.THIN, Colour.BLUE); topBottomBlue.setBorder(Border.BOTTOM, BorderLineStyle.THIN, Colour.BLUE); lr = new Label(4, 5, "Top and bottom blue", topBottomBlue); s.addCell(lr); } /** * Write out loads of labels, in order to test the shared string table */ private void writeLabelsSheet(WritableSheet ws) throws WriteException { ws.getSettings().setProtected(true); ws.getSettings().setPassword("jxl"); ws.getSettings().setVerticalFreeze(5); ws.getSettings().setDefaultRowHeight(25*20); WritableFont wf = new WritableFont(WritableFont.ARIAL, 12); wf.setItalic(true); WritableCellFormat wcf = new WritableCellFormat(wf); CellView cv = new CellView(); cv.setSize(25 * 256); cv.setFormat(wcf); ws.setColumnView(0, cv); ws.setColumnView(1, 15); for (int i = 0; i < 61; i++) { Label l1 = new Label(0, i, "Common Label"); Label l2 = new Label(1, i, "Distinct label number " + i); ws.addCell(l1); ws.addCell(l2); } // Frig this test record - it appears exactly on the boundary of an SST // continue record Label l3 = new Label(0, 61, "Common Label", wcf); Label l4 = new Label(1, 61, "1-1234567890", wcf); Label l5 = new Label(2, 61, "2-1234567890", wcf); ws.addCell(l3); ws.addCell(l4); ws.addCell(l5); for (int i = 62; i < 200; i++) { Label l1 = new Label(0, i, "Common Label"); Label l2 = new Label(1, i, "Distinct label number " + i); ws.addCell(l1); ws.addCell(l2); } // Add in a last label which doesn't take the jxl.common.format wf = new WritableFont(WritableFont.TIMES, 10, WritableFont.BOLD); wf.setColour(Colour.RED); WritableCellFormat wcf2 = new WritableCellFormat(wf); wcf2.setWrap(true); Label l = new Label(0, 205, "Different format", wcf2); ws.addCell(l); // Add some labels to column 5 for autosizing Label l6 = new Label(5, 2, "A column for autosizing", wcf2); ws.addCell(l6); l6 = new Label(5, 4, "Another label, longer this time and " + "in a different font"); ws.addCell(l6); CellView cf = new CellView(); cf.setAutosize(true); ws.setColumnView(5, cf); } /** * Test out the formula parser */ private void writeFormulaSheet(WritableSheet ws) throws WriteException { // Add some cells to manipulate Number nc = new Number(0,0,15); ws.addCell(nc); nc = new Number(0,1,16); ws.addCell(nc); nc = new Number(0,2,10); ws.addCell(nc); nc = new Number(0,3, 12); ws.addCell(nc); ws.setColumnView(2, 20); WritableCellFormat wcf = new WritableCellFormat(); wcf.setAlignment(Alignment.RIGHT); wcf.setWrap(true); CellView cv = new CellView(); cv.setSize(25 * 256); cv.setFormat(wcf); ws.setColumnView(3, cv); // Add in the formulas Formula f = null; Label l = null; f = new Formula(2,0, "A1+A2"); ws.addCell(f); l = new Label(3, 0, "a1+a2"); ws.addCell(l); f = new Formula(2,1, "A2 * 3"); ws.addCell(f); l = new Label(3,1, "A2 * 3"); ws.addCell(l); f = new Formula(2,2, "A2+A1/2.5"); ws.addCell(f); l = new Label(3,2, "A2+A1/2.5"); ws.addCell(l); f = new Formula(2,3, "3+(a1+a2)/2.5"); ws.addCell(f); l = new Label(3,3, "3+(a1+a2)/2.5"); ws.addCell(l); f = new Formula(2,4, "(a1+a2)/2.5"); ws.addCell(f); l = new Label(3,4, "(a1+a2)/2.5"); ws.addCell(l); f = new Formula(2,5, "15+((a1+a2)/2.5)*17"); ws.addCell(f); l = new Label(3,5, "15+((a1+a2)/2.5)*17"); ws.addCell(l); f = new Formula(2, 6, "SUM(a1:a4)"); ws.addCell(f); l = new Label(3, 6, "SUM(a1:a4)"); ws.addCell(l); f = new Formula(2, 7, "SUM(a1:a4)/4"); ws.addCell(f); l = new Label(3, 7, "SUM(a1:a4)/4"); ws.addCell(l); f = new Formula(2, 8, "AVERAGE(A1:A4)"); ws.addCell(f); l = new Label(3, 8, "AVERAGE(a1:a4)"); ws.addCell(l); f = new Formula(2, 9, "MIN(5,4,1,2,3)"); ws.addCell(f); l = new Label(3, 9, "MIN(5,4,1,2,3)"); ws.addCell(l); f = new Formula(2, 10, "ROUND(3.14159265, 3)"); ws.addCell(f); l = new Label(3, 10, "ROUND(3.14159265, 3)"); ws.addCell(l); f = new Formula(2, 11, "MAX(SUM(A1:A2), A1*A2, POWER(A1, 2))"); ws.addCell(f); l = new Label(3, 11, "MAX(SUM(A1:A2), A1*A2, POWER(A1, 2))"); ws.addCell(l); f = new Formula(2,12, "IF(A2>A1, \"A2 bigger\", \"A1 bigger\")"); ws.addCell(f); l = new Label(3,12, "IF(A2>A1, \"A2 bigger\", \"A1 bigger\")"); ws.addCell(l); f = new Formula(2,13, "IF(A2<=A1, \"A2 smaller\", \"A1 smaller\")"); ws.addCell(f); l = new Label(3,13, "IF(A2<=A1, \"A2 smaller\", \"A1 smaller\")"); ws.addCell(l); f = new Formula(2,14, "IF(A3<=10, \"<= 10\")"); ws.addCell(f); l = new Label(3,14, "IF(A3<=10, \"<= 10\")"); ws.addCell(l); f = new Formula(2, 15, "SUM(1,2,3,4,5)"); ws.addCell(f); l = new Label(3, 15, "SUM(1,2,3,4,5)"); ws.addCell(l); f = new Formula(2, 16, "HYPERLINK(\"http://www.andykhan.com/jexcelapi\", \"JExcelApi Home Page\")"); ws.addCell(f); l = new Label(3, 16, "HYPERLINK(\"http://www.andykhan.com/jexcelapi\", \"JExcelApi Home Page\")"); ws.addCell(l); f = new Formula(2, 17, "3*4+5"); ws.addCell(f); l = new Label(3, 17, "3*4+5"); ws.addCell(l); f = new Formula(2, 18, "\"Plain text formula\""); ws.addCell(f); l = new Label(3, 18, "Plain text formula"); ws.addCell(l); f = new Formula(2, 19, "SUM(a1,a2,-a3,a4)"); ws.addCell(f); l = new Label(3, 19, "SUM(a1,a2,-a3,a4)"); ws.addCell(l); f = new Formula(2, 20, "2*-(a1+a2)"); ws.addCell(f); l = new Label(3, 20, "2*-(a1+a2)"); ws.addCell(l); f = new Formula(2, 21, "'Number Formats'!B1/2"); ws.addCell(f); l = new Label(3, 21, "'Number Formats'!B1/2"); ws.addCell(l); f = new Formula(2, 22, "IF(F22=0, 0, F21/F22)"); ws.addCell(f); l = new Label(3, 22, "IF(F22=0, 0, F21/F22)"); ws.addCell(l); f = new Formula(2, 23, "RAND()"); ws.addCell(f); l = new Label(3, 23, "RAND()"); ws.addCell(l); StringBuffer buf = new StringBuffer(); buf.append("'"); buf.append(workbook.getSheet(0).getName()); buf.append("'!"); buf.append(CellReferenceHelper.getCellReference(9, 18)); buf.append("*25"); f = new Formula(2, 24, buf.toString()); ws.addCell(f); l = new Label(3, 24, buf.toString()); ws.addCell(l); wcf = new WritableCellFormat(DateFormats.DEFAULT); f = new Formula(2, 25, "NOW()", wcf); ws.addCell(f); l = new Label(3, 25, "NOW()"); ws.addCell(l); f = new Formula(2, 26, "$A$2+A3"); ws.addCell(f); l = new Label(3, 26, "$A$2+A3"); ws.addCell(l); f = new Formula(2, 27, "IF(COUNT(A1:A9,B1:B9)=0,\"\",COUNT(A1:A9,B1:B9))"); ws.addCell(f); l = new Label(3, 27, "IF(COUNT(A1:A9,B1:B9)=0,\"\",COUNT(A1:A9,B1:B9))"); ws.addCell(l); f = new Formula(2, 28, "SUM(A1,A2,A3,A4)"); ws.addCell(f); l = new Label(3, 28, "SUM(A1,A2,A3,A4)"); ws.addCell(l); l = new Label(1, 29, "a1"); ws.addCell(l); f = new Formula(2, 29, "SUM(INDIRECT(ADDRESS(2,29)):A4)"); ws.addCell(f); l = new Label(3, 29, "SUM(INDIRECT(ADDRESS(2,29):A4)"); ws.addCell(l); f = new Formula(2, 30, "COUNTIF(A1:A4, \">=12\")"); ws.addCell(f); l = new Label(3, 30, "COUNTIF(A1:A4, \">=12\")"); ws.addCell(l); f = new Formula(2, 31, "MAX($A$1:$A$4)"); ws.addCell(f); l = new Label(3, 31, "MAX($A$1:$A$4)"); ws.addCell(l); f = new Formula(2, 32, "OR(A1,TRUE)"); ws.addCell(f); l = new Label(3, 32, "OR(A1,TRUE)"); ws.addCell(l); f = new Formula(2, 33, "ROWS(A1:C14)"); ws.addCell(f); l = new Label(3, 33, "ROWS(A1:C14)"); ws.addCell(l); f = new Formula(2, 34, "COUNTBLANK(A1:C14)"); ws.addCell(f); l = new Label(3, 34, "COUNTBLANK(A1:C14)"); ws.addCell(l); f = new Formula(2, 35, "IF(((F1=\"Not Found\")*(F2=\"Not Found\")*(F3=\"\")*(F4=\"\")*(F5=\"\")),1,0)"); ws.addCell(f); l = new Label(3, 35, "IF(((F1=\"Not Found\")*(F2=\"Not Found\")*(F3=\"\")*(F4=\"\")*(F5=\"\")),1,0)"); ws.addCell(l); f = new Formula(2, 36, "HYPERLINK(\"http://www.amazon.co.uk/exec/obidos/ASIN/0571058086qid=1099836249/sr=1-3/ref=sr_1_11_3/202-6017285-1620664\", \"Long hyperlink\")"); ws.addCell(f); f = new Formula(2, 37, "1234567+2699"); ws.addCell(f); l = new Label(3, 37, "1234567+2699"); ws.addCell(l); f = new Formula(2, 38, "IF(ISERROR(G25/G29),0,-1)"); ws.addCell(f); l = new Label(3, 38, "IF(ISERROR(G25/G29),0,-1)"); ws.addCell(l); f = new Formula(2, 39, "SEARCH(\"C\",D40)"); ws.addCell(f); l = new Label(3, 39, "SEARCH(\"C\",D40)"); ws.addCell(l); f = new Formula(2, 40, "#REF!"); ws.addCell(f); l = new Label(3, 40, "#REF!"); ws.addCell(l); nc = new Number (1,41, 79); ws.addCell(nc); f = new Formula(2, 41, "--B42"); ws.addCell(f); l = new Label(3, 41, "--B42"); ws.addCell(l); f = new Formula(2, 42, "CHOOSE(3,A1,A2,A3,A4"); ws.addCell(f); l = new Label(3,42, "CHOOSE(3,A1,A2,A3,A4"); ws.addCell(l); f = new Formula(2, 43, "A4-A3-A2"); ws.addCell(f); l = new Label(3,43, "A4-A3-A2"); ws.addCell(l); f = new Formula(2, 44, "F29+F34+F41+F48+F55+F62+F69+F76+F83+F90+F97+F104+F111+F118+F125+F132+F139+F146+F153+F160+F167+F174+F181+F188+F195+F202+F209+F216+F223+F230+F237+F244+F251+F258+F265+F272+F279+F286+F293+F300+F305+F308"); ws.addCell(f); l = new Label(3, 44, "F29+F34+F41+F48+F55+F62+F69+F76+F83+F90+F97+F104+F111+F118+F125+F132+F139+F146+F153+F160+F167+F174+F181+F188+F195+F202+F209+F216+F223+F230+F237+F244+F251+F258+F265+F272+F279+F286+F293+F300+F305+F308"); ws.addCell(l); nc = new Number(1,45, 17); ws.addCell(nc); f = new Formula(2, 45, "formulavalue+5"); ws.addCell(f); l = new Label(3, 45, "formulavalue+5"); ws.addCell(l); // Errors /* f = new Formula(2, 25, "PLOP(15)"); // unknown function ws.addCell(f); f = new Formula(2, 26, "SUM(15,3"); // unmatched parentheses ws.addCell(f); f = new Formula(2, 27, "SUM15,3)"); // missing opening parentheses ws.addCell(f); f = new Formula(2, 28, "ROUND(3.14159)"); // missing args ws.addCell(f); f = new Formula(2, 29, "NONSHEET!A1"); // sheet not found ws.addCell(f); */ } /** * Write out the images */ private void writeImageSheet(WritableSheet ws) throws WriteException { Label l = new Label(0, 0, "Weald & Downland Open Air Museum, Sussex"); ws.addCell(l); WritableImage wi = new WritableImage (0, 3, 5, 7, new File("resources/wealdanddownland.png")); ws.addImage(wi); l = new Label(0, 12, "Merchant Adventurers Hall, York"); ws.addCell(l); wi = new WritableImage(5, 12, 4, 10, new File("resources/merchantadventurers.png")); ws.addImage(wi); // An unsupported file type /* wi = new WritableImage(0, 60, 5, 5, new File("resources/somefile.gif")); ws.addImage(wi); */ } } jexcelapi/src/jxl/demo/Demo.java0000750000175000017500000002230611207000612016743 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.demo; import java.io.File; import java.io.FileOutputStream; import java.io.OutputStream; import jxl.common.Logger; import jxl.Cell; import jxl.Range; import jxl.Workbook; /** * The main demo class which interprets the command line switches in order * to determine how to call the demo programs * The demo program uses stdout as its default output stream */ public class Demo { private static final int CSVFormat = 13; private static final int XMLFormat = 14; /** * The logger */ private static Logger logger = Logger.getLogger(Demo.class); /** * Displays the acceptable command line arguments */ private static void displayHelp() { System.err.println ("Command format: Demo [-unicode] [-csv] [-hide] excelfile"); System.err.println(" Demo -xml [-format] excelfile"); System.err.println(" Demo -readwrite|-rw excelfile output"); System.err.println(" Demo -biffdump | -bd | -wa | -write | -formulas | -features | -escher | -escherdg excelfile"); System.err.println(" Demo -ps excelfile [property] [output]"); System.err.println(" Demo -version | -logtest | -h | -help"); } /** * The main method. Gets the worksheet and then uses the API * within a simple loop to print out the spreadsheet contents as * comma separated values * * @param args the command line arguments */ public static void main(String args[]) { if (args.length == 0) { displayHelp(); System.exit(1); } if (args[0].equals("-help") || args[0].equals("-h")) { displayHelp(); System.exit(1); } if (args[0].equals("-version")) { System.out.println("v"+Workbook.getVersion()); System.exit(0); } if (args[0].equals("-logtest")) { logger.debug("A sample \"debug\" message"); logger.info("A sample \"info\" message"); logger.warn("A sample \"warning\" message"); logger.error("A sample \"error\" message"); logger.fatal("A sample \"fatal\" message"); System.exit(0); } boolean write = false; boolean readwrite = false; boolean formulas = false; boolean biffdump = false; boolean jxlversion = false; boolean propertysets = false; boolean features = false; boolean escher = false; boolean escherdg = false; String file = args[0]; String outputFile = null; String propertySet = null; if (args[0].equals("-write")) { write = true; file = args[1]; } else if (args[0].equals("-formulas")) { formulas = true; file = args[1]; } else if (args[0].equals("-features")) { features = true; file = args[1]; } else if (args[0].equals("-escher")) { escher = true; file = args[1]; } else if (args[0].equals("-escherdg")) { escherdg = true; file = args[1]; } else if (args[0].equals("-biffdump") || args[0].equals("-bd")) { biffdump = true; file = args[1]; } else if (args[0].equals("-wa")) { jxlversion = true; file = args[1]; } else if (args[0].equals("-ps")) { propertysets = true; file = args[1]; if (args.length > 2) { propertySet = args[2]; } if (args.length == 4) { outputFile = args[3]; } } else if (args[0].equals("-readwrite") || args[0].equals("-rw")) { readwrite = true; file = args[1]; outputFile = args[2]; } else { file = args[args.length - 1]; } String encoding = "UTF8"; int format = CSVFormat; boolean formatInfo = false; boolean hideCells = false; if (write == false && readwrite == false && formulas == false && biffdump == false && jxlversion == false && propertysets == false && features == false && escher == false && escherdg == false) { for (int i = 0; i < args.length - 1; i++) { if (args[i].equals("-unicode")) { encoding="UnicodeBig"; } else if (args[i].equals("-xml")) { format = XMLFormat; } else if (args[i].equals("-csv")) { format = CSVFormat; } else if (args[i].equals("-format")) { formatInfo = true; } else if (args[i].equals("-hide")) { hideCells = true; } else { System.err.println ("Command format: CSV [-unicode] [-xml|-csv] excelfile"); System.exit(1); } } } try { if (write) { Write w = new Write(file); w.write(); } else if (readwrite) { ReadWrite rw = new ReadWrite(file, outputFile); rw.readWrite(); } else if (formulas) { Workbook w = Workbook.getWorkbook(new File(file)); Formulas f = new Formulas(w, System.out, encoding); w.close(); } else if (features) { Workbook w = Workbook.getWorkbook(new File(file)); Features f = new Features(w, System.out, encoding); w.close(); } else if (escher) { Workbook w = Workbook.getWorkbook(new File(file)); Escher f = new Escher(w, System.out, encoding); w.close(); } else if (escherdg) { Workbook w = Workbook.getWorkbook(new File(file)); EscherDrawingGroup f = new EscherDrawingGroup(w, System.out, encoding); w.close(); } else if (biffdump) { BiffDump bd = new BiffDump(new File(file), System.out); } else if (jxlversion) { WriteAccess bd = new WriteAccess(new File(file)); } else if (propertysets) { OutputStream os = System.out; if (outputFile != null) { os = new FileOutputStream(outputFile); } PropertySetsReader psr = new PropertySetsReader(new File(file), propertySet, os); } else { Workbook w = Workbook.getWorkbook(new File(file)); // findTest(w); if (format == CSVFormat) { CSV csv = new CSV(w, System.out, encoding, hideCells); } else if (format == XMLFormat) { XML xml = new XML(w, System.out, encoding, formatInfo); } w.close(); } } catch (Throwable t) { System.out.println(t.toString()); t.printStackTrace(); } } /** * A private method to test the various find functions */ private static void findTest(Workbook w) { logger.info("Find test"); Cell c = w.findCellByName("named1"); if (c != null) { logger.info("named1 contents: " + c.getContents()); } c = w.findCellByName("named2"); if (c != null) { logger.info("named2 contents: " + c.getContents()); } c = w.findCellByName("namedrange"); if (c != null) { logger.info("named2 contents: " + c.getContents()); } Range[] range = w.findByName("namedrange"); if (range != null) { c = range[0].getTopLeft(); logger.info("namedrange top left contents: " + c.getContents()); c = range[0].getBottomRight(); logger.info("namedrange bottom right contents: " + c.getContents()); } range = w.findByName("nonadjacentrange"); if (range != null) { for (int i = 0; i < range.length; i++) { c = range[i].getTopLeft(); logger.info("nonadjacent top left contents: " + c.getContents()); c = range[i].getBottomRight(); logger.info("nonadjacent bottom right contents: " + c.getContents()); } } range = w.findByName("horizontalnonadjacentrange"); if (range != null) { for (int i = 0; i < range.length; i++) { c = range[i].getTopLeft(); logger.info("horizontalnonadjacent top left contents: " + c.getContents()); c = range[i].getBottomRight(); logger.info("horizontalnonadjacent bottom right contents: " + c.getContents()); } } } } jexcelapi/src/jxl/demo/Escher.java0000750000175000017500000000472011207000612017270 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2005 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.demo; import java.io.BufferedWriter; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.UnsupportedEncodingException; import jxl.Workbook; import jxl.biff.drawing.DrawingData; import jxl.biff.drawing.EscherDisplay; import jxl.read.biff.SheetImpl; /** * Displays the escher data */ public class Escher { /** * Constructor * * @param w The workbook to interrogate * @param out The output stream to which the CSV values are written * @param encoding The encoding used by the output stream. Null or * unrecognized values cause the encoding to default to UTF8 * @exception java.io.IOException */ public Escher (Workbook w, OutputStream out, String encoding) throws IOException { if (encoding == null || !encoding.equals("UnicodeBig")) { encoding = "UTF8"; } try { OutputStreamWriter osw = new OutputStreamWriter(out, encoding); BufferedWriter bw = new BufferedWriter(osw); for (int i = 0; i < w.getNumberOfSheets(); i++) { SheetImpl s = (SheetImpl) w.getSheet(i); bw.write(s.getName()); bw.newLine(); bw.newLine(); DrawingData dd = s.getDrawingData(); if (dd != null) { EscherDisplay ed = new EscherDisplay(dd, bw); ed.display(); } bw.newLine(); bw.newLine(); bw.flush(); } bw.flush(); bw.close(); } catch (UnsupportedEncodingException e) { System.err.println(e.toString()); } } } jexcelapi/src/jxl/demo/WriteAccess.java0000750000175000017500000000427611207000612020301 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.demo; import java.io.FileInputStream; import java.io.IOException; import jxl.WorkbookSettings; import jxl.biff.StringHelper; import jxl.biff.Type; import jxl.read.biff.BiffException; import jxl.read.biff.BiffRecordReader; import jxl.read.biff.File; import jxl.read.biff.Record; /** * Displays whatever generated the excel file (ie. the WriteAccess record) */ class WriteAccess { private BiffRecordReader reader; public WriteAccess(java.io.File file) throws IOException, BiffException { WorkbookSettings ws = new WorkbookSettings(); FileInputStream fis = new FileInputStream(file); File f = new File(fis, ws); reader = new BiffRecordReader(f); display(ws); fis.close(); } /** * Dumps out the contents of the excel file */ private void display(WorkbookSettings ws) throws IOException { Record r = null; boolean found = false; while (reader.hasNext() && !found) { r = reader.next(); if (r.getType() == Type.WRITEACCESS) { found = true; } } if (!found) { System.err.println("Warning: could not find write access record"); return; } byte[] data = r.getData(); String s = null; s = StringHelper.getString(data, data.length, 0, ws); System.out.println(s); } } jexcelapi/src/jxl/demo/PropertySetsReader.java0000750000175000017500000001011111207000612021654 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.demo; import java.io.BufferedWriter; import java.io.FileInputStream; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import jxl.WorkbookSettings; import jxl.biff.BaseCompoundFile; import jxl.read.biff.BiffException; import jxl.read.biff.CompoundFile; /** * Generates a biff dump of the specified excel file */ class PropertySetsReader { private BufferedWriter writer; private CompoundFile compoundFile; /** * Constructor * * @param file the file * @param propertySet the property set to read * @param os the output stream * @exception IOException * @exception BiffException */ public PropertySetsReader(java.io.File file, String propertySet, OutputStream os) throws IOException, BiffException { writer = new BufferedWriter(new OutputStreamWriter(os)); FileInputStream fis = new FileInputStream(file); int initialFileSize = 1024*1024; // 1mb int arrayGrowSize = 1024*1024;// 1mb byte[] d = new byte[initialFileSize]; int bytesRead = fis.read(d); int pos = bytesRead; while (bytesRead != -1) { if (pos >= d.length) { // Grow the array byte newArray[] = new byte[d.length + arrayGrowSize]; System.arraycopy(d, 0, newArray, 0, d.length); d = newArray; } bytesRead = fis.read(d, pos, d.length - pos); pos += bytesRead; } bytesRead = pos + 1; compoundFile = new CompoundFile(d, new WorkbookSettings()); fis.close(); if (propertySet == null) { displaySets(); } else { displayPropertySet(propertySet, os); } } /** * Displays the properties to the output stream */ void displaySets() throws IOException { int numSets = compoundFile.getNumberOfPropertySets(); for (int i = 0; i < numSets ; i++) { BaseCompoundFile.PropertyStorage ps = compoundFile.getPropertySet(i); writer.write(Integer.toString(i)); writer.write(") "); writer.write(ps.name); writer.write("(type "); writer.write(Integer.toString(ps.type)); writer.write(" size "); writer.write(Integer.toString(ps.size)); writer.write(" prev " ); writer.write(Integer.toString(ps.previous)); writer.write(" next " ); writer.write(Integer.toString(ps.next)); writer.write(" child " ); writer.write(Integer.toString(ps.child)); writer.write(" start block " ); writer.write(Integer.toString(ps.startBlock)); writer.write(")"); writer.newLine(); } writer.flush(); writer.close(); } /** * Write the property stream to the output stream */ void displayPropertySet(String ps, OutputStream os) throws IOException,BiffException { if (ps.equalsIgnoreCase("SummaryInformation")) { ps = BaseCompoundFile.SUMMARY_INFORMATION_NAME; } else if (ps.equalsIgnoreCase("DocumentSummaryInformation")) { ps = BaseCompoundFile.DOCUMENT_SUMMARY_INFORMATION_NAME; } else if (ps.equalsIgnoreCase("CompObj")) { ps = BaseCompoundFile.COMP_OBJ_NAME; } byte[] stream = compoundFile.getStream(ps); os.write(stream); } } jexcelapi/src/jxl/demo/Features.java0000750000175000017500000000614611207000612017641 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.demo; import java.io.BufferedWriter; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import jxl.Cell; import jxl.CellFeatures; import jxl.CellReferenceHelper; import jxl.Sheet; import jxl.Workbook; /** * Goes through each cell in the workbook, and if the cell has any features * associated with, it prints out the cell contents and the features */ public class Features { /** * Constructor * * @param w The workbook to interrogate * @param out The output stream to which the CSV values are written * @param encoding The encoding used by the output stream. Null or * unrecognized values cause the encoding to default to UTF8 * @exception java.io.IOException */ public Features(Workbook w, OutputStream out, String encoding) throws IOException { if (encoding == null || !encoding.equals("UnicodeBig")) { encoding = "UTF8"; } try { OutputStreamWriter osw = new OutputStreamWriter(out, encoding); BufferedWriter bw = new BufferedWriter(osw); for (int sheet = 0; sheet < w.getNumberOfSheets(); sheet++) { Sheet s = w.getSheet(sheet); bw.write(s.getName()); bw.newLine(); Cell[] row = null; Cell c = null; for (int i = 0 ; i < s.getRows() ; i++) { row = s.getRow(i); for (int j = 0; j < row.length; j++) { c = row[j]; if (c.getCellFeatures() != null) { CellFeatures features = c.getCellFeatures(); StringBuffer sb = new StringBuffer(); CellReferenceHelper.getCellReference (c.getColumn(), c.getRow(), sb); bw.write("Cell " + sb.toString() + " contents: " + c.getContents()); bw.flush(); bw.write(" comment: " + features.getComment()); bw.flush(); bw.newLine(); } } } } bw.flush(); bw.close(); } catch (UnsupportedEncodingException e) { System.err.println(e.toString()); } } } jexcelapi/src/jxl/demo/BiffDump.java0000750000175000017500000002564011207000612017557 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.demo; import java.io.BufferedWriter; import java.io.FileInputStream; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.util.HashMap; import jxl.WorkbookSettings; import jxl.biff.Type; import jxl.read.biff.BiffException; import jxl.read.biff.BiffRecordReader; import jxl.read.biff.File; import jxl.read.biff.Record; /** * Generates a biff dump of the specified excel file */ class BiffDump { private BufferedWriter writer; private BiffRecordReader reader; private HashMap recordNames; private int xfIndex; private int fontIndex; private int bofs; private static final int bytesPerLine = 16; /** * Constructor * * @param file the file * @param os the output stream * @exception IOException * @exception BiffException */ public BiffDump(java.io.File file, OutputStream os) throws IOException, BiffException { writer = new BufferedWriter(new OutputStreamWriter(os)); FileInputStream fis = new FileInputStream(file); File f = new File(fis, new WorkbookSettings()); reader = new BiffRecordReader(f); buildNameHash(); dump(); writer.flush(); writer.close(); fis.close(); } /** * Builds the hashmap of record names */ private void buildNameHash() { recordNames = new HashMap(50); recordNames.put(Type.BOF, "BOF"); recordNames.put(Type.EOF, "EOF"); recordNames.put(Type.FONT, "FONT"); recordNames.put(Type.SST, "SST"); recordNames.put(Type.LABELSST, "LABELSST"); recordNames.put(Type.WRITEACCESS, "WRITEACCESS"); recordNames.put(Type.FORMULA, "FORMULA"); recordNames.put(Type.FORMULA2, "FORMULA"); recordNames.put(Type.XF, "XF"); recordNames.put(Type.MULRK, "MULRK"); recordNames.put(Type.NUMBER, "NUMBER"); recordNames.put(Type.BOUNDSHEET, "BOUNDSHEET"); recordNames.put(Type.CONTINUE, "CONTINUE"); recordNames.put(Type.FORMAT, "FORMAT"); recordNames.put(Type.EXTERNSHEET, "EXTERNSHEET"); recordNames.put(Type.INDEX, "INDEX"); recordNames.put(Type.DIMENSION, "DIMENSION"); recordNames.put(Type.ROW, "ROW"); recordNames.put(Type.DBCELL, "DBCELL"); recordNames.put(Type.BLANK, "BLANK"); recordNames.put(Type.MULBLANK, "MULBLANK"); recordNames.put(Type.RK, "RK"); recordNames.put(Type.RK2, "RK"); recordNames.put(Type.COLINFO, "COLINFO"); recordNames.put(Type.LABEL, "LABEL"); recordNames.put(Type.SHAREDFORMULA, "SHAREDFORMULA"); recordNames.put(Type.CODEPAGE, "CODEPAGE"); recordNames.put(Type.WINDOW1, "WINDOW1"); recordNames.put(Type.WINDOW2, "WINDOW2"); recordNames.put(Type.MERGEDCELLS, "MERGEDCELLS"); recordNames.put(Type.HLINK, "HLINK"); recordNames.put(Type.HEADER, "HEADER"); recordNames.put(Type.FOOTER, "FOOTER"); recordNames.put(Type.INTERFACEHDR, "INTERFACEHDR"); recordNames.put(Type.MMS, "MMS"); recordNames.put(Type.INTERFACEEND, "INTERFACEEND"); recordNames.put(Type.DSF, "DSF"); recordNames.put(Type.FNGROUPCOUNT, "FNGROUPCOUNT"); recordNames.put(Type.COUNTRY, "COUNTRY"); recordNames.put(Type.TABID, "TABID"); recordNames.put(Type.PROTECT, "PROTECT"); recordNames.put(Type.SCENPROTECT, "SCENPROTECT"); recordNames.put(Type.OBJPROTECT, "OBJPROTECT"); recordNames.put(Type.WINDOWPROTECT, "WINDOWPROTECT"); recordNames.put(Type.PASSWORD, "PASSWORD"); recordNames.put(Type.PROT4REV, "PROT4REV"); recordNames.put(Type.PROT4REVPASS, "PROT4REVPASS"); recordNames.put(Type.BACKUP, "BACKUP"); recordNames.put(Type.HIDEOBJ, "HIDEOBJ"); recordNames.put(Type.NINETEENFOUR, "1904"); recordNames.put(Type.PRECISION, "PRECISION"); recordNames.put(Type.BOOKBOOL, "BOOKBOOL"); recordNames.put(Type.STYLE, "STYLE"); recordNames.put(Type.EXTSST, "EXTSST"); recordNames.put(Type.REFRESHALL, "REFRESHALL"); recordNames.put(Type.CALCMODE, "CALCMODE"); recordNames.put(Type.CALCCOUNT, "CALCCOUNT"); recordNames.put(Type.NAME, "NAME"); recordNames.put(Type.MSODRAWINGGROUP, "MSODRAWINGGROUP"); recordNames.put(Type.MSODRAWING, "MSODRAWING"); recordNames.put(Type.OBJ, "OBJ"); recordNames.put(Type.USESELFS, "USESELFS"); recordNames.put(Type.SUPBOOK, "SUPBOOK"); recordNames.put(Type.LEFTMARGIN, "LEFTMARGIN"); recordNames.put(Type.RIGHTMARGIN, "RIGHTMARGIN"); recordNames.put(Type.TOPMARGIN, "TOPMARGIN"); recordNames.put(Type.BOTTOMMARGIN, "BOTTOMMARGIN"); recordNames.put(Type.HCENTER, "HCENTER"); recordNames.put(Type.VCENTER, "VCENTER"); recordNames.put(Type.ITERATION, "ITERATION"); recordNames.put(Type.DELTA, "DELTA"); recordNames.put(Type.SAVERECALC, "SAVERECALC"); recordNames.put(Type.PRINTHEADERS, "PRINTHEADERS"); recordNames.put(Type.PRINTGRIDLINES, "PRINTGRIDLINES"); recordNames.put(Type.SETUP, "SETUP"); recordNames.put(Type.SELECTION, "SELECTION"); recordNames.put(Type.STRING, "STRING"); recordNames.put(Type.FONTX, "FONTX"); recordNames.put(Type.IFMT, "IFMT"); recordNames.put(Type.WSBOOL, "WSBOOL"); recordNames.put(Type.GRIDSET, "GRIDSET"); recordNames.put(Type.REFMODE, "REFMODE"); recordNames.put(Type.GUTS, "GUTS"); recordNames.put(Type.EXTERNNAME, "EXTERNNAME"); recordNames.put(Type.FBI, "FBI"); recordNames.put(Type.CRN, "CRN"); recordNames.put(Type.HORIZONTALPAGEBREAKS, "HORIZONTALPAGEBREAKS"); recordNames.put(Type.VERTICALPAGEBREAKS, "VERTICALPAGEBREAKS"); recordNames.put(Type.DEFAULTROWHEIGHT, "DEFAULTROWHEIGHT"); recordNames.put(Type.TEMPLATE, "TEMPLATE"); recordNames.put(Type.PANE, "PANE"); recordNames.put(Type.SCL, "SCL"); recordNames.put(Type.PALETTE, "PALETTE"); recordNames.put(Type.PLS, "PLS"); recordNames.put(Type.OBJPROJ, "OBJPROJ"); recordNames.put(Type.DEFCOLWIDTH, "DEFCOLWIDTH"); recordNames.put(Type.ARRAY, "ARRAY"); recordNames.put(Type.WEIRD1, "WEIRD1"); recordNames.put(Type.BOOLERR, "BOOLERR"); recordNames.put(Type.SORT, "SORT"); recordNames.put(Type.BUTTONPROPERTYSET, "BUTTONPROPERTYSET"); recordNames.put(Type.NOTE, "NOTE"); recordNames.put(Type.TXO, "TXO"); recordNames.put(Type.DV, "DV"); recordNames.put(Type.DVAL, "DVAL"); recordNames.put(Type.SERIES, "SERIES"); recordNames.put(Type.SERIESLIST, "SERIESLIST"); recordNames.put(Type.SBASEREF, "SBASEREF"); recordNames.put(Type.CONDFMT, "CONDFMT"); recordNames.put(Type.CF, "CF"); recordNames.put(Type.FILTERMODE, "FILTERMODE"); recordNames.put(Type.AUTOFILTER, "AUTOFILTER"); recordNames.put(Type.AUTOFILTERINFO, "AUTOFILTERINFO"); recordNames.put(Type.XCT, "XCT"); recordNames.put(Type.UNKNOWN, "???"); } /** * Dumps out the contents of the excel file */ private void dump() throws IOException { Record r = null; boolean cont = true; while (reader.hasNext() && cont) { r = reader.next(); cont = writeRecord(r); } } /** * Writes out the biff record * @param r * @exception IOException if an error occurs */ private boolean writeRecord(Record r) throws IOException { boolean cont = true; int pos = reader.getPos(); int code = r.getCode(); if (bofs == 0) { cont = (r.getType() == Type.BOF); } if (!cont) { return cont; } if (r.getType() == Type.BOF) { bofs++; } if (r.getType() == Type.EOF) { bofs--; } StringBuffer buf = new StringBuffer(); // Write out the record header writeSixDigitValue(pos, buf); buf.append(" ["); buf.append(recordNames.get(r.getType())); buf.append("]"); buf.append(" (0x"); buf.append(Integer.toHexString(code)); buf.append(")"); if (code == Type.XF.value) { buf.append(" (0x"); buf.append(Integer.toHexString(xfIndex)); buf.append(")"); xfIndex++; } if (code == Type.FONT.value) { if (fontIndex == 4) { fontIndex++; } buf.append(" (0x"); buf.append(Integer.toHexString(fontIndex)); buf.append(")"); fontIndex++; } writer.write(buf.toString()); writer.newLine(); byte[] standardData = new byte[4]; standardData[0] = (byte) (code & 0xff); standardData[1] = (byte) ((code & 0xff00) >> 8); standardData[2] = (byte) (r.getLength() & 0xff); standardData[3] = (byte) ((r.getLength() & 0xff00) >> 8); byte[] recordData = r.getData(); byte[] data = new byte[standardData.length + recordData.length]; System.arraycopy(standardData, 0, data, 0, standardData.length); System.arraycopy(recordData, 0, data, standardData.length, recordData.length); int byteCount = 0; int lineBytes = 0; while (byteCount < data.length) { buf = new StringBuffer(); writeSixDigitValue(pos+byteCount, buf); buf.append(" "); lineBytes = Math.min(bytesPerLine, data.length - byteCount); for (int i = 0; i < lineBytes ; i++) { writeByte(data[i+byteCount], buf); buf.append(' '); } // Perform any padding if (lineBytes < bytesPerLine) { for(int i = 0; i < bytesPerLine - lineBytes; i++) { buf.append(" "); } } buf.append(" "); for (int i = 0 ; i < lineBytes; i++) { char c = (char) data[i+byteCount]; if (c < ' ' || c > 'z') { c = '.'; } buf.append(c); } byteCount+= lineBytes; writer.write(buf.toString()); writer.newLine(); } return cont; } /** * Writes the string passed in as a minimum of four digits */ private void writeSixDigitValue(int pos, StringBuffer buf) { String val = Integer.toHexString(pos); for (int i = 6; i > val.length() ; i--) { buf.append('0'); } buf.append(val); } /** * Writes the string passed in as a minimum of four digits */ private void writeByte(byte val, StringBuffer buf) { String sv = Integer.toHexString((val & 0xff)); if (sv.length() == 1) { buf.append('0'); } buf.append(sv); } } jexcelapi/src/jxl/demo/XML.java0000750000175000017500000002400511207000612016515 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.demo; import java.io.BufferedWriter; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.UnsupportedEncodingException; import jxl.Cell; import jxl.CellType; import jxl.Sheet; import jxl.Workbook; import jxl.format.Border; import jxl.format.BorderLineStyle; import jxl.format.CellFormat; import jxl.format.Colour; import jxl.format.Font; import jxl.format.Pattern; /** * Simple demo class which uses the api to present the contents * of an excel 97 spreadsheet as an XML document, using a workbook * and output stream of your choice */ public class XML { /** * The output stream to write to */ private OutputStream out; /** * The encoding to write */ private String encoding; /** * The workbook we are reading from */ private Workbook workbook; /** * Constructor * * @param w The workbook to interrogate * @param out The output stream to which the XML values are written * @param enc The encoding used by the output stream. Null or * unrecognized values cause the encoding to default to UTF8 * @param f Indicates whether the generated XML document should contain * the cell format information * @exception java.io.IOException */ public XML(Workbook w, OutputStream out, String enc, boolean f) throws IOException { encoding = enc; workbook = w; this.out = out; if (encoding == null || !encoding.equals("UnicodeBig")) { encoding = "UTF8"; } if (f) { writeFormattedXML(); } else { writeXML(); } } /** * Writes out the workbook data as XML, without formatting information */ private void writeXML() throws IOException { try { OutputStreamWriter osw = new OutputStreamWriter(out, encoding); BufferedWriter bw = new BufferedWriter(osw); bw.write(""); bw.newLine(); bw.write(""); bw.newLine(); bw.newLine(); bw.write(""); bw.newLine(); for (int sheet = 0; sheet < workbook.getNumberOfSheets(); sheet++) { Sheet s = workbook.getSheet(sheet); bw.write(" "); bw.newLine(); bw.write(" "); bw.newLine(); Cell[] row = null; for (int i = 0 ; i < s.getRows() ; i++) { bw.write(" "); bw.newLine(); row = s.getRow(i); for (int j = 0 ; j < row.length; j++) { if (row[j].getType() != CellType.EMPTY) { bw.write(" "); bw.write(""); bw.write(""); bw.newLine(); } } bw.write(" "); bw.newLine(); } bw.write(" "); bw.newLine(); } bw.write(""); bw.newLine(); bw.flush(); bw.close(); } catch (UnsupportedEncodingException e) { System.err.println(e.toString()); } } /** * Writes out the workbook data as XML, with formatting information */ private void writeFormattedXML() throws IOException { try { OutputStreamWriter osw = new OutputStreamWriter(out, encoding); BufferedWriter bw = new BufferedWriter(osw); bw.write(""); bw.newLine(); bw.write(""); bw.newLine(); bw.newLine(); bw.write(""); bw.newLine(); for (int sheet = 0; sheet < workbook.getNumberOfSheets(); sheet++) { Sheet s = workbook.getSheet(sheet); bw.write(" "); bw.newLine(); bw.write(" "); bw.newLine(); Cell[] row = null; CellFormat format = null; Font font = null; for (int i = 0 ; i < s.getRows() ; i++) { bw.write(" "); bw.newLine(); row = s.getRow(i); for (int j = 0 ; j < row.length; j++) { // Remember that empty cells can contain format information if ((row[j].getType() != CellType.EMPTY) || (row[j].getCellFormat() != null)) { format = row[j].getCellFormat(); bw.write(" "); bw.newLine(); bw.write(" "); bw.write(""); bw.write(""); bw.newLine(); if (row[j].getCellFormat() != null) { bw.write(" "); bw.newLine(); // The font information font = format.getFont(); bw.write(" "); bw.newLine(); // The cell background information if (format.getBackgroundColour() != Colour.DEFAULT_BACKGROUND || format.getPattern() != Pattern.NONE) { bw.write(" "); bw.newLine(); } // The cell border, if it has one if (format.getBorder(Border.TOP ) != BorderLineStyle.NONE || format.getBorder(Border.BOTTOM) != BorderLineStyle.NONE || format.getBorder(Border.LEFT) != BorderLineStyle.NONE || format.getBorder(Border.RIGHT) != BorderLineStyle.NONE) { bw.write(" "); bw.newLine(); } // The cell number/date format if (!format.getFormat().getFormatString().equals("")) { bw.write(" "); bw.newLine(); } bw.write(" "); bw.newLine(); } bw.write(" "); bw.newLine(); } } bw.write(" "); bw.newLine(); } bw.write(" "); bw.newLine(); } bw.write(""); bw.newLine(); bw.flush(); bw.close(); } catch (UnsupportedEncodingException e) { System.err.println(e.toString()); } } } jexcelapi/src/jxl/demo/ReadWrite.java0000750000175000017500000003304611265616325017772 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.demo; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import jxl.common.Logger; import jxl.Cell; import jxl.CellReferenceHelper; import jxl.CellType; import jxl.Range; import jxl.Sheet; import jxl.Workbook; import jxl.format.CellFormat; import jxl.format.Colour; import jxl.format.UnderlineStyle; import jxl.read.biff.BiffException; import jxl.write.Blank; import jxl.write.DateFormat; import jxl.write.DateFormats; import jxl.write.DateTime; import jxl.write.Formula; import jxl.write.Label; import jxl.write.Number; import jxl.write.NumberFormat; import jxl.write.WritableCell; import jxl.write.WritableCellFeatures; import jxl.write.WritableCellFormat; import jxl.write.WritableFont; import jxl.write.WritableHyperlink; import jxl.write.WritableImage; import jxl.write.WritableSheet; import jxl.write.WritableWorkbook; import jxl.write.WriteException; /** * Demo class which uses the api to read in a spreadsheet and generate a clone * of that spreadsheet which contains the same data. If the spreadsheet read * in is the spreadsheet called jxlrwtest.xls (provided with the distribution) * then this class will modify certain fields in the copy of that spreadsheet. * This is illustrating that it is possible to read in a spreadsheet, modify * a few values, and write it under a new name. */ public class ReadWrite { /** * The logger */ private static Logger logger = Logger.getLogger(ReadWrite.class); /** * The spreadsheet to read in */ private File inputWorkbook; /** * The spreadsheet to output */ private File outputWorkbook; /** * Constructor * * @param output * @param input */ public ReadWrite(String input, String output) { inputWorkbook = new File(input); outputWorkbook = new File(output); logger.setSuppressWarnings(Boolean.getBoolean("jxl.nowarnings")); logger.info("Input file: " + input); logger.info("Output file: " + output); } /** * Reads in the inputFile and creates a writable copy of it called outputFile * * @exception IOException * @exception BiffException */ public void readWrite() throws IOException, BiffException, WriteException { logger.info("Reading..."); Workbook w1 = Workbook.getWorkbook(inputWorkbook); logger.info("Copying..."); WritableWorkbook w2 = Workbook.createWorkbook(outputWorkbook, w1); if (inputWorkbook.getName().equals("jxlrwtest.xls")) { modify(w2); } w2.write(); w2.close(); logger.info("Done"); } /** * If the inputFile was the test spreadsheet, then it modifies certain fields * of the writable copy * * @param w */ private void modify(WritableWorkbook w) throws WriteException { logger.info("Modifying..."); WritableSheet sheet = w.getSheet("modified"); WritableCell cell = null; CellFormat cf = null; Label l = null; WritableCellFeatures wcf = null; // Change the format of cell B4 to be emboldened cell = sheet.getWritableCell(1,3); WritableFont bold = new WritableFont(WritableFont.ARIAL, WritableFont.DEFAULT_POINT_SIZE, WritableFont.BOLD); cf = new WritableCellFormat(bold); cell.setCellFormat(cf); // Change the format of cell B5 to be underlined cell = sheet.getWritableCell(1,4); WritableFont underline = new WritableFont(WritableFont.ARIAL, WritableFont.DEFAULT_POINT_SIZE, WritableFont.NO_BOLD, false, UnderlineStyle.SINGLE); cf = new WritableCellFormat(underline); cell.setCellFormat(cf); // Change the point size of cell B6 to be 10 point cell = sheet.getWritableCell(1,5); WritableFont tenpoint = new WritableFont(WritableFont.ARIAL, 10); cf = new WritableCellFormat(tenpoint); cell.setCellFormat(cf); // Change the contents of cell B7 to read "Label - mod" cell = sheet.getWritableCell(1,6); if (cell.getType() == CellType.LABEL) { Label lc = (Label) cell; lc.setString(lc.getString() + " - mod"); } // Change cell B10 to display 7 dps cell = sheet.getWritableCell(1,9); NumberFormat sevendps = new NumberFormat("#.0000000"); cf = new WritableCellFormat(sevendps); cell.setCellFormat(cf); // Change cell B11 to display in the format 1e4 cell = sheet.getWritableCell(1,10); NumberFormat exp4 = new NumberFormat("0.####E0"); cf = new WritableCellFormat(exp4); cell.setCellFormat(cf); // Change cell B12 to be normal display cell = sheet.getWritableCell(1,11); cell.setCellFormat(WritableWorkbook.NORMAL_STYLE); // Change the contents of cell B13 to 42 cell = sheet.getWritableCell(1,12); if (cell.getType() == CellType.NUMBER) { Number n = (Number) cell; n.setValue(42); } // Add 0.1 to the contents of cell B14 cell = sheet.getWritableCell(1,13); if (cell.getType() == CellType.NUMBER) { Number n = (Number) cell; n.setValue(n.getValue() + 0.1); } // Change the date format of cell B17 to be a custom format cell = sheet.getWritableCell(1,16); DateFormat df = new DateFormat("dd MMM yyyy HH:mm:ss"); cf = new WritableCellFormat(df); cell.setCellFormat(cf); // Change the date format of cell B18 to be a standard format cell = sheet.getWritableCell(1,17); cf = new WritableCellFormat(DateFormats.FORMAT9); cell.setCellFormat(cf); // Change the date in cell B19 to be 18 Feb 1998, 11:23:28 cell = sheet.getWritableCell(1,18); if (cell.getType() == CellType.DATE) { DateTime dt = (DateTime) cell; Calendar cal = Calendar.getInstance(); cal.set(1998, 1, 18, 11, 23, 28); Date d = cal.getTime(); dt.setDate(d); } // Change the value in B23 to be 6.8. This should recalculate the // formula cell = sheet.getWritableCell(1,22); if (cell.getType() == CellType.NUMBER) { Number n = (Number) cell; n.setValue(6.8); } // Change the label in B30. This will have the effect of making // the original string unreferenced cell = sheet.getWritableCell(1, 29); if (cell.getType() == CellType.LABEL) { l = (Label) cell; l.setString("Modified string contents"); } // Insert a new row (number 35) sheet.insertRow(34); // Delete row 38 (39 after row has been inserted) sheet.removeRow(38); // Insert a new column (J) sheet.insertColumn(9); // Remove a column (L - M after column has been inserted) sheet.removeColumn(11); // Remove row 44 (contains a hyperlink), and then insert an empty // row just to keep the numbers consistent sheet.removeRow(43); sheet.insertRow(43); // Modify the hyperlinks WritableHyperlink hyperlinks[] = sheet.getWritableHyperlinks(); for (int i = 0; i < hyperlinks.length; i++) { WritableHyperlink wh = hyperlinks[i]; if (wh.getColumn() == 1 && wh.getRow() == 39) { try { // Change the hyperlink that begins in cell B40 to be a different API wh.setURL(new URL("http://www.andykhan.com/jexcelapi/index.html")); } catch (MalformedURLException e) { logger.warn(e.toString()); } } else if (wh.getColumn() == 1 && wh.getRow() == 40) { wh.setFile(new File("../jexcelapi/docs/overview-summary.html")); } else if (wh.getColumn() == 1 && wh.getRow() == 41) { wh.setFile(new File("d:/home/jexcelapi/docs/jxl/package-summary.html")); } else if (wh.getColumn() == 1 && wh.getRow() == 44) { // Remove the hyperlink at B45 sheet.removeHyperlink(wh); } } // Change the background of cell F31 from blue to red WritableCell c = sheet.getWritableCell(5,30); WritableCellFormat newFormat = new WritableCellFormat(c.getCellFormat()); newFormat.setBackground(Colour.RED); c.setCellFormat(newFormat); // Modify the contents of the merged cell l = new Label(0, 49, "Modified merged cells"); sheet.addCell(l); // Modify the chart data Number n = (Number) sheet.getWritableCell(0, 70); n.setValue(9); n = (Number) sheet.getWritableCell(0, 71); n.setValue(10); n = (Number) sheet.getWritableCell(0, 73); n.setValue(4); // Add in a cross sheet formula Formula f = new Formula(1, 80, "ROUND(COS(original!B10),2)"); sheet.addCell(f); // Add in a formula from the named cells f = new Formula(1, 83, "value1+value2"); sheet.addCell(f); // Add in a function formula using named cells f = new Formula(1, 84, "AVERAGE(value1,value1*4,value2)"); sheet.addCell(f); // Copy sheet 1 to sheet 3 // w.copySheet(0, "copy", 2); // Use the cell deep copy feature Label label = new Label(0, 88, "Some copied cells", cf); sheet.addCell(label); label = new Label(0,89, "Number from B9"); sheet.addCell(label); WritableCell wc = sheet.getWritableCell(1, 9).copyTo(1,89); sheet.addCell(wc); label = new Label(0, 90, "Label from B4 (modified format)"); sheet.addCell(label); wc = sheet.getWritableCell(1, 3).copyTo(1,90); sheet.addCell(wc); label = new Label(0, 91, "Date from B17"); sheet.addCell(label); wc = sheet.getWritableCell(1, 16).copyTo(1,91); sheet.addCell(wc); label = new Label(0, 92, "Boolean from E16"); sheet.addCell(label); wc = sheet.getWritableCell(4, 15).copyTo(1,92); sheet.addCell(wc); label = new Label(0, 93, "URL from B40"); sheet.addCell(label); wc = sheet.getWritableCell(1, 39).copyTo(1,93); sheet.addCell(wc); // Add some numbers for the formula copy for (int i = 0 ; i < 6; i++) { Number number = new Number(1,94+i, i + 1 + i/8.0); sheet.addCell(number); } label = new Label(0,100, "Formula from B27"); sheet.addCell(label); wc = sheet.getWritableCell(1, 26).copyTo(1,100); sheet.addCell(wc); label = new Label(0,101, "A brand new formula"); sheet.addCell(label); Formula formula = new Formula(1, 101, "SUM(B94:B96)"); sheet.addCell(formula); label = new Label(0,102, "A copy of it"); sheet.addCell(label); wc = sheet.getWritableCell(1,101).copyTo(1, 102); sheet.addCell(wc); // Remove the second image from the sheet WritableImage wi = sheet.getImage(1); sheet.removeImage(wi); wi = new WritableImage(1, 116, 2, 9, new File("resources/littlemoretonhall.png")); sheet.addImage(wi); // Add a list data validations label = new Label(0, 151, "Added drop down validation"); sheet.addCell(label); Blank b = new Blank(1, 151); wcf = new WritableCellFeatures(); ArrayList al = new ArrayList(); al.add("The Fellowship of the Ring"); al.add("The Two Towers"); al.add("The Return of the King"); wcf.setDataValidationList(al); b.setCellFeatures(wcf); sheet.addCell(b); // Add a number data validation label = new Label(0, 152, "Added number validation 2.718 < x < 3.142"); sheet.addCell(label); b = new Blank(1,152); wcf = new WritableCellFeatures(); wcf.setNumberValidation(2.718, 3.142, wcf.BETWEEN); b.setCellFeatures(wcf); sheet.addCell(b); // Modify the text in the first cell with a comment cell = sheet.getWritableCell(0, 156); l = (Label) cell; l.setString("Label text modified"); cell = sheet.getWritableCell(0, 157); wcf = cell.getWritableCellFeatures(); wcf.setComment("modified comment text"); cell = sheet.getWritableCell(0, 158); wcf = cell.getWritableCellFeatures(); wcf.removeComment(); // Modify the validation contents of the row 173 cell = sheet.getWritableCell(0,172); wcf = cell.getWritableCellFeatures(); Range r = wcf.getSharedDataValidationRange(); Cell botright = r.getBottomRight(); sheet.removeSharedDataValidation(cell); al = new ArrayList(); al.add("Stanley Featherstonehaugh Ukridge"); al.add("Major Plank"); al.add("Earl of Ickenham"); al.add("Sir Gregory Parsloe-Parsloe"); al.add("Honoria Glossop"); al.add("Stiffy Byng"); al.add("Bingo Little"); wcf.setDataValidationList(al); cell.setCellFeatures(wcf); sheet.applySharedDataValidation(cell, botright.getColumn() - cell.getColumn(), 1);//botright.getRow() - cell.getRow()); } } jexcelapi/src/jxl/demo/Formulas.java0000750000175000017500000001006311207000612017644 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.demo; import java.io.BufferedWriter; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Iterator; import jxl.Cell; import jxl.CellType; import jxl.FormulaCell; import jxl.Sheet; import jxl.Workbook; import jxl.biff.CellReferenceHelper; import jxl.biff.formula.FormulaException; /** * Goes through each cell in the workbook, and if the contents of that * cell is a formula, it prints out the last calculated value and * the formula string */ public class Formulas { /** * Constructor * * @param w The workbook to interrogate * @param out The output stream to which the CSV values are written * @param encoding The encoding used by the output stream. Null or * unrecognized values cause the encoding to default to UTF8 * @exception java.io.IOException */ public Formulas(Workbook w, OutputStream out, String encoding) throws IOException { if (encoding == null || !encoding.equals("UnicodeBig")) { encoding = "UTF8"; } try { OutputStreamWriter osw = new OutputStreamWriter(out, encoding); BufferedWriter bw = new BufferedWriter(osw); ArrayList parseErrors = new ArrayList(); for (int sheet = 0; sheet < w.getNumberOfSheets(); sheet++) { Sheet s = w.getSheet(sheet); bw.write(s.getName()); bw.newLine(); Cell[] row = null; Cell c = null; for (int i = 0 ; i < s.getRows() ; i++) { row = s.getRow(i); for (int j = 0; j < row.length; j++) { c = row[j]; if (c.getType() == CellType.NUMBER_FORMULA || c.getType() == CellType.STRING_FORMULA || c.getType() == CellType.BOOLEAN_FORMULA || c.getType() == CellType.DATE_FORMULA || c.getType() == CellType.FORMULA_ERROR) { FormulaCell nfc = (FormulaCell) c; StringBuffer sb = new StringBuffer(); CellReferenceHelper.getCellReference (c.getColumn(), c.getRow(), sb); try { bw.write("Formula in " + sb.toString() + " value: " + c.getContents()); bw.flush(); bw.write(" formula: " + nfc.getFormula()); bw.flush(); bw.newLine(); } catch (FormulaException e) { bw.newLine(); parseErrors.add(s.getName() + '!' + sb.toString() + ": " + e.getMessage()); } } } } } bw.flush(); bw.close(); if (parseErrors.size() > 0) { System.err.println(); System.err.println("There were " + parseErrors.size() + " errors"); Iterator i = parseErrors.iterator(); while (i.hasNext()) { System.err.println(i.next()); } } } catch (UnsupportedEncodingException e) { System.err.println(e.toString()); } } } jexcelapi/src/jxl/demo/EscherDrawingGroup.java0000750000175000017500000000447511207000612021630 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2005 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.demo; import java.io.BufferedWriter; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.UnsupportedEncodingException; import jxl.Workbook; import jxl.biff.drawing.DrawingGroup; import jxl.biff.drawing.EscherDisplay; import jxl.read.biff.WorkbookParser; /** * Displays the escher data */ public class EscherDrawingGroup { /** * Constructor * * @param w The workbook to interrogate * @param out The output stream to which the CSV values are written * @param encoding The encoding used by the output stream. Null or * unrecognized values cause the encoding to default to UTF8 * @exception java.io.IOException */ public EscherDrawingGroup (Workbook w, OutputStream out, String encoding) throws IOException { if (encoding == null || !encoding.equals("UnicodeBig")) { encoding = "UTF8"; } try { OutputStreamWriter osw = new OutputStreamWriter(out, encoding); BufferedWriter bw = new BufferedWriter(osw); WorkbookParser wp = (WorkbookParser) w; DrawingGroup dg = wp.getDrawingGroup(); if (dg != null) { EscherDisplay ed = new EscherDisplay(dg, bw); ed.display(); } bw.newLine(); bw.newLine(); bw.flush(); bw.close(); } catch (UnsupportedEncodingException e) { System.err.println(e.toString()); } } } jexcelapi/src/jxl/demo/CSV.java0000750000175000017500000000653211207000612016515 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.demo; import java.io.BufferedWriter; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.UnsupportedEncodingException; import jxl.Cell; import jxl.Sheet; import jxl.Workbook; /** * Simple demo class which uses the api to present the contents * of an excel 97 spreadsheet as comma separated values, using a workbook * and output stream of your choice */ public class CSV { /** * Constructor * * @param w The workbook to interrogate * @param out The output stream to which the CSV values are written * @param encoding The encoding used by the output stream. Null or * unrecognized values cause the encoding to default to UTF8 * @param hide Suppresses hidden cells * @exception java.io.IOException */ public CSV(Workbook w, OutputStream out, String encoding, boolean hide) throws IOException { if (encoding == null || !encoding.equals("UnicodeBig")) { encoding = "UTF8"; } try { OutputStreamWriter osw = new OutputStreamWriter(out, encoding); BufferedWriter bw = new BufferedWriter(osw); for (int sheet = 0; sheet < w.getNumberOfSheets(); sheet++) { Sheet s = w.getSheet(sheet); if (!(hide && s.getSettings().isHidden())) { bw.write("*** " + s.getName() + " ****"); bw.newLine(); Cell[] row = null; for (int i = 0 ; i < s.getRows() ; i++) { row = s.getRow(i); if (row.length > 0) { if (!(hide && row[0].isHidden())) { bw.write(row[0].getContents()); // Java 1.4 code to handle embedded commas // bw.write("\"" + row[0].getContents().replaceAll("\"","\"\"") + "\""); } for (int j = 1; j < row.length; j++) { bw.write(','); if (!(hide && row[j].isHidden())) { bw.write(row[j].getContents()); // Java 1.4 code to handle embedded quotes // bw.write("\"" + row[j].getContents().replaceAll("\"","\"\"") + "\""); } } } bw.newLine(); } } } bw.flush(); bw.close(); } catch (UnsupportedEncodingException e) { System.err.println(e.toString()); } } } jexcelapi/src/jxl/ErrorFormulaCell.java0000750000175000017500000000216211207000610020346 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl; /** * A mixin interface for numerical formulas, which combines the interfaces * for formulas and for numbers */ public interface ErrorFormulaCell extends ErrorCell, FormulaCell { } jexcelapi/src/jxl/JXLException.java0000750000175000017500000000227511207000610017450 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl; /** * Base exception class for JExcelAPI exceptions */ public class JXLException extends Exception { /** * Constructor * * @param message the exception message */ protected JXLException(String message) { super(message); } } jexcelapi/src/jxl/Range.java0000750000175000017500000000330511207000610016163 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl; /** * Represents a 3-D range of cells in a workbook. This object is * returned by the method findByName in a workbook */ public interface Range { /** * Gets the cell at the top left of this range * * @return the cell at the top left */ public Cell getTopLeft(); /** * Gets the cell at the bottom right of this range * * @return the cell at the bottom right */ public Cell getBottomRight(); /** * Gets the index of the first sheet in the range * * @return the index of the first sheet in the range */ public int getFirstSheetIndex(); /** * Gets the index of the last sheet in the range * * @return the index of the last sheet in the range */ public int getLastSheetIndex(); } jexcelapi/src/jxl/CellType.java0000750000175000017500000000515211207000610016652 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl; /** * An enumeration type listing the available content types for a cell */ public final class CellType { /** * The text description of this cell type */ private String description; /** * Private constructor * @param desc the description of this type */ private CellType(String desc) { description = desc; } /** * Returns a string description of this cell * * @return the string description for this type */ public String toString() { return description; } /** * An empty cell can still contain formatting information and comments */ public static final CellType EMPTY = new CellType("Empty"); /** */ public static final CellType LABEL = new CellType("Label"); /** */ public static final CellType NUMBER = new CellType("Number"); /** */ public static final CellType BOOLEAN = new CellType("Boolean"); /** */ public static final CellType ERROR = new CellType("Error"); /** */ public static final CellType NUMBER_FORMULA = new CellType("Numerical Formula"); /** */ public static final CellType DATE_FORMULA = new CellType("Date Formula"); /** */ public static final CellType STRING_FORMULA = new CellType("String Formula"); /** */ public static final CellType BOOLEAN_FORMULA = new CellType("Boolean Formula"); /** */ public static final CellType FORMULA_ERROR = new CellType("Formula Error"); /** */ public static final CellType DATE = new CellType("Date"); } jexcelapi/src/jxl/common/0000750000175000017500000000000011270605332015564 5ustar drazzibdrazzibjexcelapi/src/jxl/common/LengthUnit.java0000750000175000017500000000261411207000612020504 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2006 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.common; /** * Enumeration for units */ public class LengthUnit extends BaseUnit { private static int count = 0; private LengthUnit() { super(count++); } public static int getCount() { return count; } public static LengthUnit POINTS = new LengthUnit(); public static LengthUnit METRES = new LengthUnit(); public static LengthUnit CENTIMETRES = new LengthUnit(); public static LengthUnit INCHES = new LengthUnit(); } jexcelapi/src/jxl/common/log/0000750000175000017500000000000011270605332016345 5ustar drazzibdrazzibjexcelapi/src/jxl/common/log/Log4jLoggerName.java0000750000175000017500000000235011207000612022121 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.common.log; /** * Static structure containing the class name of the logger. This may * be overwritten at build time if loggers other than the default, * no-dependency logger are required */ public class LoggerName { public final static String NAME=jxl.common.log.Log4JLogger.class.getName(); } jexcelapi/src/jxl/common/log/LoggerName.java0000750000175000017500000000235111207000612021222 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.common.log; /** * Static structure containing the class name of the logger. This may * be overwritten at build time if loggers other than the default, * no-dependency logger are required */ public class LoggerName { public final static String NAME=jxl.common.log.SimpleLogger.class.getName(); } jexcelapi/src/jxl/common/log/SimpleLoggerName.java0000750000175000017500000000235111207000612022374 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.common.log; /** * Static structure containing the class name of the logger. This may * be overwritten at build time if loggers other than the default, * no-dependency logger are required */ public class LoggerName { public final static String NAME=jxl.common.log.SimpleLogger.class.getName(); } jexcelapi/src/jxl/common/log/Log4JLogger.java0000750000175000017500000000614211207000612021263 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.common.log; import org.apache.log4j.Logger; /** * A logger which uses the log4j library from jakarta. Each instance * of this class acts as a wrapper to the log4j Logger class */ public class Log4JLogger extends jxl.common.Logger { /** * The log4j logger */ private Logger log4jLogger; /** * Default constructor. This constructor is */ public Log4JLogger() { super(); } /** * Constructor invoked by the getLoggerImpl method to return a logger * for a particular class */ private Log4JLogger(Logger l) { super(); log4jLogger = l; } /** * Log a debug message */ public void debug(Object message) { log4jLogger.debug(message); } /** * Log a debug message and exception */ public void debug(Object message, Throwable t) { log4jLogger.debug(message, t); } /** * Log an error message */ public void error(Object message) { log4jLogger.error(message); } /** * Log an error message object and exception */ public void error(Object message, Throwable t) { log4jLogger.error(message, t); } /** * Log a fatal message */ public void fatal(Object message) { log4jLogger.fatal(message); } /** * Log a fatal message and exception */ public void fatal(Object message, Throwable t) { log4jLogger.fatal(message,t); } /** * Log an information message */ public void info(Object message) { log4jLogger.info(message); } /** * Logs an information message and an exception */ public void info(Object message, Throwable t) { log4jLogger.info(message, t); } /** * Log a warning message object */ public void warn(Object message) { log4jLogger.warn(message); } /** * Log a warning message with exception */ public void warn(Object message, Throwable t) { log4jLogger.warn(message, t); } /** * Accessor to the logger implementation */ protected jxl.common.Logger getLoggerImpl(Class cl) { Logger l = Logger.getLogger(cl); return new Log4JLogger(l); } } jexcelapi/src/jxl/common/log/SimpleLogger.java0000750000175000017500000001000311207000612021564 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.common.log; import jxl.common.Logger; /** * The default logger. Simple writes everything out to stdout or stderr */ public class SimpleLogger extends Logger { /** * Flag to indicate whether or not warnings should be suppressed */ private boolean suppressWarnings; /** * Constructor */ public SimpleLogger() { suppressWarnings = false; } /** * Log a debug message */ public void debug(Object message) { if (!suppressWarnings) { System.out.print("Debug: "); System.out.println(message); } } /** * Log a debug message and exception */ public void debug(Object message, Throwable t) { if (!suppressWarnings) { System.out.print("Debug: "); System.out.println(message); t.printStackTrace(); } } /** * Log an error message */ public void error(Object message) { System.err.print("Error: "); System.err.println(message); } /** * Log an error message object and exception */ public void error(Object message, Throwable t) { System.err.print("Error: "); System.err.println(message); t.printStackTrace(); } /** * Log a fatal message */ public void fatal(Object message) { System.err.print("Fatal: "); System.err.println(message); } /** * Log a fatal message and exception */ public void fatal(Object message, Throwable t) { System.err.print("Fatal: "); System.err.println(message); t.printStackTrace(); } /** * Log an information message */ public void info(Object message) { if (!suppressWarnings) { System.out.println(message); } } /** * Logs an information message and an exception */ public void info(Object message, Throwable t) { if (!suppressWarnings) { System.out.println(message); t.printStackTrace(); } } /** * Log a warning message object */ public void warn(Object message) { if (!suppressWarnings) { System.err.print("Warning: "); System.err.println(message); } } /** * Log a warning message with exception */ public void warn(Object message, Throwable t) { if (!suppressWarnings) { System.err.print("Warning: "); System.err.println(message); t.printStackTrace(); } } /** * Accessor to the logger implementation */ protected Logger getLoggerImpl(Class c) { return this; } /** * Overrides the method in the base class to suppress warnings - it can * be set using the system property jxl.nowarnings. * This method was originally present in the WorkbookSettings bean, * but has been moved to the logger class. This means it is now present * when the JVM is initialized, and subsequent to change it on * a Workbook by Workbook basis will prove fruitless * * @param w suppression flag */ public void setSuppressWarnings(boolean w) { suppressWarnings = w; } } jexcelapi/src/jxl/common/Logger.java0000750000175000017500000001074011207000612017641 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.common; import java.security.AccessControlException; /** * Abstract wrapper class for the logging interface of choice. * The methods declared here are the same as those for the log4j */ public abstract class Logger { /** * The singleton logger */ private static Logger logger = null; /** * Factory method to return the logger */ public static final Logger getLogger(Class cl) { if (logger == null) { initializeLogger(); } return logger.getLoggerImpl(cl); } /** * Initializes the logger in a thread safe manner */ private synchronized static void initializeLogger() { if (logger != null) { return; } String loggerName = jxl.common.log.LoggerName.NAME; try { // First see if there was anything defined at run time loggerName = System.getProperty("logger"); if (loggerName == null) { // Get the logger name from the compiled in logger loggerName = jxl.common.log.LoggerName.NAME; } logger = (Logger) Class.forName(loggerName).newInstance(); } catch(IllegalAccessException e) { logger = new jxl.common.log.SimpleLogger(); logger.warn("Could not instantiate logger " + loggerName + " using default"); } catch(InstantiationException e) { logger = new jxl.common.log.SimpleLogger(); logger.warn("Could not instantiate logger " + loggerName + " using default"); } catch (AccessControlException e) { logger = new jxl.common.log.SimpleLogger(); logger.warn("Could not instantiate logger " + loggerName + " using default"); } catch(ClassNotFoundException e) { logger = new jxl.common.log.SimpleLogger(); logger.warn("Could not instantiate logger " + loggerName + " using default"); } } /** * Constructor */ protected Logger() { } /** * Log a debug message */ public abstract void debug(Object message); /** * Log a debug message and exception */ public abstract void debug(Object message, Throwable t); /** * Log an error message */ public abstract void error(Object message); /** * Log an error message object and exception */ public abstract void error(Object message, Throwable t); /** * Log a fatal message */ public abstract void fatal(Object message); /** * Log a fatal message and exception */ public abstract void fatal(Object message, Throwable t); /** * Log an information message */ public abstract void info(Object message); /** * Logs an information message and an exception */ public abstract void info(Object message, Throwable t); /** * Log a warning message object */ public abstract void warn(Object message); /** * Log a warning message with exception */ public abstract void warn(Object message, Throwable t); /** * Accessor to the logger implementation */ protected abstract Logger getLoggerImpl(Class cl); /** * Empty implementation of the suppressWarnings. Subclasses may * or may not override this method. This method is included * primarily for backwards support of the jxl.nowarnings property, and * is used only by the SimpleLogger * * @param w suppression flag */ public void setSuppressWarnings(boolean w) { // default implementation does nothing } } jexcelapi/src/jxl/common/Assert.java0000750000175000017500000000334011207000612017661 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2006 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.common; /** * Simple assertion mechanism for use during development */ public final class Assert { /** * Throws an AssertionFailed exception if the specified condition is * false * * @param condition The assertion condition which must be true */ public static void verify(boolean condition) { if (!condition) { throw new AssertionFailed(); } } /** * If the condition evaluates to false, an AssertionFailed is thrown * * @param message A message thrown with the failed assertion * @param condition If this evaluates to false, an AssertionFailed is thrown */ public static void verify(boolean condition, String message) { if (!condition) { throw new AssertionFailed(message); } } } jexcelapi/src/jxl/common/LengthConverter.java0000750000175000017500000000537711207000612021545 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2006 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.common; public class LengthConverter { private static double[][] factors = new double[LengthUnit.getCount()][LengthUnit.getCount()]; static { // The identity factors factors[LengthUnit.POINTS.getIndex()][LengthUnit.POINTS.getIndex()] = 1; factors[LengthUnit.METRES.getIndex()][LengthUnit.METRES.getIndex()] = 1; factors[LengthUnit.CENTIMETRES.getIndex()][LengthUnit.CENTIMETRES.getIndex()] = 1; factors[LengthUnit.INCHES.getIndex()][LengthUnit.INCHES.getIndex()] = 1; // The points conversion factors factors[LengthUnit.POINTS.getIndex()][LengthUnit.METRES.getIndex()] = 0.00035277777778; factors[LengthUnit.POINTS.getIndex()][LengthUnit.CENTIMETRES.getIndex()] = 0.035277777778; factors[LengthUnit.POINTS.getIndex()][LengthUnit.INCHES.getIndex()] = 0.013888888889; // The metres conversion factors factors[LengthUnit.METRES.getIndex()][LengthUnit.POINTS.getIndex()] = 2877.84; factors[LengthUnit.METRES.getIndex()][LengthUnit.CENTIMETRES.getIndex()] = 100; factors[LengthUnit.METRES.getIndex()][LengthUnit.INCHES.getIndex()] = 39.37; // The centimetres conversion factors factors[LengthUnit.CENTIMETRES.getIndex()][LengthUnit.POINTS.getIndex()] = 28.34643; factors[LengthUnit.CENTIMETRES.getIndex()][LengthUnit.METRES.getIndex()] = 0.01; factors[LengthUnit.CENTIMETRES.getIndex()][LengthUnit.INCHES.getIndex()] = 0.3937; // The inches conversion factors factors[LengthUnit.INCHES.getIndex()][LengthUnit.POINTS.getIndex()] = 72; factors[LengthUnit.INCHES.getIndex()][LengthUnit.METRES.getIndex()] = 0.0254; factors[LengthUnit.INCHES.getIndex()][LengthUnit.CENTIMETRES.getIndex()] = 2.54; } public static double getConversionFactor(LengthUnit from, LengthUnit to) { return factors[from.getIndex()][to.getIndex()]; } } jexcelapi/src/jxl/common/AssertionFailed.java0000750000175000017500000000263211207000612021477 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2006 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.common; /** * An exception thrown when an assert (from the Assert class) fails */ public class AssertionFailed extends RuntimeException { /** * Default constructor * Prints the stack trace */ public AssertionFailed() { super(); printStackTrace(); } /** * Constructor with message * Prints the stack trace * * @param s Message thrown with the assertion */ public AssertionFailed(String s) { super(s); } } jexcelapi/src/jxl/common/BaseUnit.java0000750000175000017500000000214711207000612020136 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2006 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.common; public class BaseUnit { private int index; protected BaseUnit(int ind) { index = ind; } protected int getIndex() { return index; } } jexcelapi/src/jxl/BooleanFormulaCell.java0000750000175000017500000000216611207000610020640 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl; /** * A mixin interface for numerical formulas, which combines the interfaces * for formulas and for numbers */ public interface BooleanFormulaCell extends BooleanCell, FormulaCell { } jexcelapi/src/jxl/DateCell.java0000750000175000017500000000336511207000610016612 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl; import java.text.DateFormat; import java.util.Date; /** * A date cell */ public interface DateCell extends Cell { /** * Gets the date contained in this cell * * @return the cell contents */ public Date getDate(); /** * Indicates whether the date value contained in this cell refers to a date, * or merely a time * * @return TRUE if the value refers to a time */ public boolean isTime(); /** * Gets the DateFormat used to format the cell. This will normally be * the format specified in the excel spreadsheet, but in the event of any * difficulty parsing this, it will revert to the default date/time format. * * @return the DateFormat object used to format the date in the original * excel cell */ public DateFormat getDateFormat(); } jexcelapi/src/jxl/format/0000750000175000017500000000000011207000612015552 5ustar drazzibdrazzibjexcelapi/src/jxl/format/ScriptStyle.java0000750000175000017500000000535211207000612020712 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.format; /** * Enumeration class which contains the various script styles available * within the standard Excel ScriptStyle palette * */ public final class ScriptStyle { /** * The internal numerical representation of the ScriptStyle */ private int value; /** * The display string for the script style. Used when presenting the * format information */ private String string; /** * The list of ScriptStyles */ private static ScriptStyle[] styles = new ScriptStyle[0]; /** * Private constructor * * @param val * @param s the display string */ protected ScriptStyle(int val, String s) { value = val; string = s; ScriptStyle[] oldstyles = styles; styles = new ScriptStyle[oldstyles.length + 1]; System.arraycopy(oldstyles, 0, styles, 0, oldstyles.length); styles[oldstyles.length] = this; } /** * Gets the value of this style. This is the value that is written to * the generated Excel file * * @return the binary value */ public int getValue() { return value; } /** * Gets the string description for display purposes * * @return the string description */ public String getDescription() { return string; } /** * Gets the ScriptStyle from the value * * @param val * @return the ScriptStyle with that value */ public static ScriptStyle getStyle(int val) { for (int i = 0 ; i < styles.length ; i++) { if (styles[i].getValue() == val) { return styles[i]; } } return NORMAL_SCRIPT; } // The script styles public static final ScriptStyle NORMAL_SCRIPT = new ScriptStyle(0, "normal"); public static final ScriptStyle SUPERSCRIPT = new ScriptStyle(1, "super"); public static final ScriptStyle SUBSCRIPT = new ScriptStyle(2, "sub"); } jexcelapi/src/jxl/format/BoldStyle.java0000750000175000017500000000346711207000612020333 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.format; /** * Enumeration class containing the various bold styles for data */ public /*final*/ class BoldStyle { /** * The bold weight */ private int value; /** * The description */ private String string; /** * Constructor * * @param val */ protected BoldStyle(int val, String s) { value = val; string = s; } /** * Gets the value of the bold weight. This is the value that will be * written to the generated Excel file. * * @return the bold weight */ public int getValue() { return value ; } /** * Gets the string description of the bold style */ public String getDescription() { return string; } /** * Normal style */ public static final BoldStyle NORMAL = new BoldStyle(0x190, "Normal"); /** * Emboldened style */ public static final BoldStyle BOLD = new BoldStyle(0x2bc, "Bold"); } jexcelapi/src/jxl/format/Pattern.java0000750000175000017500000000721511207000612020042 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.format; /** * Enumeration class which contains the various patterns available within * the standard Excel pattern palette */ public /*final*/ class Pattern { /** * The internal numerical representation of the colour */ private int value; /** * The textual description */ private String string; /** * The list of patterns */ private static Pattern[] patterns = new Pattern[0]; /** * Private constructor * * @param val * @param s */ protected Pattern(int val, String s) { value = val; string = s; Pattern[] oldcols = patterns; patterns = new Pattern[oldcols.length + 1]; System.arraycopy(oldcols, 0, patterns, 0, oldcols.length); patterns[oldcols.length] = this; } /** * Gets the value of this pattern. This is the value that is written to * the generated Excel file * * @return the binary value */ public int getValue() { return value; } /** * Gets the textual description * * @return the string */ public String getDescription() { return string; } /** * Gets the pattern from the value * * @param val * @return the pattern with that value */ public static Pattern getPattern(int val) { for (int i = 0 ; i < patterns.length ; i++) { if (patterns[i].getValue() == val) { return patterns[i]; } } return NONE; } public final static Pattern NONE = new Pattern(0x0, "None"); public final static Pattern SOLID = new Pattern(0x1, "Solid"); public final static Pattern GRAY_50 = new Pattern(0x2, "Gray 50%"); public final static Pattern GRAY_75 = new Pattern(0x3, "Gray 75%"); public final static Pattern GRAY_25 = new Pattern(0x4, "Gray 25%"); public final static Pattern PATTERN1 = new Pattern(0x5, "Pattern 1"); public final static Pattern PATTERN2 = new Pattern(0x6, "Pattern 2"); public final static Pattern PATTERN3 = new Pattern(0x7, "Pattern 3"); public final static Pattern PATTERN4 = new Pattern(0x8, "Pattern 4"); public final static Pattern PATTERN5 = new Pattern(0x9, "Pattern 5"); public final static Pattern PATTERN6 = new Pattern(0xa, "Pattern 6"); public final static Pattern PATTERN7 = new Pattern(0xb, "Pattern 7"); public final static Pattern PATTERN8 = new Pattern(0xc, "Pattern 8"); public final static Pattern PATTERN9 = new Pattern(0xd, "Pattern 9"); public final static Pattern PATTERN10 = new Pattern(0xe, "Pattern 10"); public final static Pattern PATTERN11 = new Pattern(0xf, "Pattern 11"); public final static Pattern PATTERN12 = new Pattern(0x10, "Pattern 12"); public final static Pattern PATTERN13 = new Pattern(0x11, "Pattern 13"); public final static Pattern PATTERN14 = new Pattern(0x12, "Pattern 14"); } jexcelapi/src/jxl/format/Border.java0000750000175000017500000000310111207000612017630 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.format; /** * The location of a border */ public /*final*/ class Border { /** * The string description */ private String string; /** * Constructor */ protected Border(String s) { string = s; } /** * Gets the description */ public String getDescription() { return string; } public final static Border NONE = new Border("none"); public final static Border ALL = new Border("all"); public final static Border TOP = new Border("top"); public final static Border BOTTOM = new Border("bottom"); public final static Border LEFT = new Border("left"); public final static Border RIGHT = new Border("right"); } jexcelapi/src/jxl/format/Format.java0000750000175000017500000000235211207000612017652 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.format; /** * Exposes the cell formatting information */ public interface Format { /** * Accesses the excel format string which is applied to the cell * Note that this is the string that excel uses, and not the java * equivalent * * @return the cell format string */ public String getFormatString(); } jexcelapi/src/jxl/format/PaperSize.java0000750000175000017500000002337111207000612020330 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.format; /** * Enumeration type which contains the available excel paper sizes and their * codes */ public final class PaperSize { private static final int LAST_PAPER_SIZE = 89; /** * The excel encoding */ private int val; /** * The paper sizes */ private static PaperSize[] paperSizes = new PaperSize[LAST_PAPER_SIZE + 1]; /** * Constructor */ private PaperSize(int v, boolean growArray) { val = v; if (v >= paperSizes.length && growArray) { // Grow the array and add this to it PaperSize[] newarray = new PaperSize[v + 1]; System.arraycopy(paperSizes, 0, newarray, 0, paperSizes.length); paperSizes = newarray; } if (v < paperSizes.length) { paperSizes[v] = this; } } /** * Constructor */ private PaperSize(int v) { this(v, true); } /** * Accessor for the internal binary value association with this paper size * * @return the internal value */ public int getValue() { return val; } /** * Gets the paper size for a specific value * * @param val the value * @return the paper size */ public static PaperSize getPaperSize(int val) { PaperSize p = val > paperSizes.length - 1 ? null : paperSizes[val]; return p == null ? new PaperSize(val, false) : p; } /** US Letter 8.5 x 11" */ public static final PaperSize UNDEFINED = new PaperSize(0); /** US Letter 8.5 x 11" */ public static final PaperSize LETTER = new PaperSize(1); /** Letter small 8.5" 11" */ public static final PaperSize LETTER_SMALL = new PaperSize(2); /** Tabloid 11" x 17" */ public static final PaperSize TABLOID = new PaperSize(3); /** Leger 17" x 11" */ public static final PaperSize LEDGER = new PaperSize(4); /** US Legal 8.5" x 14" */ public static final PaperSize LEGAL = new PaperSize(5); /** Statement 5.5" x 8.5" */ public static final PaperSize STATEMENT = new PaperSize(6); /** Executive 7.25" x 10.5" */ public static final PaperSize EXECUTIVE = new PaperSize(7); /** A3 297mm x 420mm */ public static final PaperSize A3 = new PaperSize(8); /** A4 210mm x 297mm */ public static final PaperSize A4 = new PaperSize(9); /** A4 Small 210mm x 297 mm */ public static final PaperSize A4_SMALL = new PaperSize(10); /** A5 148mm x 210mm */ public static final PaperSize A5 = new PaperSize(11); /** B4 (JIS) 257mm x 364mm */ public static final PaperSize B4 = new PaperSize(12); /** B5 (JIS) 182mm x 257mm */ public static final PaperSize B5 = new PaperSize(13); /** Folio 8.5" x 13" */ public static final PaperSize FOLIO = new PaperSize(14); /** Quarto 215mm x 275mm */ public static final PaperSize QUARTO = new PaperSize(15); /** 10" x 14" */ public static final PaperSize SIZE_10x14 = new PaperSize(16); /** 11" x 17" */ public static final PaperSize SIZE_10x17 = new PaperSize(17); /** NOTE 8.5" x 11" */ public static final PaperSize NOTE = new PaperSize(18); /** Envelope #9 3 7/8" x 8 7/8" */ public static final PaperSize ENVELOPE_9 = new PaperSize(19); /** Envelope #10 4 1/8" x 9.5" */ public static final PaperSize ENVELOPE_10 = new PaperSize(20); /** Envelope #11 4.5" x 10 3/8" */ public static final PaperSize ENVELOPE_11 = new PaperSize(21); /** Envelope #12 4.75" x 11" */ public static final PaperSize ENVELOPE_12 = new PaperSize(22); /** Envelope #14 5" x 11.5" */ public static final PaperSize ENVELOPE_14 = new PaperSize(23); /** C 17" x 22" */ public static final PaperSize C = new PaperSize(24); /** D 22" x 34" */ public static final PaperSize D = new PaperSize(25); /** E 34" x 44" */ public static final PaperSize E = new PaperSize(26); /** Envelope DL 110mm 220mm */ public static final PaperSize ENVELOPE_DL = new PaperSize(27); /** Envelope C5 162mm 229mm */ public static final PaperSize ENVELOPE_C5 = new PaperSize(28); /** Envelope C3 324mm 458mm */ public static final PaperSize ENVELOPE_C3 = new PaperSize(29); /** Envelope C4 229mm 324mm */ public static final PaperSize ENVELOPE_C4 = new PaperSize(30); /** Envelope C6 114mm 162mm */ public static final PaperSize ENVELOPE_C6 = new PaperSize(31); /** Envelope C6/C5 114mm 229mm */ public static final PaperSize ENVELOPE_C6_C5 = new PaperSize(32); /** B4 (ISO) 250mm 353mm */ public static final PaperSize B4_ISO = new PaperSize(33); /** B5 (ISO) 176mm 250mm */ public static final PaperSize B5_ISO = new PaperSize(34); /** B6 (ISO) 125mm 176mm */ public static final PaperSize B6_ISO = new PaperSize(35); /** Envelope Italy 110mm 230mm */ public static final PaperSize ENVELOPE_ITALY = new PaperSize(36); /** Envelope Monarch 3 7/8" 7.5" */ public static final PaperSize ENVELOPE_MONARCH = new PaperSize(37); /** 6.75 Envelope 3 5/8" 6.5" */ public static final PaperSize ENVELOPE_6_75 = new PaperSize(38); /** US Standard Fanfold 14 7/8" 11" */ public static final PaperSize US_FANFOLD = new PaperSize(39); /** German Std. Fanfold 8.5" 12" */ public static final PaperSize GERMAN_FANFOLD = new PaperSize(40); /** German Legal Fanfold 8.5" 13" */ public static final PaperSize GERMAN_LEGAL_FANFOLD = new PaperSize(41); /** B4 (ISO) 250mm 353mm */ public static final PaperSize B4_ISO_2 = new PaperSize(42); /** Japanese Postcard 100mm 148mm */ public static final PaperSize JAPANESE_POSTCARD = new PaperSize(43); /** 911 9" 11" */ public static final PaperSize SIZE_9x11 = new PaperSize(44); /** 1011 10" 11" */ public static final PaperSize SIZE_10x11 = new PaperSize(45); /** 1511 15" 11" */ public static final PaperSize SIZE_15x11 = new PaperSize(46); /** Envelope Invite 220mm 220mm */ public static final PaperSize ENVELOPE_INVITE = new PaperSize(47); /* 48 & 49 Undefined */ /** Letter Extra 9.5" 12" */ public static final PaperSize LETTER_EXTRA = new PaperSize(50); /** Legal Extra 9.5" 15" */ public static final PaperSize LEGAL_EXTRA = new PaperSize(51); /** Tabloid Extra 11 11/16" 18" */ public static final PaperSize TABLOID_EXTRA = new PaperSize(52); /** A4 Extra 235mm 322mm */ public static final PaperSize A4_EXTRA = new PaperSize(53); /** Letter Transverse 8.5" 11" */ public static final PaperSize LETTER_TRANSVERSE = new PaperSize(54); /** A4 Transverse 210mm 297mm */ public static final PaperSize A4_TRANSVERSE = new PaperSize(55); /** Letter Extra Transv. 9.5" 12" */ public static final PaperSize LETTER_EXTRA_TRANSVERSE = new PaperSize(56); /** Super A/A4 227mm 356mm */ public static final PaperSize SUPER_A_A4 = new PaperSize(57); /** Super B/A3 305mm 487mm */ public static final PaperSize SUPER_B_A3 = new PaperSize(58); /** Letter Plus 8.5" x 12 11/16" */ public static final PaperSize LETTER_PLUS = new PaperSize(59); /** A4 Plus 210mm 330mm */ public static final PaperSize A4_PLUS = new PaperSize(60); /** A5 Transverse 148mm 210mm */ public static final PaperSize A5_TRANSVERSE = new PaperSize(61); /** B5 (JIS) Transverse 182mm 257mm */ public static final PaperSize B5_TRANSVERSE = new PaperSize(62); /** A3 Extra 322mm 445mm */ public static final PaperSize A3_EXTRA = new PaperSize(63); /** A5 Extra 174mm 235mm */ public static final PaperSize A5_EXTRA = new PaperSize(64); /** B5 (ISO) Extra 201mm 276mm */ public static final PaperSize B5_EXTRA = new PaperSize(65); /** A2 420mm 594mm */ public static final PaperSize A2 = new PaperSize(66); /** A3 Transverse 297mm 420mm */ public static final PaperSize A3_TRANSVERSE = new PaperSize(67); /** A3 Extra Transverse 322mm 445mm */ public static final PaperSize A3_EXTRA_TRANSVERSE = new PaperSize(68); /** Dbl. Japanese Postcard 200mm 148mm */ public static final PaperSize DOUBLE_JAPANESE_POSTCARD = new PaperSize(69); /** A6 105mm 148mm */ public static final PaperSize A6 = new PaperSize(70); /* 71 - 74 undefined */ /** Letter Rotated 11" 8.5" */ public static final PaperSize LETTER_ROTATED = new PaperSize(75); /** A3 Rotated 420mm 297mm */ public static final PaperSize A3_ROTATED = new PaperSize(76); /** A4 Rotated 297mm 210mm */ public static final PaperSize A4_ROTATED = new PaperSize(77); /** A5 Rotated 210mm 148mm */ public static final PaperSize A5_ROTATED = new PaperSize(78); /** B4 (JIS) Rotated 364mm 257mm */ public static final PaperSize B4_ROTATED = new PaperSize(79); /** B5 (JIS) Rotated 257mm 182mm */ public static final PaperSize B5_ROTATED = new PaperSize(80); /** Japanese Postcard Rot. 148mm 100mm */ public static final PaperSize JAPANESE_POSTCARD_ROTATED = new PaperSize(81); /** Dbl. Jap. Postcard Rot. 148mm 200mm */ public static final PaperSize DOUBLE_JAPANESE_POSTCARD_ROTATED = new PaperSize(82); /** A6 Rotated 148mm 105mm */ public static final PaperSize A6_ROTATED = new PaperSize(83); /* 84 - 87 undefined */ /** B6 (JIS) 128mm 182mm */ public static final PaperSize B6 = new PaperSize(88); /** B6 (JIS) Rotated 182mm 128mm */ public static final PaperSize B6_ROTATED = new PaperSize(89); } jexcelapi/src/jxl/format/PageOrientation.java0000750000175000017500000000245611207000612021517 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.format; /** * Enumeration type which describes the page orientation */ public final class PageOrientation { /** * Constructor */ private PageOrientation() { } /** * Portrait orientation */ public static PageOrientation PORTRAIT = new PageOrientation(); /** * Landscape orientation */ public static PageOrientation LANDSCAPE = new PageOrientation(); } jexcelapi/src/jxl/format/Orientation.java0000750000175000017500000000704711207000612020723 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.format; /** * Enumeration type which describes the orientation of data within a cell */ public final class Orientation { /** * The internal binary value which gets written to the generated Excel file */ private int value; /** * The textual description */ private String string; /** * The list of alignments */ private static Orientation[] orientations = new Orientation[0]; /** * Constructor * * @param val */ protected Orientation(int val, String s) { value = val; string = s; Orientation[] oldorients = orientations; orientations = new Orientation[oldorients.length + 1]; System.arraycopy(oldorients, 0, orientations, 0, oldorients.length); orientations[oldorients.length] = this; } /** * Accessor for the binary value * * @return the internal binary value */ public int getValue() { return value; } /** * Gets the textual description */ public String getDescription() { return string; } /** * Gets the alignment from the value * * @param val * @return the alignment with that value */ public static Orientation getOrientation(int val) { for (int i = 0 ; i < orientations.length ; i++) { if (orientations[i].getValue() == val) { return orientations[i]; } } return HORIZONTAL; } /** * Cells with this specified orientation will be horizontal */ public static Orientation HORIZONTAL = new Orientation(0, "horizontal"); /** * Cells with this specified orientation have their data * presented vertically */ public static Orientation VERTICAL = new Orientation(0xff, "vertical"); /** * Cells with this specified orientation will have their data * presented with a rotation of 90 degrees upwards */ public static Orientation PLUS_90 = new Orientation(90, "up 90"); /** * Cells with this specified orientation will have their data * presented with a rotation of 90 degrees downwards */ public static Orientation MINUS_90 = new Orientation(180, "down 90"); /** * Cells with this specified orientation will have their data * presented with a rotation 45 degrees upwards */ public static Orientation PLUS_45 = new Orientation(45, "up 45"); /** * Cells with this specified orientation will have their data * presented with a rotation 45 degrees downwards */ public static Orientation MINUS_45 = new Orientation(135, "down 45"); /** * Cells with this specified orientation will have their text stacked * downwards, but not rotated */ public static Orientation STACKED = new Orientation(255, "stacked"); } jexcelapi/src/jxl/format/RGB.java0000750000175000017500000000367111207000612017041 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2005 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.format; /** * A structure which contains the RGB values for a particular colour */ public final class RGB { /** * The red component of this colour */ private int red; /** * The green component of this colour */ private int green; /** * The blue component of this colour */ private int blue; /** * Constructor * * @param r the red component * @param g the green component * @param b the blue component */ public RGB(int r, int g, int b) { red = r; green = g; blue = b; } /** * Accessor for the red component * * @return the red component of the colour, between 0 and 255 */ public int getRed() { return red; } /** * Accessor for the green component * * @return the green component of the colour, between 0 and 255 */ public int getGreen() { return green; } /** * Accessor for the blue component * * @return the blue component of the colour, between 0 and 255 */ public int getBlue() { return blue; } } jexcelapi/src/jxl/format/Colour.java0000750000175000017500000002303211207000612017663 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.format; /** * Enumeration class which contains the various colours available within * the standard Excel colour palette * */ public /*final*/ class Colour { /** * The internal numerical representation of the colour */ private int value; /** * The default RGB value */ private RGB rgb; /** * The display string for the colour. Used when presenting the * format information */ private String string; /** * The list of internal colours */ private static Colour[] colours = new Colour[0]; /** * Private constructor * * @param val * @param s the display string * @param r the default red value * @param g the default green value * @param b the default blue value */ protected Colour(int val, String s, int r, int g, int b) { value = val; string = s; rgb = new RGB(r,g,b); Colour[] oldcols = colours; colours = new Colour[oldcols.length + 1]; System.arraycopy(oldcols, 0, colours, 0, oldcols.length); colours[oldcols.length] = this; } /** * Gets the value of this colour. This is the value that is written to * the generated Excel file * * @return the binary value */ public int getValue() { return value; } /** * Gets the string description for display purposes * * @return the string description */ public String getDescription() { return string; } /** * Gets the default red content of this colour. Used when writing the * default colour palette * * @return the red content of this colour * @deprecated use getDefaultRGB instead */ public int getDefaultRed() { return rgb.getRed(); } /** * Gets the default green content of this colour. Used when writing the * default colour palette * * @return the green content of this colour * @deprecated use getDefaultRGB instead */ public int getDefaultGreen() { return rgb.getGreen(); } /** * Gets the default blue content of this colour. Used when writing the * default colour palette * * @return the blue content of this colour * @deprecated use getDefaultRGB instead */ public int getDefaultBlue() { return rgb.getBlue(); } /** * Returns the default RGB of the colour * * @return the default RGB */ public RGB getDefaultRGB() { return rgb; } /** * Gets the internal colour from the value * * @param val * @return the colour with that value */ public static Colour getInternalColour(int val) { for (int i = 0 ; i < colours.length ; i++) { if (colours[i].getValue() == val) { return colours[i]; } } return UNKNOWN; } /** * Returns all available colours - used when generating the default palette * * @return all available colours */ public static Colour[] getAllColours() { return colours; } // Major colours public final static Colour UNKNOWN = new Colour(0x7fee, "unknown", 0, 0, 0); public final static Colour BLACK = new Colour(0x7fff, "black", 0, 0, 0); public final static Colour WHITE = new Colour(0x9, "white", 0xff, 0xff, 0xff); public final static Colour DEFAULT_BACKGROUND1 = new Colour(0x0, "default background", 0xff, 0xff, 0xff); public final static Colour DEFAULT_BACKGROUND = new Colour(0xc0, "default background", 0xff, 0xff, 0xff); public final static Colour PALETTE_BLACK = new Colour(0x8, "black", 0x1, 0, 0); // the first item in the colour palette // Other colours public final static Colour RED = new Colour(0xa, "red",0xff,0,0); public final static Colour BRIGHT_GREEN = new Colour(0xb, "bright green",0,0xff,0); public final static Colour BLUE = new Colour(0xc, "blue",0,0,0xff); public final static Colour YELLOW = new Colour(0xd, "yellow",0xff,0xff,0); public final static Colour PINK = new Colour(0xe, "pink",0xff,0,0xff); public final static Colour TURQUOISE = new Colour(0xf, "turquoise",0,0xff,0xff); public final static Colour DARK_RED = new Colour(0x10, "dark red",0x80,0,0); public final static Colour GREEN = new Colour(0x11, "green",0,0x80,0); public final static Colour DARK_BLUE = new Colour(0x12, "dark blue",0,0,0x80); public final static Colour DARK_YELLOW = new Colour(0x13, "dark yellow",0x80,0x80,0); public final static Colour VIOLET = new Colour(0x14, "violet",0x80,0x80,0); public final static Colour TEAL = new Colour(0x15, "teal",0,0x80,0x80); public final static Colour GREY_25_PERCENT = new Colour(0x16 ,"grey 25%",0xc0,0xc0,0xc0); public final static Colour GREY_50_PERCENT = new Colour(0x17, "grey 50%",0x80,0x80,0x80); public final static Colour PERIWINKLE = new Colour(0x18, "periwinkle%",0x99, 0x99, 0xff); public final static Colour PLUM2 = new Colour(0x19, "plum",0x99, 0x33, 0x66); public final static Colour IVORY = new Colour(0x1a, "ivory",0xff, 0xff, 0xcc); public final static Colour LIGHT_TURQUOISE2= new Colour(0x1b, "light turquoise",0xcc, 0xff, 0xff); public final static Colour DARK_PURPLE = new Colour(0x1c, "dark purple",0x66, 0x0, 0x66); public final static Colour CORAL = new Colour(0x1d, "coral",0xff, 0x80, 0x80); public final static Colour OCEAN_BLUE = new Colour(0x1e, "ocean blue",0x0, 0x66, 0xcc); public final static Colour ICE_BLUE = new Colour(0x1f, "ice blue",0xcc, 0xcc, 0xff); public final static Colour DARK_BLUE2 = new Colour(0x20, "dark blue",0,0,0x80); public final static Colour PINK2 = new Colour(0x21, "pink",0xff,0,0xff); public final static Colour YELLOW2 = new Colour(0x22, "yellow",0xff,0xff,0x0); public final static Colour TURQOISE2 = new Colour(0x23, "turqoise",0x0,0xff,0xff); public final static Colour VIOLET2 = new Colour(0x24, "violet",0x80,0x0,0x80); public final static Colour DARK_RED2 = new Colour(0x25, "dark red",0x80,0x0,0x0); public final static Colour TEAL2 = new Colour(0x26, "teal",0x0,0x80,0x80); public final static Colour BLUE2 = new Colour(0x27, "blue",0x0,0x0,0xff); public final static Colour SKY_BLUE = new Colour(0x28, "sky blue",0,0xcc,0xff); public final static Colour LIGHT_TURQUOISE = new Colour(0x29, "light turquoise",0xcc,0xff,0xff); public final static Colour LIGHT_GREEN = new Colour(0x2a, "light green",0xcc,0xff,0xcc); public final static Colour VERY_LIGHT_YELLOW = new Colour(0x2b, "very light yellow",0xff,0xff,0x99); public final static Colour PALE_BLUE = new Colour(0x2c, "pale blue",0x99,0xcc,0xff); public final static Colour ROSE = new Colour(0x2d, "rose",0xff,0x99,0xcc); public final static Colour LAVENDER = new Colour(0x2e, "lavender",0xcc,0x99,0xff); public final static Colour TAN = new Colour(0x2f, "tan",0xff,0xcc,0x99); public final static Colour LIGHT_BLUE = new Colour(0x30, "light blue", 0x33, 0x66, 0xff); public final static Colour AQUA = new Colour(0x31, "aqua",0x33,0xcc,0xcc); public final static Colour LIME = new Colour(0x32, "lime",0x99,0xcc,0); public final static Colour GOLD = new Colour(0x33, "gold",0xff,0xcc,0); public final static Colour LIGHT_ORANGE = new Colour(0x34, "light orange",0xff,0x99,0); public final static Colour ORANGE = new Colour(0x35, "orange",0xff,0x66,0); public final static Colour BLUE_GREY = new Colour(0x36, "blue grey",0x66,0x66,0xcc); public final static Colour GREY_40_PERCENT = new Colour(0x37, "grey 40%",0x96,0x96,0x96); public final static Colour DARK_TEAL = new Colour(0x38, "dark teal",0,0x33,0x66); public final static Colour SEA_GREEN = new Colour(0x39, "sea green",0x33,0x99,0x66); public final static Colour DARK_GREEN = new Colour(0x3a, "dark green",0,0x33,0); public final static Colour OLIVE_GREEN = new Colour(0x3b, "olive green",0x33,0x33,0); public final static Colour BROWN = new Colour(0x3c, "brown",0x99,0x33,0); public final static Colour PLUM = new Colour(0x3d, "plum",0x99,0x33,0x66); public final static Colour INDIGO = new Colour(0x3e, "indigo",0x33,0x33,0x99); public final static Colour GREY_80_PERCENT = new Colour(0x3f, "grey 80%",0x33,0x33,0x33); public final static Colour AUTOMATIC = new Colour(0x40, "automatic", 0xff, 0xff, 0xff); // Colours added for backwards compatibility public final static Colour GRAY_80 = GREY_80_PERCENT; public final static Colour GRAY_50 = GREY_50_PERCENT; public final static Colour GRAY_25 = GREY_25_PERCENT; } jexcelapi/src/jxl/format/BorderLineStyle.java0000750000175000017500000000713711207000612021476 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.format; /** * The border line style */ public /*final*/ class BorderLineStyle { /** * The value */ private int value; /** * The string description */ private String string; /** * The list of alignments */ private static BorderLineStyle[] styles = new BorderLineStyle[0]; /** * Constructor */ protected BorderLineStyle(int val, String s) { value = val; string = s; BorderLineStyle[] oldstyles = styles; styles = new BorderLineStyle[oldstyles.length + 1]; System.arraycopy(oldstyles, 0, styles, 0, oldstyles.length); styles[oldstyles.length] = this; } /** * Gets the value for this line style * * @return the value */ public int getValue() { return value; } /** * Gets the textual description */ public String getDescription() { return string; } /** * Gets the alignment from the value * * @param val * @return the alignment with that value */ public static BorderLineStyle getStyle(int val) { for (int i = 0 ; i < styles.length ; i++) { if (styles[i].getValue() == val) { return styles[i]; } } return NONE; } public final static BorderLineStyle NONE = new BorderLineStyle(0, "none"); public final static BorderLineStyle THIN = new BorderLineStyle(1, "thin"); public final static BorderLineStyle MEDIUM = new BorderLineStyle(2, "medium"); public final static BorderLineStyle DASHED = new BorderLineStyle(3, "dashed"); public final static BorderLineStyle DOTTED = new BorderLineStyle(4, "dotted"); public final static BorderLineStyle THICK = new BorderLineStyle(5, "thick"); public final static BorderLineStyle DOUBLE = new BorderLineStyle(6, "double"); public final static BorderLineStyle HAIR = new BorderLineStyle(7, "hair"); public final static BorderLineStyle MEDIUM_DASHED = new BorderLineStyle(8, "medium dashed"); public final static BorderLineStyle DASH_DOT = new BorderLineStyle(9, "dash dot"); public final static BorderLineStyle MEDIUM_DASH_DOT = new BorderLineStyle(0xa, "medium dash dot"); public final static BorderLineStyle DASH_DOT_DOT = new BorderLineStyle(0xb, "Dash dot dot"); public final static BorderLineStyle MEDIUM_DASH_DOT_DOT = new BorderLineStyle(0xc, "Medium dash dot dot"); public final static BorderLineStyle SLANTED_DASH_DOT = new BorderLineStyle(0xd, "Slanted dash dot"); } jexcelapi/src/jxl/format/UnderlineStyle.java0000750000175000017500000000602411207000612021370 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.format; /** * Enumeration class which contains the various underline styles available * within the standard Excel UnderlineStyle palette * */ public final class UnderlineStyle { /** * The internal numerical representation of the UnderlineStyle */ private int value; /** * The display string for the underline style. Used when presenting the * format information */ private String string; /** * The list of UnderlineStyles */ private static UnderlineStyle[] styles = new UnderlineStyle[0]; /** * Private constructor * * @param val * @param s the display string */ protected UnderlineStyle(int val, String s) { value = val; string = s; UnderlineStyle[] oldstyles = styles; styles = new UnderlineStyle[oldstyles.length + 1]; System.arraycopy(oldstyles, 0, styles, 0, oldstyles.length); styles[oldstyles.length] = this; } /** * Gets the value of this style. This is the value that is written to * the generated Excel file * * @return the binary value */ public int getValue() { return value; } /** * Gets the string description for display purposes * * @return the string description */ public String getDescription() { return string; } /** * Gets the UnderlineStyle from the value * * @param val * @return the UnderlineStyle with that value */ public static UnderlineStyle getStyle(int val) { for (int i = 0 ; i < styles.length ; i++) { if (styles[i].getValue() == val) { return styles[i]; } } return NO_UNDERLINE; } // The underline styles public static final UnderlineStyle NO_UNDERLINE = new UnderlineStyle(0, "none"); public static final UnderlineStyle SINGLE = new UnderlineStyle(1, "single"); public static final UnderlineStyle DOUBLE = new UnderlineStyle(2, "double"); public static final UnderlineStyle SINGLE_ACCOUNTING = new UnderlineStyle(0x21, "single accounting"); public static final UnderlineStyle DOUBLE_ACCOUNTING = new UnderlineStyle(0x22, "double accounting"); } jexcelapi/src/jxl/format/PageOrder.java0000750000175000017500000000242611207000612020274 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.format; /** * Enumeration type which describes the page orientation */ public class PageOrder { /** * Constructor */ private PageOrder() { } /** * Top to Down then Right. */ public static PageOrder DOWN_THEN_RIGHT = new PageOrder(); /** * Left to Right then Down. */ public static PageOrder RIGHT_THEN_DOWN = new PageOrder(); } jexcelapi/src/jxl/format/Font.java0000750000175000017500000000403611207000612017331 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.format; /** * Interface which exposes the user font display information to the user */ public interface Font { /** * Gets the name of this font * * @return the name of this font */ public String getName(); /** * Gets the point size for this font, if the font hasn't been initialized * * @return the point size */ public int getPointSize(); /** * Gets the bold weight for this font * * @return the bold weight for this font */ public int getBoldWeight(); /** * Returns the italic flag * * @return TRUE if this font is italic, FALSE otherwise */ public boolean isItalic(); /** * Returns the strike-out flag * * @return TRUE if this font is struck-out, FALSE otherwise */ public boolean isStruckout(); /** * Gets the underline style for this font * * @return the underline style */ public UnderlineStyle getUnderlineStyle(); /** * Gets the colour for this font * * @return the colour */ public Colour getColour(); /** * Gets the script style * * @return the script style */ public ScriptStyle getScriptStyle(); } jexcelapi/src/jxl/format/CellFormat.java0000750000175000017500000000733711207000612020462 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.format; /** * Interface for cell formats */ public interface CellFormat { /** * Gets the format used by this format * * @return the format */ public Format getFormat(); /** * Gets the font information used by this format * * @return the font */ public Font getFont(); /** * Gets whether or not the contents of this cell are wrapped * * @return TRUE if this cell's contents are wrapped, FALSE otherwise */ public boolean getWrap(); /** * Gets the horizontal cell alignment * * @return the alignment */ public Alignment getAlignment(); /** * Gets the vertical cell alignment * * @return the alignment */ public VerticalAlignment getVerticalAlignment(); /** * Gets the orientation * * @return the orientation */ public Orientation getOrientation(); /** * Gets the line style for the given cell border * If a border type of ALL or NONE is specified, then a line style of * NONE is returned * * @param border the cell border we are interested in * @return the line style of the specified border */ public BorderLineStyle getBorder(Border border); /** * Gets the line style for the given cell border * If a border type of ALL or NONE is specified, then a line style of * NONE is returned * * @param border the cell border we are interested in * @return the line style of the specified border */ public BorderLineStyle getBorderLine(Border border); /** * Gets the colour for the given cell border * If a border type of ALL or NONE is specified, then a line style of * NONE is returned * If the specified cell does not have an associated line style, then * the colour the line would be is still returned * * @param border the cell border we are interested in * @return the line style of the specified border */ public Colour getBorderColour(Border border); /** * Determines if this cell format has any borders at all. Used to * set the new borders when merging a group of cells * * @return TRUE if this cell has any borders, FALSE otherwise */ public boolean hasBorders(); /** * Gets the background colour used by this cell * * @return the foreground colour */ public Colour getBackgroundColour(); /** * Gets the pattern used by this cell format * * @return the background pattern */ public Pattern getPattern(); /** * Gets the indentation of the cell text * * @return the indentation */ public int getIndentation(); /** * Gets the shrink to fit flag * * @return TRUE if this format is shrink to fit, FALSE otherise */ public boolean isShrinkToFit(); /** * Accessor for whether a particular cell is locked * * @return TRUE if this cell is locked, FALSE otherwise */ public boolean isLocked(); } jexcelapi/src/jxl/format/VerticalAlignment.java0000750000175000017500000000600111207000612022025 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.format; /** * Enumeration type which describes the vertical alignment of data within a cell */ public /*final*/ class VerticalAlignment { /** * The internal binary value which gets written to the generated Excel file */ private int value; /** * The textual description */ private String string; /** * The list of alignments */ private static VerticalAlignment[] alignments = new VerticalAlignment[0]; /** * Constructor * * @param val */ protected VerticalAlignment(int val, String s) { value = val; string = s; VerticalAlignment[] oldaligns = alignments; alignments = new VerticalAlignment[oldaligns.length + 1]; System.arraycopy(oldaligns, 0, alignments, 0, oldaligns.length); alignments[oldaligns.length] = this; } /** * Accessor for the binary value * * @return the internal binary value */ public int getValue() { return value; } /** * Gets the textual description */ public String getDescription() { return string; } /** * Gets the alignment from the value * * @param val * @return the alignment with that value */ public static VerticalAlignment getAlignment(int val) { for (int i = 0 ; i < alignments.length ; i++) { if (alignments[i].getValue() == val) { return alignments[i]; } } return BOTTOM; } /** * Cells with this specified vertical alignment will have their data * aligned at the top */ public static VerticalAlignment TOP = new VerticalAlignment(0, "top"); /** * Cells with this specified vertical alignment will have their data * aligned centrally */ public static VerticalAlignment CENTRE = new VerticalAlignment(1, "centre"); /** * Cells with this specified vertical alignment will have their data * aligned at the bottom */ public static VerticalAlignment BOTTOM = new VerticalAlignment(2, "bottom"); /** * Cells with this specified vertical alignment will have their data * justified */ public static VerticalAlignment JUSTIFY = new VerticalAlignment(3, "Justify"); } jexcelapi/src/jxl/format/Alignment.java0000750000175000017500000000623611207000612020345 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.format; /** * Enumeration class which contains the various alignments for data within a * cell */ public /*final*/ class Alignment { /** * The internal numerical repreentation of the alignment */ private int value; /** * The string description of this alignment */ private String string; /** * The list of alignments */ private static Alignment[] alignments = new Alignment[0]; /** * Private constructor * * @param val * @param string */ protected Alignment(int val,String s) { value = val; string = s; Alignment[] oldaligns = alignments; alignments = new Alignment[oldaligns.length + 1]; System.arraycopy(oldaligns, 0, alignments, 0, oldaligns.length); alignments[oldaligns.length] = this; } /** * Gets the value of this alignment. This is the value that is written to * the generated Excel file * * @return the binary value */ public int getValue() { return value; } /** * Gets the string description of this alignment * * @return the string description */ public String getDescription() { return string; } /** * Gets the alignment from the value * * @param val * @return the alignment with that value */ public static Alignment getAlignment(int val) { for (int i = 0 ; i < alignments.length ; i++) { if (alignments[i].getValue() == val) { return alignments[i]; } } return GENERAL; } /** * The standard alignment */ public static Alignment GENERAL = new Alignment(0, "general"); /** * Data cells with this alignment will appear at the left hand edge of the * cell */ public static Alignment LEFT = new Alignment(1, "left"); /** * Data in cells with this alignment will be centred */ public static Alignment CENTRE = new Alignment(2, "centre"); /** * Data in cells with this alignment will be right aligned */ public static Alignment RIGHT = new Alignment(3, "right"); /** * Data in cells with this alignment will fill the cell */ public static Alignment FILL = new Alignment(4,"fill"); /** * Data in cells with this alignment will be justified */ public static Alignment JUSTIFY = new Alignment(5, "justify"); } jexcelapi/src/jxl/NumberFormulaCell.java0000750000175000017500000000216411207000610020507 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl; /** * A mixin interface for numerical formulas, which combines the interfaces * for formulas and for numbers */ public interface NumberFormulaCell extends NumberCell, FormulaCell { } jexcelapi/src/jxl/Hyperlink.java0000750000175000017500000000602511207000610017076 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl; import java.io.File; import java.net.URL; /** * Hyperlink information. Only URLs or file links are supported * * Hyperlinks may apply to a range of cells; in such cases the methods * getRow and getColumn return the cell at the top left of the range * the hyperlink refers to. Hyperlinks have no specific cell format * information applied to them, so the getCellFormat method will return null */ public interface Hyperlink { /** * Returns the row number of this cell * * @return the row number of this cell */ public int getRow(); /** * Returns the column number of this cell * * @return the column number of this cell */ public int getColumn(); /** * Gets the range of cells which activate this hyperlink * The get sheet index methods will all return -1, because the * cells will all be present on the same sheet * * @return the range of cells which activate the hyperlink */ public Range getRange(); /** * Determines whether this is a hyperlink to a file * * @return TRUE if this is a hyperlink to a file, FALSE otherwise */ public boolean isFile(); /** * Determines whether this is a hyperlink to a web resource * * @return TRUE if this is a URL */ public boolean isURL(); /** * Determines whether this is a hyperlink to a location in this workbook * * @return TRUE if this is a link to an internal location */ public boolean isLocation(); /** * Returns the row number of the bottom right cell * * @return the row number of this cell */ public int getLastRow(); /** * Returns the column number of the bottom right cell * * @return the column number of this cell */ public int getLastColumn(); /** * Gets the URL referenced by this Hyperlink * * @return the URL, or NULL if this hyperlink is not a URL */ public URL getURL(); /** * Returns the local file eferenced by this Hyperlink * * @return the file, or NULL if this hyperlink is not a file */ public File getFile(); } jexcelapi/src/jxl/read/0000750000175000017500000000000011207000610015173 5ustar drazzibdrazzibjexcelapi/src/jxl/read/biff/0000750000175000017500000000000011270605332016115 5ustar drazzibdrazzibjexcelapi/src/jxl/read/biff/PasswordRecord.java0000750000175000017500000000306511207000612021716 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.biff.IntegerHelper; import jxl.biff.RecordData; import jxl.biff.Type; /** * A password record */ class PasswordRecord extends RecordData { /** * The password */ private String password; /** * The binary data */ private int passwordHash; /** * Constructor * * @param t the raw bytes */ public PasswordRecord(Record t) { super(Type.PASSWORD); byte[] data = t.getData(); passwordHash = IntegerHelper.getInt(data[0], data[1]); } /** * Gets the binary data for output to file * * @return the password hash */ public int getPasswordHash() { return passwordHash; } } jexcelapi/src/jxl/read/biff/TemplateRecord.java0000750000175000017500000000274211207000612021670 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2009 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.common.Logger; import jxl.biff.RecordData; /** * A template record */ class TemplateRecord extends RecordData { /** * The logger */ private static Logger logger = Logger.getLogger(TemplateRecord.class); /** * The template */ private boolean template; /** * Constructor * * @param t the record */ public TemplateRecord(Record t) { super(t); template = true; } /** * Accessor for the template mode * * @return the template mode */ public boolean getTemplate() { return template; } } jexcelapi/src/jxl/read/biff/NumberFormulaRecord.java0000750000175000017500000001123411207000612022667 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import java.text.DecimalFormat; import java.text.NumberFormat; import jxl.common.Logger; import jxl.CellType; import jxl.NumberCell; import jxl.NumberFormulaCell; import jxl.biff.DoubleHelper; import jxl.biff.FormattingRecords; import jxl.biff.FormulaData; import jxl.biff.WorkbookMethods; import jxl.biff.formula.ExternalSheet; import jxl.biff.formula.FormulaException; import jxl.biff.formula.FormulaParser; /** * A formula's last calculated value */ class NumberFormulaRecord extends CellValue implements NumberCell, FormulaData, NumberFormulaCell { /** * The logger */ private static Logger logger = Logger.getLogger(NumberFormulaRecord.class); /** * The last calculated value of the formula */ private double value; /** * The number format */ private NumberFormat format; /** * The string format for the double value */ private static final DecimalFormat defaultFormat = new DecimalFormat("#.###"); /** * The formula as an excel string */ private String formulaString; /** * A handle to the class needed to access external sheets */ private ExternalSheet externalSheet; /** * A handle to the name table */ private WorkbookMethods nameTable; /** * The raw data */ private byte[] data; /** * Constructs this object from the raw data * * @param t the raw data * @param fr the formatting record * @param es the external sheet * @param nt the name table * @param si the sheet */ public NumberFormulaRecord(Record t, FormattingRecords fr, ExternalSheet es, WorkbookMethods nt, SheetImpl si) { super(t, fr, si); externalSheet = es; nameTable = nt; data = getRecord().getData(); format = fr.getNumberFormat(getXFIndex()); if (format == null) { format = defaultFormat; } value = DoubleHelper.getIEEEDouble(data, 6); } /** * Interface method which returns the value * * @return the last calculated value of the formula */ public double getValue() { return value; } /** * Returns the numerical value as a string * * @return The numerical value of the formula as a string */ public String getContents() { return !Double.isNaN(value) ? format.format(value) : ""; } /** * Returns the cell type * * @return The cell type */ public CellType getType() { return CellType.NUMBER_FORMULA; } /** * Gets the raw bytes for the formula. This will include the * parsed tokens array. Used when copying spreadsheets * * @return the raw record data */ public byte[] getFormulaData() throws FormulaException { if (!getSheet().getWorkbookBof().isBiff8()) { throw new FormulaException(FormulaException.BIFF8_SUPPORTED); } // Lop off the standard information byte[] d = new byte[data.length - 6]; System.arraycopy(data, 6, d, 0, data.length - 6); return d; } /** * Gets the formula as an excel string * * @return the formula as an excel string * @exception FormulaException */ public String getFormula() throws FormulaException { if (formulaString == null) { byte[] tokens = new byte[data.length - 22]; System.arraycopy(data, 22, tokens, 0, tokens.length); FormulaParser fp = new FormulaParser (tokens, this, externalSheet, nameTable, getSheet().getWorkbook().getSettings()); fp.parse(); formulaString = fp.getFormula(); } return formulaString; } /** * Gets the NumberFormat used to format this cell. This is the java * equivalent of the Excel format * * @return the NumberFormat used to format the cell */ public NumberFormat getNumberFormat() { return format; } } jexcelapi/src/jxl/read/biff/SheetImpl.java0000750000175000017500000007274111207000612020656 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import java.util.ArrayList; import java.util.Iterator; import java.util.regex.Pattern; import jxl.common.Logger; import jxl.common.Assert; import jxl.Cell; import jxl.CellType; import jxl.CellView; import jxl.Hyperlink; import jxl.Image; import jxl.LabelCell; import jxl.Range; import jxl.Sheet; import jxl.SheetSettings; import jxl.WorkbookSettings; import jxl.biff.BuiltInName; import jxl.biff.AutoFilter; import jxl.biff.CellFinder; import jxl.biff.CellReferenceHelper; import jxl.biff.ConditionalFormat; import jxl.biff.DataValidation; import jxl.biff.EmptyCell; import jxl.biff.FormattingRecords; import jxl.biff.Type; import jxl.biff.WorkspaceInformationRecord; import jxl.biff.drawing.Chart; import jxl.biff.drawing.Drawing; import jxl.biff.drawing.DrawingData; import jxl.biff.drawing.DrawingGroupObject; import jxl.format.CellFormat; /** * Represents a sheet within a workbook. Provides a handle to the individual * cells, or lines of cells (grouped by Row or Column) * In order to simplify this class due to code bloat, the actual reading * logic has been delegated to the SheetReaderClass. This class' main * responsibility is now to implement the API methods declared in the * Sheet interface */ public class SheetImpl implements Sheet { /** * The logger */ private static Logger logger = Logger.getLogger(SheetImpl.class); /** * The excel file */ private File excelFile; /** * A handle to the shared string table */ private SSTRecord sharedStrings; /** * A handle to the sheet BOF record, which indicates the stream type */ private BOFRecord sheetBof; /** * A handle to the workbook BOF record, which indicates the stream type */ private BOFRecord workbookBof; /** * A handle to the formatting records */ private FormattingRecords formattingRecords; /** * The name of this sheet */ private String name; /** * The number of rows */ private int numRows; /** * The number of columns */ private int numCols; /** * The cells */ private Cell[][] cells; /** * The start position in the stream of this sheet */ private int startPosition; /** * The list of specified (ie. non default) column widths */ private ColumnInfoRecord[] columnInfos; /** * The array of row records */ private RowRecord[] rowRecords; /** * The list of non-default row properties */ private ArrayList rowProperties; /** * An array of column info records. They are held this way before * they are transferred to the more convenient array */ private ArrayList columnInfosArray; /** * A list of shared formula groups */ private ArrayList sharedFormulas; /** * A list of hyperlinks on this page */ private ArrayList hyperlinks; /** * A list of charts on this page */ private ArrayList charts; /** * A list of drawings on this page */ private ArrayList drawings; /** * A list of drawings (as opposed to comments/validation/charts) on this * page */ private ArrayList images; /** * A list of data validations on this page */ private DataValidation dataValidation; /** * A list of merged cells on this page */ private Range[] mergedCells; /** * Indicates whether the columnInfos array has been initialized */ private boolean columnInfosInitialized; /** * Indicates whether the rowRecords array has been initialized */ private boolean rowRecordsInitialized; /** * Indicates whether or not the dates are based around the 1904 date system */ private boolean nineteenFour; /** * The workspace options */ private WorkspaceInformationRecord workspaceOptions; /** * The hidden flag */ private boolean hidden; /** * The environment specific print record */ private PLSRecord plsRecord; /** * The property set record associated with this workbook */ private ButtonPropertySetRecord buttonPropertySet; /** * The sheet settings */ private SheetSettings settings; /** * The horizontal page breaks contained on this sheet */ private int[] rowBreaks; /** * The vertical page breaks contained on this sheet */ private int[] columnBreaks; /** * The maximum row outline level */ private int maxRowOutlineLevel; /** * The maximum column outline level */ private int maxColumnOutlineLevel; /** * The list of local names for this sheet */ private ArrayList localNames; /** * The list of conditional formats for this sheet */ private ArrayList conditionalFormats; /** * The autofilter information */ private AutoFilter autoFilter; /** * A handle to the workbook which contains this sheet. Some of the records * need this in order to reference external sheets */ private WorkbookParser workbook; /** * A handle to the workbook settings */ private WorkbookSettings workbookSettings; /** * Constructor * * @param f the excel file * @param sst the shared string table * @param fr formatting records * @param sb the bof record which indicates the start of the sheet * @param wb the bof record which indicates the start of the sheet * @param nf the 1904 flag * @param wp the workbook which this sheet belongs to * @exception BiffException */ SheetImpl(File f, SSTRecord sst, FormattingRecords fr, BOFRecord sb, BOFRecord wb, boolean nf, WorkbookParser wp) throws BiffException { excelFile = f; sharedStrings = sst; formattingRecords = fr; sheetBof = sb; workbookBof = wb; columnInfosArray = new ArrayList(); sharedFormulas = new ArrayList(); hyperlinks = new ArrayList(); rowProperties = new ArrayList(10); columnInfosInitialized = false; rowRecordsInitialized = false; nineteenFour = nf; workbook = wp; workbookSettings = workbook.getSettings(); // Mark the position in the stream, and then skip on until the end startPosition = f.getPos(); if (sheetBof.isChart()) { // Set the start pos to include the bof so the sheet reader can handle it startPosition -= (sheetBof.getLength() + 4); } Record r = null; int bofs = 1; while (bofs >= 1) { r = f.next(); // use this form for quick performance if (r.getCode() == Type.EOF.value) { bofs--; } if (r.getCode() == Type.BOF.value) { bofs++; } } } /** * Returns the cell for the specified location eg. "A4", using the * CellReferenceHelper * * @param loc the cell reference * @return the cell at the specified co-ordinates */ public Cell getCell(String loc) { return getCell(CellReferenceHelper.getColumn(loc), CellReferenceHelper.getRow(loc)); } /** * Returns the cell specified at this row and at this column * * @param row the row number * @param column the column number * @return the cell at the specified co-ordinates */ public Cell getCell(int column, int row) { // just in case this has been cleared, but something else holds // a reference to it if (cells == null) { readSheet(); } Cell c = cells[row][column]; if (c == null) { c = new EmptyCell(column, row); cells[row][column] = c; } return c; } /** * Gets the cell whose contents match the string passed in. * If no match is found, then null is returned. The search is performed * on a row by row basis, so the lower the row number, the more * efficiently the algorithm will perform * * @param contents the string to match * @return the Cell whose contents match the paramter, null if not found */ public Cell findCell(String contents) { CellFinder cellFinder = new CellFinder(this); return cellFinder.findCell(contents); } /** * Gets the cell whose contents match the string passed in. * If no match is found, then null is returned. The search is performed * on a row by row basis, so the lower the row number, the more * efficiently the algorithm will perform * * @param contents the string to match * @param firstCol the first column within the range * @param firstRow the first row of the range * @param lastCol the last column within the range * @param lastRow the last row within the range * @param reverse indicates whether to perform a reverse search or not * @return the Cell whose contents match the parameter, null if not found */ public Cell findCell(String contents, int firstCol, int firstRow, int lastCol, int lastRow, boolean reverse) { CellFinder cellFinder = new CellFinder(this); return cellFinder.findCell(contents, firstCol, firstRow, lastCol, lastRow, reverse); } /** * Gets the cell whose contents match the regular expressionstring passed in. * If no match is found, then null is returned. The search is performed * on a row by row basis, so the lower the row number, the more * efficiently the algorithm will perform * * @param pattern the regular expression string to match * @param firstCol the first column within the range * @param firstRow the first row of the range * @param lastRow the last row within the range * @param lastCol the last column within the ranage * @param reverse indicates whether to perform a reverse search or not * @return the Cell whose contents match the parameter, null if not found */ public Cell findCell(Pattern pattern, int firstCol, int firstRow, int lastCol, int lastRow, boolean reverse) { CellFinder cellFinder = new CellFinder(this); return cellFinder.findCell(pattern, firstCol, firstRow, lastCol, lastRow, reverse); } /** * Gets the cell whose contents match the string passed in. * If no match is found, then null is returned. The search is performed * on a row by row basis, so the lower the row number, the more * efficiently the algorithm will perform. This method differs * from the findCell methods in that only cells with labels are * queried - all numerical cells are ignored. This should therefore * improve performance. * * @param contents the string to match * @return the Cell whose contents match the paramter, null if not found */ public LabelCell findLabelCell(String contents) { CellFinder cellFinder = new CellFinder(this); return cellFinder.findLabelCell(contents); } /** * Returns the number of rows in this sheet * * @return the number of rows in this sheet */ public int getRows() { // just in case this has been cleared, but something else holds // a reference to it if (cells == null) { readSheet(); } return numRows; } /** * Returns the number of columns in this sheet * * @return the number of columns in this sheet */ public int getColumns() { // just in case this has been cleared, but something else holds // a reference to it if (cells == null) { readSheet(); } return numCols; } /** * Gets all the cells on the specified row. The returned array will * be stripped of all trailing empty cells * * @param row the rows whose cells are to be returned * @return the cells on the given row */ public Cell[] getRow(int row) { // just in case this has been cleared, but something else holds // a reference to it if (cells == null) { readSheet(); } // Find the last non-null cell boolean found = false; int col = numCols - 1; while (col >= 0 && !found) { if (cells[row][col] != null) { found = true; } else { col--; } } // Only create entries for non-null cells Cell[] c = new Cell[col + 1]; for (int i = 0; i <= col; i++) { c[i] = getCell(i, row); } return c; } /** * Gets all the cells on the specified column. The returned array * will be stripped of all trailing empty cells * * @param col the column whose cells are to be returned * @return the cells on the specified column */ public Cell[] getColumn(int col) { // just in case this has been cleared, but something else holds // a reference to it if (cells == null) { readSheet(); } // Find the last non-null cell boolean found = false; int row = numRows - 1; while (row >= 0 && !found) { if (cells[row][col] != null) { found = true; } else { row--; } } // Only create entries for non-null cells Cell[] c = new Cell[row + 1]; for (int i = 0; i <= row; i++) { c[i] = getCell(col, i); } return c; } /** * Gets the name of this sheet * * @return the name of the sheet */ public String getName() { return name; } /** * Sets the name of this sheet * * @param s the sheet name */ final void setName(String s) { name = s; } /** * Determines whether the sheet is hidden * * @return whether or not the sheet is hidden * @deprecated in favour of the getSettings function */ public boolean isHidden() { return hidden; } /** * Gets the column info record for the specified column. If no * column is specified, null is returned * * @param col the column * @return the ColumnInfoRecord if specified, NULL otherwise */ public ColumnInfoRecord getColumnInfo(int col) { if (!columnInfosInitialized) { // Initialize the array Iterator i = columnInfosArray.iterator(); ColumnInfoRecord cir = null; while (i.hasNext()) { cir = (ColumnInfoRecord) i.next(); int startcol = Math.max(0, cir.getStartColumn()); int endcol = Math.min(columnInfos.length - 1, cir.getEndColumn()); for (int c = startcol; c <= endcol; c++) { columnInfos[c] = cir; } if (endcol < startcol) { columnInfos[startcol] = cir; } } columnInfosInitialized = true; } return col < columnInfos.length ? columnInfos[col] : null; } /** * Gets all the column info records * * @return the ColumnInfoRecordArray */ public ColumnInfoRecord[] getColumnInfos() { // Just chuck all the column infos we have into an array ColumnInfoRecord[] infos = new ColumnInfoRecord[columnInfosArray.size()]; for (int i = 0; i < columnInfosArray.size(); i++) { infos[i] = (ColumnInfoRecord) columnInfosArray.get(i); } return infos; } /** * Sets the visibility of this sheet * * @param h hidden flag */ final void setHidden(boolean h) { hidden = h; } /** * Clears out the array of cells. This is done for memory allocation * reasons when reading very large sheets */ final void clear() { cells = null; mergedCells = null; columnInfosArray.clear(); sharedFormulas.clear(); hyperlinks.clear(); columnInfosInitialized = false; if (!workbookSettings.getGCDisabled()) { System.gc(); } } /** * Reads in the contents of this sheet */ final void readSheet() { // If this sheet contains only a chart, then set everything to // empty and do not bother parsing the sheet // Thanks to steve.brophy for spotting this if (!sheetBof.isWorksheet()) { numRows = 0; numCols = 0; cells = new Cell[0][0]; // return; } SheetReader reader = new SheetReader(excelFile, sharedStrings, formattingRecords, sheetBof, workbookBof, nineteenFour, workbook, startPosition, this); reader.read(); // Take stuff that was read in numRows = reader.getNumRows(); numCols = reader.getNumCols(); cells = reader.getCells(); rowProperties = reader.getRowProperties(); columnInfosArray = reader.getColumnInfosArray(); hyperlinks = reader.getHyperlinks(); conditionalFormats = reader.getConditionalFormats(); autoFilter = reader.getAutoFilter(); charts = reader.getCharts(); drawings = reader.getDrawings(); dataValidation = reader.getDataValidation(); mergedCells = reader.getMergedCells(); settings = reader.getSettings(); settings.setHidden(hidden); rowBreaks = reader.getRowBreaks(); columnBreaks = reader.getColumnBreaks(); workspaceOptions = reader.getWorkspaceOptions(); plsRecord = reader.getPLS(); buttonPropertySet = reader.getButtonPropertySet(); maxRowOutlineLevel = reader.getMaxRowOutlineLevel(); maxColumnOutlineLevel = reader.getMaxColumnOutlineLevel(); reader = null; if (!workbookSettings.getGCDisabled()) { System.gc(); } if (columnInfosArray.size() > 0) { ColumnInfoRecord cir = (ColumnInfoRecord) columnInfosArray.get(columnInfosArray.size() - 1); columnInfos = new ColumnInfoRecord[cir.getEndColumn() + 1]; } else { columnInfos = new ColumnInfoRecord[0]; } // Add any local names if (localNames != null) { for (Iterator it = localNames.iterator(); it.hasNext() ;) { NameRecord nr = (NameRecord) it.next(); if (nr.getBuiltInName() == BuiltInName.PRINT_AREA) { if(nr.getRanges().length > 0) { NameRecord.NameRange rng = nr.getRanges()[0]; settings.setPrintArea(rng.getFirstColumn(), rng.getFirstRow(), rng.getLastColumn(), rng.getLastRow()); } } else if (nr.getBuiltInName() == BuiltInName.PRINT_TITLES) { // There can be 1 or 2 entries. // Row entries have hardwired column entries (first and last // possible column) // Column entries have hardwired row entries (first and last // possible row) for (int i = 0 ; i < nr.getRanges().length ; i++) { NameRecord.NameRange rng = nr.getRanges()[i]; if (rng.getFirstColumn() == 0 && rng.getLastColumn() == 255) { settings.setPrintTitlesRow(rng.getFirstRow(), rng.getLastRow()); } else { settings.setPrintTitlesCol(rng.getFirstColumn(), rng.getLastColumn()); } } } } } } /** * Gets the hyperlinks on this sheet * * @return an array of hyperlinks */ public Hyperlink[] getHyperlinks() { Hyperlink[] hl = new Hyperlink[hyperlinks.size()]; for (int i = 0; i < hyperlinks.size(); i++) { hl[i] = (Hyperlink) hyperlinks.get(i); } return hl; } /** * Gets the cells which have been merged on this sheet * * @return an array of range objects */ public Range[] getMergedCells() { if (mergedCells == null) { return new Range[0]; } return mergedCells; } /** * Gets the non-default rows. Used when copying spreadsheets * * @return an array of row properties */ public RowRecord[] getRowProperties() { RowRecord[] rp = new RowRecord[rowProperties.size()]; for (int i = 0; i < rp.length; i++) { rp[i] = (RowRecord) rowProperties.get(i); } return rp; } /** * Gets the data validations. Used when copying sheets * * @return the data validations */ public DataValidation getDataValidation() { return dataValidation; } /** * Gets the row record. Usually called by the cell in the specified * row in order to determine its size * * @param r the row * @return the RowRecord for the specified row */ RowRecord getRowInfo(int r) { if (!rowRecordsInitialized) { rowRecords = new RowRecord[getRows()]; Iterator i = rowProperties.iterator(); int rownum = 0; RowRecord rr = null; while (i.hasNext()) { rr = (RowRecord) i.next(); rownum = rr.getRowNumber(); if (rownum < rowRecords.length) { rowRecords[rownum] = rr; } } rowRecordsInitialized = true; } return r < rowRecords.length ? rowRecords[r] : null; } /** * Gets the row breaks. Called when copying sheets * * @return the explicit row breaks */ public final int[] getRowPageBreaks() { return rowBreaks; } /** * Gets the row breaks. Called when copying sheets * * @return the explicit row breaks */ public final int[] getColumnPageBreaks() { return columnBreaks; } /** * Gets the charts. Called when copying sheets * * @return the charts on this page */ public final Chart[] getCharts() { Chart[] ch = new Chart[charts.size()]; for (int i = 0; i < ch.length; i++) { ch[i] = (Chart) charts.get(i); } return ch; } /** * Gets the drawings. Called when copying sheets * * @return the drawings on this page */ public final DrawingGroupObject[] getDrawings() { DrawingGroupObject[] dr = new DrawingGroupObject[drawings.size()]; dr = (DrawingGroupObject[]) drawings.toArray(dr); return dr; } /** * Determines whether the sheet is protected * * @return whether or not the sheet is protected * @deprecated in favour of the getSettings() api */ public boolean isProtected() { return settings.isProtected(); } /** * Gets the workspace options for this sheet. Called during the copy * process * * @return the workspace options */ public WorkspaceInformationRecord getWorkspaceOptions() { return workspaceOptions; } /** * Accessor for the sheet settings * * @return the settings for this sheet */ public SheetSettings getSettings() { return settings; } /** * Accessor for the workbook. In addition to be being used by this package, * it is also used during the importSheet process * * @return the workbook */ public WorkbookParser getWorkbook() { return workbook; } /** * Gets the column format for the specified column * * @param col the column number * @return the column format, or NULL if the column has no specific format * @deprecated use getColumnView instead */ public CellFormat getColumnFormat(int col) { CellView cv = getColumnView(col); return cv.getFormat(); } /** * Gets the column width for the specified column * * @param col the column number * @return the column width, or the default width if the column has no * specified format */ public int getColumnWidth(int col) { return getColumnView(col).getSize() / 256; } /** * Gets the column width for the specified column * * @param col the column number * @return the column format, or the default format if no override is specified */ public CellView getColumnView(int col) { ColumnInfoRecord cir = getColumnInfo(col); CellView cv = new CellView(); if (cir != null) { cv.setDimension(cir.getWidth() / 256); //deprecated cv.setSize(cir.getWidth()); cv.setHidden(cir.getHidden()); cv.setFormat(formattingRecords.getXFRecord(cir.getXFIndex())); } else { cv.setDimension(settings.getDefaultColumnWidth()); //deprecated cv.setSize(settings.getDefaultColumnWidth() * 256); } return cv; } /** * Gets the row height for the specified column * * @param row the row number * @return the row height, or the default height if the row has no * specified format * @deprecated use getRowView instead */ public int getRowHeight(int row) { return getRowView(row).getDimension(); } /** * Gets the row view for the specified row * * @param row the row number * @return the row format, or the default format if no override is specified */ public CellView getRowView(int row) { RowRecord rr = getRowInfo(row); CellView cv = new CellView(); if (rr != null) { cv.setDimension(rr.getRowHeight()); //deprecated cv.setSize(rr.getRowHeight()); cv.setHidden(rr.isCollapsed()); if (rr.hasDefaultFormat()) { cv.setFormat(formattingRecords.getXFRecord(rr.getXFIndex())); } } else { cv.setDimension(settings.getDefaultRowHeight()); cv.setSize(settings.getDefaultRowHeight()); //deprecated } return cv; } /** * Used when copying sheets in order to determine the type of this sheet * * @return the BOF Record */ public BOFRecord getSheetBof() { return sheetBof; } /** * Used when copying sheets in order to determine the type of the containing * workboook * * @return the workbook BOF Record */ public BOFRecord getWorkbookBof() { return workbookBof; } /** * Accessor for the environment specific print record, invoked when * copying sheets * * @return the environment specific print record */ public PLSRecord getPLS() { return plsRecord; } /** * Accessor for the button property set, used during copying * * @return the button property set */ public ButtonPropertySetRecord getButtonPropertySet() { return buttonPropertySet; } /** * Accessor for the number of images on the sheet * * @return the number of images on this sheet */ public int getNumberOfImages() { if (images == null) { initializeImages(); } return images.size(); } /** * Accessor for the image * * @param i the 0 based image number * @return the image at the specified position */ public Image getDrawing(int i) { if (images == null) { initializeImages(); } return (Image) images.get(i); } /** * Initializes the images */ private void initializeImages() { if (images != null) { return; } images = new ArrayList(); DrawingGroupObject[] dgos = getDrawings(); for (int i = 0; i < dgos.length; i++) { if (dgos[i] instanceof Drawing) { images.add(dgos[i]); } } } /** * Used by one of the demo programs for debugging purposes only */ public DrawingData getDrawingData() { SheetReader reader = new SheetReader(excelFile, sharedStrings, formattingRecords, sheetBof, workbookBof, nineteenFour, workbook, startPosition, this); reader.read(); return reader.getDrawingData(); } /** * Adds a local name to this shate * * @param nr the local name to add */ void addLocalName(NameRecord nr) { if (localNames == null) { localNames = new ArrayList(); } localNames.add(nr); } /** * Gets the conditional formats * * @return the conditional formats */ public ConditionalFormat[] getConditionalFormats() { ConditionalFormat[] formats = new ConditionalFormat[conditionalFormats.size()]; formats = (ConditionalFormat[]) conditionalFormats.toArray(formats); return formats; } /** * Returns the autofilter * * @return the autofilter */ public AutoFilter getAutoFilter() { return autoFilter; } /** * Accessor for the maximum column outline level. Used during a copy * * @return the maximum column outline level, or 0 if no outlines/groups */ public int getMaxColumnOutlineLevel() { return maxColumnOutlineLevel; } /** * Accessor for the maximum row outline level. Used during a copy * * @return the maximum row outline level, or 0 if no outlines/groups */ public int getMaxRowOutlineLevel() { return maxRowOutlineLevel; } } jexcelapi/src/jxl/read/biff/SharedFormulaRecord.java0000750000175000017500000001357411207000612022656 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import java.text.NumberFormat; import java.util.ArrayList; import jxl.common.Logger; import jxl.Cell; import jxl.CellType; import jxl.biff.FormattingRecords; import jxl.biff.IntegerHelper; import jxl.biff.WorkbookMethods; import jxl.biff.formula.ExternalSheet; /** * A shared formula */ class SharedFormulaRecord { /** * The logger */ private static Logger logger = Logger.getLogger(SharedFormulaRecord.class); /** * The first row to which this shared formula applies */ private int firstRow; /** * The last row to which this shared formula applies */ private int lastRow; /** * The first column to which this shared formula applies */ private int firstCol; /** * The last column to which this shared formula applies */ private int lastCol; /** * The first (template) formula comprising this group */ private BaseSharedFormulaRecord templateFormula; /** * The rest of the cells comprising this shared formula */ private ArrayList formulas; /** * The token data */ private byte[] tokens; /** * A handle to the external sheet */ private ExternalSheet externalSheet; /** * A handle to the sheet */ private SheetImpl sheet; /** * Constructs this object from the raw data. Creates either a * NumberFormulaRecord or a StringFormulaRecord depending on whether * this formula represents a numerical calculation or not * * @param t the raw data * @param fr the base shared formula * @param es the workbook, which contains the external sheet references * @param nt the workbook * @param si the sheet */ public SharedFormulaRecord(Record t, BaseSharedFormulaRecord fr, ExternalSheet es, WorkbookMethods nt, SheetImpl si) { sheet = si; byte[] data = t.getData(); firstRow = IntegerHelper.getInt(data[0], data[1]); lastRow = IntegerHelper.getInt(data[2], data[3]); firstCol = data[4] & 0xff; lastCol = data[5] & 0xff; formulas = new ArrayList(); templateFormula = fr; tokens = new byte[data.length - 10]; System.arraycopy(data, 10, tokens, 0, tokens.length); } /** * Adds this formula to the list of formulas, if it falls within * the bounds * * @param fr the formula record to test for membership of this group * @return TRUE if the formulas was added, FALSE otherwise */ public boolean add(BaseSharedFormulaRecord fr) { boolean added = false; int r = fr.getRow(); if (r >= firstRow && r <= lastRow) { int c = fr.getColumn(); if (c >= firstCol && c <= lastCol) { formulas.add(fr); added = true; } } return added; } /** * Manufactures individual cell formulas out the whole shared formula * debacle * * @param fr the formatting records * @param nf flag indicating whether this uses the 1904 date system * @return an array of formulas to be added to the sheet */ Cell[] getFormulas(FormattingRecords fr, boolean nf) { Cell[] sfs = new Cell[formulas.size() + 1]; // This can happen if there are many identical formulas in the // sheet and excel has not sliced and diced them exclusively if (templateFormula == null) { logger.warn("Shared formula template formula is null"); return new Cell[0]; } templateFormula.setTokens(tokens); NumberFormat templateNumberFormat = null; // See if the template formula evaluates to date if (templateFormula.getType() == CellType.NUMBER_FORMULA) { SharedNumberFormulaRecord snfr = (SharedNumberFormulaRecord) templateFormula; templateNumberFormat = snfr.getNumberFormat(); if (fr.isDate(templateFormula.getXFIndex())) { templateFormula = new SharedDateFormulaRecord(snfr, fr, nf, sheet, snfr.getFilePos()); templateFormula.setTokens(snfr.getTokens()); } } sfs[0] = templateFormula; BaseSharedFormulaRecord f = null; for (int i = 0; i < formulas.size(); i++) { f = (BaseSharedFormulaRecord) formulas.get(i); // See if the formula evaluates to date if (f.getType() == CellType.NUMBER_FORMULA) { SharedNumberFormulaRecord snfr = (SharedNumberFormulaRecord) f; if (fr.isDate(f.getXFIndex())) { f = new SharedDateFormulaRecord(snfr, fr, nf, sheet, snfr.getFilePos()); } else { ;// snfr.setNumberFormat(templateNumberFormat); } } f.setTokens(tokens); sfs[i + 1] = f; } return sfs; } /** * Accessor for the template formula. Called when a shared formula has, * for some reason, specified an inappropriate range and it is necessary * to retrieve the template from a previously available shared formula */ BaseSharedFormulaRecord getTemplateFormula() { return templateFormula; } } jexcelapi/src/jxl/read/biff/Excel9FileRecord.java0000750000175000017500000000276211207000612022050 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2009 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.common.Logger; import jxl.biff.RecordData; /** * A excel9file record */ class Excel9FileRecord extends RecordData { /** * The logger */ private static Logger logger = Logger.getLogger(Excel9FileRecord.class); /** * The template */ private boolean excel9file; /** * Constructor * * @param t the record */ public Excel9FileRecord(Record t) { super(t); excel9file = true; } /** * Accessor for the template mode * * @return the template mode */ public boolean getExcel9File() { return excel9file; } } jexcelapi/src/jxl/read/biff/TopMarginRecord.java0000750000175000017500000000222511207000612022011 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.biff.Type; /** * Record for the left margin settings */ class TopMarginRecord extends MarginRecord { /** * Constructor * @param r the record */ TopMarginRecord(Record r) { super(Type.TOPMARGIN, r); } } jexcelapi/src/jxl/read/biff/Formula.java0000750000175000017500000000236711207000610020364 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.Cell; /** * Interface which is used for copying formulas from a read only * to a writable spreadsheet */ public interface Formula extends Cell { /** * Gets the raw bytes for the formula. This will include the * parsed tokens array * * @return the raw record data */ public byte[] getFormulaData(); } jexcelapi/src/jxl/read/biff/SharedErrorFormulaRecord.java0000750000175000017500000001140711207000612023661 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2005 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.common.Logger; import jxl.CellType; import jxl.ErrorCell; import jxl.ErrorFormulaCell; import jxl.biff.FormattingRecords; import jxl.biff.FormulaData; import jxl.biff.IntegerHelper; import jxl.biff.WorkbookMethods; import jxl.biff.formula.ExternalSheet; import jxl.biff.formula.FormulaErrorCode; import jxl.biff.formula.FormulaException; import jxl.biff.formula.FormulaParser; /** * A number formula record, manufactured out of the Shared Formula * "optimization" */ public class SharedErrorFormulaRecord extends BaseSharedFormulaRecord implements ErrorCell, FormulaData, ErrorFormulaCell { /** * The logger */ private static Logger logger = Logger.getLogger(SharedErrorFormulaRecord.class); /** * The error code of this cell */ private int errorCode; /** * The raw data */ private byte[] data; /** * The error code */ private FormulaErrorCode error; /** * Constructs this number * * @param t the data * @param excelFile the excel biff data * @param v the errorCode * @param fr the formatting records * @param es the external sheet * @param nt the name table * @param si the sheet */ public SharedErrorFormulaRecord(Record t, File excelFile, int ec, FormattingRecords fr, ExternalSheet es, WorkbookMethods nt, SheetImpl si) { super(t, fr, es, nt, si, excelFile.getPos()); errorCode = ec; } /** * Interface method which gets the error code for this cell. If this cell * does not represent an error, then it returns 0. Always use the * method isError() to determine this prior to calling this method * * @return the error code if this cell contains an error, 0 otherwise */ public int getErrorCode() { return errorCode; } /** * Returns the numerical value as a string * * @return The numerical value of the formula as a string */ public String getContents() { if (error == null) { error = FormulaErrorCode.getErrorCode(errorCode); } return error != FormulaErrorCode.UNKNOWN ? error.getDescription() : "ERROR " + errorCode; } /** * Accessor for the cell type * * @return the cell type */ public CellType getType() { return CellType.FORMULA_ERROR; } /** * Gets the raw bytes for the formula. This will include the * parsed tokens array. Used when copying spreadsheets * * @return the raw record data * @exception FormulaException */ public byte[] getFormulaData() throws FormulaException { if (!getSheet().getWorkbookBof().isBiff8()) { throw new FormulaException(FormulaException.BIFF8_SUPPORTED); } // Get the tokens, taking into account the mapping from shared // formula specific values into normal values FormulaParser fp = new FormulaParser (getTokens(), this, getExternalSheet(), getNameTable(), getSheet().getWorkbook().getSettings()); fp.parse(); byte[] rpnTokens = fp.getBytes(); byte[] data = new byte[rpnTokens.length + 22]; // Set the standard info for this cell IntegerHelper.getTwoBytes(getRow(), data, 0); IntegerHelper.getTwoBytes(getColumn(), data, 2); IntegerHelper.getTwoBytes(getXFIndex(), data, 4); data[6] = (byte) 0x02; // indicates this cell is an error value data[8] = (byte) errorCode; data[12] = (byte) 0xff; data[13] = (byte) 0xff; // Now copy in the parsed tokens System.arraycopy(rpnTokens, 0, data, 22, rpnTokens.length); IntegerHelper.getTwoBytes(rpnTokens.length, data, 20); // Lop off the standard information byte[] d = new byte[data.length - 6]; System.arraycopy(data, 6, d, 0, data.length - 6); return d; } } jexcelapi/src/jxl/read/biff/PrintHeadersRecord.java0000750000175000017500000000303411207000612022500 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.biff.RecordData; /** * Contains the print grid lines option of this worksheet */ class PrintHeadersRecord extends RecordData { /** * print grid lines flag */ private boolean printHeaders; /** * Constructs the value from the raw data * * @param ph the raw data */ public PrintHeadersRecord(Record ph) { super(ph); byte[] data = ph.getData(); printHeaders = (data[0] == 1 ? true : false); } /** * Accessor for the print headers flag * * @return TRUE to print headers, FALSE otherwise */ public boolean getPrintHeaders() { return printHeaders; } } jexcelapi/src/jxl/read/biff/LeftMarginRecord.java0000750000175000017500000000224111207000612022137 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.biff.Type; /** * Record for the left margin settings */ class LeftMarginRecord extends MarginRecord { /** * Constructor * * @param r the raw record */ LeftMarginRecord(Record r) { super(Type.LEFTMARGIN, r); } } jexcelapi/src/jxl/read/biff/DateRecord.java0000750000175000017500000002022411207000610020763 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import java.util.TimeZone; import jxl.common.Assert; import jxl.common.Logger; import jxl.CellFeatures; import jxl.CellType; import jxl.DateCell; import jxl.NumberCell; import jxl.biff.FormattingRecords; import jxl.format.CellFormat; /** * A date which is stored in the cell */ class DateRecord implements DateCell, CellFeaturesAccessor { /** * The logger */ private static Logger logger = Logger.getLogger(DateRecord.class); /** * The date represented within this cell */ private Date date; /** * The row number of this cell record */ private int row; /** * The column number of this cell record */ private int column; /** * Indicates whether this is a full date, or merely a time */ private boolean time; /** * The format to use when displaying this cell's contents as a string */ private DateFormat format; /** * The raw cell format */ private CellFormat cellFormat; /** * The index to the XF Record */ private int xfIndex; /** * A handle to the formatting records */ private FormattingRecords formattingRecords; /** * A handle to the sheet */ private SheetImpl sheet; /** * The cell features */ private CellFeatures features; /** * A flag to indicate whether this objects formatting things have * been initialized */ private boolean initialized; // The default formats used when returning the date as a string private static final SimpleDateFormat dateFormat = new SimpleDateFormat("dd MMM yyyy"); private static final SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss"); // The number of days between 1 Jan 1900 and 1 March 1900. Excel thinks // the day before this was 29th Feb 1900, but it was 28th Feb 1900. // I guess the programmers thought nobody would notice that they // couldn't be bothered to program this dating anomaly properly private static final int nonLeapDay = 61; private static final TimeZone gmtZone = TimeZone.getTimeZone("GMT"); // The number of days between 01 Jan 1900 and 01 Jan 1970 - this gives // the UTC offset private static final int utcOffsetDays = 25569; // The number of days between 01 Jan 1904 and 01 Jan 1970 - this gives // the UTC offset using the 1904 date system private static final int utcOffsetDays1904 = 24107; // The number of milliseconds in a day private static final long secondsInADay = 24 * 60 * 60; private static final long msInASecond = 1000; private static final long msInADay = secondsInADay * msInASecond; /** * Constructs this object from the raw data * * @param num the numerical representation of this * @param xfi the java equivalent of the excel date format * @param fr the formatting records * @param nf flag indicating whether we are using the 1904 date system * @param si the sheet */ public DateRecord(NumberCell num, int xfi, FormattingRecords fr, boolean nf, SheetImpl si) { row = num.getRow(); column = num.getColumn(); xfIndex = xfi; formattingRecords = fr; sheet = si; initialized = false; format = formattingRecords.getDateFormat(xfIndex); // This value represents the number of days since 01 Jan 1900 double numValue = num.getValue(); if (Math.abs(numValue) < 1) { if (format == null) { format = timeFormat; } time = true; } else { if (format == null) { format = dateFormat; } time = false; } // Work round a bug in excel. Excel seems to think there is a date // called the 29th Feb, 1900 - but in actual fact this was not a leap year. // Therefore for values less than 61 in the 1900 date system, // add one to the numeric value if (!nf && !time && numValue < nonLeapDay) { numValue += 1; } // Get rid of any timezone adjustments - we are not interested // in automatic adjustments format.setTimeZone(gmtZone); // Convert this to the number of days since 01 Jan 1970 int offsetDays = nf ? utcOffsetDays1904 : utcOffsetDays; double utcDays = numValue - offsetDays; // Convert this into utc by multiplying by the number of milliseconds // in a day. Use the round function prior to ms conversion due // to a rounding feature of Excel (contributed by Jurgen long utcValue = Math.round(utcDays * secondsInADay) * msInASecond; date = new Date(utcValue); } /** * Interface method which returns the row number of this cell * * @return the zero base row number */ public final int getRow() { return row; } /** * Interface method which returns the column number of this cell * * @return the zero based column number */ public final int getColumn() { return column; } /** * Gets the date * * @return the date */ public Date getDate() { return date; } /** * Gets the cell contents as a string. This method will use the java * equivalent of the excel formatting string * * @return the label */ public String getContents() { return format.format(date); } /** * Accessor for the cell type * * @return the cell type */ public CellType getType() { return CellType.DATE; } /** * Indicates whether the date value contained in this cell refers to a date, * or merely a time * * @return TRUE if the value refers to a time */ public boolean isTime() { return time; } /** * Gets the DateFormat used to format the cell. This will normally be * the format specified in the excel spreadsheet, but in the event of any * difficulty parsing this, it will revert to the default date/time format. * * @return the DateFormat object used to format the date in the original * excel cell */ public DateFormat getDateFormat() { Assert.verify(format != null); return format; } /** * Gets the CellFormat object for this cell. Used by the WritableWorkbook * API * * @return the CellFormat used for this cell */ public CellFormat getCellFormat() { if (!initialized) { cellFormat = formattingRecords.getXFRecord(xfIndex); initialized = true; } return cellFormat; } /** * Determines whether or not this cell has been hidden * * @return TRUE if this cell has been hidden, FALSE otherwise */ public boolean isHidden() { ColumnInfoRecord cir = sheet.getColumnInfo(column); if (cir != null && cir.getWidth() == 0) { return true; } RowRecord rr = sheet.getRowInfo(row); if (rr != null && (rr.getRowHeight() == 0 || rr.isCollapsed())) { return true; } return false; } /** * Accessor for the sheet * * @return the containing sheet */ protected final SheetImpl getSheet() { return sheet; } /** * Accessor for the cell features * * @return the cell features or NULL if this cell doesn't have any */ public CellFeatures getCellFeatures() { return features; } /** * Sets the cell features * * @param cf the cell features */ public void setCellFeatures(CellFeatures cf) { features = cf; } } jexcelapi/src/jxl/read/biff/PLSRecord.java0000750000175000017500000000246711207000612020557 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.biff.RecordData; /** * The environment specific print record */ public class PLSRecord extends RecordData { /** * Constructs this object from the raw data * * @param r the raw data */ public PLSRecord(Record r) { super(r); } /** * Gets the data * * @return the binary data */ public byte[] getData() { return getRecord().getData(); } } jexcelapi/src/jxl/read/biff/RefreshAllRecord.java0000750000175000017500000000320011207000612022132 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2009 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.common.Logger; import jxl.biff.IntegerHelper; import jxl.biff.RecordData; /** * A Refresh all mode record */ class RefreshAllRecord extends RecordData { /** * The logger */ private static Logger logger = Logger.getLogger(RefreshAllRecord.class); /** * The refresh all mode */ private boolean refreshAll; /** * Constructor * * @param t the record */ public RefreshAllRecord(Record t) { super(t); byte[] data = t.getData(); int mode = IntegerHelper.getInt(data[0], data[1]); refreshAll = (mode == 1); } /** * Accessor for the refreshAll mode * * @return the refreshAll mode */ public boolean getRefreshAll() { return refreshAll; } } jexcelapi/src/jxl/read/biff/PaneRecord.java0000750000175000017500000000413711207000612021000 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.common.Logger; import jxl.biff.IntegerHelper; import jxl.biff.RecordData; /** * Contains the cell dimensions of this worksheet */ class PaneRecord extends RecordData { /** * The logger */ private static Logger logger = Logger.getLogger(PaneRecord.class); /** * The number of rows visible in the top left pane */ private int rowsVisible; /** * The number of columns visible in the top left pane */ private int columnsVisible; /** * Constructs the dimensions from the raw data * * @param t the raw data */ public PaneRecord(Record t) { super(t); byte[] data = t.getData(); columnsVisible = IntegerHelper.getInt(data[0], data[1]); rowsVisible = IntegerHelper.getInt(data[2], data[3]); } /** * Accessor for the number of rows in the top left pane * * @return the number of rows visible in the top left pane */ public final int getRowsVisible() { return rowsVisible; } /** * Accessor for the numbe rof columns visible in the top left pane * * @return the number of columns visible in the top left pane */ public final int getColumnsVisible() { return columnsVisible; } } jexcelapi/src/jxl/read/biff/CompoundFile.java0000750000175000017500000004015411207000610021337 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import java.util.ArrayList; import java.util.Iterator; import jxl.common.Logger; import jxl.WorkbookSettings; import jxl.biff.BaseCompoundFile; import jxl.biff.IntegerHelper; /** * Reads in and defrags an OLE compound compound file * (Made public only for the PropertySets demo) */ public final class CompoundFile extends BaseCompoundFile { /** * The logger */ private static Logger logger = Logger.getLogger(CompoundFile.class); /** * The original OLE stream, organized into blocks, which can * appear at any physical location in the file */ private byte[] data; /** * The number of blocks it takes to store the big block depot */ private int numBigBlockDepotBlocks; /** * The start block of the small block depot */ private int sbdStartBlock; /** * The start block of the root entry */ private int rootStartBlock; /** * The header extension block */ private int extensionBlock; /** * The number of header extension blocks */ private int numExtensionBlocks; /** * The root entry */ private byte[] rootEntry; /** * The sequence of blocks which comprise the big block chain */ private int[] bigBlockChain; /** * The sequence of blocks which comprise the small block chain */ private int[] smallBlockChain; /** * The chain of blocks which comprise the big block depot */ private int[] bigBlockDepotBlocks; /** * The list of property sets */ private ArrayList propertySets; /** * The workbook settings */ private WorkbookSettings settings; /** * The property storage root entry */ private PropertyStorage rootEntryPropertyStorage; /** * Initializes the compound file * * @param d the raw data of the ole stream * @param ws the workbook settings * @exception BiffException */ public CompoundFile(byte[] d, WorkbookSettings ws) throws BiffException { super(); data = d; settings = ws; // First verify the OLE identifier for (int i = 0; i < IDENTIFIER.length; i++) { if (data[i] != IDENTIFIER[i]) { throw new BiffException(BiffException.unrecognizedOLEFile); } } propertySets = new ArrayList(); numBigBlockDepotBlocks = IntegerHelper.getInt (data[NUM_BIG_BLOCK_DEPOT_BLOCKS_POS], data[NUM_BIG_BLOCK_DEPOT_BLOCKS_POS + 1], data[NUM_BIG_BLOCK_DEPOT_BLOCKS_POS + 2], data[NUM_BIG_BLOCK_DEPOT_BLOCKS_POS + 3]); sbdStartBlock = IntegerHelper.getInt (data[SMALL_BLOCK_DEPOT_BLOCK_POS], data[SMALL_BLOCK_DEPOT_BLOCK_POS + 1], data[SMALL_BLOCK_DEPOT_BLOCK_POS + 2], data[SMALL_BLOCK_DEPOT_BLOCK_POS + 3]); rootStartBlock = IntegerHelper.getInt (data[ROOT_START_BLOCK_POS], data[ROOT_START_BLOCK_POS + 1], data[ROOT_START_BLOCK_POS + 2], data[ROOT_START_BLOCK_POS + 3]); extensionBlock = IntegerHelper.getInt (data[EXTENSION_BLOCK_POS], data[EXTENSION_BLOCK_POS + 1], data[EXTENSION_BLOCK_POS + 2], data[EXTENSION_BLOCK_POS + 3]); numExtensionBlocks = IntegerHelper.getInt (data[NUM_EXTENSION_BLOCK_POS], data[NUM_EXTENSION_BLOCK_POS + 1], data[NUM_EXTENSION_BLOCK_POS + 2], data[NUM_EXTENSION_BLOCK_POS + 3]); bigBlockDepotBlocks = new int[numBigBlockDepotBlocks]; int pos = BIG_BLOCK_DEPOT_BLOCKS_POS; int bbdBlocks = numBigBlockDepotBlocks; if (numExtensionBlocks != 0) { bbdBlocks = (BIG_BLOCK_SIZE - BIG_BLOCK_DEPOT_BLOCKS_POS) / 4; } for (int i = 0; i < bbdBlocks; i++) { bigBlockDepotBlocks[i] = IntegerHelper.getInt (d[pos], d[pos + 1], d[pos + 2], d[pos + 3]); pos += 4; } for (int j = 0; j < numExtensionBlocks; j++) { pos = (extensionBlock + 1) * BIG_BLOCK_SIZE; int blocksToRead = Math.min(numBigBlockDepotBlocks - bbdBlocks, BIG_BLOCK_SIZE / 4 - 1); for (int i = bbdBlocks; i < bbdBlocks + blocksToRead; i++) { bigBlockDepotBlocks[i] = IntegerHelper.getInt (d[pos], d[pos + 1], d[pos + 2], d[pos + 3]); pos += 4; } bbdBlocks += blocksToRead; if (bbdBlocks < numBigBlockDepotBlocks) { extensionBlock = IntegerHelper.getInt (d[pos], d[pos + 1], d[pos + 2], d[pos + 3]); } } readBigBlockDepot(); readSmallBlockDepot(); rootEntry = readData(rootStartBlock); readPropertySets(); } /** * Reads the big block depot entries */ private void readBigBlockDepot() { int pos = 0; int index = 0; bigBlockChain = new int[numBigBlockDepotBlocks * BIG_BLOCK_SIZE / 4]; for (int i = 0; i < numBigBlockDepotBlocks; i++) { pos = (bigBlockDepotBlocks[i] + 1) * BIG_BLOCK_SIZE; for (int j = 0; j < BIG_BLOCK_SIZE / 4; j++) { bigBlockChain[index] = IntegerHelper.getInt (data[pos], data[pos + 1], data[pos + 2], data[pos + 3]); pos += 4; index++; } } } /** * Reads the small block chain's depot entries */ private void readSmallBlockDepot() throws BiffException { int pos = 0; int index = 0; int sbdBlock = sbdStartBlock; smallBlockChain = new int[0]; // Some non-excel generators specify -1 for an empty small block depot // simply warn and return if (sbdBlock == -1) { logger.warn("invalid small block depot number"); return; } int blockCount = 0; for (; blockCount <= bigBlockChain.length && sbdBlock != -2; blockCount++) { // Allocate some more space to the small block chain int[] oldChain = smallBlockChain; smallBlockChain = new int[smallBlockChain.length + BIG_BLOCK_SIZE / 4]; System.arraycopy(oldChain, 0, smallBlockChain, 0, oldChain.length); pos = (sbdBlock + 1) * BIG_BLOCK_SIZE; for (int j = 0; j < BIG_BLOCK_SIZE / 4; j++) { smallBlockChain[index] = IntegerHelper.getInt (data[pos], data[pos + 1], data[pos + 2], data[pos + 3]); pos += 4; index++; } sbdBlock = bigBlockChain[sbdBlock]; } if (blockCount > bigBlockChain.length) { // Attempted to read more blocks than the block chain contains entries // for. This indicates a loop in the chain throw new BiffException(BiffException.corruptFileFormat); } } /** * Reads all the property sets */ private void readPropertySets() { int offset = 0; byte[] d = null; while (offset < rootEntry.length) { d = new byte[PROPERTY_STORAGE_BLOCK_SIZE]; System.arraycopy(rootEntry, offset, d, 0, d.length); PropertyStorage ps = new PropertyStorage(d); // sometimes the MAC Operating system leaves some property storage // names blank. Contributed by Jacky if (ps.name == null || ps.name.length() == 0) { if (ps.type == ROOT_ENTRY_PS_TYPE) { ps.name = ROOT_ENTRY_NAME; logger.warn("Property storage name for " + ps.type + " is empty - setting to " + ROOT_ENTRY_NAME); } else { if (ps.size != 0) { logger.warn("Property storage type " + ps.type + " is non-empty and has no associated name"); } } } propertySets.add(ps); if (ps.name.equalsIgnoreCase(ROOT_ENTRY_NAME)) { rootEntryPropertyStorage = ps; } offset += PROPERTY_STORAGE_BLOCK_SIZE; } if (rootEntryPropertyStorage == null) { rootEntryPropertyStorage = (PropertyStorage) propertySets.get(0); } } /** * Gets the defragmented stream from this ole compound file * * @param streamName the stream name to get * @return the defragmented ole stream * @exception BiffException */ public byte[] getStream(String streamName) throws BiffException { PropertyStorage ps = findPropertyStorage(streamName, rootEntryPropertyStorage); // Property set can't be found from the direct hierarchy, so just // search on the name if (ps == null) { ps = getPropertyStorage(streamName); } if (ps.size >= SMALL_BLOCK_THRESHOLD || streamName.equalsIgnoreCase(ROOT_ENTRY_NAME)) { return getBigBlockStream(ps); } else { return getSmallBlockStream(ps); } } /** * Gets the defragmented stream from this ole compound file. Used when * copying workbooks with macros * * @param psIndex the property storage index * @return the defragmented ole stream * @exception BiffException */ public byte[] getStream(int psIndex) throws BiffException { PropertyStorage ps = getPropertyStorage(psIndex); if (ps.size >= SMALL_BLOCK_THRESHOLD || ps.name.equalsIgnoreCase(ROOT_ENTRY_NAME)) { return getBigBlockStream(ps); } else { return getSmallBlockStream(ps); } } /** * Recursively searches the property storages in hierarchy order * for the appropriate name. This is the public version which is * invoked from the writable version * when copying a sheet with addition property sets. */ public PropertyStorage findPropertyStorage(String name) { return findPropertyStorage(name, rootEntryPropertyStorage); } /** * Recursively searches the property storages in hierarchy order * for the appropriate name. */ private PropertyStorage findPropertyStorage(String name, PropertyStorage base) { if (base.child == -1) { return null; } // Get the child PropertyStorage child = getPropertyStorage(base.child); if (child.name.equalsIgnoreCase(name)) { return child; } // Find the previous property storages on the same level PropertyStorage prev = child; while (prev.previous != -1) { prev = getPropertyStorage(prev.previous); if (prev.name.equalsIgnoreCase(name)) { return prev; } } // Find the next property storages on the same level PropertyStorage next = child; while (next.next != -1) { next = getPropertyStorage(next.next); if (next.name.equalsIgnoreCase(name)) { return next; } } return findPropertyStorage(name, child); } /** * Gets the property set with the specified name * @param name the property storage name * @return the property storage record * @exception BiffException * @deprecated remove me */ private PropertyStorage getPropertyStorage(String name) throws BiffException { // Find the workbook property Iterator i = propertySets.iterator(); boolean found = false; boolean multiple = false; PropertyStorage ps = null; while (i.hasNext()) { PropertyStorage ps2 = (PropertyStorage) i.next(); if (ps2.name.equalsIgnoreCase(name)) { multiple = found == true ? true : false; found = true; ps = ps2; } } if (multiple) { logger.warn("found multiple copies of property set " + name); } if (!found) { throw new BiffException(BiffException.streamNotFound); } return ps; } /** * Gets the property set with the specified name * @param index the index of the property storage * @return the property storage record */ private PropertyStorage getPropertyStorage(int index) { return (PropertyStorage) propertySets.get(index); } /** * Build up the resultant stream using the big blocks * * @param ps the property storage * @return the big block stream */ private byte[] getBigBlockStream(PropertyStorage ps) { int numBlocks = ps.size / BIG_BLOCK_SIZE; if (ps.size % BIG_BLOCK_SIZE != 0) { numBlocks++; } byte[] streamData = new byte[numBlocks * BIG_BLOCK_SIZE]; int block = ps.startBlock; int count = 0; int pos = 0; while (block != -2 && count < numBlocks) { pos = (block + 1) * BIG_BLOCK_SIZE; System.arraycopy(data, pos, streamData, count * BIG_BLOCK_SIZE, BIG_BLOCK_SIZE); count++; block = bigBlockChain[block]; } if (block != -2 && count == numBlocks) { logger.warn("Property storage size inconsistent with block chain."); } return streamData; } /** * Build up the resultant stream using the small blocks * @param ps the property storage * @return the data * @exception BiffException */ private byte[] getSmallBlockStream(PropertyStorage ps) throws BiffException { byte[] rootdata = readData(rootEntryPropertyStorage.startBlock); byte[] sbdata = new byte[0]; int block = ps.startBlock; int pos = 0; int blockCount = 0; for (; blockCount <= smallBlockChain.length && block != -2; blockCount++) { // grow the array byte[] olddata = sbdata; sbdata = new byte[olddata.length + SMALL_BLOCK_SIZE]; System.arraycopy(olddata, 0, sbdata, 0, olddata.length); // Copy in the new data pos = block * SMALL_BLOCK_SIZE; System.arraycopy(rootdata, pos, sbdata, olddata.length, SMALL_BLOCK_SIZE); block = smallBlockChain[block]; if (block == -1) { logger.warn("Incorrect terminator for small block stream " + ps.name); block = -2; // kludge to force the loop termination } } if (blockCount > smallBlockChain.length) { // Attempted to read more blocks than the block chain contains entries // for. This indicates a loop in the chain throw new BiffException(BiffException.corruptFileFormat); } return sbdata; } /** * Reads the block chain from the specified block and returns the * data as a continuous stream of bytes * * @param bl the block number * @return the data */ private byte[] readData(int bl) throws BiffException { int block = bl; int pos = 0; byte[] entry = new byte[0]; int blockCount = 0; for (; blockCount <= bigBlockChain.length && block != -2; blockCount++) { // Grow the array byte[] oldEntry = entry; entry = new byte[oldEntry.length + BIG_BLOCK_SIZE]; System.arraycopy(oldEntry, 0, entry, 0, oldEntry.length); pos = (block + 1) * BIG_BLOCK_SIZE; System.arraycopy(data, pos, entry, oldEntry.length, BIG_BLOCK_SIZE); if (bigBlockChain[block] == block) { throw new BiffException(BiffException.corruptFileFormat); } block = bigBlockChain[block]; } if (blockCount > bigBlockChain.length) { // Attempted to read more blocks than the block chain contains entries // for. This indicates a loop in the chain throw new BiffException(BiffException.corruptFileFormat); } return entry; } /** * Gets the number of property sets * @return the number of property sets */ public int getNumberOfPropertySets() { return propertySets.size(); } /** * Gets the property set. Invoked when copying worksheets with macros. * Simply calls the private counterpart * * @param ps the property set name * @return the property set with the given name */ public PropertyStorage getPropertySet(int index) { return getPropertyStorage(index); } } jexcelapi/src/jxl/read/biff/#SheetImpl.java#0000750000175000017500000007273111207000610020761 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import java.util.ArrayList; import java.util.Iterator; import java.util.regex.Pattern; import common.Logger; import common.Assert; import jxl.Cell; import jxl.CellType; import jxl.CellView; import jxl.Hyperlink; import jxl.Image; import jxl.LabelCell; import jxl.Range; import jxl.Sheet; import jxl.SheetSettings; import jxl.WorkbookSettings; import jxl.biff.BuiltInName; import jxl.biff.AutoFilter; import jxl.biff.CellFinder; import jxl.biff.CellReferenceHelper; import jxl.biff.ConditionalFormat; import jxl.biff.DataValidation; import jxl.biff.EmptyCell; import jxl.biff.FormattingRecords; import jxl.biff.Type; import jxl.biff.WorkspaceInformationRecord; import jxl.biff.drawing.Chart; import jxl.biff.drawing.Drawing; import jxl.biff.drawing.DrawingData; import jxl.biff.drawing.DrawingGroupObject; import jxl.format.CellFormat; /** * Represents a sheet within a workbook. Provides a handle to the individual * cells, or lines of cells (grouped by Row or Column) * In order to simplify this class due to code bloat, the actual reading * logic has been delegated to the SheetReaderClass. This class' main * responsibility is now to implement the API methods declared in the * Sheet interface */ public class SheetImpl implements Sheet { /** * The logger */ private static Logger logger = Logger.getLogger(SheetImpl.class); /** * The excel file */ private File excelFile; /** * A handle to the shared string table */ private SSTRecord sharedStrings; /** * A handle to the sheet BOF record, which indicates the stream type */ private BOFRecord sheetBof; /** * A handle to the workbook BOF record, which indicates the stream type */ private BOFRecord workbookBof; /** * A handle to the formatting records */ private FormattingRecords formattingRecords; /** * The name of this sheet */ private String name; /** * The number of rows */ private int numRows; /** * The number of columns */ private int numCols; /** * The cells */ private Cell[][] cells; /** * The start position in the stream of this sheet */ private int startPosition; /** * The list of specified (ie. non default) column widths */ private ColumnInfoRecord[] columnInfos; /** * The array of row records */ private RowRecord[] rowRecords; /** * The list of non-default row properties */ private ArrayList rowProperties; /** * An array of column info records. They are held this way before * they are transferred to the more convenient array */ private ArrayList columnInfosArray; /** * A list of shared formula groups */ private ArrayList sharedFormulas; /** * A list of hyperlinks on this page */ private ArrayList hyperlinks; /** * A list of charts on this page */ private ArrayList charts; /** * A list of drawings on this page */ private ArrayList drawings; /** * A list of drawings (as opposed to comments/validation/charts) on this * page */ private ArrayList images; /** * A list of data validations on this page */ private DataValidation dataValidation; /** * A list of merged cells on this page */ private Range[] mergedCells; /** * Indicates whether the columnInfos array has been initialized */ private boolean columnInfosInitialized; /** * Indicates whether the rowRecords array has been initialized */ private boolean rowRecordsInitialized; /** * Indicates whether or not the dates are based around the 1904 date system */ private boolean nineteenFour; /** * The workspace options */ private WorkspaceInformationRecord workspaceOptions; /** * The hidden flag */ private boolean hidden; /** * The environment specific print record */ private PLSRecord plsRecord; /** * The property set record associated with this workbook */ private ButtonPropertySetRecord buttonPropertySet; /** * The sheet settings */ private SheetSettings settings; /** * The horizontal page breaks contained on this sheet */ private int[] rowBreaks; /** * The vertical page breaks contained on this sheet */ private int[] columnBreaks; /** * The maximum row outline level */ private int maxRowOutlineLevel; /** * The maximum column outline level */ private int maxColumnOutlineLevel; /** * The list of local names for this sheet */ private ArrayList localNames; /** * The list of conditional formats for this sheet */ private ArrayList conditionalFormats; /** * The autofilter information */ private AutoFilter autoFilter; /** * A handle to the workbook which contains this sheet. Some of the records * need this in order to reference external sheets */ private WorkbookParser workbook; /** * A handle to the workbook settings */ private WorkbookSettings workbookSettings; /** * Constructor * * @param f the excel file * @param sst the shared string table * @param fr formatting records * @param sb the bof record which indicates the start of the sheet * @param wb the bof record which indicates the start of the sheet * @param nf the 1904 flag * @param wp the workbook which this sheet belongs to * @exception BiffException */ SheetImpl(File f, SSTRecord sst, FormattingRecords fr, BOFRecord sb, BOFRecord wb, boolean nf, WorkbookParser wp) throws BiffException { excelFile = f; sharedStrings = sst; formattingRecords = fr; sheetBof = sb; workbookBof = wb; columnInfosArray = new ArrayList(); sharedFormulas = new ArrayList(); hyperlinks = new ArrayList(); rowProperties = new ArrayList(10); columnInfosInitialized = false; rowRecordsInitialized = false; nineteenFour = nf; workbook = wp; workbookSettings = workbook.getSettings(); // Mark the position in the stream, and then skip on until the end startPosition = f.getPos(); if (sheetBof.isChart()) { // Set the start pos to include the bof so the sheet reader can handle it startPosition -= (sheetBof.getLength() + 4); } Record r = null; int bofs = 1; while (bofs >= 1) { r = f.next(); // use this form for quick performance if (r.getCode() == Type.EOF.value) { bofs--; } if (r.getCode() == Type.BOF.value) { bofs++; } } } /** * Returns the cell for the specified location eg. "A4", using the * CellReferenceHelper * * @param loc the cell reference * @return the cell at the specified co-ordinates */ public Cell getCell(String loc) { return getCell(CellReferenceHelper.getColumn(loc), CellReferenceHelper.getRow(loc)); } /** * Returns the cell specified at this row and at this column * * @param row the row number * @param column the column number * @return the cell at the specified co-ordinates */ public Cell getCell(int column, int row) { // just in case this has been cleared, but something else holds // a reference to it if (cells == null) { readSheet(); } Cell c = cells[row][column]; if (c == null) { c = new EmptyCell(column, row); cells[row][column] = c; } return c; } /** * Gets the cell whose contents match the string passed in. * If no match is found, then null is returned. The search is performed * on a row by row basis, so the lower the row number, the more * efficiently the algorithm will perform * * @param contents the string to match * @return the Cell whose contents match the paramter, null if not found */ public Cell findCell(String contents) { CellFinder cellFinder = new CellFinder(this); return cellFinder.findCell(contents); } /** * Gets the cell whose contents match the string passed in. * If no match is found, then null is returned. The search is performed * on a row by row basis, so the lower the row number, the more * efficiently the algorithm will perform * * @param contents the string to match * @param firstCol the first column within the range * @param firstRow the first row of the range * @param lastCol the last column within the range * @param lastRow the last row within the range * @param reverse indicates whether to perform a reverse search or not * @return the Cell whose contents match the parameter, null if not found */ public Cell findCell(String contents, int firstCol, int firstRow, int lastCol, int lastRow, boolean reverse) { CellFinder cellFinder = new CellFinder(this); return cellFinder.findCell(contents, firstCol, firstRow, lastCol, lastRow, reverse); } /** * Gets the cell whose contents match the regular expressionstring passed in. * If no match is found, then null is returned. The search is performed * on a row by row basis, so the lower the row number, the more * efficiently the algorithm will perform * * @param pattern the regular expression string to match * @param firstCol the first column within the range * @param firstRow the first row of the range * @param lastRow the last row within the range * @param lastCol the last column within the ranage * @param reverse indicates whether to perform a reverse search or not * @return the Cell whose contents match the parameter, null if not found */ public Cell findCell(Pattern pattern, int firstCol, int firstRow, int lastCol, int lastRow, boolean reverse) { CellFinder cellFinder = new CellFinder(this); return cellFinder.findCell(pattern, firstCol, firstRow, lastCol, lastRow, reverse); } /** * Gets the cell whose contents match the string passed in. * If no match is found, then null is returned. The search is performed * on a row by row basis, so the lower the row number, the more * efficiently the algorithm will perform. This method differs * from the findCell methods in that only cells with labels are * queried - all numerical cells are ignored. This should therefore * improve performance. * * @param contents the string to match * @return the Cell whose contents match the paramter, null if not found */ public LabelCell findLabelCell(String contents) { CellFinder cellFinder = new CellFinder(this); return cellFinder.findLabelCell(contents); } /** * Returns the number of rows in this sheet * * @return the number of rows in this sheet */ public int getRows() { // just in case this has been cleared, but something else holds // a reference to it if (cells == null) { readSheet(); } return numRows; } /** * Returns the number of columns in this sheet * * @return the number of columns in this sheet */ public int getColumns() { // just in case this has been cleared, but something else holds // a reference to it if (cells == null) { readSheet(); } return numCols; } /** * Gets all the cells on the specified row. The returned array will * be stripped of all trailing empty cells * * @param row the rows whose cells are to be returned * @return the cells on the given row */ public Cell[] getRow(int row) { // just in case this has been cleared, but something else holds // a reference to it if (cells == null) { readSheet(); } // Find the last non-null cell boolean found = false; int col = numCols - 1; while (col >= 0 && !found) { if (cells[row][col] != null) { found = true; } else { col--; } } // Only create entries for non-null cells Cell[] c = new Cell[col + 1]; for (int i = 0; i <= col; i++) { c[i] = getCell(i, row); } return c; } /** * Gets all the cells on the specified column. The returned array * will be stripped of all trailing empty cells * * @param col the column whose cells are to be returned * @return the cells on the specified column */ public Cell[] getColumn(int col) { // just in case this has been cleared, but something else holds // a reference to it if (cells == null) { readSheet(); } // Find the last non-null cell boolean found = false; int row = numRows - 1; while (row >= 0 && !found) { if (cells[row][col] != null) { found = true; } else { row--; } } // Only create entries for non-null cells Cell[] c = new Cell[row + 1]; for (int i = 0; i <= row; i++) { c[i] = getCell(col, i); } return c; } /** * Gets the name of this sheet * * @return the name of the sheet */ public String getName() { return name; } /** * Sets the name of this sheet * * @param s the sheet name */ final void setName(String s) { name = s; } /** * Determines whether the sheet is hidden * * @return whether or not the sheet is hidden * @deprecated in favour of the getSettings function */ public boolean isHidden() { return hidden; } /** * Gets the column info record for the specified column. If no * column is specified, null is returned * * @param col the column * @return the ColumnInfoRecord if specified, NULL otherwise */ public ColumnInfoRecord getColumnInfo(int col) { if (!columnInfosInitialized) { // Initialize the array Iterator i = columnInfosArray.iterator(); ColumnInfoRecord cir = null; while (i.hasNext()) { cir = (ColumnInfoRecord) i.next(); int startcol = Math.max(0, cir.getStartColumn()); int endcol = Math.min(columnInfos.length - 1, cir.getEndColumn()); for (int c = startcol; c <= endcol; c++) { columnInfos[c] = cir; } if (endcol < startcol) { columnInfos[startcol] = cir; } } columnInfosInitialized = true; } return col < columnInfos.length ? columnInfos[col] : null; } /** * Gets all the column info records * * @return the ColumnInfoRecordArray */ public ColumnInfoRecord[] getColumnInfos() { // Just chuck all the column infos we have into an array ColumnInfoRecord[] infos = new ColumnInfoRecord[columnInfosArray.size()]; for (int i = 0; i < columnInfosArray.size(); i++) { infos[i] = (ColumnInfoRecord) columnInfosArray.get(i); } return infos; } /** * Sets the visibility of this sheet * * @param h hidden flag */ final void setHidden(boolean h) { hidden = h; } /** * Clears out the array of cells. This is done for memory allocation * reasons when reading very large sheets */ final void clear() { cells = null; mergedCells = null; columnInfosArray.clear(); sharedFormulas.clear(); hyperlinks.clear(); columnInfosInitialized = false; if (!workbookSettings.getGCDisabled()) { System.gc(); } } /** * Reads in the contents of this sheet */ final void readSheet() { // If this sheet contains only a chart, then set everything to // empty and do not bother parsing the sheet // Thanks to steve.brophy for spotting this if (!sheetBof.isWorksheet()) { numRows = 0; numCols = 0; cells = new Cell[0][0]; // return; } SheetReader reader = new SheetReader(excelFile, sharedStrings, formattingRecords, sheetBof, workbookBof, nineteenFour, workbook, startPosition, this); reader.read(); // Take stuff that was read in numRows = reader.getNumRows(); numCols = reader.getNumCols(); cells = reader.getCells(); rowProperties = reader.getRowProperties(); columnInfosArray = reader.getColumnInfosArray(); hyperlinks = reader.getHyperlinks(); conditionalFormats = reader.getConditionalFormats(); autoFilter = reader.getAutoFilter(); charts = reader.getCharts(); drawings = reader.getDrawings(); dataValidation = reader.getDataValidation(); mergedCells = reader.getMergedCells(); settings = reader.getSettings(); settings.setHidden(hidden); rowBreaks = reader.getRowBreaks(); columnBreaks = reader.getColumnBreaks(); workspaceOptions = reader.getWorkspaceOptions(); plsRecord = reader.getPLS(); buttonPropertySet = reader.getButtonPropertySet(); maxRowOutlineLevel = reader.getMaxRowOutlineLevel(); maxColumnOutlineLevel = reader.getMaxColumnOutlineLevel(); reader = null; if (!workbookSettings.getGCDisabled()) { System.gc(); } if (columnInfosArray.size() > 0) { ColumnInfoRecord cir = (ColumnInfoRecord) columnInfosArray.get(columnInfosArray.size() - 1); columnInfos = new ColumnInfoRecord[cir.getEndColumn() + 1]; } else { columnInfos = new ColumnInfoRecord[0]; } // Add any local names if (localNames != null) { for (Iterator it = localNames.iterator(); it.hasNext() ;) { NameRecord nr = (NameRecord) it.next(); if (nr.getBuiltInName() == BuiltInName.PRINT_AREA) { if(nr.getRanges().length > 0) { NameRecord.NameRange rng = nr.getRanges()[0]; settings.setPrintArea(rng.getFirstColumn(), rng.getFirstRow(), rng.getLastColumn(), rng.getLastRow()); } } else if (nr.getBuiltInName() == BuiltInName.PRINT_TITLES) { // There can be 1 or 2 entries. // Row entries have hardwired column entries (first and last // possible column) // Column entries have hardwired row entries (first and last // possible row) for (int i = 0 ; i < nr.getRanges().length ; i++) { NameRecord.NameRange rng = nr.getRanges()[i]; if (rng.getFirstColumn() == 0 && rng.getLastColumn() == 255) { settings.setPrintTitlesRow(rng.getFirstRow(), rng.getLastRow()); } else { settings.setPrintTitlesCol(rng.getFirstColumn(), rng.getLastColumn()); } } } } } } /** * Gets the hyperlinks on this sheet * * @return an array of hyperlinks */ public Hyperlink[] getHyperlinks() { Hyperlink[] hl = new Hyperlink[hyperlinks.size()]; for (int i = 0; i < hyperlinks.size(); i++) { hl[i] = (Hyperlink) hyperlinks.get(i); } return hl; } /** * Gets the cells which have been merged on this sheet * * @return an array of range objects */ public Range[] getMergedCells() { if (mergedCells == null) { return new Range[0]; } return mergedCells; } /** * Gets the non-default rows. Used when copying spreadsheets * * @return an array of row properties */ public RowRecord[] getRowProperties() { RowRecord[] rp = new RowRecord[rowProperties.size()]; for (int i = 0; i < rp.length; i++) { rp[i] = (RowRecord) rowProperties.get(i); } return rp; } /** * Gets the data validations. Used when copying sheets * * @return the data validations */ public DataValidation getDataValidation() { return dataValidation; } /** * Gets the row record. Usually called by the cell in the specified * row in order to determine its size * * @param r the row * @return the RowRecord for the specified row */ RowRecord getRowInfo(int r) { if (!rowRecordsInitialized) { rowRecords = new RowRecord[getRows()]; Iterator i = rowProperties.iterator(); int rownum = 0; RowRecord rr = null; while (i.hasNext()) { rr = (RowRecord) i.next(); rownum = rr.getRowNumber(); if (rownum < rowRecords.length) { rowRecords[rownum] = rr; } } rowRecordsInitialized = true; } return r < rowRecords.length ? rowRecords[r] : null; } /** * Gets the row breaks. Called when copying sheets * * @return the explicit row breaks */ public final int[] getRowPageBreaks() { return rowBreaks; } /** * Gets the row breaks. Called when copying sheets * * @return the explicit row breaks */ public final int[] getColumnPageBreaks() { return columnBreaks; } /** * Gets the charts. Called when copying sheets * * @return the charts on this page */ public final Chart[] getCharts() { Chart[] ch = new Chart[charts.size()]; for (int i = 0; i < ch.length; i++) { ch[i] = (Chart) charts.get(i); } return ch; } /** * Gets the drawings. Called when copying sheets * * @return the drawings on this page */ public final DrawingGroupObject[] getDrawings() { DrawingGroupObject[] dr = new DrawingGroupObject[drawings.size()]; dr = (DrawingGroupObject[]) drawings.toArray(dr); return dr; } /** * Determines whether the sheet is protected * * @return whether or not the sheet is protected * @deprecated in favour of the getSettings() api */ public boolean isProtected() { return settings.isProtected(); } /** * Gets the workspace options for this sheet. Called during the copy * process * * @return the workspace options */ public WorkspaceInformationRecord getWorkspaceOptions() { return workspaceOptions; } /** * Accessor for the sheet settings * * @return the settings for this sheet */ public SheetSettings getSettings() { return settings; } /** * Accessor for the workbook. In addition to be being used by this package, * it is also used during the importSheet process * * @return the workbook */ public WorkbookParser getWorkbook() { return workbook; } /** * Gets the column format for the specified column * * @param col the column number * @return the column format, or NULL if the column has no specific format * @deprecated use getColumnView instead */ public CellFormat getColumnFormat(int col) { CellView cv = getColumnView(col); return cv.getFormat(); } /** * Gets the column width for the specified column * * @param col the column number * @return the column width, or the default width if the column has no * specified format */ public int getColumnWidth(int col) { return getColumnView(col).getSize() / 256; } /** * Gets the column width for the specified column * * @param col the column number * @return the column format, or the default format if no override is specified */ public CellView getColumnView(int col) { ColumnInfoRecord cir = getColumnInfo(col); CellView cv = new CellView(); if (cir != null) { cv.setDimension(cir.getWidth() / 256); //deprecated cv.setSize(cir.getWidth()); cv.setHidden(cir.getHidden()); cv.setFormat(formattingRecords.getXFRecord(cir.getXFIndex())); } else { cv.setDimension(settings.getDefaultColumnWidth()); //deprecated cv.setSize(settings.getDefaultColumnWidth() * 256); } return cv; } /** * Gets the row height for the specified column * * @param row the row number * @return the row height, or the default height if the row has no * specified format * @deprecated use getRowView instead */ public int getRowHeight(int row) { return getRowView(row).getDimension(); } /** * Gets the row view for the specified row * * @param row the row number * @return the row format, or the default format if no override is specified */ public CellView getRowView(int row) { RowRecord rr = getRowInfo(row); CellView cv = new CellView(); if (rr != null) { cv.setDimension(rr.getRowHeight()); //deprecated cv.setSize(rr.getRowHeight()); cv.setHidden(rr.isCollapsed()); if (rr.hasDefaultFormat()) { cv.setFormat(formattingRecords.getXFRecord(rr.getXFIndex())); } } else { cv.setDimension(settings.getDefaultRowHeight()); cv.setSize(settings.getDefaultRowHeight()); //deprecated } return cv; } /** * Used when copying sheets in order to determine the type of this sheet * * @return the BOF Record */ public BOFRecord getSheetBof() { return sheetBof; } /** * Used when copying sheets in order to determine the type of the containing * workboook * * @return the workbook BOF Record */ public BOFRecord getWorkbookBof() { return workbookBof; } /** * Accessor for the environment specific print record, invoked when * copying sheets * * @return the environment specific print record */ public PLSRecord getPLS() { return plsRecord; } /** * Accessor for the button property set, used during copying * * @return the button property set */ public ButtonPropertySetRecord getButtonPropertySet() { return buttonPropertySet; } /** * Accessor for the number of images on the sheet * * @return the number of images on this sheet */ public int getNumberOfImages() { if (images == null) { initializeImages(); } return images.size(); } /** * Accessor for the image * * @param i the 0 based image number * @return the image at the specified position */ public Image getDrawing(int i) { if (images == null) { initializeImages(); } return (Image) images.get(i); } /** * Initializes the images */ private void initializeImages() { if (images != null) { return; } images = new ArrayList(); DrawingGroupObject[] dgos = getDrawings(); for (int i = 0; i < dgos.length; i++) { if (dgos[i] instanceof Drawing) { images.add(dgos[i]); } } } /** * Used by one of the demo programs for debugging purposes only */ public DrawingData getDrawingData() { SheetReader reader = new SheetReader(excelFile, sharedStrings, formattingRecords, sheetBof, workbookBof, nineteenFour, workbook, startPosition, this); reader.read(); return reader.getDrawingData(); } /** * Adds a local name to this shate * * @param nr the local name to add */ void addLocalName(NameRecord nr) { if (localNames == null) { localNames = new ArrayList(); } localNames.add(nr); } /** * Gets the conditional formats * * @return the conditional formats */ public ConditionalFormat[] getConditionalFormats() { ConditionalFormat[] formats = new ConditionalFormat[conditionalFormats.size()]; formats = (ConditionalFormat[]) conditionalFormats.toArray(formats); return formats; } /** * Returns the autofilter * * @return the autofilter */ public AutoFilter getAutoFilter() { return autoFilter; } /** * Accessor for the maximum column outline level. Used during a copy * * @return the maximum column outline level, or 0 if no outlines/groups */ public int getMaxColumnOutlineLevel() { return maxColumnOutlineLevel; } /** * Accessor for the maximum row outline level. Used during a copy * * @return the maximum row outline level, or 0 if no outlines/groups */ public int getMaxRowOutlineLevel() { return maxRowOutlineLevel; } } jexcelapi/src/jxl/read/biff/CalcModeRecord.java0000750000175000017500000000317011207000610021556 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2005 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.common.Logger; import jxl.biff.IntegerHelper; import jxl.biff.RecordData; /** * A calculation mode record */ class CalcModeRecord extends RecordData { /** * The logger */ private static Logger logger = Logger.getLogger(CalcModeRecord.class); /** * The calculation mode */ private boolean automatic; /** * Constructor * * @param t the record */ public CalcModeRecord(Record t) { super(t); byte[] data = t.getData(); int mode = IntegerHelper.getInt(data[0], data[1]); automatic = (mode == 1); } /** * Accessor for the calculation mode * * @return the calculation mode */ public boolean isAutomatic() { return automatic; } } jexcelapi/src/jxl/read/biff/NumberRecord.java0000750000175000017500000000546011207000612021345 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import java.text.DecimalFormat; import java.text.NumberFormat; import jxl.common.Logger; import jxl.CellType; import jxl.NumberCell; import jxl.biff.DoubleHelper; import jxl.biff.FormattingRecords; /** * A number record. This is stored as 8 bytes, as opposed to the * 4 byte RK record */ class NumberRecord extends CellValue implements NumberCell { /** * The logger */ private static Logger logger = Logger.getLogger(NumberRecord.class); /** * The value */ private double value; /** * The java equivalent of the excel format */ private NumberFormat format; /** * The formatter to convert the value into a string */ private static DecimalFormat defaultFormat = new DecimalFormat("#.###"); /** * Constructs this object from the raw data * * @param t the raw data * @param fr the available formats * @param si the sheet */ public NumberRecord(Record t, FormattingRecords fr, SheetImpl si) { super(t, fr, si); byte[] data = getRecord().getData(); value = DoubleHelper.getIEEEDouble(data, 6); // Now get the number format format = fr.getNumberFormat(getXFIndex()); if (format == null) { format = defaultFormat; } } /** * Accessor for the value * * @return the value */ public double getValue() { return value; } /** * Returns the contents of this cell as a string * * @return the value formatted into a string */ public String getContents() { return format.format(value); } /** * Accessor for the cell type * * @return the cell type */ public CellType getType() { return CellType.NUMBER; } /** * Gets the NumberFormat used to format this cell. This is the java * equivalent of the Excel format * * @return the NumberFormat used to format the cell */ public NumberFormat getNumberFormat() { return format; } } jexcelapi/src/jxl/read/biff/BoundsheetRecord.java0000750000175000017500000000727611207000610022222 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2001 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.WorkbookSettings; import jxl.biff.IntegerHelper; import jxl.biff.RecordData; import jxl.biff.StringHelper; /** * A boundsheet record, which contains the worksheet name */ class BoundsheetRecord extends RecordData { /** * The offset into the sheet */ private int offset; /** * The type of sheet this is */ private byte typeFlag; /** * The visibility flag */ private byte visibilityFlag; /** * The length of the worksheet name */ private int length; /** * The worksheet name */ private String name; /** * Dummy indicators for overloading the constructor */ private static class Biff7 {}; public static Biff7 biff7 = new Biff7(); /** * Constructs this object from the raw data * * @param t the raw data * @param s the workbook settings */ public BoundsheetRecord(Record t, WorkbookSettings s) { super(t); byte[] data = getRecord().getData(); offset = IntegerHelper.getInt(data[0], data[1], data[2], data[3]); typeFlag = data[5]; visibilityFlag = data[4]; length = data[6]; if (data[7] == 0) { // Standard ASCII encoding byte[] bytes = new byte[length]; System.arraycopy(data, 8, bytes, 0, length); name = StringHelper.getString(bytes, length, 0, s); } else { // little endian Unicode encoding byte[] bytes = new byte[length * 2]; System.arraycopy(data, 8, bytes, 0, length * 2); name = StringHelper.getUnicodeString(bytes, length, 0); } } /** * Constructs this object from the raw data * * @param t the raw data * @param biff7 a dummy value to tell the record to interpret the * data as biff7 */ public BoundsheetRecord(Record t, Biff7 biff7) { super(t); byte[] data = getRecord().getData(); offset = IntegerHelper.getInt(data[0], data[1], data[2], data[3]); typeFlag = data[5]; visibilityFlag = data[4]; length = data[6]; byte[] bytes = new byte[length]; System.arraycopy(data, 7, bytes, 0, length); name = new String(bytes); } /** * Accessor for the worksheet name * * @return the worksheet name */ public String getName() { return name; } /** * Accessor for the hidden flag * * @return TRUE if this is a hidden sheet, FALSE otherwise */ public boolean isHidden() { return visibilityFlag != 0; } /** * Accessor to determine if this is a worksheet, or some other nefarious * type of object * * @return TRUE if this is a worksheet, FALSE otherwise */ public boolean isSheet() { return typeFlag == 0; } /** * Accessor to determine if this is a chart * * @return TRUE if this is a chart, FALSE otherwise */ public boolean isChart() { return typeFlag == 2; } } jexcelapi/src/jxl/read/biff/WindowProtectedRecord.java0000750000175000017500000000326011207000612023232 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2009 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.common.Logger; import jxl.biff.IntegerHelper; import jxl.biff.RecordData; /** * A windowProtected mode record */ class WindowProtectedRecord extends RecordData { /** * The logger */ private static Logger logger = Logger.getLogger(WindowProtectedRecord.class); /** * The windowProtected mode */ private boolean windowProtected; /** * Constructor * * @param t the record */ public WindowProtectedRecord(Record t) { super(t); byte[] data = t.getData(); int mode = IntegerHelper.getInt(data[0], data[1]); windowProtected = (mode == 1); } /** * Accessor for the windowProtected * * @return the windowProtected mode */ public boolean getWindowProtected() { return windowProtected; } } jexcelapi/src/jxl/read/biff/CellFeaturesAccessor.java0000750000175000017500000000251111207000610023007 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2005 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.CellFeatures; /** * Allows the setting of the cell features in this package only */ interface CellFeaturesAccessor { /** * Sets the cell features * * @param cf the cell features */ public void setCellFeatures(CellFeatures cf); /** * Convenience function (due to casting) to get the cell features * * @return the cell features */ public CellFeatures getCellFeatures(); } jexcelapi/src/jxl/read/biff/ColumnInfoRecord.java0000750000175000017500000000672111207000610022165 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.biff.IntegerHelper; import jxl.biff.RecordData; import jxl.biff.Type; /** * Contains the display info data which affects the entire columns */ public class ColumnInfoRecord extends RecordData { /** * The raw data */ private byte[] data; /** * The start for which to apply the format information */ private int startColumn; /** * The end column for which to apply the format information */ private int endColumn; /** * The index to the XF record, which applies to each cell in this column */ private int xfIndex; /** * The width of the column in 1/256 of a character */ private int width; /** * A hidden flag */ private boolean hidden; /** * The column's outline level */ private int outlineLevel; /** * The column collapsed flag */ private boolean collapsed; /** * Constructor which creates this object from the binary data * * @param t the record */ ColumnInfoRecord(Record t) { super(Type.COLINFO); data = t.getData(); startColumn = IntegerHelper.getInt(data[0], data[1]); endColumn = IntegerHelper.getInt(data[2], data[3]); width = IntegerHelper.getInt(data[4], data[5]); xfIndex = IntegerHelper.getInt(data[6], data[7]); int options = IntegerHelper.getInt(data[8], data[9]); hidden = ((options & 0x1) != 0); outlineLevel = ((options & 0x700) >> 8); collapsed = ((options & 0x1000) != 0); } /** * Accessor for the start column of this range * * @return the start column index */ public int getStartColumn() { return startColumn; } /** * Accessor for the end column of this range * * @return the end column index */ public int getEndColumn() { return endColumn; } /** * Accessor for the column format index * * @return the format index */ public int getXFIndex() { return xfIndex; } /** * Accessor for the column's outline level * * @return the column's outline level */ public int getOutlineLevel() { return outlineLevel; } /** * Accessor for whether the column is collapsed * * @return the column's collapsed state */ public boolean getCollapsed() { return collapsed; } /** * Accessor for the width of the column * * @return the width */ public int getWidth() { return width; } /** * Accessor for the hidden flag. Used when copying sheets * * @return TRUE if the columns are hidden, FALSE otherwise */ public boolean getHidden() { return hidden; } } jexcelapi/src/jxl/read/biff/LabelRecord.java0000750000175000017500000000574411207000610021137 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.CellType; import jxl.LabelCell; import jxl.WorkbookSettings; import jxl.biff.FormattingRecords; import jxl.biff.IntegerHelper; import jxl.biff.StringHelper; /** * A label which is stored in the cell */ class LabelRecord extends CellValue implements LabelCell { /** * The length of the label in characters */ private int length; /** * The label */ private String string; /** * Dummy indicators for overloading the constructor */ private static class Biff7 {}; public static Biff7 biff7 = new Biff7(); /** * Constructs this object from the raw data * * @param t the raw data * @param fr the formatting records * @param si the sheet * @param ws the workbook settings */ public LabelRecord(Record t, FormattingRecords fr, SheetImpl si, WorkbookSettings ws) { super(t, fr, si); byte[] data = getRecord().getData(); length = IntegerHelper.getInt(data[6], data[7]); if (data[8] == 0x0) { string = StringHelper.getString(data, length, 9, ws); } else { string = StringHelper.getUnicodeString(data, length, 9); } } /** * Constructs this object from the raw data * * @param t the raw data * @param fr the formatting records * @param si the sheet * @param ws the workbook settings * @param dummy dummy overload to indicate a biff 7 workbook */ public LabelRecord(Record t, FormattingRecords fr, SheetImpl si, WorkbookSettings ws, Biff7 dummy) { super(t, fr, si); byte[] data = getRecord().getData(); length = IntegerHelper.getInt(data[6], data[7]); string = StringHelper.getString(data, length, 8, ws); } /** * Gets the label * * @return the label */ public String getString() { return string; } /** * Gets the cell contents as a string * * @return the label */ public String getContents() { return string; } /** * Accessor for the cell type * * @return the cell type */ public CellType getType() { return CellType.LABEL; } } jexcelapi/src/jxl/read/biff/PrintGridLinesRecord.java0000750000175000017500000000306411207000612023010 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.biff.RecordData; /** * Contains the print grid lines option of this worksheet */ class PrintGridLinesRecord extends RecordData { /** * print grid lines flag */ private boolean printGridLines; /** * Constructs the value from the raw data * * @param pgl the raw data */ public PrintGridLinesRecord(Record pgl) { super(pgl); byte[] data = pgl.getData(); printGridLines = (data[0] == 1 ? true : false); } /** * Accessor for the print grid lines flag * * @return TRUE to print grid lines, FALSE otherwise */ public boolean getPrintGridLines() { return printGridLines; } } jexcelapi/src/jxl/read/biff/SSTRecord.java0000750000175000017500000002712211207000612020565 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.common.Assert; import jxl.WorkbookSettings; import jxl.biff.IntegerHelper; import jxl.biff.RecordData; import jxl.biff.StringHelper; /** * Holds all the strings in the shared string table */ class SSTRecord extends RecordData { /** * The total number of strings in this table */ private int totalStrings; /** * The number of unique strings */ private int uniqueStrings; /** * The shared strings */ private String[] strings; /** * The array of continuation breaks */ private int[] continuationBreaks; /** * A holder for a byte array */ private static class ByteArrayHolder { /** * the byte holder */ public byte[] bytes; } /** * A holder for a boolean */ private static class BooleanHolder { /** * the holder holder */ public boolean value; } /** * Constructs this object from the raw data * * @param t the raw data * @param continuations the continuations * @param ws the workbook settings */ public SSTRecord(Record t, Record[] continuations, WorkbookSettings ws) { super(t); // If a continue record appears in the middle of // a string, then the encoding character is repeated // Concatenate everything into one big bugger of a byte array int totalRecordLength = 0; for (int i = 0; i < continuations.length; i++) { totalRecordLength += continuations[i].getLength(); } totalRecordLength += getRecord().getLength(); byte[] data = new byte[totalRecordLength]; // First the original data gets put in int pos = 0; System.arraycopy(getRecord().getData(), 0, data, 0, getRecord().getLength()); pos += getRecord().getLength(); // Now copy in everything else. continuationBreaks = new int[continuations.length]; Record r = null; for (int i = 0; i < continuations.length; i++) { r = continuations[i]; System.arraycopy(r.getData(), 0, data, pos, r.getLength()); continuationBreaks[i] = pos; pos += r.getLength(); } totalStrings = IntegerHelper.getInt(data[0], data[1], data[2], data[3]); uniqueStrings = IntegerHelper.getInt(data[4], data[5], data[6], data[7]); strings = new String[uniqueStrings]; readStrings(data, 8, ws); } /** * Reads in all the strings from the raw data * * @param data the raw data * @param offset the offset * @param ws the workbook settings */ private void readStrings(byte[] data, int offset, WorkbookSettings ws) { int pos = offset; int numChars; byte optionFlags; String s = null; boolean asciiEncoding = false; boolean richString = false; boolean extendedString = false; int formattingRuns = 0; int extendedRunLength = 0; for (int i = 0; i < uniqueStrings; i++) { // Read in the number of characters numChars = IntegerHelper.getInt(data[pos], data[pos + 1]); pos += 2; optionFlags = data[pos]; pos++; // See if it is an extended string extendedString = ((optionFlags & 0x04) != 0); // See if string contains formatting information richString = ((optionFlags & 0x08) != 0); if (richString) { // Read in the crun formattingRuns = IntegerHelper.getInt(data[pos], data[pos + 1]); pos += 2; } if (extendedString) { // Read in cchExtRst extendedRunLength = IntegerHelper.getInt (data[pos], data[pos + 1], data[pos + 2], data[pos + 3]); pos += 4; } // See if string is ASCII (compressed) or unicode asciiEncoding = ((optionFlags & 0x01) == 0); ByteArrayHolder bah = new ByteArrayHolder(); BooleanHolder bh = new BooleanHolder(); bh.value = asciiEncoding; pos += getChars(data, bah, pos, bh, numChars); asciiEncoding = bh.value; if (asciiEncoding) { s = StringHelper.getString(bah.bytes, numChars, 0, ws); } else { s = StringHelper.getUnicodeString(bah.bytes, numChars, 0); } strings[i] = s; // For rich strings, skip over the formatting runs if (richString) { pos += 4 * formattingRuns; } // For extended strings, skip over the extended string data if (extendedString) { pos += extendedRunLength; } if (pos > data.length) { Assert.verify(false, "pos exceeds record length"); } } } /** * Gets the chars in the ascii array, taking into account continuation * breaks * * @param source the original source * @param bah holder for the new byte array * @param pos the current position in the source * @param ascii holder for a return ascii flag * @param numChars the number of chars in the string * @return the number of bytes read from the source */ private int getChars(byte[] source, ByteArrayHolder bah, int pos, BooleanHolder ascii, int numChars) { int i = 0; boolean spansBreak = false; if (ascii.value) { bah.bytes = new byte[numChars]; } else { bah.bytes = new byte[numChars * 2]; } while (i < continuationBreaks.length && !spansBreak) { spansBreak = pos <= continuationBreaks[i] && (pos + bah.bytes.length > continuationBreaks[i]); if (!spansBreak) { i++; } } // If it doesn't span a break simply do an array copy into the // destination array and finish if (!spansBreak) { System.arraycopy(source, pos, bah.bytes, 0, bah.bytes.length); return bah.bytes.length; } // Copy the portion before the break pos into the array int breakpos = continuationBreaks[i]; System.arraycopy(source, pos, bah.bytes, 0, breakpos - pos); int bytesRead = breakpos - pos; int charsRead; if (ascii.value) { charsRead = bytesRead; } else { charsRead = bytesRead / 2; } bytesRead += getContinuedString(source, bah, bytesRead, i, ascii, numChars - charsRead); return bytesRead; } /** * Gets the rest of the string after a continuation break * * @param source the original bytes * @param bah the holder for the new bytes * @param destPos the des pos * @param contBreakIndex the index of the continuation break * @param ascii the ascii flag holder * @param charsLeft the number of chars left in the array * @return the number of bytes read in the continued string */ private int getContinuedString(byte[] source, ByteArrayHolder bah, int destPos, int contBreakIndex, BooleanHolder ascii, int charsLeft) { int breakpos = continuationBreaks[contBreakIndex]; int bytesRead = 0; while (charsLeft > 0) { Assert.verify(contBreakIndex < continuationBreaks.length, "continuation break index"); if (ascii.value && source[breakpos] == 0) { // The string is consistently ascii throughout int length = contBreakIndex == continuationBreaks.length - 1 ? charsLeft : Math.min (charsLeft, continuationBreaks[contBreakIndex + 1] - breakpos - 1); System.arraycopy(source, breakpos + 1, bah.bytes, destPos, length); destPos += length; bytesRead += length + 1; charsLeft -= length; ascii.value = true; } else if (!ascii.value && source[breakpos] != 0) { // The string is Unicode throughout int length = contBreakIndex == continuationBreaks.length - 1 ? charsLeft * 2 : Math.min (charsLeft * 2, continuationBreaks[contBreakIndex + 1] - breakpos - 1); // It looks like the string continues as Unicode too. That's handy System.arraycopy(source, breakpos + 1, bah.bytes, destPos, length); destPos += length; bytesRead += length + 1; charsLeft -= length / 2; ascii.value = false; } else if (!ascii.value && source[breakpos] == 0) { // Bummer - the string starts off as Unicode, but after the // continuation it is in straightforward ASCII encoding int chars = contBreakIndex == continuationBreaks.length - 1 ? charsLeft: Math.min (charsLeft, continuationBreaks[contBreakIndex + 1] - breakpos - 1); for (int j = 0; j < chars; j++) { bah.bytes[destPos] = source[breakpos + j + 1]; destPos += 2; } bytesRead += chars + 1; charsLeft -= chars; ascii.value = false; } else { // Double Bummer - the string starts off as ASCII, but after the // continuation it is in Unicode. This impacts the allocated array // Reallocate what we have of the byte array so that it is all // Unicode byte[] oldBytes = bah.bytes; bah.bytes = new byte[destPos * 2 + charsLeft * 2]; for (int j = 0; j < destPos; j++) { bah.bytes[j * 2] = oldBytes[j]; } destPos = destPos * 2; int length = contBreakIndex == continuationBreaks.length - 1 ? charsLeft * 2 : Math.min (charsLeft * 2, continuationBreaks[contBreakIndex + 1] - breakpos - 1); System.arraycopy(source, breakpos + 1, bah.bytes, destPos, length); destPos += length; bytesRead += length + 1; charsLeft -= length / 2; ascii.value = false; } contBreakIndex++; if (contBreakIndex < continuationBreaks.length) { breakpos = continuationBreaks[contBreakIndex]; } } return bytesRead; } /** * Gets the string at the specified position * * @param index the index of the string to return * @return the strings */ public String getString(int index) { Assert.verify(index < uniqueStrings); return strings[index]; } } jexcelapi/src/jxl/read/biff/SheetReader.java0000750000175000017500000015127211267106132021166 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import jxl.common.Assert; import jxl.common.Logger; import jxl.Cell; import jxl.CellFeatures; import jxl.CellReferenceHelper; import jxl.CellType; import jxl.DateCell; import jxl.HeaderFooter; import jxl.Range; import jxl.SheetSettings; import jxl.WorkbookSettings; import jxl.biff.AutoFilter; import jxl.biff.AutoFilterInfoRecord; import jxl.biff.AutoFilterRecord; import jxl.biff.ConditionalFormat; import jxl.biff.ConditionalFormatRangeRecord; import jxl.biff.ConditionalFormatRecord; import jxl.biff.ContinueRecord; import jxl.biff.DataValidation; import jxl.biff.DataValidityListRecord; import jxl.biff.DataValiditySettingsRecord; import jxl.biff.FilterModeRecord; import jxl.biff.FormattingRecords; import jxl.biff.Type; import jxl.biff.WorkspaceInformationRecord; import jxl.biff.drawing.Button; import jxl.biff.drawing.Chart; import jxl.biff.drawing.CheckBox; import jxl.biff.drawing.ComboBox; import jxl.biff.drawing.Comment; import jxl.biff.drawing.Drawing; import jxl.biff.drawing.Drawing2; import jxl.biff.drawing.DrawingData; import jxl.biff.drawing.DrawingDataException; import jxl.biff.drawing.MsoDrawingRecord; import jxl.biff.drawing.NoteRecord; import jxl.biff.drawing.ObjRecord; import jxl.biff.drawing.TextObjectRecord; import jxl.biff.formula.FormulaException; import jxl.format.PageOrder; import jxl.format.PageOrientation; import jxl.format.PaperSize; /** * Reads the sheet. This functionality was originally part of the * SheetImpl class, but was separated out in order to simplify the former * class */ final class SheetReader { /** * The logger */ private static Logger logger = Logger.getLogger(SheetReader.class); /** * The excel file */ private File excelFile; /** * A handle to the shared string table */ private SSTRecord sharedStrings; /** * A handle to the sheet BOF record, which indicates the stream type */ private BOFRecord sheetBof; /** * A handle to the workbook BOF record, which indicates the stream type */ private BOFRecord workbookBof; /** * A handle to the formatting records */ private FormattingRecords formattingRecords; /** * The number of rows */ private int numRows; /** * The number of columns */ private int numCols; /** * The cells */ private Cell[][] cells; /** * Any cells which are out of the defined bounds */ private ArrayList outOfBoundsCells; /** * The start position in the stream of this sheet */ private int startPosition; /** * The list of non-default row properties */ private ArrayList rowProperties; /** * An array of column info records. They are held this way before * they are transferred to the more convenient array */ private ArrayList columnInfosArray; /** * A list of shared formula groups */ private ArrayList sharedFormulas; /** * A list of hyperlinks on this page */ private ArrayList hyperlinks; /** * The list of conditional formats on this page */ private ArrayList conditionalFormats; /** * The autofilter information */ private AutoFilter autoFilter; /** * A list of merged cells on this page */ private Range[] mergedCells; /** * The list of data validations on this page */ private DataValidation dataValidation; /** * The list of charts on this page */ private ArrayList charts; /** * The list of drawings on this page */ private ArrayList drawings; /** * The drawing data for the drawings */ private DrawingData drawingData; /** * Indicates whether or not the dates are based around the 1904 date system */ private boolean nineteenFour; /** * The PLS print record */ private PLSRecord plsRecord; /** * The property set record associated with this workbook */ private ButtonPropertySetRecord buttonPropertySet; /** * The workspace options */ private WorkspaceInformationRecord workspaceOptions; /** * The horizontal page breaks contained on this sheet */ private int[] rowBreaks; /** * The vertical page breaks contained on this sheet */ private int[] columnBreaks; /** * The maximum row outline level */ private int maxRowOutlineLevel; /** * The maximum column outline level */ private int maxColumnOutlineLevel; /** * The sheet settings */ private SheetSettings settings; /** * The workbook settings */ private WorkbookSettings workbookSettings; /** * A handle to the workbook which contains this sheet. Some of the records * need this in order to reference external sheets */ private WorkbookParser workbook; /** * A handle to the sheet */ private SheetImpl sheet; /** * Constructor * * @param fr the formatting records * @param sst the shared string table * @param f the excel file * @param sb the bof record which indicates the start of the sheet * @param wb the bof record which indicates the start of the sheet * @param wp the workbook which this sheet belongs to * @param sp the start position of the sheet bof in the excel file * @param sh the sheet * @param nf 1904 date record flag * @exception BiffException */ SheetReader(File f, SSTRecord sst, FormattingRecords fr, BOFRecord sb, BOFRecord wb, boolean nf, WorkbookParser wp, int sp, SheetImpl sh) { excelFile = f; sharedStrings = sst; formattingRecords = fr; sheetBof = sb; workbookBof = wb; columnInfosArray = new ArrayList(); sharedFormulas = new ArrayList(); hyperlinks = new ArrayList(); conditionalFormats = new ArrayList(); rowProperties = new ArrayList(10); charts = new ArrayList(); drawings = new ArrayList(); outOfBoundsCells = new ArrayList(); nineteenFour = nf; workbook = wp; startPosition = sp; sheet = sh; settings = new SheetSettings(sh); workbookSettings = workbook.getSettings(); } /** * Adds the cell to the array * * @param cell the cell to add */ private void addCell(Cell cell) { // Sometimes multiple cells (eg. MULBLANK) can exceed the // column/row boundaries. Ignore these if (cell.getRow() < numRows && cell.getColumn() < numCols) { if (cells[cell.getRow()][cell.getColumn()] != null) { StringBuffer sb = new StringBuffer(); CellReferenceHelper.getCellReference (cell.getColumn(), cell.getRow(), sb); logger.warn("Cell " + sb.toString() + " already contains data"); } cells[cell.getRow()][cell.getColumn()] = cell; } else { outOfBoundsCells.add(cell); /* logger.warn("Cell " + CellReferenceHelper.getCellReference (cell.getColumn(), cell.getRow()) + " exceeds defined cell boundaries in Dimension record " + "(" + numCols + "x" + numRows + ")"); */ } } /** * Reads in the contents of this sheet */ final void read() { Record r = null; BaseSharedFormulaRecord sharedFormula = null; boolean sharedFormulaAdded = false; boolean cont = true; // Set the position within the file excelFile.setPos(startPosition); // Handles to the last drawing and obj records MsoDrawingRecord msoRecord = null; ObjRecord objRecord = null; boolean firstMsoRecord = true; // Handle to the last conditional format record ConditionalFormat condFormat = null; // Handle to the autofilter records FilterModeRecord filterMode = null; AutoFilterInfoRecord autoFilterInfo = null; // A handle to window2 record Window2Record window2Record = null; // A handle to printgridlines record PrintGridLinesRecord printGridLinesRecord = null; // A handle to printheaders record PrintHeadersRecord printHeadersRecord = null; // Hash map of comments, indexed on objectId. As each corresponding // note record is encountered, these are removed from the array HashMap comments = new HashMap(); // A list of object ids - used for cross referencing ArrayList objectIds = new ArrayList(); // A handle to a continue record read in ContinueRecord continueRecord = null; while (cont) { r = excelFile.next(); Type type = r.getType(); if (type == Type.UNKNOWN && r.getCode() == 0) { logger.warn("Biff code zero found"); // Try a dimension record if (r.getLength() == 0xa) { logger.warn("Biff code zero found - trying a dimension record."); r.setType(Type.DIMENSION); } else { logger.warn("Biff code zero found - Ignoring."); } } if (type == Type.DIMENSION) { DimensionRecord dr = null; if (workbookBof.isBiff8()) { dr = new DimensionRecord(r); } else { dr = new DimensionRecord(r, DimensionRecord.biff7); } numRows = dr.getNumberOfRows(); numCols = dr.getNumberOfColumns(); cells = new Cell[numRows][numCols]; } else if (type == Type.LABELSST) { LabelSSTRecord label = new LabelSSTRecord(r, sharedStrings, formattingRecords, sheet); addCell(label); } else if (type == Type.RK || type == Type.RK2) { RKRecord rkr = new RKRecord(r, formattingRecords, sheet); if (formattingRecords.isDate(rkr.getXFIndex())) { DateCell dc = new DateRecord (rkr, rkr.getXFIndex(), formattingRecords, nineteenFour, sheet); addCell(dc); } else { addCell(rkr); } } else if (type == Type.HLINK) { HyperlinkRecord hr = new HyperlinkRecord(r, sheet, workbookSettings); hyperlinks.add(hr); } else if (type == Type.MERGEDCELLS) { MergedCellsRecord mc = new MergedCellsRecord(r, sheet); if (mergedCells == null) { mergedCells = mc.getRanges(); } else { Range[] newMergedCells = new Range[mergedCells.length + mc.getRanges().length]; System.arraycopy(mergedCells, 0, newMergedCells, 0, mergedCells.length); System.arraycopy(mc.getRanges(), 0, newMergedCells, mergedCells.length, mc.getRanges().length); mergedCells = newMergedCells; } } else if (type == Type.MULRK) { MulRKRecord mulrk = new MulRKRecord(r); // Get the individual cell records from the multiple record int num = mulrk.getNumberOfColumns(); int ixf = 0; for (int i = 0; i < num; i++) { ixf = mulrk.getXFIndex(i); NumberValue nv = new NumberValue (mulrk.getRow(), mulrk.getFirstColumn() + i, RKHelper.getDouble(mulrk.getRKNumber(i)), ixf, formattingRecords, sheet); if (formattingRecords.isDate(ixf)) { DateCell dc = new DateRecord(nv, ixf, formattingRecords, nineteenFour, sheet); addCell(dc); } else { nv.setNumberFormat(formattingRecords.getNumberFormat(ixf)); addCell(nv); } } } else if (type == Type.NUMBER) { NumberRecord nr = new NumberRecord(r, formattingRecords, sheet); if (formattingRecords.isDate(nr.getXFIndex())) { DateCell dc = new DateRecord(nr, nr.getXFIndex(), formattingRecords, nineteenFour, sheet); addCell(dc); } else { addCell(nr); } } else if (type == Type.BOOLERR) { BooleanRecord br = new BooleanRecord(r, formattingRecords, sheet); if (br.isError()) { ErrorRecord er = new ErrorRecord(br.getRecord(), formattingRecords, sheet); addCell(er); } else { addCell(br); } } else if (type == Type.PRINTGRIDLINES) { printGridLinesRecord = new PrintGridLinesRecord(r); settings.setPrintGridLines(printGridLinesRecord.getPrintGridLines()); } else if (type == Type.PRINTHEADERS) { printHeadersRecord = new PrintHeadersRecord(r); settings.setPrintHeaders(printHeadersRecord.getPrintHeaders()); } else if (type == Type.WINDOW2) { window2Record = null; if (workbookBof.isBiff8()) { window2Record = new Window2Record(r); } else { window2Record = new Window2Record(r, Window2Record.biff7); } settings.setShowGridLines(window2Record.getShowGridLines()); settings.setDisplayZeroValues(window2Record.getDisplayZeroValues()); settings.setSelected(true); settings.setPageBreakPreviewMode(window2Record.isPageBreakPreview()); } else if (type == Type.PANE) { PaneRecord pr = new PaneRecord(r); if (window2Record != null && window2Record.getFrozen()) { settings.setVerticalFreeze(pr.getRowsVisible()); settings.setHorizontalFreeze(pr.getColumnsVisible()); } } else if (type == Type.CONTINUE) { // don't know what this is for, but keep hold of it anyway continueRecord = new ContinueRecord(r); } else if (type == Type.NOTE) { if (!workbookSettings.getDrawingsDisabled()) { NoteRecord nr = new NoteRecord(r); // Get the comment for the object id Comment comment = (Comment) comments.remove (new Integer(nr.getObjectId())); if (comment == null) { logger.warn(" cannot find comment for note id " + nr.getObjectId() + "...ignoring"); } else { comment.setNote(nr); drawings.add(comment); addCellComment(comment.getColumn(), comment.getRow(), comment.getText(), comment.getWidth(), comment.getHeight()); } } } else if (type == Type.ARRAY) { ; } else if (type == Type.PROTECT) { ProtectRecord pr = new ProtectRecord(r); settings.setProtected(pr.isProtected()); } else if (type == Type.SHAREDFORMULA) { if (sharedFormula == null) { logger.warn("Shared template formula is null - " + "trying most recent formula template"); SharedFormulaRecord lastSharedFormula = (SharedFormulaRecord) sharedFormulas.get(sharedFormulas.size() - 1); if (lastSharedFormula != null) { sharedFormula = lastSharedFormula.getTemplateFormula(); } } SharedFormulaRecord sfr = new SharedFormulaRecord (r, sharedFormula, workbook, workbook, sheet); sharedFormulas.add(sfr); sharedFormula = null; } else if (type == Type.FORMULA || type == Type.FORMULA2) { FormulaRecord fr = new FormulaRecord(r, excelFile, formattingRecords, workbook, workbook, sheet, workbookSettings); if (fr.isShared()) { BaseSharedFormulaRecord prevSharedFormula = sharedFormula; sharedFormula = (BaseSharedFormulaRecord) fr.getFormula(); // See if it fits in any of the shared formulas sharedFormulaAdded = addToSharedFormulas(sharedFormula); if (sharedFormulaAdded) { sharedFormula = prevSharedFormula; } // If we still haven't added the previous base shared formula, // revert it to an ordinary formula and add it to the cell if (!sharedFormulaAdded && prevSharedFormula != null) { // Do nothing. It's possible for the biff file to contain the // record sequence // FORMULA-SHRFMLA-FORMULA-SHRFMLA-FORMULA-FORMULA-FORMULA // ie. it first lists all the formula templates, then it // lists all the individual formulas addCell(revertSharedFormula(prevSharedFormula)); } } else { Cell cell = fr.getFormula(); try { // See if the formula evaluates to date if (fr.getFormula().getType() == CellType.NUMBER_FORMULA) { NumberFormulaRecord nfr = (NumberFormulaRecord) fr.getFormula(); if (formattingRecords.isDate(nfr.getXFIndex())) { cell = new DateFormulaRecord(nfr, formattingRecords, workbook, workbook, nineteenFour, sheet); } } addCell(cell); } catch (FormulaException e) { // Something has gone wrong trying to read the formula data eg. it // might be unsupported biff7 data logger.warn (CellReferenceHelper.getCellReference (cell.getColumn(), cell.getRow()) + " " + e.getMessage()); } } } else if (type == Type.LABEL) { LabelRecord lr = null; if (workbookBof.isBiff8()) { lr = new LabelRecord(r, formattingRecords, sheet, workbookSettings); } else { lr = new LabelRecord(r, formattingRecords, sheet, workbookSettings, LabelRecord.biff7); } addCell(lr); } else if (type == Type.RSTRING) { RStringRecord lr = null; // RString records are obsolete in biff 8 Assert.verify(!workbookBof.isBiff8()); lr = new RStringRecord(r, formattingRecords, sheet, workbookSettings, RStringRecord.biff7); addCell(lr); } else if (type == Type.NAME) { ; } else if (type == Type.PASSWORD) { PasswordRecord pr = new PasswordRecord(r); settings.setPasswordHash(pr.getPasswordHash()); } else if (type == Type.ROW) { RowRecord rr = new RowRecord(r); // See if the row has anything funny about it if (!rr.isDefaultHeight() || !rr.matchesDefaultFontHeight() || rr.isCollapsed() || rr.hasDefaultFormat() || rr.getOutlineLevel() != 0) { rowProperties.add(rr); } } else if (type == Type.BLANK) { if (!workbookSettings.getIgnoreBlanks()) { BlankCell bc = new BlankCell(r, formattingRecords, sheet); addCell(bc); } } else if (type == Type.MULBLANK) { if (!workbookSettings.getIgnoreBlanks()) { MulBlankRecord mulblank = new MulBlankRecord(r); // Get the individual cell records from the multiple record int num = mulblank.getNumberOfColumns(); for (int i = 0; i < num; i++) { int ixf = mulblank.getXFIndex(i); MulBlankCell mbc = new MulBlankCell (mulblank.getRow(), mulblank.getFirstColumn() + i, ixf, formattingRecords, sheet); addCell(mbc); } } } else if (type == Type.SCL) { SCLRecord scl = new SCLRecord(r); settings.setZoomFactor(scl.getZoomFactor()); } else if (type == Type.COLINFO) { ColumnInfoRecord cir = new ColumnInfoRecord(r); columnInfosArray.add(cir); } else if (type == Type.HEADER) { HeaderRecord hr = null; if (workbookBof.isBiff8()) { hr = new HeaderRecord(r, workbookSettings); } else { hr = new HeaderRecord(r, workbookSettings, HeaderRecord.biff7); } HeaderFooter header = new HeaderFooter(hr.getHeader()); settings.setHeader(header); } else if (type == Type.FOOTER) { FooterRecord fr = null; if (workbookBof.isBiff8()) { fr = new FooterRecord(r, workbookSettings); } else { fr = new FooterRecord(r, workbookSettings, FooterRecord.biff7); } HeaderFooter footer = new HeaderFooter(fr.getFooter()); settings.setFooter(footer); } else if (type == Type.SETUP) { SetupRecord sr = new SetupRecord(r); // If the setup record has its not initialized bit set, then // use the sheet settings default values if (sr.getInitialized()) { if (sr.isPortrait()) { settings.setOrientation(PageOrientation.PORTRAIT); } else { settings.setOrientation(PageOrientation.LANDSCAPE); } if (sr.isRightDown()) { settings.setPageOrder(PageOrder.RIGHT_THEN_DOWN); } else { settings.setPageOrder(PageOrder.DOWN_THEN_RIGHT); } settings.setPaperSize(PaperSize.getPaperSize(sr.getPaperSize())); settings.setHeaderMargin(sr.getHeaderMargin()); settings.setFooterMargin(sr.getFooterMargin()); settings.setScaleFactor(sr.getScaleFactor()); settings.setPageStart(sr.getPageStart()); settings.setFitWidth(sr.getFitWidth()); settings.setFitHeight(sr.getFitHeight()); settings.setHorizontalPrintResolution (sr.getHorizontalPrintResolution()); settings.setVerticalPrintResolution(sr.getVerticalPrintResolution()); settings.setCopies(sr.getCopies()); if (workspaceOptions != null) { settings.setFitToPages(workspaceOptions.getFitToPages()); } } } else if (type == Type.WSBOOL) { workspaceOptions = new WorkspaceInformationRecord(r); } else if (type == Type.DEFCOLWIDTH) { DefaultColumnWidthRecord dcwr = new DefaultColumnWidthRecord(r); settings.setDefaultColumnWidth(dcwr.getWidth()); } else if (type == Type.DEFAULTROWHEIGHT) { DefaultRowHeightRecord drhr = new DefaultRowHeightRecord(r); if (drhr.getHeight() != 0) { settings.setDefaultRowHeight(drhr.getHeight()); } } else if (type == Type.CONDFMT) { ConditionalFormatRangeRecord cfrr = new ConditionalFormatRangeRecord(r); condFormat = new ConditionalFormat(cfrr); conditionalFormats.add(condFormat); } else if (type == Type.CF) { ConditionalFormatRecord cfr = new ConditionalFormatRecord(r); condFormat.addCondition(cfr); } else if (type == Type.FILTERMODE) { filterMode = new FilterModeRecord(r); } else if (type == Type.AUTOFILTERINFO) { autoFilterInfo = new AutoFilterInfoRecord(r); } else if (type == Type.AUTOFILTER) { if (!workbookSettings.getAutoFilterDisabled()) { AutoFilterRecord af = new AutoFilterRecord(r); if (autoFilter == null) { autoFilter = new AutoFilter(filterMode, autoFilterInfo); filterMode = null; autoFilterInfo = null; } autoFilter.add(af); } } else if (type == Type.LEFTMARGIN) { MarginRecord m = new LeftMarginRecord(r); settings.setLeftMargin(m.getMargin()); } else if (type == Type.RIGHTMARGIN) { MarginRecord m = new RightMarginRecord(r); settings.setRightMargin(m.getMargin()); } else if (type == Type.TOPMARGIN) { MarginRecord m = new TopMarginRecord(r); settings.setTopMargin(m.getMargin()); } else if (type == Type.BOTTOMMARGIN) { MarginRecord m = new BottomMarginRecord(r); settings.setBottomMargin(m.getMargin()); } else if (type == Type.HORIZONTALPAGEBREAKS) { HorizontalPageBreaksRecord dr = null; if (workbookBof.isBiff8()) { dr = new HorizontalPageBreaksRecord(r); } else { dr = new HorizontalPageBreaksRecord (r, HorizontalPageBreaksRecord.biff7); } rowBreaks = dr.getRowBreaks(); } else if (type == Type.VERTICALPAGEBREAKS) { VerticalPageBreaksRecord dr = null; if (workbookBof.isBiff8()) { dr = new VerticalPageBreaksRecord(r); } else { dr = new VerticalPageBreaksRecord (r, VerticalPageBreaksRecord.biff7); } columnBreaks = dr.getColumnBreaks(); } else if (type == Type.PLS) { plsRecord = new PLSRecord(r); // Check for Continue records while (excelFile.peek().getType() == Type.CONTINUE) { r.addContinueRecord(excelFile.next()); } } else if (type == Type.DVAL) { if (!workbookSettings.getCellValidationDisabled()) { DataValidityListRecord dvlr = new DataValidityListRecord(r); if (dvlr.getObjectId() == -1) { if (msoRecord != null && objRecord == null) { // there is a drop down associated with this data validation if (drawingData == null) { drawingData = new DrawingData(); } Drawing2 d2 = new Drawing2(msoRecord, drawingData, workbook.getDrawingGroup()); drawings.add(d2); msoRecord = null; dataValidation = new DataValidation(dvlr); } else { // no drop down dataValidation = new DataValidation(dvlr); } } else if (objectIds.contains(new Integer(dvlr.getObjectId()))) { dataValidation = new DataValidation(dvlr); } else { logger.warn("object id " + dvlr.getObjectId() + " referenced " + " by data validity list record not found - ignoring"); } } } else if (type == Type.HCENTER) { CentreRecord hr = new CentreRecord(r); settings.setHorizontalCentre(hr.isCentre()); } else if (type == Type.VCENTER) { CentreRecord vc = new CentreRecord(r); settings.setVerticalCentre(vc.isCentre()); } else if (type == Type.DV) { if (!workbookSettings.getCellValidationDisabled()) { DataValiditySettingsRecord dvsr = new DataValiditySettingsRecord(r, workbook, workbook, workbook.getSettings()); if (dataValidation != null) { dataValidation.add(dvsr); addCellValidation(dvsr.getFirstColumn(), dvsr.getFirstRow(), dvsr.getLastColumn(), dvsr.getLastRow(), dvsr); } else { logger.warn("cannot add data validity settings"); } } } else if (type == Type.OBJ) { objRecord = new ObjRecord(r); if (!workbookSettings.getDrawingsDisabled()) { // sometimes excel writes out continue records instead of drawing // records, so forcibly hack the stashed continue record into // a drawing record if (msoRecord == null && continueRecord != null) { logger.warn("Cannot find drawing record - using continue record"); msoRecord = new MsoDrawingRecord(continueRecord.getRecord()); continueRecord = null; } handleObjectRecord(objRecord, msoRecord, comments); objectIds.add(new Integer(objRecord.getObjectId())); } // Save chart handling until the chart BOF record appears if (objRecord.getType() != ObjRecord.CHART) { objRecord = null; msoRecord = null; } } else if (type == Type.MSODRAWING) { if (!workbookSettings.getDrawingsDisabled()) { if (msoRecord != null) { // For form controls, a rogue MSODRAWING record can crop up // after the main one. Add these into the drawing data drawingData.addRawData(msoRecord.getData()); } msoRecord = new MsoDrawingRecord(r); if (firstMsoRecord) { msoRecord.setFirst(); firstMsoRecord = false; } } } else if (type == Type.BUTTONPROPERTYSET) { buttonPropertySet = new ButtonPropertySetRecord(r); } else if (type == Type.CALCMODE) { CalcModeRecord cmr = new CalcModeRecord(r); settings.setAutomaticFormulaCalculation(cmr.isAutomatic()); } else if (type == Type.SAVERECALC) { SaveRecalcRecord cmr = new SaveRecalcRecord(r); settings.setRecalculateFormulasBeforeSave(cmr.getRecalculateOnSave()); } else if (type == Type.GUTS) { GuttersRecord gr = new GuttersRecord(r); maxRowOutlineLevel = gr.getRowOutlineLevel() > 0 ? gr.getRowOutlineLevel() - 1 : 0; maxColumnOutlineLevel = gr.getColumnOutlineLevel() > 0 ? gr.getRowOutlineLevel() - 1 : 0; } else if (type == Type.BOF) { BOFRecord br = new BOFRecord(r); Assert.verify(!br.isWorksheet()); int startpos = excelFile.getPos() - r.getLength() - 4; // Skip to the end of the nested bof // Thanks to Rohit for spotting this Record r2 = excelFile.next(); while (r2.getCode() != Type.EOF.value) { r2 = excelFile.next(); } if (br.isChart()) { if (!workbook.getWorkbookBof().isBiff8()) { logger.warn("only biff8 charts are supported"); } else { if (drawingData == null) { drawingData = new DrawingData(); } if (!workbookSettings.getDrawingsDisabled()) { Chart chart = new Chart(msoRecord, objRecord, drawingData, startpos, excelFile.getPos(), excelFile, workbookSettings); charts.add(chart); if (workbook.getDrawingGroup() != null) { workbook.getDrawingGroup().add(chart); } } } // Reset the drawing records msoRecord = null; objRecord = null; } // If this worksheet is just a chart, then the EOF reached // represents the end of the sheet as well as the end of the chart if (sheetBof.isChart()) { cont = false; } } else if (type == Type.EOF) { cont = false; } } // Restore the file to its accurate position excelFile.restorePos(); // Add any out of bounds cells if (outOfBoundsCells.size() > 0) { handleOutOfBoundsCells(); } // Add all the shared formulas to the sheet as individual formulas Iterator i = sharedFormulas.iterator(); while (i.hasNext()) { SharedFormulaRecord sfr = (SharedFormulaRecord) i.next(); Cell[] sfnr = sfr.getFormulas(formattingRecords, nineteenFour); for (int sf = 0; sf < sfnr.length; sf++) { addCell(sfnr[sf]); } } // If the last base shared formula wasn't added to the sheet, then // revert it to an ordinary formula and add it if (!sharedFormulaAdded && sharedFormula != null) { addCell(revertSharedFormula(sharedFormula)); } // If there is a stray msoDrawing record, then flag to the drawing group // that one has been omitted if (msoRecord != null && workbook.getDrawingGroup() != null) { workbook.getDrawingGroup().setDrawingsOmitted(msoRecord, objRecord); } // Check that the comments hash is empty if (!comments.isEmpty()) { logger.warn("Not all comments have a corresponding Note record"); } } /** * Sees if the shared formula belongs to any of the shared formula * groups * * @param fr the candidate shared formula * @return TRUE if the formula was added, FALSE otherwise */ private boolean addToSharedFormulas(BaseSharedFormulaRecord fr) { boolean added = false; SharedFormulaRecord sfr = null; for (int i=0, size=sharedFormulas.size(); i row && cells[row].length > col) { c = cells[row][col]; } if (c == null) { MulBlankCell mbc = new MulBlankCell(row, col, 0, formattingRecords, sheet); CellFeatures cf = new CellFeatures(); cf.setValidationSettings(dvsr); mbc.setCellFeatures(cf); addCell(mbc); } else if (c instanceof CellFeaturesAccessor) { // Check to see if the cell already contains a comment CellFeaturesAccessor cv = (CellFeaturesAccessor) c; CellFeatures cf = cv.getCellFeatures(); if (cf == null) { cf = new CellFeatures(); cv.setCellFeatures(cf); } cf.setValidationSettings(dvsr); } else { logger.warn("Not able to add comment to cell type " + c.getClass().getName() + " at " + CellReferenceHelper.getCellReference(col, row)); } } } } /** * Reads in the object record * * @param objRecord the obj record * @param msoRecord the mso drawing record read in earlier * @param comments the hash map of comments */ private void handleObjectRecord(ObjRecord objRecord, MsoDrawingRecord msoRecord, HashMap comments) { if (msoRecord == null) { logger.warn("Object record is not associated with a drawing " + " record - ignoring"); return; } try { // Handle images if (objRecord.getType() == ObjRecord.PICTURE) { if (drawingData == null) { drawingData = new DrawingData(); } Drawing drawing = new Drawing(msoRecord, objRecord, drawingData, workbook.getDrawingGroup(), sheet); drawings.add(drawing); return; } // Handle comments if (objRecord.getType() == ObjRecord.EXCELNOTE) { if (drawingData == null) { drawingData = new DrawingData(); } Comment comment = new Comment(msoRecord, objRecord, drawingData, workbook.getDrawingGroup(), workbookSettings); // Sometimes Excel writes out Continue records instead of drawing // records, so forcibly hack all of these into a drawing record Record r2 = excelFile.next(); if (r2.getType() == Type.MSODRAWING || r2.getType() == Type.CONTINUE) { MsoDrawingRecord mso = new MsoDrawingRecord(r2); comment.addMso(mso); r2 = excelFile.next(); } Assert.verify(r2.getType() == Type.TXO); TextObjectRecord txo = new TextObjectRecord(r2); comment.setTextObject(txo); r2 = excelFile.next(); Assert.verify(r2.getType() == Type.CONTINUE); ContinueRecord text = new ContinueRecord(r2); comment.setText(text); r2 = excelFile.next(); if (r2.getType() == Type.CONTINUE) { ContinueRecord formatting = new ContinueRecord(r2); comment.setFormatting(formatting); } comments.put(new Integer(comment.getObjectId()), comment); return; } // Handle combo boxes if (objRecord.getType() == ObjRecord.COMBOBOX) { if (drawingData == null) { drawingData = new DrawingData(); } ComboBox comboBox = new ComboBox(msoRecord, objRecord, drawingData, workbook.getDrawingGroup(), workbookSettings); drawings.add(comboBox); return; } // Handle check boxes if (objRecord.getType() == ObjRecord.CHECKBOX) { if (drawingData == null) { drawingData = new DrawingData(); } CheckBox checkBox = new CheckBox(msoRecord, objRecord, drawingData, workbook.getDrawingGroup(), workbookSettings); Record r2 = excelFile.next(); Assert.verify(r2.getType() == Type.MSODRAWING || r2.getType() == Type.CONTINUE); if (r2.getType() == Type.MSODRAWING || r2.getType() == Type.CONTINUE) { MsoDrawingRecord mso = new MsoDrawingRecord(r2); checkBox.addMso(mso); r2 = excelFile.next(); } Assert.verify(r2.getType() == Type.TXO); TextObjectRecord txo = new TextObjectRecord(r2); checkBox.setTextObject(txo); if (txo.getTextLength() == 0) { return; } r2 = excelFile.next(); Assert.verify(r2.getType() == Type.CONTINUE); ContinueRecord text = new ContinueRecord(r2); checkBox.setText(text); r2 = excelFile.next(); if (r2.getType() == Type.CONTINUE) { ContinueRecord formatting = new ContinueRecord(r2); checkBox.setFormatting(formatting); } drawings.add(checkBox); return; } // Handle form buttons if (objRecord.getType() == ObjRecord.BUTTON) { if (drawingData == null) { drawingData = new DrawingData(); } Button button = new Button(msoRecord, objRecord, drawingData, workbook.getDrawingGroup(), workbookSettings); Record r2 = excelFile.next(); Assert.verify(r2.getType() == Type.MSODRAWING || r2.getType() == Type.CONTINUE); if (r2.getType() == Type.MSODRAWING || r2.getType() == Type.CONTINUE) { MsoDrawingRecord mso = new MsoDrawingRecord(r2); button.addMso(mso); r2 = excelFile.next(); } Assert.verify(r2.getType() == Type.TXO); TextObjectRecord txo = new TextObjectRecord(r2); button.setTextObject(txo); r2 = excelFile.next(); Assert.verify(r2.getType() == Type.CONTINUE); ContinueRecord text = new ContinueRecord(r2); button.setText(text); r2 = excelFile.next(); if (r2.getType() == Type.CONTINUE) { ContinueRecord formatting = new ContinueRecord(r2); button.setFormatting(formatting); } drawings.add(button); return; } // Non-supported types which have multiple record types if (objRecord.getType() == ObjRecord.TEXT) { logger.warn(objRecord.getType() + " Object on sheet \"" + sheet.getName() + "\" not supported - omitting"); // Still need to add the drawing data to preserve the hierarchy if (drawingData == null) { drawingData = new DrawingData(); } drawingData.addData(msoRecord.getData()); Record r2 = excelFile.next(); Assert.verify(r2.getType() == Type.MSODRAWING || r2.getType() == Type.CONTINUE); if (r2.getType() == Type.MSODRAWING || r2.getType() == Type.CONTINUE) { MsoDrawingRecord mso = new MsoDrawingRecord(r2); drawingData.addRawData(mso.getData()); r2 = excelFile.next(); } Assert.verify(r2.getType() == Type.TXO); if (workbook.getDrawingGroup() != null) // can be null for Excel 95 { workbook.getDrawingGroup().setDrawingsOmitted(msoRecord, objRecord); } return; } // Handle other types if (objRecord.getType() != ObjRecord.CHART) { logger.warn(objRecord.getType() + " Object on sheet \"" + sheet.getName() + "\" not supported - omitting"); // Still need to add the drawing data to preserve the hierarchy if (drawingData == null) { drawingData = new DrawingData(); } drawingData.addData(msoRecord.getData()); if (workbook.getDrawingGroup() != null) // can be null for Excel 95 { workbook.getDrawingGroup().setDrawingsOmitted(msoRecord, objRecord); } return; } } catch (DrawingDataException e) { logger.warn(e.getMessage() + "...disabling drawings for the remainder of the workbook"); workbookSettings.setDrawingsDisabled(true); } } /** * Gets the drawing data - for use as part of the Escher debugging tool */ DrawingData getDrawingData() { return drawingData; } /** * Handle any cells which fall outside of the bounds specified within * the dimension record */ private void handleOutOfBoundsCells() { int resizedRows = numRows; int resizedCols = numCols; // First, determine the new bounds for (Iterator i = outOfBoundsCells.iterator() ; i.hasNext() ;) { Cell cell = (Cell) i.next(); resizedRows = Math.max(resizedRows, cell.getRow() + 1); resizedCols = Math.max(resizedCols, cell.getColumn() + 1); } // There used to be a warning here about exceeding the sheet dimensions, // but removed it when I added the ability to perform data validation // on entire rows or columns - in which case it would blow out any // existing dimensions // Resize the columns, if necessary if (resizedCols > numCols) { for (int r = 0 ; r < numRows ; r++) { Cell[] newRow = new Cell[resizedCols]; Cell[] oldRow = cells[r]; System.arraycopy(oldRow, 0, newRow, 0, oldRow.length); cells[r] = newRow; } } // Resize the rows, if necessary if (resizedRows > numRows) { Cell[][] newCells = new Cell[resizedRows][]; System.arraycopy(cells, 0, newCells, 0, cells.length); cells = newCells; // Create the new rows for (int i = numRows; i < resizedRows; i++) { newCells[i] = new Cell[resizedCols]; } } numRows = resizedRows; numCols = resizedCols; // Now add all the out of bounds cells into the new cells for (Iterator i = outOfBoundsCells.iterator(); i.hasNext(); ) { Cell cell = (Cell) i.next(); addCell(cell); } outOfBoundsCells.clear(); } /** * Accessor for the maximum column outline level * * @return the maximum column outline level, or 0 if no outlines/groups */ public int getMaxColumnOutlineLevel() { return maxColumnOutlineLevel; } /** * Accessor for the maximum row outline level * * @return the maximum row outline level, or 0 if no outlines/groups */ public int getMaxRowOutlineLevel() { return maxRowOutlineLevel; } } jexcelapi/src/jxl/read/biff/SharedBooleanFormulaRecord.java0000750000175000017500000001114611207000612024147 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2005 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.common.Assert; import jxl.common.Logger; import jxl.BooleanCell; import jxl.BooleanFormulaCell; import jxl.CellType; import jxl.biff.DoubleHelper; import jxl.biff.FormattingRecords; import jxl.biff.FormulaData; import jxl.biff.IntegerHelper; import jxl.biff.WorkbookMethods; import jxl.biff.formula.ExternalSheet; import jxl.biff.formula.FormulaException; import jxl.biff.formula.FormulaParser; /** * A shared boolean formula record */ public class SharedBooleanFormulaRecord extends BaseSharedFormulaRecord implements BooleanCell, FormulaData, BooleanFormulaCell { /** * The logger */ private static Logger logger = Logger.getLogger(SharedBooleanFormulaRecord.class); /** * The boolean value of this cell. If this cell represents an error, * this will be false */ private boolean value; /** * Constructs this number * * @param t the data * @param excelFile the excel biff data * @param v the value * @param fr the formatting records * @param es the external sheet * @param nt the name table * @param si the sheet */ public SharedBooleanFormulaRecord(Record t, File excelFile, boolean v, FormattingRecords fr, ExternalSheet es, WorkbookMethods nt, SheetImpl si) { super(t, fr, es, nt, si, excelFile.getPos()); value = v; } /** * Interface method which Gets the boolean value stored in this cell. If * this cell contains an error, then returns FALSE. Always query this cell * type using the accessor method isError() prior to calling this method * * @return TRUE if this cell contains TRUE, FALSE if it contains FALSE or * an error code */ public boolean getValue() { return value; } /** * Returns the numerical value as a string * * @return The numerical value of the formula as a string */ public String getContents() { // return Boolean.toString(value) - only available in 1.4 or later return (new Boolean(value)).toString(); } /** * Returns the cell type * * @return The cell type */ public CellType getType() { return CellType.BOOLEAN_FORMULA; } /** * Gets the raw bytes for the formula. This will include the * parsed tokens array. Used when copying spreadsheets * * @return the raw record data * @exception FormulaException */ public byte[] getFormulaData() throws FormulaException { if (!getSheet().getWorkbookBof().isBiff8()) { throw new FormulaException(FormulaException.BIFF8_SUPPORTED); } // Get the tokens, taking into account the mapping from shared // formula specific values into normal values FormulaParser fp = new FormulaParser (getTokens(), this, getExternalSheet(), getNameTable(), getSheet().getWorkbook().getSettings()); fp.parse(); byte[] rpnTokens = fp.getBytes(); byte[] data = new byte[rpnTokens.length + 22]; // Set the standard info for this cell IntegerHelper.getTwoBytes(getRow(), data, 0); IntegerHelper.getTwoBytes(getColumn(), data, 2); IntegerHelper.getTwoBytes(getXFIndex(), data, 4); data[6] = (byte) 1; data[8] = (byte) (value == true ? 1 : 0); data[12] = (byte) 0xff; data[13] = (byte) 0xff; // Now copy in the parsed tokens System.arraycopy(rpnTokens, 0, data, 22, rpnTokens.length); IntegerHelper.getTwoBytes(rpnTokens.length, data, 20); // Lop off the standard information byte[] d = new byte[data.length - 6]; System.arraycopy(data, 6, d, 0, data.length - 6); return d; } } jexcelapi/src/jxl/read/biff/HeaderRecord.java0000750000175000017500000000505111207000610021277 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.common.Logger; import jxl.WorkbookSettings; import jxl.biff.IntegerHelper; import jxl.biff.RecordData; import jxl.biff.StringHelper; /** * A workbook page header record */ public class HeaderRecord extends RecordData { /** * The logger */ private static Logger logger = Logger.getLogger(HeaderRecord.class); /** * The footer */ private String header; /** * Dummy indicators for overloading the constructor */ private static class Biff7 {}; public static Biff7 biff7 = new Biff7(); /** * Constructs this object from the raw data * * @param t the record data * @param ws the workbook settings */ HeaderRecord(Record t, WorkbookSettings ws) { super(t); byte[] data = getRecord().getData(); if (data.length == 0) { return; } int chars = IntegerHelper.getInt(data[0], data[1]); boolean unicode = data[2] == 1; if (unicode) { header = StringHelper.getUnicodeString(data, chars, 3); } else { header = StringHelper.getString(data, chars, 3, ws); } } /** * Constructs this object from the raw data * * @param t the record data * @param ws the workbook settings * @param dummy dummy record to indicate a biff7 document */ HeaderRecord(Record t, WorkbookSettings ws, Biff7 dummy) { super(t); byte[] data = getRecord().getData(); if (data.length == 0) { return; } int chars = data[0]; header = StringHelper.getString(data, chars, 1, ws); } /** * Gets the header string * * @return the header string */ String getHeader() { return header; } } jexcelapi/src/jxl/read/biff/SCLRecord.java0000750000175000017500000000333311207000612020533 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan, Adam Caldwell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.biff.IntegerHelper; import jxl.biff.RecordData; import jxl.biff.Type; /** * Class containing the zoom factor for display */ class SCLRecord extends RecordData { /** * The numerator of the zoom */ private int numerator; /** * The denominator of the zoom */ private int denominator; /** * Constructs this record from the raw data * @param r the record */ protected SCLRecord(Record r) { super(Type.SCL); byte[] data = r.getData(); numerator = IntegerHelper.getInt(data[0], data[1]); denominator = IntegerHelper.getInt(data[2], data[3]); } /** * Accessor for the zoom factor * * @return the zoom factor as the nearest integer percentage */ public int getZoomFactor() { return numerator * 100 / denominator; } } jexcelapi/src/jxl/read/biff/RKRecord.java0000750000175000017500000000545611207000612020436 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import java.text.DecimalFormat; import java.text.NumberFormat; import jxl.common.Logger; import jxl.CellType; import jxl.NumberCell; import jxl.biff.FormattingRecords; import jxl.biff.IntegerHelper; /** * An individual RK record */ class RKRecord extends CellValue implements NumberCell { /** * The logger */ private static Logger logger = Logger.getLogger(RKRecord.class); /** * The value */ private double value; /** * The java equivalent of the excel format */ private NumberFormat format; /** * The formatter to convert the value into a string */ private static DecimalFormat defaultFormat = new DecimalFormat("#.###"); /** * Constructs this object from the raw data * * @param t the raw data * @param fr the available cell formats * @param si the sheet */ public RKRecord(Record t, FormattingRecords fr, SheetImpl si) { super(t, fr, si); byte[] data = getRecord().getData(); int rknum = IntegerHelper.getInt(data[6], data[7], data[8], data[9]); value = RKHelper.getDouble(rknum); // Now get the number format format = fr.getNumberFormat(getXFIndex()); if (format == null) { format = defaultFormat; } } /** * Accessor for the value * * @return the value */ public double getValue() { return value; } /** * Returns the contents of this cell as a string * * @return the value formatted into a string */ public String getContents() { return format.format(value); } /** * Accessor for the cell type * * @return the cell type */ public CellType getType() { return CellType.NUMBER; } /** * Gets the NumberFormat used to format this cell. This is the java * equivalent of the Excel format * * @return the NumberFormat used to format the cell */ public NumberFormat getNumberFormat() { return format; } } jexcelapi/src/jxl/read/biff/RowRecord.java0000750000175000017500000001026211207000612020660 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2001 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.common.Logger; import jxl.biff.IntegerHelper; import jxl.biff.RecordData; /** * A row record */ public class RowRecord extends RecordData { /** * The logger */ private static Logger logger = Logger.getLogger(RowRecord.class); /** * The number of this row */ private int rowNumber; /** * The height of this row */ private int rowHeight; /** * Flag to indicate whether this row is collapsed or not */ private boolean collapsed; /** * Indicates whether this row has an explicit default format */ private boolean defaultFormat; /** * Indicates whether the row record height matches the default font height */ private boolean matchesDefFontHeight; /** * The (default) xf index for cells on this row */ private int xfIndex; /** * The outline level of the row */ private int outlineLevel; /** * Is this the icon indicator row of a group? */ private boolean groupStart; /** * Indicates that the row is default height */ private static final int defaultHeightIndicator = 0xff; /** * Constructs this object from the raw data * * @param t the raw data */ RowRecord(Record t) { super(t); byte[] data = getRecord().getData(); rowNumber = IntegerHelper.getInt(data[0], data[1]); rowHeight = IntegerHelper.getInt(data[6], data[7]); int options = IntegerHelper.getInt(data[12], data[13], data[14], data[15]); outlineLevel = (options & 0x7); groupStart = (options & 0x10) != 0; collapsed = (options & 0x20) != 0; matchesDefFontHeight = (options & 0x40) == 0; defaultFormat = (options & 0x80) != 0; xfIndex = (options & 0x0fff0000) >> 16; } /** * Interrogates whether this row is of default height * * @return TRUE if this is set to the default height, FALSE otherwise */ boolean isDefaultHeight() { return rowHeight == defaultHeightIndicator; } /** * Interrogates this row to see whether it matches the default font height * * @return TRUE if this matches the default font height, FALSE otherwise */ public boolean matchesDefaultFontHeight() { return matchesDefFontHeight; } /** * Gets the row number * * @return the number of this row */ public int getRowNumber() { return rowNumber; } /** * Accessor for the row's outline level * * @return the row's outline level */ public int getOutlineLevel() { return outlineLevel; } /** * Accessor for row's groupStart value * * @return the row's groupStart value */ public boolean getGroupStart() { return groupStart; } /** * Gets the height of the row * * @return the row height */ public int getRowHeight() { return rowHeight; } /** * Queries whether the row is collapsed * * @return the collapsed indicator */ public boolean isCollapsed() { return collapsed; } /** * Gets the default xf index for this row * * @return the xf index */ public int getXFIndex() { return xfIndex; } /** * Queries whether the row has a specific default cell format applied * * @return the default cell format */ public boolean hasDefaultFormat() { return defaultFormat; } } jexcelapi/src/jxl/read/biff/DimensionRecord.java0000750000175000017500000000625411207000610022042 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.common.Logger; import jxl.biff.IntegerHelper; import jxl.biff.RecordData; /** * Contains the cell dimensions of this worksheet */ class DimensionRecord extends RecordData { /** * The logger */ private static Logger logger = Logger.getLogger(DimensionRecord.class); /** * The number of rows in this sheet */ private int numRows; /** * The number of columns in this worksheet */ private int numCols; /** * Dummy indicators for overloading the constructor */ private static class Biff7 {}; public static Biff7 biff7 = new Biff7(); /** * Constructs the dimensions from the raw data * * @param t the raw data */ public DimensionRecord(Record t) { super(t); byte[] data = t.getData(); // Sometimes, if the spreadsheet is being generated by dodgy VB modules, // even though the excel format is biff8, the dimension record is // generated in the old biff 7 format. This horrible if construct // handles that eventuality if (data.length == 10) { read10ByteData(data); } else { read14ByteData(data); } } /** * Constructs the dimensions from the raw data * * @param t the raw data * @param biff7 an indicator to initialise this record for biff 7 format */ public DimensionRecord(Record t, Biff7 biff7) { super(t); byte[] data = t.getData(); read10ByteData(data); } /** * Reads in the data for data records of length 10 * @param data the data to read */ private void read10ByteData(byte[] data) { numRows = IntegerHelper.getInt(data[2], data[3]); numCols = IntegerHelper.getInt(data[6], data[7]); } /** * Reads in the data for data records of length 14 * @param data the data to read */ private void read14ByteData(byte[] data) { numRows = IntegerHelper.getInt(data[4], data[5], data[6], data[7]); numCols = IntegerHelper.getInt(data[10], data[11]); } /** * Accessor for the number of rows in this sheet * * @return the number of rows */ public int getNumberOfRows() { return numRows; } /** * Accessor for the number of columns in this sheet * * @return the number of columns */ public int getNumberOfColumns() { return numCols; } } jexcelapi/src/jxl/read/biff/SharedStringFormulaRecord.java0000750000175000017500000001610011207000612024031 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.common.Assert; import jxl.common.Logger; import jxl.CellType; import jxl.LabelCell; import jxl.StringFormulaCell; import jxl.WorkbookSettings; import jxl.biff.FormattingRecords; import jxl.biff.FormulaData; import jxl.biff.IntegerHelper; import jxl.biff.StringHelper; import jxl.biff.Type; import jxl.biff.WorkbookMethods; import jxl.biff.formula.ExternalSheet; import jxl.biff.formula.FormulaException; import jxl.biff.formula.FormulaParser; /** * A string formula record, manufactured out of the Shared Formula * "optimization" */ public class SharedStringFormulaRecord extends BaseSharedFormulaRecord implements LabelCell, FormulaData, StringFormulaCell { /** * The logger */ private static Logger logger = Logger.getLogger (SharedStringFormulaRecord.class); /** * The value of this string formula */ private String value; // Dummy value for overloading the constructor when the string evaluates // to null private static final class EmptyString {}; protected static final EmptyString EMPTY_STRING = new EmptyString(); /** * Constructs this string formula * * @param t the record * @param excelFile the excel file * @param fr the formatting record * @param es the external sheet * @param nt the workbook * @param si the sheet * @param ws the workbook settings */ public SharedStringFormulaRecord(Record t, File excelFile, FormattingRecords fr, ExternalSheet es, WorkbookMethods nt, SheetImpl si, WorkbookSettings ws) { super(t, fr, es, nt, si, excelFile.getPos()); int pos = excelFile.getPos(); // Save the position in the excel file int filepos = excelFile.getPos(); // Look for the string record in one of the records after the // formula. Put a cap on it to prevent ednas Record nextRecord = excelFile.next(); int count = 0; while (nextRecord.getType() != Type.STRING && count < 4) { nextRecord = excelFile.next(); count++; } Assert.verify(count < 4, " @ " + pos); byte[] stringData = nextRecord.getData(); // Read in any continuation records nextRecord = excelFile.peek(); while (nextRecord.getType() == Type.CONTINUE) { nextRecord = excelFile.next(); // move the pointer within the data byte[] d = new byte[stringData.length + nextRecord.getLength() - 1]; System.arraycopy(stringData, 0, d, 0, stringData.length); System.arraycopy(nextRecord.getData(), 1, d, stringData.length, nextRecord.getLength() - 1); stringData = d; nextRecord = excelFile.peek(); } int chars = IntegerHelper.getInt(stringData[0], stringData[1]); boolean unicode = false; int startpos = 3; if (stringData.length == chars + 2) { // String might only consist of a one byte length indicator, instead // of the more normal 2 startpos = 2; unicode = false; } else if (stringData[2] == 0x1) { // unicode string, two byte length indicator startpos = 3; unicode = true; } else { // ascii string, two byte length indicator startpos = 3; unicode = false; } if (!unicode) { value = StringHelper.getString(stringData, chars, startpos, ws); } else { value = StringHelper.getUnicodeString(stringData, chars, startpos); } // Restore the position in the excel file, to enable the SHRFMLA // record to be picked up excelFile.setPos(filepos); } /** * Constructs this string formula * * @param t the record * @param excelFile the excel file * @param fr the formatting record * @param es the external sheet * @param nt the workbook * @param si the sheet * @param dummy the overload indicator */ public SharedStringFormulaRecord(Record t, File excelFile, FormattingRecords fr, ExternalSheet es, WorkbookMethods nt, SheetImpl si, EmptyString dummy) { super(t, fr, es, nt, si, excelFile.getPos()); value = ""; } /** * Accessor for the value * * @return the value */ public String getString() { return value; } /** * Accessor for the contents as a string * * @return the value as a string */ public String getContents() { return value; } /** * Accessor for the cell type * * @return the cell type */ public CellType getType() { return CellType.STRING_FORMULA; } /** * Gets the raw bytes for the formula. This will include the * parsed tokens array. Used when copying spreadsheets * * @return the raw record data * @exception FormulaException */ public byte[] getFormulaData() throws FormulaException { if (!getSheet().getWorkbookBof().isBiff8()) { throw new FormulaException(FormulaException.BIFF8_SUPPORTED); } // Get the tokens, taking into account the mapping from shared // formula specific values into normal values FormulaParser fp = new FormulaParser (getTokens(), this, getExternalSheet(), getNameTable(), getSheet().getWorkbook().getSettings()); fp.parse(); byte[] rpnTokens = fp.getBytes(); byte[] data = new byte[rpnTokens.length + 22]; // Set the standard info for this cell IntegerHelper.getTwoBytes(getRow(), data, 0); IntegerHelper.getTwoBytes(getColumn(), data, 2); IntegerHelper.getTwoBytes(getXFIndex(), data, 4); // Set the two most significant bytes of the value to be 0xff in // order to identify this as a string data[6] = 0; data[12] = -1; data[13] = -1; // Now copy in the parsed tokens System.arraycopy(rpnTokens, 0, data, 22, rpnTokens.length); IntegerHelper.getTwoBytes(rpnTokens.length, data, 20); // Lop off the standard information byte[] d = new byte[data.length - 6]; System.arraycopy(data, 6, d, 0, data.length - 6); return d; } } jexcelapi/src/jxl/read/biff/SetupRecord.java0000750000175000017500000001335611207000612021220 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.common.Logger; import jxl.biff.DoubleHelper; import jxl.biff.IntegerHelper; import jxl.biff.RecordData; import jxl.biff.Type; /** * Contains the page set up for a sheet */ public class SetupRecord extends RecordData { // The logger private static Logger logger = Logger.getLogger(SetupRecord.class); /** * The raw data */ private byte[] data; /** * The orientation flag */ private boolean portraitOrientation; /** * The Page Order flag */ private boolean pageOrder; /** * The header margin */ private double headerMargin; /** * The footer margin */ private double footerMargin; /** * The paper size */ private int paperSize; /** * The scale factor */ private int scaleFactor; /** * The page start */ private int pageStart; /** * The fit width */ private int fitWidth; /** * The fit height */ private int fitHeight; /** * The horizontal print resolution */ private int horizontalPrintResolution; /** * The vertical print resolution */ private int verticalPrintResolution; /** * The number of copies */ private int copies; /** * Indicates whether the setup data should be initiliazed in the setup * box */ private boolean initialized; /** * Constructor which creates this object from the binary data * * @param t the record */ SetupRecord(Record t) { super(Type.SETUP); data = t.getData(); paperSize = IntegerHelper.getInt(data[0], data[1]); scaleFactor = IntegerHelper.getInt(data[2], data[3]); pageStart = IntegerHelper.getInt(data[4], data[5]); fitWidth = IntegerHelper.getInt(data[6], data[7]); fitHeight = IntegerHelper.getInt(data[8], data[9]); horizontalPrintResolution = IntegerHelper.getInt(data[12], data[13]); verticalPrintResolution = IntegerHelper.getInt(data[14], data[15]); copies = IntegerHelper.getInt(data[32], data[33]); headerMargin = DoubleHelper.getIEEEDouble(data, 16); footerMargin = DoubleHelper.getIEEEDouble(data, 24); int grbit = IntegerHelper.getInt(data[10], data[11]); pageOrder = ((grbit & 0x01) != 0); portraitOrientation = ((grbit & 0x02) != 0); initialized = ( (grbit & 0x04) == 0); } /** * Accessor for the orientation. Called when copying sheets * * @return TRUE if the orientation is portrait, FALSE if it is landscape */ public boolean isPortrait() { return portraitOrientation; } /** * Accessor for the page order. Called when copying sheets * * @return TRUE if the page order is Left to Right, then Down, otherwise * FALSE */ public boolean isRightDown() { return pageOrder; } /** * Accessor for the header. Called when copying sheets * * @return the header margin */ public double getHeaderMargin() { return headerMargin; } /** * Accessor for the footer. Called when copying sheets * * @return the footer margin */ public double getFooterMargin() { return footerMargin; } /** * Accessor for the paper size. Called when copying sheets * * @return the footer margin */ public int getPaperSize() { return paperSize; } /** * Accessor for the scale factor. Called when copying sheets * * @return the scale factor */ public int getScaleFactor() { return scaleFactor; } /** * Accessor for the page height. called when copying sheets * * @return the page to start printing at */ public int getPageStart() { return pageStart; } /** * Accessor for the fit width. Called when copying sheets * * @return the fit width */ public int getFitWidth() { return fitWidth; } /** * Accessor for the fit height. Called when copying sheets * * @return the fit height */ public int getFitHeight() { return fitHeight; } /** * The horizontal print resolution. Called when copying sheets * * @return the horizontal print resolution */ public int getHorizontalPrintResolution() { return horizontalPrintResolution; } /** * Accessor for the vertical print resolution. Called when copying sheets * * @return an vertical print resolution */ public int getVerticalPrintResolution() { return verticalPrintResolution; } /** * Accessor for the number of copies * * @return the number of copies */ public int getCopies() { return copies; } /** * Accessor for the initialized flag * * @return whether the print page setup should be initialized in the dialog * box */ public boolean getInitialized() { return initialized; } } jexcelapi/src/jxl/read/biff/WorkbookParser.java0000750000175000017500000010037311263366234021750 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import jxl.common.Assert; import jxl.common.Logger; import jxl.Cell; import jxl.Range; import jxl.Sheet; import jxl.Workbook; import jxl.WorkbookSettings; import jxl.biff.BuiltInName; import jxl.biff.CellReferenceHelper; import jxl.biff.EmptyCell; import jxl.biff.FontRecord; import jxl.biff.Fonts; import jxl.biff.FormatRecord; import jxl.biff.FormattingRecords; import jxl.biff.NameRangeException; import jxl.biff.NumFormatRecordsException; import jxl.biff.PaletteRecord; import jxl.biff.RangeImpl; import jxl.biff.StringHelper; import jxl.biff.Type; import jxl.biff.WorkbookMethods; import jxl.biff.XCTRecord; import jxl.biff.XFRecord; import jxl.biff.drawing.DrawingGroup; import jxl.biff.drawing.MsoDrawingGroupRecord; import jxl.biff.drawing.Origin; import jxl.biff.formula.ExternalSheet; /** * Parses the biff file passed in, and builds up an internal representation of * the spreadsheet */ public class WorkbookParser extends Workbook implements ExternalSheet, WorkbookMethods { /** * The logger */ private static Logger logger = Logger.getLogger(WorkbookParser.class); /** * The excel file */ private File excelFile; /** * The number of open bofs */ private int bofs; /** * Indicates whether or not the dates are based around the 1904 date system */ private boolean nineteenFour; /** * The shared string table */ private SSTRecord sharedStrings; /** * The names of all the worksheets */ private ArrayList boundsheets; /** * The xf records */ private FormattingRecords formattingRecords; /** * The fonts used by this workbook */ private Fonts fonts; /** * The sheets contained in this workbook */ private ArrayList sheets; /** * The last sheet accessed */ private SheetImpl lastSheet; /** * The index of the last sheet retrieved */ private int lastSheetIndex; /** * The named records found in this workbook */ private HashMap namedRecords; /** * The list of named records */ private ArrayList nameTable; /** * The list of add in functions */ private ArrayList addInFunctions; /** * The external sheet record. Used by formulas, and names */ private ExternalSheetRecord externSheet; /** * The list of supporting workbooks - used by formulas */ private ArrayList supbooks; /** * The bof record for this workbook */ private BOFRecord workbookBof; /** * The Mso Drawing Group record for this workbook */ private MsoDrawingGroupRecord msoDrawingGroup; /** * The property set record associated with this workbook */ private ButtonPropertySetRecord buttonPropertySet; /** * Workbook protected flag */ private boolean wbProtected; /** * Contains macros flag */ private boolean containsMacros; /** * The workbook settings */ private WorkbookSettings settings; /** * The drawings contained in this workbook */ private DrawingGroup drawingGroup; /** * The country record (containing the language and regional settings) * for this workbook */ private CountryRecord countryRecord; private ArrayList xctRecords; /** * Constructs this object from the raw excel data * * @param f the excel 97 biff file * @param s the workbook settings */ public WorkbookParser(File f, WorkbookSettings s) { super(); excelFile = f; boundsheets = new ArrayList(10); fonts = new Fonts(); formattingRecords = new FormattingRecords(fonts); sheets = new ArrayList(10); supbooks = new ArrayList(10); namedRecords = new HashMap(); lastSheetIndex = -1; wbProtected = false; containsMacros = false; settings = s; xctRecords = new ArrayList(10); } /** * Gets the sheets within this workbook. * NOTE: Use of this method for * very large worksheets can cause performance and out of memory problems. * Use the alternative method getSheet() to retrieve each sheet individually * * @return an array of the individual sheets */ public Sheet[] getSheets() { Sheet[] sheetArray = new Sheet[getNumberOfSheets()]; return (Sheet[]) sheets.toArray(sheetArray); } /** * Interface method from WorkbookMethods - gets the specified * sheet within this workbook * * @param index the zero based index of the required sheet * @return The sheet specified by the index */ public Sheet getReadSheet(int index) { return getSheet(index); } /** * Gets the specified sheet within this workbook * * @param index the zero based index of the required sheet * @return The sheet specified by the index */ public Sheet getSheet(int index) { // First see if the last sheet index is the same as this sheet index. // If so, then the same sheet is being re-requested, so simply // return it instead of rereading it if ((lastSheet != null) && lastSheetIndex == index) { return lastSheet; } // Flush out all of the cached data in the last sheet if (lastSheet != null) { lastSheet.clear(); if (!settings.getGCDisabled()) { System.gc(); } } lastSheet = (SheetImpl) sheets.get(index); lastSheetIndex = index; lastSheet.readSheet(); return lastSheet; } /** * Gets the sheet with the specified name from within this workbook * * @param name the sheet name * @return The sheet with the specified name, or null if it is not found */ public Sheet getSheet(String name) { // Iterate through the boundsheet records int pos = 0; boolean found = false; Iterator i = boundsheets.iterator(); BoundsheetRecord br = null; while (i.hasNext() && !found) { br = (BoundsheetRecord) i.next(); if (br.getName().equals(name)) { found = true; } else { pos++; } } return found ? getSheet(pos) : null; } /** * Gets the sheet names * * @return an array of strings containing the sheet names */ public String[] getSheetNames() { String[] names = new String[boundsheets.size()]; BoundsheetRecord br = null; for (int i = 0; i < names.length; i++) { br = (BoundsheetRecord) boundsheets.get(i); names[i] = br.getName(); } return names; } /** * Package protected function which gets the real internal sheet index * based upon the external sheet reference. This is used for extern sheet * references which are specified in formulas * * @param index the external sheet reference * @return the actual sheet index */ public int getExternalSheetIndex(int index) { // For biff7, the whole external reference thing works differently // Hopefully for our purposes sheet references will all be local if (workbookBof.isBiff7()) { return index; } Assert.verify(externSheet != null); int firstTab = externSheet.getFirstTabIndex(index); return firstTab; } /** * Package protected function which gets the real internal sheet index * based upon the external sheet reference. This is used for extern sheet * references which are specified in formulas * * @param index the external sheet reference * @return the actual sheet index */ public int getLastExternalSheetIndex(int index) { // For biff7, the whole external reference thing works differently // Hopefully for our purposes sheet references will all be local if (workbookBof.isBiff7()) { return index; } Assert.verify(externSheet != null); int lastTab = externSheet.getLastTabIndex(index); return lastTab; } /** * Gets the name of the external sheet specified by the index * * @param index the external sheet index * @return the name of the external sheet */ public String getExternalSheetName(int index) { // For biff7, the whole external reference thing works differently // Hopefully for our purposes sheet references will all be local if (workbookBof.isBiff7()) { BoundsheetRecord br = (BoundsheetRecord) boundsheets.get(index); return br.getName(); } int supbookIndex = externSheet.getSupbookIndex(index); SupbookRecord sr = (SupbookRecord) supbooks.get(supbookIndex); int firstTab = externSheet.getFirstTabIndex(index); int lastTab = externSheet.getLastTabIndex(index); String firstTabName = ""; String lastTabName = ""; if (sr.getType() == SupbookRecord.INTERNAL) { // It's an internal reference - get the name from the boundsheets list if (firstTab == 65535) { firstTabName = "#REF"; } else { BoundsheetRecord br = (BoundsheetRecord) boundsheets.get(firstTab); firstTabName = br.getName(); } if (lastTab==65535) { lastTabName = "#REF"; } else { BoundsheetRecord br = (BoundsheetRecord) boundsheets.get(lastTab); lastTabName = br.getName(); } String sheetName = (firstTab == lastTab) ? firstTabName : firstTabName + ':' + lastTabName; // if the sheet name contains apostrophes then escape them sheetName = sheetName.indexOf('\'') == -1 ? sheetName : StringHelper.replace(sheetName, "\'", "\'\'"); // if the sheet name contains spaces, then enclose in quotes return sheetName.indexOf(' ') == -1 ? sheetName : '\'' + sheetName + '\''; } else if (sr.getType() == SupbookRecord.EXTERNAL) { // External reference - get the sheet name from the supbook record StringBuffer sb = new StringBuffer(); java.io.File fl = new java.io.File(sr.getFileName()); sb.append("'"); sb.append(fl.getAbsolutePath()); sb.append("["); sb.append(fl.getName()); sb.append("]"); sb.append((firstTab == 65535) ? "#REF" : sr.getSheetName(firstTab)); if (lastTab != firstTab) { sb.append(sr.getSheetName(lastTab)); } sb.append("'"); return sb.toString(); } // An unknown supbook - return unkown logger.warn("Unknown Supbook 3"); return "[UNKNOWN]"; } /** * Gets the name of the external sheet specified by the index * * @param index the external sheet index * @return the name of the external sheet */ public String getLastExternalSheetName(int index) { // For biff7, the whole external reference thing works differently // Hopefully for our purposes sheet references will all be local if (workbookBof.isBiff7()) { BoundsheetRecord br = (BoundsheetRecord) boundsheets.get(index); return br.getName(); } int supbookIndex = externSheet.getSupbookIndex(index); SupbookRecord sr = (SupbookRecord) supbooks.get(supbookIndex); int lastTab = externSheet.getLastTabIndex(index); if (sr.getType() == SupbookRecord.INTERNAL) { // It's an internal reference - get the name from the boundsheets list if (lastTab == 65535) { return "#REF"; } else { BoundsheetRecord br = (BoundsheetRecord) boundsheets.get(lastTab); return br.getName(); } } else if (sr.getType() == SupbookRecord.EXTERNAL) { // External reference - get the sheet name from the supbook record StringBuffer sb = new StringBuffer(); java.io.File fl = new java.io.File(sr.getFileName()); sb.append("'"); sb.append(fl.getAbsolutePath()); sb.append("["); sb.append(fl.getName()); sb.append("]"); sb.append((lastTab == 65535) ? "#REF" : sr.getSheetName(lastTab)); sb.append("'"); return sb.toString(); } // An unknown supbook - return unkown logger.warn("Unknown Supbook 4"); return "[UNKNOWN]"; } /** * Returns the number of sheets in this workbook * * @return the number of sheets in this workbook */ public int getNumberOfSheets() { return sheets.size(); } /** * Closes this workbook, and frees makes any memory allocated available * for garbage collection */ public void close() { if (lastSheet != null) { lastSheet.clear(); } excelFile.clear(); if (!settings.getGCDisabled()) { System.gc(); } } /** * Adds the sheet to the end of the array * * @param s the sheet to add */ final void addSheet(Sheet s) { sheets.add(s); } /** * Does the hard work of building up the object graph from the excel bytes * * @exception BiffException * @exception PasswordException if the workbook is password protected */ protected void parse() throws BiffException, PasswordException { Record r = null; BOFRecord bof = new BOFRecord(excelFile.next()); workbookBof = bof; bofs++; if (!bof.isBiff8() && !bof.isBiff7()) { throw new BiffException(BiffException.unrecognizedBiffVersion); } if (!bof.isWorkbookGlobals()) { throw new BiffException(BiffException.expectedGlobals); } ArrayList continueRecords = new ArrayList(); ArrayList localNames = new ArrayList(); nameTable = new ArrayList(); addInFunctions = new ArrayList(); // Skip to the first worksheet while (bofs == 1) { r = excelFile.next(); if (r.getType() == Type.SST) { continueRecords.clear(); Record nextrec = excelFile.peek(); while (nextrec.getType() == Type.CONTINUE) { continueRecords.add(excelFile.next()); nextrec = excelFile.peek(); } // cast the array Record[] records = new Record[continueRecords.size()]; records = (Record[]) continueRecords.toArray(records); sharedStrings = new SSTRecord(r, records, settings); } else if (r.getType() == Type.FILEPASS) { throw new PasswordException(); } else if (r.getType() == Type.NAME) { NameRecord nr = null; if (bof.isBiff8()) { nr = new NameRecord(r, settings, nameTable.size()); } else { nr = new NameRecord(r, settings, nameTable.size(), NameRecord.biff7); } // Add all local and global names to the name table in order to // preserve the indexing nameTable.add(nr); if (nr.isGlobal()) { namedRecords.put(nr.getName(), nr); } else { localNames.add(nr); } } else if (r.getType() == Type.FONT) { FontRecord fr = null; if (bof.isBiff8()) { fr = new FontRecord(r, settings); } else { fr = new FontRecord(r, settings, FontRecord.biff7); } fonts.addFont(fr); } else if (r.getType() == Type.PALETTE) { PaletteRecord palette = new PaletteRecord(r); formattingRecords.setPalette(palette); } else if (r.getType() == Type.NINETEENFOUR) { NineteenFourRecord nr = new NineteenFourRecord(r); nineteenFour = nr.is1904(); } else if (r.getType() == Type.FORMAT) { FormatRecord fr = null; if (bof.isBiff8()) { fr = new FormatRecord(r, settings, FormatRecord.biff8); } else { fr = new FormatRecord(r, settings, FormatRecord.biff7); } try { formattingRecords.addFormat(fr); } catch (NumFormatRecordsException e) { // This should not happen. Bomb out Assert.verify(false, e.getMessage()); } } else if (r.getType() == Type.XF) { XFRecord xfr = null; if (bof.isBiff8()) { xfr = new XFRecord(r, settings, XFRecord.biff8); } else { xfr = new XFRecord(r, settings, XFRecord.biff7); } try { formattingRecords.addStyle(xfr); } catch (NumFormatRecordsException e) { // This should not happen. Bomb out Assert.verify(false, e.getMessage()); } } else if (r.getType() == Type.BOUNDSHEET) { BoundsheetRecord br = null; if (bof.isBiff8()) { br = new BoundsheetRecord(r, settings); } else { br = new BoundsheetRecord(r, BoundsheetRecord.biff7); } if (br.isSheet()) { boundsheets.add(br); } else if (br.isChart() && !settings.getDrawingsDisabled()) { boundsheets.add(br); } } else if (r.getType() == Type.EXTERNSHEET) { if (bof.isBiff8()) { externSheet = new ExternalSheetRecord(r, settings); } else { externSheet = new ExternalSheetRecord(r, settings, ExternalSheetRecord.biff7); } } else if (r.getType() == Type.XCT) { XCTRecord xctr = new XCTRecord(r); xctRecords.add(xctr); } else if (r.getType() == Type.CODEPAGE) { CodepageRecord cr = new CodepageRecord(r); settings.setCharacterSet(cr.getCharacterSet()); } else if (r.getType() == Type.SUPBOOK) { Record nextrec = excelFile.peek(); while (nextrec.getType() == Type.CONTINUE) { r.addContinueRecord(excelFile.next()); nextrec = excelFile.peek(); } SupbookRecord sr = new SupbookRecord(r, settings); supbooks.add(sr); } else if (r.getType() == Type.EXTERNNAME) { ExternalNameRecord enr = new ExternalNameRecord(r, settings); if (enr.isAddInFunction()) { addInFunctions.add(enr.getName()); } } else if (r.getType() == Type.PROTECT) { ProtectRecord pr = new ProtectRecord(r); wbProtected = pr.isProtected(); } else if (r.getType() == Type.OBJPROJ) { containsMacros = true; } else if (r.getType() == Type.COUNTRY) { countryRecord = new CountryRecord(r); } else if (r.getType() == Type.MSODRAWINGGROUP) { if (!settings.getDrawingsDisabled()) { msoDrawingGroup = new MsoDrawingGroupRecord(r); if (drawingGroup == null) { drawingGroup = new DrawingGroup(Origin.READ); } drawingGroup.add(msoDrawingGroup); Record nextrec = excelFile.peek(); while (nextrec.getType() == Type.CONTINUE) { drawingGroup.add(excelFile.next()); nextrec = excelFile.peek(); } } } else if (r.getType() == Type.BUTTONPROPERTYSET) { buttonPropertySet = new ButtonPropertySetRecord(r); } else if (r.getType() == Type.EOF) { bofs--; } else if (r.getType() == Type.REFRESHALL) { RefreshAllRecord rfm = new RefreshAllRecord(r); settings.setRefreshAll(rfm.getRefreshAll()); } else if (r.getType() == Type.TEMPLATE) { TemplateRecord rfm = new TemplateRecord(r); settings.setTemplate(rfm.getTemplate()); } else if (r.getType() == Type.EXCEL9FILE) { Excel9FileRecord e9f = new Excel9FileRecord(r); settings.setExcel9File(e9f.getExcel9File()); } else if (r.getType() == Type.WINDOWPROTECT) { WindowProtectedRecord winp = new WindowProtectedRecord(r); settings.setWindowProtected(winp.getWindowProtected()); } else if (r.getType() == Type.HIDEOBJ) { HideobjRecord hobj = new HideobjRecord(r); settings.setHideobj(hobj.getHideMode()); } else if (r.getType() == Type.WRITEACCESS) { WriteAccessRecord war = new WriteAccessRecord(r, bof.isBiff8(), settings); settings.setWriteAccess(war.getWriteAccess()); } else { // logger.info("Unsupported record type: " + // Integer.toHexString(r.getCode())+"h"); } } bof = null; if (excelFile.hasNext()) { r = excelFile.next(); if (r.getType() == Type.BOF) { bof = new BOFRecord(r); } } // Only get sheets for which there is a corresponding Boundsheet record while (bof != null && getNumberOfSheets() < boundsheets.size()) { if (!bof.isBiff8() && !bof.isBiff7()) { throw new BiffException(BiffException.unrecognizedBiffVersion); } if (bof.isWorksheet()) { // Read the sheet in SheetImpl s = new SheetImpl(excelFile, sharedStrings, formattingRecords, bof, workbookBof, nineteenFour, this); BoundsheetRecord br = (BoundsheetRecord) boundsheets.get (getNumberOfSheets()); s.setName(br.getName()); s.setHidden(br.isHidden()); addSheet(s); } else if (bof.isChart()) { // Read the sheet in SheetImpl s = new SheetImpl(excelFile, sharedStrings, formattingRecords, bof, workbookBof, nineteenFour, this); BoundsheetRecord br = (BoundsheetRecord) boundsheets.get (getNumberOfSheets()); s.setName(br.getName()); s.setHidden(br.isHidden()); addSheet(s); } else { logger.warn("BOF is unrecognized"); while (excelFile.hasNext() && r.getType() != Type.EOF) { r = excelFile.next(); } } // The next record will normally be a BOF or empty padding until // the end of the block is reached. In exceptionally unlucky cases, // the last EOF will coincide with a block division, so we have to // check there is more data to retrieve. // Thanks to liamg for spotting this bof = null; if (excelFile.hasNext()) { r = excelFile.next(); if (r.getType() == Type.BOF) { bof = new BOFRecord(r); } } } // Add all the local names to the specific sheets for (Iterator it = localNames.iterator() ; it.hasNext() ;) { NameRecord nr = (NameRecord) it.next(); if (nr.getBuiltInName() == null) { logger.warn("Usage of a local non-builtin name"); } else if (nr.getBuiltInName() == BuiltInName.PRINT_AREA || nr.getBuiltInName() == BuiltInName.PRINT_TITLES) { // appears to use the internal tab number rather than the // external sheet index SheetImpl s = (SheetImpl) sheets.get(nr.getSheetRef() - 1); s.addLocalName(nr); } } } /** * Accessor for the formattingRecords, used by the WritableWorkbook * when creating a copy of this * * @return the formatting records */ public FormattingRecords getFormattingRecords() { return formattingRecords; } /** * Accessor for the externSheet, used by the WritableWorkbook * when creating a copy of this * * @return the external sheet record */ public ExternalSheetRecord getExternalSheetRecord() { return externSheet; } /** * Accessor for the MsoDrawingGroup, used by the WritableWorkbook * when creating a copy of this * * @return the Mso Drawing Group record */ public MsoDrawingGroupRecord getMsoDrawingGroupRecord() { return msoDrawingGroup; } /** * Accessor for the supbook records, used by the WritableWorkbook * when creating a copy of this * * @return the supbook records */ public SupbookRecord[] getSupbookRecords() { SupbookRecord[] sr = new SupbookRecord[supbooks.size()]; return (SupbookRecord[]) supbooks.toArray(sr); } /** * Accessor for the name records. Used by the WritableWorkbook when * creating a copy of this * * @return the array of names */ public NameRecord[] getNameRecords() { NameRecord[] na = new NameRecord[nameTable.size()]; return (NameRecord[]) nameTable.toArray(na); } /** * Accessor for the fonts, used by the WritableWorkbook * when creating a copy of this * @return the fonts used in this workbook */ public Fonts getFonts() { return fonts; } /** * Returns the cell for the specified location eg. "Sheet1!A4". * This is identical to using the CellReferenceHelper with its * associated performance overheads, consequently it should * be use sparingly * * @param loc the cell to retrieve * @return the cell at the specified location */ public Cell getCell(String loc) { Sheet s = getSheet(CellReferenceHelper.getSheet(loc)); return s.getCell(loc); } /** * Gets the named cell from this workbook. If the name refers to a * range of cells, then the cell on the top left is returned. If * the name cannot be found, null is returned * * @param name the name of the cell/range to search for * @return the cell in the top left of the range if found, NULL * otherwise */ public Cell findCellByName(String name) { NameRecord nr = (NameRecord) namedRecords.get(name); if (nr == null) { return null; } NameRecord.NameRange[] ranges = nr.getRanges(); // Go and retrieve the first cell in the first range Sheet s = getSheet(getExternalSheetIndex(ranges[0].getExternalSheet())); int col = ranges[0].getFirstColumn(); int row = ranges[0].getFirstRow(); // If the sheet boundaries fall short of the named cell, then return // an empty cell to stop an exception being thrown if (col > s.getColumns() || row > s.getRows()) { return new EmptyCell(col, row); } Cell cell = s.getCell(col, row); return cell; } /** * Gets the named range from this workbook. The Range object returns * contains all the cells from the top left to the bottom right * of the range. * If the named range comprises an adjacent range, * the Range[] will contain one object; for non-adjacent * ranges, it is necessary to return an array of length greater than * one. * If the named range contains a single cell, the top left and * bottom right cell will be the same cell * * @param name the name to find * @return the range of cells */ public Range[] findByName(String name) { NameRecord nr = (NameRecord) namedRecords.get(name); if (nr == null) { return null; } NameRecord.NameRange[] ranges = nr.getRanges(); Range[] cellRanges = new Range[ranges.length]; for (int i = 0; i < ranges.length; i++) { cellRanges[i] = new RangeImpl (this, getExternalSheetIndex(ranges[i].getExternalSheet()), ranges[i].getFirstColumn(), ranges[i].getFirstRow(), getLastExternalSheetIndex(ranges[i].getExternalSheet()), ranges[i].getLastColumn(), ranges[i].getLastRow()); } return cellRanges; } /** * Gets the named ranges * * @return the list of named cells within the workbook */ public String[] getRangeNames() { Object[] keys = namedRecords.keySet().toArray(); String[] names = new String[keys.length]; System.arraycopy(keys, 0, names, 0, keys.length); return names; } /** * Method used when parsing formulas to make sure we are trying * to parse a supported biff version * * @return the BOF record */ public BOFRecord getWorkbookBof() { return workbookBof; } /** * Determines whether the sheet is protected * * @return whether or not the sheet is protected */ public boolean isProtected() { return wbProtected; } /** * Accessor for the settings * * @return the workbook settings */ public WorkbookSettings getSettings() { return settings; } /** * Accessor/implementation method for the external sheet reference * * @param sheetName the sheet name to look for * @return the external sheet index */ public int getExternalSheetIndex(String sheetName) { return 0; } /** * Accessor/implementation method for the external sheet reference * * @param sheetName the sheet name to look for * @return the external sheet index */ public int getLastExternalSheetIndex(String sheetName) { return 0; } /** * Gets the name at the specified index * * @param index the index into the name table * @return the name of the cell * @exception NameRangeException */ public String getName(int index) throws NameRangeException { // Assert.verify(index >= 0 && index < nameTable.size()); if (index < 0 || index >= nameTable.size()) { throw new NameRangeException(); } return ((NameRecord) nameTable.get(index)).getName(); } /** * Gets the index of the name record for the name * * @param name the name to search for * @return the index in the name table */ public int getNameIndex(String name) { NameRecord nr = (NameRecord) namedRecords.get(name); return nr != null ? nr.getIndex() : 0; } /** * Accessor for the drawing group * * @return the drawing group */ public DrawingGroup getDrawingGroup() { return drawingGroup; } /** * Accessor for the CompoundFile. For this feature to return non-null * value, the propertySets feature in WorkbookSettings must be enabled * and the workbook must contain additional property sets. This * method is used during the workbook copy * * @return the base compound file if it contains additional data items * and property sets are enabled */ public CompoundFile getCompoundFile() { return excelFile.getCompoundFile(); } /** * Accessor for the containsMacros * * @return TRUE if this workbook contains macros, FALSE otherwise */ public boolean containsMacros() { return containsMacros; } /** * Accessor for the button property set, used during copying * * @return the button property set */ public ButtonPropertySetRecord getButtonPropertySet() { return buttonPropertySet; } /** * Accessor for the country record, using during copying * * @return the country record read in */ public CountryRecord getCountryRecord() { return countryRecord; } /** * Accessor for addin function names * * @return list of add in function names */ public String[] getAddInFunctionNames() { String[] addins = new String[0]; return (String[]) addInFunctions.toArray(addins); } /** * Gets the sheet index in this workbook. Used when importing a sheet * * @param sheet the sheet * @return the 0-based sheet index, or -1 if it is not found */ public int getIndex(Sheet sheet) { String name = sheet.getName(); int index = -1; int pos = 0; for (Iterator i = boundsheets.iterator() ; i.hasNext() && index == -1 ;) { BoundsheetRecord br = (BoundsheetRecord) i.next(); if (br.getName().equals(name)) { index = pos; } else { pos++; } } return index; } public XCTRecord[] getXCTRecords() { XCTRecord[] xctr = new XCTRecord[0]; return (XCTRecord[]) xctRecords.toArray(xctr); } } jexcelapi/src/jxl/read/biff/RightMarginRecord.java0000750000175000017500000000223311207000612022323 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.biff.Type; /** * Record for the left margin settings */ class RightMarginRecord extends MarginRecord { /** * Constructor * @param r the record */ RightMarginRecord(Record r) { super(Type.RIGHTMARGIN, r); } } jexcelapi/src/jxl/read/biff/SupbookRecord.java0000750000175000017500000001640511207330004021541 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.common.Logger; import jxl.WorkbookSettings; import jxl.biff.IntegerHelper; import jxl.biff.RecordData; import jxl.biff.StringHelper; /** * A record containing the references to the various sheets (internal and * external) referenced by formulas in this workbook */ public class SupbookRecord extends RecordData { /** * The logger */ private static Logger logger = Logger.getLogger(SupbookRecord.class); /** * The type of this supbook record */ private Type type; /** * The number of sheets - internal & external supbooks only */ private int numSheets; /** * The name of the external file */ private String fileName; /** * The names of the external sheets */ private String[] sheetNames; /** * The type of supbook this refers to */ private static class Type {}; public static final Type INTERNAL = new Type(); public static final Type EXTERNAL = new Type(); public static final Type ADDIN = new Type(); public static final Type LINK = new Type(); public static final Type UNKNOWN = new Type(); /** * Constructs this object from the raw data * * @param t the raw data * @param ws the workbook settings */ SupbookRecord(Record t, WorkbookSettings ws) { super(t); byte[] data = getRecord().getData(); // First deduce the type if (data.length == 4) { if (data[2] == 0x01 && data[3] == 0x04) { type = INTERNAL; } else if (data[2] == 0x01 && data[3] == 0x3a) { type = ADDIN; } else { type = UNKNOWN; } } else if (data[0] == 0 && data[1] == 0) { type = LINK; } else { type = EXTERNAL; } if (type == INTERNAL) { numSheets = IntegerHelper.getInt(data[0], data[1]); } if (type == EXTERNAL) { readExternal(data, ws); } } /** * Reads the external data records * * @param data the data * @param ws the workbook settings */ private void readExternal(byte[] data, WorkbookSettings ws) { numSheets = IntegerHelper.getInt(data[0], data[1]); // subtract file name encoding from the length int ln = IntegerHelper.getInt(data[2], data[3]) - 1; int pos = 0; if (data[4] == 0) { // non-unicode string int encoding = data[5]; pos = 6; if (encoding == 0) { fileName = StringHelper.getString(data, ln, pos, ws); pos += ln; } else { fileName = getEncodedFilename(data, ln, pos); pos += ln; } } else { // unicode string int encoding = IntegerHelper.getInt(data[5], data[6]); pos = 7; if (encoding == 0) { fileName = StringHelper.getUnicodeString(data, ln, pos); pos += ln * 2; } else { fileName = getUnicodeEncodedFilename(data, ln, pos); pos += ln * 2; } } sheetNames = new String[numSheets]; for (int i = 0; i < sheetNames.length; i++) { ln = IntegerHelper.getInt(data[pos], data[pos + 1]); if (data[pos + 2] == 0x0) { sheetNames[i] = StringHelper.getString(data, ln, pos + 3, ws); pos += ln + 3; } else if (data[pos + 2] == 0x1) { sheetNames[i] = StringHelper.getUnicodeString(data, ln, pos + 3); pos += ln * 2 + 3; } } } /** * Gets the type of this supbook record * * @return the type of this supbook */ public Type getType() { return type; } /** * Gets the number of sheets. This will only be non-zero for internal * and external supbooks * * @return the number of sheets */ public int getNumberOfSheets() { return numSheets; } /** * Gets the name of the external file * * @return the name of the external file */ public String getFileName() { return fileName; } /** * Gets the name of the external sheet * * @param i the index of the external sheet * @return the name of the sheet */ public String getSheetName(int i) { return sheetNames[i]; } /** * Gets the data - used when copying a spreadsheet * * @return the raw external sheet data */ public byte[] getData() { return getRecord().getData(); } /** * Gets the encoded string from the data array * * @param data the data * @param ln length of the string * @param pos the position in the array * @return the string */ private String getEncodedFilename(byte[] data, int ln, int pos) { StringBuffer buf = new StringBuffer(); int endpos = pos + ln; while (pos < endpos) { char c = (char) data[pos]; if (c == '\u0001') { // next character is a volume letter pos++; c = (char) data[pos]; buf.append(c); buf.append(":\\\\"); } else if (c == '\u0002') { // file is on the same volume buf.append('\\'); } else if (c == '\u0003') { // down directory buf.append('\\'); } else if (c == '\u0004') { // up directory buf.append("..\\"); } else { // just add on the character buf.append(c); } pos++; } return buf.toString(); } /** * Gets the encoded string from the data array * * @param data the data * @param ln length of the string * @param pos the position in the array * @return the string */ private String getUnicodeEncodedFilename(byte[] data, int ln, int pos) { StringBuffer buf = new StringBuffer(); int endpos = pos + ln * 2; while (pos < endpos) { char c = (char) IntegerHelper.getInt(data[pos], data[pos + 1]); if (c == '\u0001') { // next character is a volume letter pos += 2; c = (char) IntegerHelper.getInt(data[pos], data[pos + 1]); buf.append(c); buf.append(":\\\\"); } else if (c == '\u0002') { // file is on the same volume buf.append('\\'); } else if (c == '\u0003') { // down directory buf.append('\\'); } else if (c == '\u0004') { // up directory buf.append("..\\"); } else { // just add on the character buf.append(c); } pos += 2; } return buf.toString(); } } jexcelapi/src/jxl/read/biff/CountryRecord.java0000750000175000017500000000372511207000610021560 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2005 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.common.Logger; import jxl.biff.IntegerHelper; import jxl.biff.RecordData; /** * Contains the cell dimensions of this worksheet */ public class CountryRecord extends RecordData { /** * The logger */ private static Logger logger = Logger.getLogger(CountryRecord.class); /** * The user interface language */ private int language; /** * The regional settings */ private int regionalSettings; /** * Constructs the dimensions from the raw data * * @param t the raw data */ public CountryRecord(Record t) { super(t); byte[] data = t.getData(); language = IntegerHelper.getInt(data[0], data[1]); regionalSettings = IntegerHelper.getInt(data[2], data[3]); } /** * Accessor for the language code * * @return the language code */ public int getLanguageCode() { return language; } /** * Accessor for the regional settings code * * @return the regional settings code */ public int getRegionalSettingsCode() { return regionalSettings; } } jexcelapi/src/jxl/read/biff/SharedNumberFormulaRecord.java0000750000175000017500000001226511207000612024023 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import java.text.DecimalFormat; import java.text.NumberFormat; import jxl.common.Logger; import jxl.CellType; import jxl.NumberCell; import jxl.NumberFormulaCell; import jxl.biff.DoubleHelper; import jxl.biff.FormattingRecords; import jxl.biff.FormulaData; import jxl.biff.IntegerHelper; import jxl.biff.WorkbookMethods; import jxl.biff.formula.ExternalSheet; import jxl.biff.formula.FormulaException; import jxl.biff.formula.FormulaParser; /** * A number formula record, manufactured out of the Shared Formula * "optimization" */ public class SharedNumberFormulaRecord extends BaseSharedFormulaRecord implements NumberCell, FormulaData, NumberFormulaCell { /** * The logger */ private static Logger logger = Logger.getLogger(SharedNumberFormulaRecord.class); /** * The value of this number */ private double value; /** * The cell format */ private NumberFormat format; /** * A handle to the formatting records */ private FormattingRecords formattingRecords; /** * The string format for the double value */ private static DecimalFormat defaultFormat = new DecimalFormat("#.###"); /** * Constructs this number * * @param t the data * @param excelFile the excel biff data * @param v the value * @param fr the formatting records * @param es the external sheet * @param nt the name table * @param si the sheet */ public SharedNumberFormulaRecord(Record t, File excelFile, double v, FormattingRecords fr, ExternalSheet es, WorkbookMethods nt, SheetImpl si) { super(t, fr, es, nt, si, excelFile.getPos()); value = v; format = defaultFormat; // format is set up later from the // SharedFormulaRecord } /** * Sets the format for the number based on the Excel spreadsheets' format. * This is called from SheetImpl when it has been definitely established * that this cell is a number and not a date * * @param f the format */ final void setNumberFormat(NumberFormat f) { if (f != null) { format = f; } } /** * Accessor for the value * * @return the value */ public double getValue() { return value; } /** * Accessor for the contents as a string * * @return the value as a string */ public String getContents() { return !Double.isNaN(value) ? format.format(value) : ""; } /** * Accessor for the cell type * * @return the cell type */ public CellType getType() { return CellType.NUMBER_FORMULA; } /** * Gets the raw bytes for the formula. This will include the * parsed tokens array. Used when copying spreadsheets * * @return the raw record data * @exception FormulaException */ public byte[] getFormulaData() throws FormulaException { if (!getSheet().getWorkbookBof().isBiff8()) { throw new FormulaException(FormulaException.BIFF8_SUPPORTED); } // Get the tokens, taking into account the mapping from shared // formula specific values into normal values FormulaParser fp = new FormulaParser (getTokens(), this, getExternalSheet(), getNameTable(), getSheet().getWorkbook().getSettings()); fp.parse(); byte[] rpnTokens = fp.getBytes(); byte[] data = new byte[rpnTokens.length + 22]; // Set the standard info for this cell IntegerHelper.getTwoBytes(getRow(), data, 0); IntegerHelper.getTwoBytes(getColumn(), data, 2); IntegerHelper.getTwoBytes(getXFIndex(), data, 4); DoubleHelper.getIEEEBytes(value, data, 6); // Now copy in the parsed tokens System.arraycopy(rpnTokens, 0, data, 22, rpnTokens.length); IntegerHelper.getTwoBytes(rpnTokens.length, data, 20); // Lop off the standard information byte[] d = new byte[data.length - 6]; System.arraycopy(data, 6, d, 0, data.length - 6); return d; } /** * Gets the NumberFormat used to format this cell. This is the java * equivalent of the Excel format * * @return the NumberFormat used to format the cell */ public NumberFormat getNumberFormat() { return format; } } jexcelapi/src/jxl/read/biff/StringFormulaRecord.java0000750000175000017500000001623711207000612022715 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.common.Assert; import jxl.common.Logger; import jxl.CellType; import jxl.LabelCell; import jxl.StringFormulaCell; import jxl.WorkbookSettings; import jxl.biff.FormattingRecords; import jxl.biff.FormulaData; import jxl.biff.IntegerHelper; import jxl.biff.StringHelper; import jxl.biff.Type; import jxl.biff.WorkbookMethods; import jxl.biff.formula.ExternalSheet; import jxl.biff.formula.FormulaException; import jxl.biff.formula.FormulaParser; /** * A string formula's last calculated value */ class StringFormulaRecord extends CellValue implements LabelCell, FormulaData, StringFormulaCell { /** * The logger */ private static Logger logger = Logger.getLogger(StringFormulaRecord.class); /** * The last calculated value of the formula */ private String value; /** * A handle to the class needed to access external sheets */ private ExternalSheet externalSheet; /** * A handle to the name table */ private WorkbookMethods nameTable; /** * The formula as an excel string */ private String formulaString; /** * The raw data */ private byte[] data; /** * Constructs this object from the raw data. We need to use the excelFile * to retrieve the String record which follows this formula record * * @param t the raw data * @param excelFile the excel file * @param fr the formatting records * @param es the external sheet records * @param nt the workbook * @param si the sheet impl * @param ws the workbook settings */ public StringFormulaRecord(Record t, File excelFile, FormattingRecords fr, ExternalSheet es, WorkbookMethods nt, SheetImpl si, WorkbookSettings ws) { super(t, fr, si); externalSheet = es; nameTable = nt; data = getRecord().getData(); int pos = excelFile.getPos(); // Look for the string record in one of the records after the // formula. Put a cap on it to prevent looping Record nextRecord = excelFile.next(); int count = 0; while (nextRecord.getType() != Type.STRING && count < 4) { nextRecord = excelFile.next(); count++; } Assert.verify(count < 4, " @ " + pos); byte[] stringData = nextRecord.getData(); // Read in any continuation records nextRecord = excelFile.peek(); while (nextRecord.getType() == Type.CONTINUE) { nextRecord = excelFile.next(); // move the pointer within the data byte[] d = new byte[stringData.length + nextRecord.getLength() - 1]; System.arraycopy(stringData, 0, d, 0, stringData.length); System.arraycopy(nextRecord.getData(), 1, d, stringData.length, nextRecord.getLength() - 1); stringData = d; nextRecord = excelFile.peek(); } readString(stringData, ws); } /** * Constructs this object from the raw data. Used when reading in formula * strings which evaluate to null (in the case of some IF statements) * * @param t the raw data * @param fr the formatting records * @param es the external sheet records * @param nt the workbook * @param si the sheet impl * @param ws the workbook settings */ public StringFormulaRecord(Record t, FormattingRecords fr, ExternalSheet es, WorkbookMethods nt, SheetImpl si) { super(t, fr, si); externalSheet = es; nameTable = nt; data = getRecord().getData(); value = ""; } /** * Reads in the string * * @param d the data * @param ws the workbook settings */ private void readString(byte[] d, WorkbookSettings ws) { int pos = 0; int chars = IntegerHelper.getInt(d[0], d[1]); if (chars == 0) { value=""; return; } pos += 2; int optionFlags = d[pos]; pos++; if ((optionFlags & 0xf) != optionFlags) { // Uh oh - looks like a plain old string, not unicode // Recalculate all the positions pos = 0; chars = IntegerHelper.getInt(d[0], (byte) 0); optionFlags = d[1]; pos = 2; } // See if it is an extended string boolean extendedString = ((optionFlags & 0x04) != 0); // See if string contains formatting information boolean richString = ((optionFlags & 0x08) != 0); if (richString) { pos += 2; } if (extendedString) { pos += 4; } // See if string is ASCII (compressed) or unicode boolean asciiEncoding = ((optionFlags & 0x01) == 0); if (asciiEncoding) { value = StringHelper.getString(d, chars, pos, ws); } else { value = StringHelper.getUnicodeString(d, chars, pos); } } /** * Interface method which returns the value * * @return the last calculated value of the formula */ public String getContents() { return value; } /** * Interface method which returns the value * * @return the last calculated value of the formula */ public String getString() { return value; } /** * Returns the cell type * * @return The cell type */ public CellType getType() { return CellType.STRING_FORMULA; } /** * Gets the raw bytes for the formula. This will include the * parsed tokens array * * @return the raw record data */ public byte[] getFormulaData() throws FormulaException { if (!getSheet().getWorkbook().getWorkbookBof().isBiff8()) { throw new FormulaException(FormulaException.BIFF8_SUPPORTED); } // Lop off the standard information byte[] d = new byte[data.length - 6]; System.arraycopy(data, 6, d, 0, data.length - 6); return d; } /** * Gets the formula as an excel string * * @return the formula as an excel string * @exception FormulaException */ public String getFormula() throws FormulaException { if (formulaString == null) { byte[] tokens = new byte[data.length - 22]; System.arraycopy(data, 22, tokens, 0, tokens.length); FormulaParser fp = new FormulaParser (tokens, this, externalSheet, nameTable, getSheet().getWorkbook().getSettings()); fp.parse(); formulaString = fp.getFormula(); } return formulaString; } } jexcelapi/src/jxl/read/biff/CellValue.java0000750000175000017500000001102011207000610020615 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.common.Logger; import jxl.Cell; import jxl.CellFeatures; import jxl.biff.FormattingRecords; import jxl.biff.IntegerHelper; import jxl.biff.RecordData; import jxl.biff.XFRecord; import jxl.format.CellFormat; /** * Abstract class for all records which actually contain cell values */ public abstract class CellValue extends RecordData implements Cell, CellFeaturesAccessor { /** * The logger */ private static Logger logger = Logger.getLogger(CellValue.class); /** * The row number of this cell record */ private int row; /** * The column number of this cell record */ private int column; /** * The XF index */ private int xfIndex; /** * A handle to the formatting records, so that we can * retrieve the formatting information */ private FormattingRecords formattingRecords; /** * A lazy initialize flag for the cell format */ private boolean initialized; /** * The cell format */ private XFRecord format; /** * A handle back to the sheet */ private SheetImpl sheet; /** * The cell features */ private CellFeatures features; /** * Constructs this object from the raw cell data * * @param t the raw cell data * @param fr the formatting records * @param si the sheet containing this cell */ protected CellValue(Record t, FormattingRecords fr, SheetImpl si) { super(t); byte[] data = getRecord().getData(); row = IntegerHelper.getInt(data[0], data[1]); column = IntegerHelper.getInt(data[2], data[3]); xfIndex = IntegerHelper.getInt(data[4], data[5]); sheet = si; formattingRecords = fr; initialized = false; } /** * Interface method which returns the row number of this cell * * @return the zero base row number */ public final int getRow() { return row; } /** * Interface method which returns the column number of this cell * * @return the zero based column number */ public final int getColumn() { return column; } /** * Gets the XFRecord corresponding to the index number. Used when * copying a spreadsheet * * @return the xf index for this cell */ public final int getXFIndex() { return xfIndex; } /** * Gets the CellFormat object for this cell. Used by the WritableWorkbook * API * * @return the CellFormat used for this cell */ public CellFormat getCellFormat() { if (!initialized) { format = formattingRecords.getXFRecord(xfIndex); initialized = true; } return format; } /** * Determines whether or not this cell has been hidden * * @return TRUE if this cell has been hidden, FALSE otherwise */ public boolean isHidden() { ColumnInfoRecord cir = sheet.getColumnInfo(column); if (cir != null && (cir.getWidth() == 0 || cir.getHidden())) { return true; } RowRecord rr = sheet.getRowInfo(row); if (rr != null && (rr.getRowHeight() == 0 || rr.isCollapsed())) { return true; } return false; } /** * Accessor for the sheet * * @return the sheet */ protected SheetImpl getSheet() { return sheet; } /** * Accessor for the cell features * * @return the cell features or NULL if this cell doesn't have any */ public CellFeatures getCellFeatures() { return features; } /** * Sets the cell features during the reading process * * @param cf the cell features */ public void setCellFeatures(CellFeatures cf) { if (features != null) { logger.warn("current cell features not null - overwriting"); } features = cf; } } jexcelapi/src/jxl/read/biff/WriteAccessRecord.java0000750000175000017500000000351611207000612022331 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2009 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.WorkbookSettings; import jxl.biff.RecordData; import jxl.biff.StringHelper; import jxl.biff.Type; /** * A write access record */ class WriteAccessRecord extends RecordData { /** * The write access user name */ private String wauser; /** * Constructor * * @param t the raw bytes * @param isBiff8 Is record BIFF8 (else BIFF7) */ public WriteAccessRecord(Record t, boolean isBiff8, WorkbookSettings ws) { super(Type.WRITEACCESS); byte[] data = t.getData(); if (isBiff8) { wauser= StringHelper.getUnicodeString(data, 112/2, 0); } else { // BIFF7 does not use unicode encoding in string int length= data[1]; wauser= StringHelper.getString(data, length, 1, ws); } } /** * Gets the binary data for output to file * * @return write access user name */ public String getWriteAccess() { return wauser; } } jexcelapi/src/jxl/read/biff/File.java0000750000175000017500000001721511207000610017634 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InterruptedIOException; import jxl.common.Logger; import jxl.WorkbookSettings; import jxl.biff.BaseCompoundFile; import jxl.biff.IntegerHelper; import jxl.biff.Type; /** * File containing the data from the binary stream */ public class File { /** * The logger */ private static Logger logger = Logger.getLogger(File.class); /** * The data from the excel 97 file */ private byte[] data; /** * The current position within the file */ private int filePos; /** * The saved pos */ private int oldPos; /** * The initial file size */ private int initialFileSize; /** * The amount to increase the growable array by */ private int arrayGrowSize; /** * A handle to the compound file. This is only preserved when the * copying of PropertySets is enabled */ private CompoundFile compoundFile; /** * The workbook settings */ private WorkbookSettings workbookSettings; /** * Constructs a file from the input stream * * @param is the input stream * @param ws the workbook settings * @exception IOException * @exception BiffException */ public File(InputStream is, WorkbookSettings ws) throws IOException, BiffException { // Initialize the file sizing parameters from the settings workbookSettings = ws; initialFileSize = workbookSettings.getInitialFileSize(); arrayGrowSize = workbookSettings.getArrayGrowSize(); byte[] d = new byte[initialFileSize]; int bytesRead = is.read(d); int pos = bytesRead; // Handle thread interruptions, in case the user keeps pressing // the Submit button from a browser. Thanks to Mike Smith for this if (Thread.currentThread().isInterrupted()) { throw new InterruptedIOException(); } while (bytesRead != -1) { if (pos >= d.length) { // Grow the array byte[] newArray = new byte[d.length + arrayGrowSize]; System.arraycopy(d, 0, newArray, 0, d.length); d = newArray; } bytesRead = is.read(d, pos, d.length - pos); pos += bytesRead; if (Thread.currentThread().isInterrupted()) { throw new InterruptedIOException(); } } bytesRead = pos + 1; // Perform file reading checks and throw exceptions as necessary if (bytesRead == 0) { throw new BiffException(BiffException.excelFileNotFound); } CompoundFile cf = new CompoundFile(d, ws); try { data = cf.getStream("workbook"); } catch (BiffException e) { // this might be in excel 95 format - try again data = cf.getStream("book"); } if (!workbookSettings.getPropertySetsDisabled() && (cf.getNumberOfPropertySets() > BaseCompoundFile.STANDARD_PROPERTY_SETS.length)) { compoundFile = cf; } cf = null; if (!workbookSettings.getGCDisabled()) { System.gc(); } // Uncomment the following lines to send the pure workbook stream // (ie. a defragged ole stream) to an output file // FileOutputStream fos = new FileOutputStream("defraggedxls"); // fos.write(data); // fos.close(); } /** * Constructs a file from already defragged binary data. Useful for * displaying subportions of excel streams. This is only used during * special runs of the "BiffDump" demo program and should not be invoked * as part of standard JExcelApi parsing * * @param d the already parsed data */ public File(byte[] d) { data = d; } /** * Returns the next data record and increments the pointer * * @return the next data record */ Record next() { Record r = new Record(data, filePos, this); return r; } /** * Peek ahead to the next record, without incrementing the file position * * @return the next record */ Record peek() { int tempPos = filePos; Record r = new Record(data, filePos, this); filePos = tempPos; return r; } /** * Skips forward the specified number of bytes * * @param bytes the number of bytes to skip forward */ public void skip(int bytes) { filePos += bytes; } /** * Copies the bytes into a new array and returns it. * * @param pos the position to read from * @param length the number of bytes to read * @return The bytes read */ public byte[] read(int pos, int length) { byte[] ret = new byte[length]; try { System.arraycopy(data, pos, ret, 0, length); } catch (ArrayIndexOutOfBoundsException e) { logger.error("Array index out of bounds at position " + pos + " record length " + length); throw e; } return ret; } /** * Gets the position in the stream * * @return the position in the stream */ public int getPos() { return filePos; } /** * Saves the current position and temporarily sets the position to be the * new one. The original position may be restored usind the restorePos() * method. This is used when reading in the cell values of the sheet - an * addition in 1.6 for memory allocation reasons. * * These methods are used by the SheetImpl.readSheet() when it is reading * in all the cell values * * @param p the temporary position */ public void setPos(int p) { oldPos = filePos; filePos = p; } /** * Restores the original position * * These methods are used by the SheetImpl.readSheet() when it is reading * in all the cell values */ public void restorePos() { filePos = oldPos; } /** * Moves to the first bof in the file */ private void moveToFirstBof() { boolean bofFound = false; while (!bofFound) { int code = IntegerHelper.getInt(data[filePos], data[filePos + 1]); if (code == Type.BOF.value) { bofFound = true; } else { skip(128); } } } /** * "Closes" the biff file * * @deprecated As of version 1.6 use workbook.close() instead */ public void close() { } /** * Clears the contents of the file */ public void clear() { data = null; } /** * Determines if the current position exceeds the end of the file * * @return TRUE if there is more data left in the array, FALSE otherwise */ public boolean hasNext() { // Allow four bytes for the record code and its length return filePos < data.length - 4; } /** * Accessor for the compound file. The returned value will only be non-null * if the property sets feature is enabled and the workbook contains * additional property sets * * @return the compound file */ CompoundFile getCompoundFile() { return compoundFile; } } jexcelapi/src/jxl/read/biff/ButtonPropertySetRecord.java0000750000175000017500000000272011207000610023603 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2004 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.common.Logger; import jxl.biff.RecordData; /** * Data associated with a button property set */ public class ButtonPropertySetRecord extends RecordData { /** * The logger */ private static Logger logger = Logger.getLogger(ButtonPropertySetRecord.class); /** * Constructor * * @param t the record */ ButtonPropertySetRecord(Record t) { super(t); } /** * Accessor for the binary data * * @return the binary data */ public byte[] getData() { return getRecord().getData(); } } jexcelapi/src/jxl/read/biff/HorizontalPageBreaksRecord.java0000750000175000017500000000504711207000610024172 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.common.Logger; import jxl.biff.IntegerHelper; import jxl.biff.RecordData; /** * Contains the cell dimensions of this worksheet */ class HorizontalPageBreaksRecord extends RecordData { /** * The logger */ private final Logger logger = Logger.getLogger (HorizontalPageBreaksRecord.class); /** * The row page breaks */ private int[] rowBreaks; /** * Dummy indicators for overloading the constructor */ private static class Biff7 {}; public static Biff7 biff7 = new Biff7(); /** * Constructs the dimensions from the raw data * * @param t the raw data */ public HorizontalPageBreaksRecord(Record t) { super(t); byte[] data = t.getData(); int numbreaks = IntegerHelper.getInt(data[0], data[1]); int pos = 2; rowBreaks = new int[numbreaks]; for (int i = 0; i < numbreaks; i++) { rowBreaks[i] = IntegerHelper.getInt(data[pos], data[pos + 1]); pos += 6; } } /** * Constructs the dimensions from the raw data * * @param t the raw data * @param biff7 an indicator to initialise this record for biff 7 format */ public HorizontalPageBreaksRecord(Record t, Biff7 biff7) { super(t); byte[] data = t.getData(); int numbreaks = IntegerHelper.getInt(data[0], data[1]); int pos = 2; rowBreaks = new int[numbreaks]; for (int i = 0; i < numbreaks; i++) { rowBreaks[i] = IntegerHelper.getInt(data[pos], data[pos + 1]); pos += 2; } } /** * Gets the row breaks * * @return the row breaks on the current sheet */ public int[] getRowBreaks() { return rowBreaks; } } jexcelapi/src/jxl/read/biff/BaseSharedFormulaRecord.java0000750000175000017500000000756511207000610023452 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.biff.FormattingRecords; import jxl.biff.FormulaData; import jxl.biff.WorkbookMethods; import jxl.biff.formula.ExternalSheet; import jxl.biff.formula.FormulaException; import jxl.biff.formula.FormulaParser; /** * A base class for shared formula records */ public abstract class BaseSharedFormulaRecord extends CellValue implements FormulaData { /** * The formula as an excel string */ private String formulaString; /** * The position of the next record in the file. Used when looking for * for subsequent records eg. a string value */ private int filePos; /** * The array of parsed tokens */ private byte[] tokens; /** * The external sheet */ private ExternalSheet externalSheet; /** * The name table */ private WorkbookMethods nameTable; /** * Constructs this number * * @param t the record * @param fr the formatting records * @param es the external sheet * @param nt the name table * @param si the sheet * @param pos the position of the next record in the file */ public BaseSharedFormulaRecord(Record t, FormattingRecords fr, ExternalSheet es, WorkbookMethods nt, SheetImpl si, int pos) { super(t, fr, si); externalSheet = es; nameTable = nt; filePos = pos; } /** * Gets the formula as an excel string * * @return the formula as an excel string * @exception FormulaException */ public String getFormula() throws FormulaException { if (formulaString == null) { FormulaParser fp = new FormulaParser (tokens, this, externalSheet, nameTable, getSheet().getWorkbook().getSettings()); fp.parse(); formulaString = fp.getFormula(); } return formulaString; } /** * Called by the shared formula record to set the tokens for * this formula * * @param t the tokens */ void setTokens(byte[] t) { tokens = t; } /** * Accessor for the tokens which make up this formula * * @return the tokens */ protected final byte[] getTokens() { return tokens; } /** * Access for the external sheet * * @return the external sheet */ protected final ExternalSheet getExternalSheet() { return externalSheet; } /** * Access for the name table * * @return the name table */ protected final WorkbookMethods getNameTable() { return nameTable; } /** * In case the shared formula is not added for any reason, we need * to expose the raw record data , in order to try again * * @return the record data from the base class */ public Record getRecord() { return super.getRecord(); } /** * Accessor for the position of the next record * * @return the position of the next record */ final int getFilePos() { return filePos; } } jexcelapi/src/jxl/read/biff/DateFormulaRecord.java0000750000175000017500000000766111207000610022323 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import java.text.NumberFormat; import jxl.CellType; import jxl.DateCell; import jxl.DateFormulaCell; import jxl.biff.FormattingRecords; import jxl.biff.FormulaData; import jxl.biff.WorkbookMethods; import jxl.biff.formula.ExternalSheet; import jxl.biff.formula.FormulaException; import jxl.biff.formula.FormulaParser; /** * A date formula's last calculated value */ class DateFormulaRecord extends DateRecord implements DateCell, FormulaData, DateFormulaCell { /** * The formula as an excel string */ private String formulaString; /** * A handle to the class needed to access external sheets */ private ExternalSheet externalSheet; /** * A handle to the name table */ private WorkbookMethods nameTable; /** * The raw data */ private byte[] data; /** * Constructs this object from the raw data * * @param t the basic number formula record * @param fr the formatting records * @param es the external sheet * @param nt the name table * @param nf flag indicating whether the 1904 date system is in use * @param si the sheet */ public DateFormulaRecord(NumberFormulaRecord t, FormattingRecords fr, ExternalSheet es, WorkbookMethods nt, boolean nf, SheetImpl si) throws FormulaException { super(t, t.getXFIndex(), fr, nf, si); externalSheet = es; nameTable = nt; data = t.getFormulaData(); } /** * Returns the cell type * * @return The cell type */ public CellType getType() { return CellType.DATE_FORMULA; } /** * Gets the raw bytes for the formula. This will include the * parsed tokens array. Used when copying spreadsheets * * @return the raw record data */ public byte[] getFormulaData() throws FormulaException { if (!getSheet().getWorkbookBof().isBiff8()) { throw new FormulaException(FormulaException.BIFF8_SUPPORTED); } // Data is already the formula data, so don't do any more manipulation return data; } /** * Gets the formula as an excel string * * @return the formula as an excel string * @exception FormulaException */ public String getFormula() throws FormulaException { // Note that the standard information was lopped off by the NumberFormula // record when creating this formula if (formulaString == null) { byte[] tokens = new byte[data.length - 16]; System.arraycopy(data, 16, tokens, 0, tokens.length); FormulaParser fp = new FormulaParser (tokens, this, externalSheet, nameTable, getSheet().getWorkbook().getSettings()); fp.parse(); formulaString = fp.getFormula(); } return formulaString; } /** * Interface method which returns the value * * @return the last calculated value of the formula */ public double getValue() { return 0; } /** * Dummy implementation in order to adhere to the NumberCell interface * * @return NULL */ public NumberFormat getNumberFormat() { return null; } } jexcelapi/src/jxl/read/biff/RStringRecord.java0000750000175000017500000000461411207000612021505 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.CellType; import jxl.LabelCell; import jxl.WorkbookSettings; import jxl.biff.FormattingRecords; import jxl.biff.IntegerHelper; import jxl.biff.StringHelper; /** * A label which is stored in the cell */ class RStringRecord extends CellValue implements LabelCell { /** * The length of the label in characters */ private int length; /** * The label */ private String string; /** * Dummy indicators for overloading the constructor */ private static class Biff7 {}; public static Biff7 biff7 = new Biff7(); /** * Constructs this object from the raw data * * @param t the raw data * @param fr the formatting records * @param si the sheet * @param ws the workbook settings * @param dummy dummy overload to indicate a biff 7 workbook */ public RStringRecord(Record t, FormattingRecords fr, SheetImpl si, WorkbookSettings ws, Biff7 dummy) { super(t, fr, si); byte[] data = getRecord().getData(); length = IntegerHelper.getInt(data[6], data[7]); string = StringHelper.getString(data, length, 8, ws); } /** * Gets the label * * @return the label */ public String getString() { return string; } /** * Gets the cell contents as a string * * @return the label */ public String getContents() { return string; } /** * Accessor for the cell type * * @return the cell type */ public CellType getType() { return CellType.LABEL; } } jexcelapi/src/jxl/read/biff/Window2Record.java0000750000175000017500000001144611207000612021447 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.common.Logger; import jxl.biff.IntegerHelper; import jxl.biff.RecordData; /** * Contains the cell dimensions of this worksheet */ class Window2Record extends RecordData { /** * The logger */ private static Logger logger = Logger.getLogger(Window2Record.class); /** * Selected flag */ private boolean selected; /** * Show grid lines flag */ private boolean showGridLines; /** * Display zero values flag */ private boolean displayZeroValues; /** * The window contains frozen panes */ private boolean frozenPanes; /** * The window contains panes that are frozen but not split */ private boolean frozenNotSplit; /** * The view mode: normal or pagebreakpreview */ private boolean pageBreakPreviewMode; /** * The page break preview magnification */ private int pageBreakPreviewMagnification; /** * The normal view magnification */ private int normalMagnification; // Dummy overload private static class Biff7 {}; public static final Biff7 biff7 = new Biff7(); /** * Constructs the dimensions from the raw data * * @param t the raw data */ public Window2Record(Record t) { super(t); byte[] data = t.getData(); int options = IntegerHelper.getInt(data[0], data[1]); selected = ((options & 0x200) != 0); showGridLines = ((options & 0x02) != 0); frozenPanes = ((options & 0x08) != 0); displayZeroValues = ((options & 0x10) != 0); frozenNotSplit = ((options & 0x100) != 0); pageBreakPreviewMode = ((options & 0x800) != 0); pageBreakPreviewMagnification = IntegerHelper.getInt(data[10], data[11]); normalMagnification = IntegerHelper.getInt(data[12], data[13]); } /** * Constructs the dimensions from the raw data. Dummy overload for * biff7 workbooks * * @param t the raw data * @param dummy the overload */ public Window2Record(Record t, Biff7 biff7) { super(t); byte[] data = t.getData(); int options = IntegerHelper.getInt(data[0], data[1]); selected = ((options & 0x200) != 0); showGridLines = ((options & 0x02) != 0); frozenPanes = ((options & 0x08) != 0); displayZeroValues = ((options & 0x10) != 0); frozenNotSplit = ((options & 0x100) != 0); pageBreakPreviewMode = ((options & 0x800) != 0); } /** * Accessor for the selected flag * * @return TRUE if this sheet is selected, FALSE otherwise */ public boolean isSelected() { return selected; } /** * Accessor for the show grid lines flag * * @return TRUE to show grid lines, FALSE otherwise */ public boolean getShowGridLines() { return showGridLines; } /** * Accessor for the zero values flag * * @return TRUE if this sheet displays zero values, FALSE otherwise */ public boolean getDisplayZeroValues() { return displayZeroValues; } /** * Accessor for the frozen panes flag * * @return TRUE if this contains frozen panes, FALSE otherwise */ public boolean getFrozen() { return frozenPanes; } /** * Accessor for the frozen not split flag * * @return TRUE if this contains frozen, FALSE otherwise */ public boolean getFrozenNotSplit() { return frozenNotSplit; } /** * Accessor for the page break preview mode * * @return TRUE if this sheet is in page break preview, FALSE otherwise */ public boolean isPageBreakPreview() { return pageBreakPreviewMode; } /** * Accessor for the page break preview magnification * * @return the cached paged break preview magnfication factor in percent */ public int getPageBreakPreviewMagnificaiton() { return pageBreakPreviewMagnification; } /** * Accessor for the normal view magnification * * @return the cached normal view magnfication factor in percent */ public int getNormalMagnificaiton() { return normalMagnification; } } jexcelapi/src/jxl/read/biff/PaletteRecord.java0000750000175000017500000000245311207000612021512 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.biff.RecordData; /** * A password record */ public class PaletteRecord extends RecordData { /** * Constructor * * @param t the raw bytes */ PaletteRecord(Record t) { super(t); } /** * Accessor for the binary data - used when copying * * @return the binary data */ public byte[] getData() { return getRecord().getData(); } } jexcelapi/src/jxl/read/biff/MulBlankRecord.java0000750000175000017500000000604111207000612021616 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.common.Logger; import jxl.biff.IntegerHelper; import jxl.biff.RecordData; /** * Contains an array of Blank, formatted cells */ class MulBlankRecord extends RecordData { /** * The logger */ private static Logger logger = Logger.getLogger(MulBlankRecord.class); /** * The row containing these numbers */ private int row; /** * The first column these rk number occur on */ private int colFirst; /** * The last column these blank numbers occur on */ private int colLast; /** * The number of blank numbers contained in this record */ private int numblanks; /** * The array of xf indices */ private int[] xfIndices; /** * Constructs the blank records from the raw data * * @param t the raw data */ public MulBlankRecord(Record t) { super(t); byte[] data = getRecord().getData(); int length = getRecord().getLength(); row = IntegerHelper.getInt(data[0], data[1]); colFirst = IntegerHelper.getInt(data[2], data[3]); colLast = IntegerHelper.getInt(data[length - 2], data[length - 1]); numblanks = colLast - colFirst + 1; xfIndices = new int[numblanks]; readBlanks(data); } /** * Reads the blanks from the raw data * * @param data the raw data */ private void readBlanks(byte[] data) { int pos = 4; for (int i = 0; i < numblanks; i++) { xfIndices[i] = IntegerHelper.getInt(data[pos], data[pos + 1]); pos += 2; } } /** * Accessor for the row * * @return the row of containing these blank numbers */ public int getRow() { return row; } /** * The first column containing the blank numbers * * @return the first column */ public int getFirstColumn() { return colFirst; } /** * Accessor for the number of blank values * * @return the number of blank values */ public int getNumberOfColumns() { return numblanks; } /** * Return a specific formatting index * @param index the cell index in the group * @return the formatting index */ public int getXFIndex(int index) { return xfIndices[index]; } } jexcelapi/src/jxl/read/biff/BiffException.java0000750000175000017500000000472611207000610021505 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.JXLException; /** * Exception thrown when reading a biff file */ public class BiffException extends JXLException { /** * Inner class containing the various error messages */ private static class BiffMessage { /** * The formatted message */ public String message; /** * Constructs this exception with the specified message * * @param m the messageA */ BiffMessage(String m) { message = m; } } /** */ static final BiffMessage unrecognizedBiffVersion = new BiffMessage("Unrecognized biff version"); /** */ static final BiffMessage expectedGlobals = new BiffMessage("Expected globals"); /** */ static final BiffMessage excelFileTooBig = new BiffMessage("Not all of the excel file could be read"); /** */ static final BiffMessage excelFileNotFound = new BiffMessage("The input file was not found"); /** */ static final BiffMessage unrecognizedOLEFile = new BiffMessage("Unable to recognize OLE stream"); /** */ static final BiffMessage streamNotFound = new BiffMessage("Compound file does not contain the specified stream"); /** */ static final BiffMessage passwordProtected = new BiffMessage("The workbook is password protected"); /** */ static final BiffMessage corruptFileFormat = new BiffMessage("The file format is corrupt"); /** * Constructs this exception with the specified message * * @param m the message */ public BiffException(BiffMessage m) { super(m.message); } } jexcelapi/src/jxl/read/biff/#!ediff-merge!#42480EU#0000750000175000017500000000723211207000610021314 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.biff.IntegerHelper; import jxl.biff.RecordData; import jxl.biff.Type; /** * Contains the display info data which affects the entire columns */ public class ColumnInfoRecord extends RecordData { /** * The raw data */ private byte[] data; /** * The start for which to apply the format information */ private int startColumn; /** * The end column for which to apply the format information */ private int endColumn; /** * The index to the XF record, which applies to each cell in this column */ private int xfIndex; /** * The width of the column in 1/256 of a character */ private int width; /** * A hidden flag */ private boolean hidden; /** * The column's outline level */ private int outlineLevel; /** * The column collapsed flag */ private boolean collapsed; /** * Constructor which creates this object from the binary data * * @param t the record */ ColumnInfoRecord(Record t) { super(Type.COLINFO); data = t.getData(); startColumn = IntegerHelper.getInt(data[0], data[1]); endColumn = IntegerHelper.getInt(data[2], data[3]); width = IntegerHelper.getInt(data[4], data[5]); xfIndex = IntegerHelper.getInt(data[6], data[7]); int options = IntegerHelper.getInt(data[8], data[9]); hidden = ((options & 0x1) != 0); <<<<<<< variant A >>>>>>> variant B //20070227DR start outlineLevel = ((options & 0x700) >> 8); collapsed = ((options & 0x1000) != 0); //20070227DR end ======= end } /** * Accessor for the start column of this range * * @return the start column index */ public int getStartColumn() { return startColumn; } /** * Accessor for the end column of this range * * @return the end column index */ public int getEndColumn() { return endColumn; } /** * Accessor for the column format index * * @return the format index */ public int getXFIndex() { return xfIndex; } <<<<<<< variant A >>>>>>> variant B /** Accessor for the column's outline level * * @return the column's outline level * * 20070227DR */ public int getOutlineLevel() { return outlineLevel; } /** Accessor for whether the column is collapsed * * @return the column's collapsed state * * 20070227DR */ public boolean getCollapsed() { return collapsed; } ======= end /** * Accessor for the width of the column * * @return the width */ public int getWidth() { return width; } /** * Accessor for the hidden flag. Used when copying sheets * * @return TRUE if the columns are hidden, FALSE otherwise */ public boolean getHidden() { return hidden; } } jexcelapi/src/jxl/read/biff/HyperlinkRecord.java0000750000175000017500000002363611263366341022107 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import java.io.File; import java.net.MalformedURLException; import java.net.URL; import jxl.common.Logger; import jxl.CellReferenceHelper; import jxl.Hyperlink; import jxl.Range; import jxl.Sheet; import jxl.WorkbookSettings; import jxl.biff.IntegerHelper; import jxl.biff.RecordData; import jxl.biff.SheetRangeImpl; import jxl.biff.StringHelper; /** * A number record. This is stored as 8 bytes, as opposed to the * 4 byte RK record */ public class HyperlinkRecord extends RecordData implements Hyperlink { /** * The logger */ private static Logger logger = Logger.getLogger(HyperlinkRecord.class); /** * The first row */ private int firstRow; /** * The last row */ private int lastRow; /** * The first column */ private int firstColumn; /** * The last column */ private int lastColumn; /** * The URL referred to by this hyperlink */ private URL url; /** * The local file referred to by this hyperlink */ private File file; /** * The location in this workbook referred to by this hyperlink */ private String location; /** * The range of cells which activate this hyperlink */ private SheetRangeImpl range; /** * The type of this hyperlink */ private LinkType linkType; /** * The excel type of hyperlink */ private static class LinkType {}; private static final LinkType urlLink = new LinkType(); private static final LinkType fileLink = new LinkType(); private static final LinkType workbookLink = new LinkType(); private static final LinkType unknown = new LinkType(); /** * Constructs this object from the raw data * * @param t the raw data * @param s the sheet * @param ws the workbook settings */ HyperlinkRecord(Record t, Sheet s, WorkbookSettings ws) { super(t); linkType = unknown; byte[] data = getRecord().getData(); // Build up the range of cells occupied by this hyperlink firstRow = IntegerHelper.getInt(data[0], data[1]); lastRow = IntegerHelper.getInt(data[2], data[3]); firstColumn = IntegerHelper.getInt(data[4], data[5]); lastColumn = IntegerHelper.getInt(data[6], data[7]); range = new SheetRangeImpl(s, firstColumn, firstRow, lastColumn, lastRow); int options = IntegerHelper.getInt(data[28], data[29], data[30], data[31]); boolean description = (options & 0x14) != 0; int startpos = 32; int descbytes = 0; if (description) { int descchars = IntegerHelper.getInt (data[startpos], data[startpos + 1], data[startpos + 2], data[startpos + 3]); descbytes = descchars * 2 + 4; } startpos += descbytes; boolean targetFrame = (options & 0x80) != 0; int targetbytes = 0; if (targetFrame) { int targetchars = IntegerHelper.getInt (data[startpos], data[startpos + 1], data[startpos + 2], data[startpos + 3]); targetbytes = targetchars * 2 + 4; } startpos += targetbytes; // Try and determine the type if ((options & 0x3) == 0x03) { linkType = urlLink; // check the guid monicker if (data[startpos] == 0x03) { linkType = fileLink; } } else if ((options & 0x01) != 0) { linkType = fileLink; // check the guid monicker if (data[startpos] == (byte) 0xe0) { linkType = urlLink; } } else if ((options & 0x08) != 0) { linkType = workbookLink; } // Try and determine the type if (linkType == urlLink) { String urlString = null; try { startpos += 16; // Get the url, ignoring the 0 char at the end int bytes = IntegerHelper.getInt(data[startpos], data[startpos + 1], data[startpos + 2], data[startpos + 3]); urlString = StringHelper.getUnicodeString(data, bytes / 2 - 1, startpos + 4); url = new URL(urlString); } catch (MalformedURLException e) { logger.warn("URL " + urlString + " is malformed. Trying a file"); try { linkType = fileLink; file = new File(urlString); } catch (Exception e3) { logger.warn("Cannot set to file. Setting a default URL"); // Set a default URL try { linkType = urlLink; url = new URL("http://www.andykhan.com/jexcelapi/index.html"); } catch (MalformedURLException e2) { // fail silently } } } catch (Throwable e) { StringBuffer sb1 = new StringBuffer(); StringBuffer sb2 = new StringBuffer(); CellReferenceHelper.getCellReference(firstColumn, firstRow, sb1); CellReferenceHelper.getCellReference(lastColumn, lastRow, sb2); sb1.insert(0, "Exception when parsing URL "); sb1.append('\"').append(sb2.toString()).append("\". Using default."); logger.warn(sb1, e); // Set a default URL try { url = new URL("http://www.andykhan.com/jexcelapi/index.html"); } catch (MalformedURLException e2) { // fail silently } } } else if (linkType == fileLink) { try { startpos += 16; // Get the name of the local file, ignoring the zero character at the // end int upLevelCount = IntegerHelper.getInt(data[startpos], data[startpos + 1]); int chars = IntegerHelper.getInt(data[startpos + 2], data[startpos + 3], data[startpos + 4], data[startpos + 5]); String fileName = StringHelper.getString(data, chars - 1, startpos + 6, ws); StringBuffer sb = new StringBuffer(); for (int i = 0; i < upLevelCount; i++) { sb.append("..\\"); } sb.append(fileName); file = new File(sb.toString()); } catch (Throwable e) { logger.warn("Exception when parsing file " + e.getClass().getName() + "."); file = new File("."); } } else if (linkType == workbookLink) { int chars = IntegerHelper.getInt(data[32], data[33], data[34], data[35]); location = StringHelper.getUnicodeString(data, chars - 1, 36); } else { // give up logger.warn("Cannot determine link type"); return; } } /** * Determines whether this is a hyperlink to a file * * @return TRUE if this is a hyperlink to a file, FALSE otherwise */ public boolean isFile() { return linkType == fileLink; } /** * Determines whether this is a hyperlink to a web resource * * @return TRUE if this is a URL */ public boolean isURL() { return linkType == urlLink; } /** * Determines whether this is a hyperlink to a location in this workbook * * @return TRUE if this is a link to an internal location */ public boolean isLocation() { return linkType == workbookLink; } /** * Returns the row number of the top left cell * * @return the row number of this cell */ public int getRow() { return firstRow; } /** * Returns the column number of the top left cell * * @return the column number of this cell */ public int getColumn() { return firstColumn; } /** * Returns the row number of the bottom right cell * * @return the row number of this cell */ public int getLastRow() { return lastRow; } /** * Returns the column number of the bottom right cell * * @return the column number of this cell */ public int getLastColumn() { return lastColumn; } /** * Gets the URL referenced by this Hyperlink * * @return the URL, or NULL if this hyperlink is not a URL */ public URL getURL() { return url; } /** * Returns the local file eferenced by this Hyperlink * * @return the file, or NULL if this hyperlink is not a file */ public File getFile() { return file; } /** * Exposes the base class method. This is used when copying hyperlinks * * @return the Record data */ public Record getRecord() { return super.getRecord(); } /** * Gets the range of cells which activate this hyperlink * The get sheet index methods will all return -1, because the * cells will all be present on the same sheet * * @return the range of cells which activate the hyperlink */ public Range getRange() { return range; } /** * Gets the location referenced by this hyperlink * * @return the location */ public String getLocation() { return location; } } jexcelapi/src/jxl/read/biff/ErrorFormulaRecord.java0000750000175000017500000001046411207000610022532 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.common.Assert; import jxl.CellType; import jxl.ErrorCell; import jxl.ErrorFormulaCell; import jxl.biff.FormattingRecords; import jxl.biff.FormulaData; import jxl.biff.WorkbookMethods; import jxl.biff.formula.ExternalSheet; import jxl.biff.formula.FormulaErrorCode; import jxl.biff.formula.FormulaException; import jxl.biff.formula.FormulaParser; /** * An error resulting from the calculation of a formula */ class ErrorFormulaRecord extends CellValue implements ErrorCell, FormulaData, ErrorFormulaCell { /** * The error code of this cell */ private int errorCode; /** * A handle to the class needed to access external sheets */ private ExternalSheet externalSheet; /** * A handle to the name table */ private WorkbookMethods nameTable; /** * The formula as an excel string */ private String formulaString; /** * The raw data */ private byte[] data; /** * The error code */ private FormulaErrorCode error; /** * Constructs this object from the raw data * * @param t the raw data * @param fr the formatting records * @param es the external sheet * @param nt the name table * @param si the sheet */ public ErrorFormulaRecord(Record t, FormattingRecords fr, ExternalSheet es, WorkbookMethods nt, SheetImpl si) { super(t, fr, si); externalSheet = es; nameTable = nt; data = getRecord().getData(); Assert.verify(data[6] == 2); errorCode = data[8]; } /** * Interface method which gets the error code for this cell. If this cell * does not represent an error, then it returns 0. Always use the * method isError() to determine this prior to calling this method * * @return the error code if this cell contains an error, 0 otherwise */ public int getErrorCode() { return errorCode; } /** * Returns the numerical value as a string * * @return The numerical value of the formula as a string */ public String getContents() { if (error == null) { error = FormulaErrorCode.getErrorCode(errorCode); } return error != FormulaErrorCode.UNKNOWN ? error.getDescription() : "ERROR " + errorCode; } /** * Returns the cell type * * @return The cell type */ public CellType getType() { return CellType.FORMULA_ERROR; } /** * Gets the raw bytes for the formula. This will include the * parsed tokens array * * @return the raw record data */ public byte[] getFormulaData() throws FormulaException { if (!getSheet().getWorkbookBof().isBiff8()) { throw new FormulaException(FormulaException.BIFF8_SUPPORTED); } // Lop off the standard information byte[] d = new byte[data.length - 6]; System.arraycopy(data, 6, d, 0, data.length - 6); return d; } /** * Gets the formula as an excel string * * @return the formula as an excel string * @exception FormulaException */ public String getFormula() throws FormulaException { if (formulaString == null) { byte[] tokens = new byte[data.length - 22]; System.arraycopy(data, 22, tokens, 0, tokens.length); FormulaParser fp = new FormulaParser (tokens, this, externalSheet, nameTable, getSheet().getWorkbook().getSettings()); fp.parse(); formulaString = fp.getFormula(); } return formulaString; } } jexcelapi/src/jxl/read/biff/FooterRecord.java0000750000175000017500000000465211207000610021353 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.WorkbookSettings; import jxl.biff.IntegerHelper; import jxl.biff.RecordData; import jxl.biff.StringHelper; /** * A workbook page footer record */ public class FooterRecord extends RecordData { /** * The footer */ private String footer; /** * Dummy indicators for overloading the constructor */ private static class Biff7 {}; public static Biff7 biff7 = new Biff7(); /** * Constructs this object from the raw data * * @param t the record data * @param ws the workbook settings */ FooterRecord(Record t, WorkbookSettings ws) { super(t); byte[] data = getRecord().getData(); if (data.length == 0) { return; } int chars = IntegerHelper.getInt(data[0], data[1]); boolean unicode = data[2] == 1; if (unicode) { footer = StringHelper.getUnicodeString(data, chars, 3); } else { footer = StringHelper.getString(data, chars, 3, ws); } } /** * Constructs this object from the raw data * * @param t the record data * @param ws the workbook settings * @param dummy dummy record to indicate a biff7 document */ FooterRecord(Record t, WorkbookSettings ws, Biff7 dummy) { super(t); byte[] data = getRecord().getData(); if (data.length == 0) { return; } int chars = data[0]; footer = StringHelper.getString(data, chars, 1, ws); } /** * Gets the footer string * * @return the footer string */ String getFooter() { return footer; } } jexcelapi/src/jxl/read/biff/ExternalNameRecord.java0000750000175000017500000000452611207000610022500 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2001 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.common.Logger; import jxl.WorkbookSettings; import jxl.biff.IntegerHelper; import jxl.biff.RecordData; import jxl.biff.StringHelper; /** * A row record */ public class ExternalNameRecord extends RecordData { /** * The logger */ private static Logger logger = Logger.getLogger(ExternalNameRecord.class); /** * The name */ private String name; /** * Add in function flag */ private boolean addInFunction; /** * Constructs this object from the raw data * * @param t the raw data * @param ws the workbook settings */ ExternalNameRecord(Record t, WorkbookSettings ws) { super(t); byte[] data = getRecord().getData(); int options = IntegerHelper.getInt(data[0], data[1]); if (options == 0) { addInFunction = true; } if (!addInFunction) { return; } int length = data[6]; boolean unicode = (data[7] != 0); if (unicode) { name = StringHelper.getUnicodeString(data, length, 8); } else { name = StringHelper.getString(data, length, 8, ws); } } /** * Queries whether this name record refers to an external record * * @return TRUE if this name record is an add in function, FALSE otherwise */ public boolean isAddInFunction() { return addInFunction; } /** * Gets the name * * @return the name */ public String getName() { return name; } } jexcelapi/src/jxl/read/biff/LabelSSTRecord.java0000750000175000017500000000431711207000612021526 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.CellType; import jxl.LabelCell; import jxl.biff.FormattingRecords; import jxl.biff.IntegerHelper; /** * A label which is stored in the shared string table */ class LabelSSTRecord extends CellValue implements LabelCell { /** * The index into the shared string table */ private int index; /** * The label */ private String string; /** * Constructor. Retrieves the index from the raw data and looks it up * in the shared string table * * @param stringTable the shared string table * @param t the raw data * @param fr the formatting records * @param si the sheet */ public LabelSSTRecord(Record t, SSTRecord stringTable, FormattingRecords fr, SheetImpl si) { super(t, fr, si); byte[] data = getRecord().getData(); index = IntegerHelper.getInt(data[6], data[7], data[8], data[9]); string = stringTable.getString(index); } /** * Gets the label * * @return the label */ public String getString() { return string; } /** * Gets this cell's contents as a string * * @return the label */ public String getContents() { return string; } /** * Returns the cell type * * @return the cell type */ public CellType getType() { return CellType.LABEL; } } jexcelapi/src/jxl/read/biff/ExternalSheetRecord.java0000750000175000017500000001047611207000610022671 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.common.Logger; import jxl.WorkbookSettings; import jxl.biff.IntegerHelper; import jxl.biff.RecordData; /** * An Externsheet record, containing the details of externally references * workbooks */ public class ExternalSheetRecord extends RecordData { /** * The logger */ private static Logger logger = Logger.getLogger(ExternalSheetRecord.class); /** * Dummy indicators for overloading the constructor */ private static class Biff7 {}; public static Biff7 biff7 = new Biff7(); /** * An XTI structure */ private static class XTI { /** * the supbook index */ int supbookIndex; /** * the first tab */ int firstTab; /** * the last tab */ int lastTab; /** * Constructor * * @param s the supbook index * @param f the first tab * @param l the last tab */ XTI(int s, int f, int l) { supbookIndex = s; firstTab = f; lastTab = l; } } /** * The array of XTI structures */ private XTI[] xtiArray; /** * Constructs this object from the raw data * * @param t the raw data * @param ws the workbook settings */ ExternalSheetRecord(Record t, WorkbookSettings ws) { super(t); byte[] data = getRecord().getData(); int numxtis = IntegerHelper.getInt(data[0], data[1]); if (data.length < numxtis * 6 + 2) { xtiArray = new XTI[0]; logger.warn("Could not process external sheets. Formulas may " + "be compromised."); return; } xtiArray = new XTI[numxtis]; int pos = 2; for (int i = 0; i < numxtis; i++) { int s = IntegerHelper.getInt(data[pos], data[pos + 1]); int f = IntegerHelper.getInt(data[pos + 2], data[pos + 3]); int l = IntegerHelper.getInt(data[pos + 4], data[pos + 5]); xtiArray[i] = new XTI(s, f, l); pos += 6; } } /** * Constructs this object from the raw data in biff 7 format. * Does nothing here * * @param t the raw data * @param settings the workbook settings * @param dummy dummy override to identify biff7 funcionality */ ExternalSheetRecord(Record t, WorkbookSettings settings, Biff7 dummy) { super(t); logger.warn("External sheet record for Biff 7 not supported"); } /** * Accessor for the number of external sheet records * @return the number of XTI records */ public int getNumRecords() { return xtiArray != null ? xtiArray.length : 0; } /** * Gets the supbook index for the specified external sheet * * @param index the index of the supbook record * @return the supbook index */ public int getSupbookIndex(int index) { return xtiArray[index].supbookIndex; } /** * Gets the first tab index for the specified external sheet * * @param index the index of the supbook record * @return the first tab index */ public int getFirstTabIndex(int index) { return xtiArray[index].firstTab; } /** * Gets the last tab index for the specified external sheet * * @param index the index of the supbook record * @return the last tab index */ public int getLastTabIndex(int index) { return xtiArray[index].lastTab; } /** * Used when copying a workbook to access the raw external sheet data * * @return the raw external sheet data */ public byte[] getData() { return getRecord().getData(); } } jexcelapi/src/jxl/read/biff/FormulaRecord.java0000750000175000017500000001736711207000610021531 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.common.Assert; import jxl.common.Logger; import jxl.CellType; import jxl.WorkbookSettings; import jxl.biff.DoubleHelper; import jxl.biff.FormattingRecords; import jxl.biff.IntegerHelper; import jxl.biff.WorkbookMethods; import jxl.biff.formula.ExternalSheet; /** * A formula's last calculated value */ class FormulaRecord extends CellValue { /** * The logger */ private static Logger logger = Logger.getLogger(FormulaRecord.class); /** * The "real" formula record - will be either a string a or a number */ private CellValue formula; /** * Flag to indicate whether this is a shared formula */ private boolean shared; /** * Static class for a dummy override, indicating that the formula * passed in is not a shared formula */ private static class IgnoreSharedFormula {}; public static final IgnoreSharedFormula ignoreSharedFormula = new IgnoreSharedFormula(); /** * Constructs this object from the raw data. Creates either a * NumberFormulaRecord or a StringFormulaRecord depending on whether * this formula represents a numerical calculation or not * * @param t the raw data * @param excelFile the excel file * @param fr the formatting records * @param es the workbook, which contains the external sheet references * @param nt the name table * @param si the sheet * @param ws the workbook settings */ public FormulaRecord(Record t, File excelFile, FormattingRecords fr, ExternalSheet es, WorkbookMethods nt, SheetImpl si, WorkbookSettings ws) { super(t, fr, si); byte[] data = getRecord().getData(); shared = false; // Check to see if this forms part of a shared formula int grbit = IntegerHelper.getInt(data[14], data[15]); if ((grbit & 0x08) != 0) { shared = true; if (data[6] == 0 && data[12] == -1 && data[13] == -1) { // It is a shared string formula formula = new SharedStringFormulaRecord (t, excelFile, fr, es, nt, si, ws); } else if (data[6] == 3 && data[12] == -1 && data[13] == -1) { // We have a string which evaluates to null formula = new SharedStringFormulaRecord (t, excelFile, fr, es, nt, si, SharedStringFormulaRecord.EMPTY_STRING); } else if (data[6] == 2 && data[12] == -1 && data[13] == -1) { // The cell is in error int errorCode = data[8]; formula = new SharedErrorFormulaRecord(t, excelFile, errorCode, fr, es, nt, si); } else if (data[6] == 1 && data[12] == -1 && data[13] == -1) { boolean value = data[8] == 1 ? true : false; formula = new SharedBooleanFormulaRecord (t, excelFile, value, fr, es, nt, si); } else { // It is a numerical formula double value = DoubleHelper.getIEEEDouble(data, 6); SharedNumberFormulaRecord snfr = new SharedNumberFormulaRecord (t, excelFile, value, fr, es, nt, si); snfr.setNumberFormat(fr.getNumberFormat(getXFIndex())); formula = snfr; } return; } // microsoft and their goddam magic values determine whether this // is a string or a number value if (data[6] == 0 && data[12] == -1 && data[13] == -1) { // we have a string formula = new StringFormulaRecord(t, excelFile, fr, es, nt, si, ws); } else if (data[6] == 1 && data[12] == -1 && data[13] == -1) { // We have a boolean formula // multiple values. Thanks to Frank for spotting this formula = new BooleanFormulaRecord(t, fr, es, nt, si); } else if (data[6] == 2 && data[12] == -1 && data[13] == -1) { // The cell is in error formula = new ErrorFormulaRecord(t, fr, es, nt, si); } else if (data[6] == 3 && data[12] == -1 && data[13] == -1) { // we have a string which evaluates to null formula = new StringFormulaRecord(t, fr, es, nt, si); } else { // it is most assuredly a number formula = new NumberFormulaRecord(t, fr, es, nt, si); } } /** * Constructs this object from the raw data. Creates either a * NumberFormulaRecord or a StringFormulaRecord depending on whether * this formula represents a numerical calculation or not * * @param t the raw data * @param excelFile the excel file * @param fr the formatting records * @param es the workbook, which contains the external sheet references * @param nt the name table * @param i a dummy override to indicate that we don't want to do * any shared formula processing * @param si the sheet impl * @param ws the workbook settings */ public FormulaRecord(Record t, File excelFile, FormattingRecords fr, ExternalSheet es, WorkbookMethods nt, IgnoreSharedFormula i, SheetImpl si, WorkbookSettings ws) { super(t, fr, si); byte[] data = getRecord().getData(); shared = false; // microsoft and their magic values determine whether this // is a string or a number value if (data[6] == 0 && data[12] == -1 && data[13] == -1) { // we have a string formula = new StringFormulaRecord(t, excelFile, fr, es, nt, si, ws); } else if (data[6] == 1 && data[12] == -1 && data[13] == -1) { // We have a boolean formula // multiple values. Thanks to Frank for spotting this formula = new BooleanFormulaRecord(t, fr, es, nt, si); } else if (data[6] == 2 && data[12] == -1 && data[13] == -1) { // The cell is in error formula = new ErrorFormulaRecord(t, fr, es, nt, si); } else { // it is most assuredly a number formula = new NumberFormulaRecord(t, fr, es, nt, si); } } /** * Returns the numerical value as a string * * @return The numerical value of the formula as a string */ public String getContents() { Assert.verify(false); return ""; } /** * Returns the cell type * * @return The cell type */ public CellType getType() { Assert.verify(false); return CellType.EMPTY; } /** * Gets the "real" formula * * @return the cell value */ final CellValue getFormula() { return formula; } /** * Interrogates this formula to determine if it forms part of a shared * formula * * @return TRUE if this is shared formula, FALSE otherwise */ final boolean isShared() { return shared; } } jexcelapi/src/jxl/read/biff/SaveRecalcRecord.java0000750000175000017500000000325711207000612022127 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2005 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.common.Logger; import jxl.biff.IntegerHelper; import jxl.biff.RecordData; /** * A calculation mode record */ class SaveRecalcRecord extends RecordData { /** * The logger */ private static Logger logger = Logger.getLogger(SaveRecalcRecord.class); /** * The calculation mode */ private boolean recalculateOnSave; /** * Constructor * * @param t the record */ public SaveRecalcRecord(Record t) { super(t); byte[] data = t.getData(); int mode = IntegerHelper.getInt(data[0], data[1]); recalculateOnSave = (mode == 1); } /** * Accessor for the recalculate on save mode * * @return the recalculate on save mode */ public boolean getRecalculateOnSave() { return recalculateOnSave; } } jexcelapi/src/jxl/read/biff/DefaultColumnWidthRecord.java0000750000175000017500000000305411207000610023652 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.biff.IntegerHelper; import jxl.biff.RecordData; /** * Contains the default column width for cells in this sheet */ class DefaultColumnWidthRecord extends RecordData { /** * The default columns width, in characters */ private int width; /** * Constructs the def col width from the raw data * * @param t the raw data */ public DefaultColumnWidthRecord(Record t) { super(t); byte[] data = t.getData(); width = IntegerHelper.getInt(data[0], data[1]); } /** * Accessor for the default width * * @return the width */ public int getWidth() { return width; } } jexcelapi/src/jxl/read/biff/SharedDateFormulaRecord.java0000750000175000017500000001161511207000612023446 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import java.text.DateFormat; import java.util.Date; import jxl.CellType; import jxl.DateCell; import jxl.DateFormulaCell; import jxl.biff.DoubleHelper; import jxl.biff.FormattingRecords; import jxl.biff.FormulaData; import jxl.biff.IntegerHelper; import jxl.biff.formula.FormulaException; import jxl.biff.formula.FormulaParser; /** * A number formula record, manufactured out of the Shared Formula * "optimization" */ public class SharedDateFormulaRecord extends BaseSharedFormulaRecord implements DateCell, FormulaData, DateFormulaCell { /** * Re-use the date record to handle all the formatting information and * date calculations */ private DateRecord dateRecord; /** * The double value */ private double value; /** * Constructs this number formula * * @param nfr the number formula records * @param fr the formatting records * @param nf flag indicating whether this uses the 1904 date system * @param si the sheet * @param pos the position */ public SharedDateFormulaRecord(SharedNumberFormulaRecord nfr, FormattingRecords fr, boolean nf, SheetImpl si, int pos) { super(nfr.getRecord(), fr, nfr.getExternalSheet(), nfr.getNameTable(), si, pos); dateRecord = new DateRecord(nfr, nfr.getXFIndex(), fr, nf, si); value = nfr.getValue(); } /** * Accessor for the value * * @return the value */ public double getValue() { return value; } /** * Accessor for the contents as a string * * @return the value as a string */ public String getContents() { return dateRecord.getContents(); } /** * Accessor for the cell type * * @return the cell type */ public CellType getType() { return CellType.DATE_FORMULA; } /** * Gets the raw bytes for the formula. This will include the * parsed tokens array. Used when copying spreadsheets * * @return the raw record data * @exception FormulaException */ public byte[] getFormulaData() throws FormulaException { if (!getSheet().getWorkbookBof().isBiff8()) { throw new FormulaException(FormulaException.BIFF8_SUPPORTED); } // Get the tokens, taking into account the mapping from shared // formula specific values into normal values FormulaParser fp = new FormulaParser (getTokens(), this, getExternalSheet(), getNameTable(), getSheet().getWorkbook().getSettings()); fp.parse(); byte[] rpnTokens = fp.getBytes(); byte[] data = new byte[rpnTokens.length + 22]; // Set the standard info for this cell IntegerHelper.getTwoBytes(getRow(), data, 0); IntegerHelper.getTwoBytes(getColumn(), data, 2); IntegerHelper.getTwoBytes(getXFIndex(), data, 4); DoubleHelper.getIEEEBytes(value, data, 6); // Now copy in the parsed tokens System.arraycopy(rpnTokens, 0, data, 22, rpnTokens.length); IntegerHelper.getTwoBytes(rpnTokens.length, data, 20); // Lop off the standard information byte[] d = new byte[data.length - 6]; System.arraycopy(data, 6, d, 0, data.length - 6); return d; } /** * Gets the date * * @return the date */ public Date getDate() { return dateRecord.getDate(); } /** * Indicates whether the date value contained in this cell refers to a date, * or merely a time * * @return TRUE if the value refers to a time */ public boolean isTime() { return dateRecord.isTime(); } /** * Gets the DateFormat used to format the cell. This will normally be * the format specified in the excel spreadsheet, but in the event of any * difficulty parsing this, it will revert to the default date/time format. * * @return the DateFormat object used to format the date in the original * excel cell */ public DateFormat getDateFormat() { return dateRecord.getDateFormat(); } } jexcelapi/src/jxl/read/biff/BooleanFormulaRecord.java0000750000175000017500000001037211207000610023016 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.common.Assert; import jxl.BooleanCell; import jxl.BooleanFormulaCell; import jxl.CellType; import jxl.biff.FormattingRecords; import jxl.biff.FormulaData; import jxl.biff.WorkbookMethods; import jxl.biff.formula.ExternalSheet; import jxl.biff.formula.FormulaException; import jxl.biff.formula.FormulaParser; /** * A boolean formula's last calculated value */ class BooleanFormulaRecord extends CellValue implements BooleanCell, FormulaData, BooleanFormulaCell { /** * The boolean value of this cell. If this cell represents an error, * this will be false */ private boolean value; /** * A handle to the class needed to access external sheets */ private ExternalSheet externalSheet; /** * A handle to the name table */ private WorkbookMethods nameTable; /** * The formula as an excel string */ private String formulaString; /** * The raw data */ private byte[] data; /** * Constructs this object from the raw data * * @param t the raw data * @param fr the formatting records * @param si the sheet * @param es the sheet * @param nt the name table */ public BooleanFormulaRecord(Record t, FormattingRecords fr, ExternalSheet es, WorkbookMethods nt, SheetImpl si) { super(t, fr, si); externalSheet = es; nameTable = nt; value = false; data = getRecord().getData(); Assert.verify(data[6] != 2); value = data[8] == 1 ? true : false; } /** * Interface method which Gets the boolean value stored in this cell. If * this cell contains an error, then returns FALSE. Always query this cell * type using the accessor method isError() prior to calling this method * * @return TRUE if this cell contains TRUE, FALSE if it contains FALSE or * an error code */ public boolean getValue() { return value; } /** * Returns the numerical value as a string * * @return The numerical value of the formula as a string */ public String getContents() { // return Boolean.toString(value) - only available in 1.4 or later return (new Boolean(value)).toString(); } /** * Returns the cell type * * @return The cell type */ public CellType getType() { return CellType.BOOLEAN_FORMULA; } /** * Gets the raw bytes for the formula. This will include the * parsed tokens array * * @return the raw record data */ public byte[] getFormulaData() throws FormulaException { if (!getSheet().getWorkbookBof().isBiff8()) { throw new FormulaException(FormulaException.BIFF8_SUPPORTED); } // Lop off the standard information byte[] d = new byte[data.length - 6]; System.arraycopy(data, 6, d, 0, data.length - 6); return d; } /** * Gets the formula as an excel string * * @return the formula as an excel string * @exception FormulaException */ public String getFormula() throws FormulaException { if (formulaString == null) { byte[] tokens = new byte[data.length - 22]; System.arraycopy(data, 22, tokens, 0, tokens.length); FormulaParser fp = new FormulaParser (tokens, this, externalSheet, nameTable, getSheet().getWorkbook().getSettings()); fp.parse(); formulaString = fp.getFormula(); } return formulaString; } } jexcelapi/src/jxl/read/biff/MarginRecord.java0000750000175000017500000000310711207000612021326 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.biff.DoubleHelper; import jxl.biff.RecordData; import jxl.biff.Type; /** * Abstract class containing the margin value for top,left,right and bottom * margins */ abstract class MarginRecord extends RecordData { /** * The size of the margin */ private double margin; /** * Constructs this record from the raw data * * @param t the type * @param r the record */ protected MarginRecord(Type t, Record r) { super(t); byte[] data = r.getData(); margin = DoubleHelper.getIEEEDouble(data, 0); } /** * Accessor for the margin * * @return the margin */ double getMargin() { return margin; } } jexcelapi/src/jxl/read/biff/HideobjRecord.java0000750000175000017500000000307011207000612021454 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2009 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.common.Logger; import jxl.biff.IntegerHelper; import jxl.biff.RecordData; /** * A hideobj record */ class HideobjRecord extends RecordData { /** * The logger */ private static Logger logger = Logger.getLogger(HideobjRecord.class); /** * The hide obj mode */ private int hidemode; /** * Constructor * * @param t the record */ public HideobjRecord(Record t) { super(t); byte[] data = t.getData(); hidemode = IntegerHelper.getInt(data[0], data[1]); } /** * Accessor for the hide mode mode * * @return the hide mode */ public int getHideMode() { return hidemode; } } jexcelapi/src/jxl/read/biff/#!ediff-merge!#32320NU#0000750000175000017500000000726511207000610021323 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.biff.IntegerHelper; import jxl.biff.RecordData; import jxl.biff.Type; /** * Contains the display info data which affects the entire columns */ public class ColumnInfoRecord extends RecordData { /** * The raw data */ private byte[] data; /** * The start for which to apply the format information */ private int startColumn; /** * The end column for which to apply the format information */ private int endColumn; /** * The index to the XF record, which applies to each cell in this column */ private int xfIndex; /** * The width of the column in 1/256 of a character */ private int width; /** * A hidden flag */ private boolean hidden; /** the column's outline level * 20070227DR */ private int outlineLevel; /** column collapsed flag * 20070227DR */ private boolean collapsed; /** * Constructor which creates this object from the binary data * * @param t the record */ ColumnInfoRecord(Record t) { super(Type.COLINFO); data = t.getData(); startColumn = IntegerHelper.getInt(data[0], data[1]); endColumn = IntegerHelper.getInt(data[2], data[3]); width = IntegerHelper.getInt(data[4], data[5]); xfIndex = IntegerHelper.getInt(data[6], data[7]); int options = IntegerHelper.getInt(data[8], data[9]); hidden = ((options & 0x1) != 0); <<<<<<< variant A >>>>>>> variant B //20070227DR start outlineLevel = ((options & 0x700) >> 8); collapsed = ((options & 0x1000) != 0); //20070227DR end ======= end } /** * Accessor for the start column of this range * * @return the start column index */ public int getStartColumn() { return startColumn; } /** * Accessor for the end column of this range * * @return the end column index */ public int getEndColumn() { return endColumn; } /** * Accessor for the column format index * * @return the format index */ public int getXFIndex() { return xfIndex; } <<<<<<< variant A >>>>>>> variant B /** Accessor for the column's outline level * * @return the column's outline level * * 20070227DR */ public int getOutlineLevel() { return outlineLevel; } /** Accessor for whether the column is collapsed * * @return the column's collapsed state * * 20070227DR */ public boolean getCollapsed() { return collapsed; } ======= end /** * Accessor for the width of the column * * @return the width */ public int getWidth() { return width; } /** * Accessor for the hidden flag. Used when copying sheets * * @return TRUE if the columns are hidden, FALSE otherwise */ public boolean getHidden() { return hidden; } } jexcelapi/src/jxl/read/biff/NineteenFourRecord.java0000750000175000017500000000316411207000612022515 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2001 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.biff.RecordData; /** * Identifies the date system as the 1904 system or not */ class NineteenFourRecord extends RecordData { /** * The base year for dates */ private boolean nineteenFour; /** * Constructs this object from the raw data * * @param t the raw data */ public NineteenFourRecord(Record t) { super(t); byte[] data = getRecord().getData(); nineteenFour = data[0] == 1 ? true : false; } /** * Accessor to see whether this spreadsheets dates are based around * 1904 * * @return true if this workbooks dates are based around the 1904 * date system */ public boolean is1904() { return nineteenFour; } } jexcelapi/src/jxl/read/biff/MergedCellsRecord.java0000750000175000017500000000444111207000612022301 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.Range; import jxl.Sheet; import jxl.biff.IntegerHelper; import jxl.biff.RecordData; import jxl.biff.SheetRangeImpl; /** * A merged cells record for a given sheet */ public class MergedCellsRecord extends RecordData { /** * The ranges of the cells merged on this sheet */ private Range[] ranges; /** * Constructs this object from the raw data * * @param t the raw data * @param s the sheet */ MergedCellsRecord(Record t, Sheet s) { super(t); byte[] data = getRecord().getData(); int numRanges = IntegerHelper.getInt(data[0], data[1]); ranges = new Range[numRanges]; int pos = 2; int firstRow = 0; int lastRow = 0; int firstCol = 0; int lastCol = 0; for (int i = 0; i < numRanges; i++) { firstRow = IntegerHelper.getInt(data[pos], data[pos + 1]); lastRow = IntegerHelper.getInt(data[pos + 2], data[pos + 3]); firstCol = IntegerHelper.getInt(data[pos + 4], data[pos + 5]); lastCol = IntegerHelper.getInt(data[pos + 6], data[pos + 7]); ranges[i] = new SheetRangeImpl(s, firstCol, firstRow, lastCol, lastRow); pos += 8; } } /** * Gets the ranges which have been merged in this sheet * * @return the ranges of cells which have been merged */ public Range[] getRanges() { return ranges; } } jexcelapi/src/jxl/read/biff/RKHelper.java0000750000175000017500000000331111207000612020423 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; /** * Helper to convert an RK number into a double or an integer */ final class RKHelper { /** * Private constructor to prevent instantiation */ private RKHelper() { } /** * Converts excel's internal RK format into a double value * * @param rk the rk number in bits * @return the double representation */ public static double getDouble(int rk) { if ((rk & 0x02) != 0) { int intval = rk >> 2; double value = intval; if ((rk & 0x01) != 0) { value /= 100; } return value; } else { long valbits = (rk & 0xfffffffc); valbits <<= 32; double value = Double.longBitsToDouble(valbits); if ((rk & 0x01) != 0) { value /= 100; } return value; } } } jexcelapi/src/jxl/read/biff/VerticalPageBreaksRecord.java0000750000175000017500000000506411207000612023613 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.common.Logger; import jxl.biff.IntegerHelper; import jxl.biff.RecordData; /** * Contains the cell dimensions of this worksheet */ class VerticalPageBreaksRecord extends RecordData { /** * The logger */ private final Logger logger = Logger.getLogger (VerticalPageBreaksRecord.class); /** * The row page breaks */ private int[] columnBreaks; /** * Dummy indicators for overloading the constructor */ private static class Biff7 {}; public static Biff7 biff7 = new Biff7(); /** * Constructs the dimensions from the raw data * * @param t the raw data */ public VerticalPageBreaksRecord(Record t) { super(t); byte[] data = t.getData(); int numbreaks = IntegerHelper.getInt(data[0], data[1]); int pos = 2; columnBreaks = new int[numbreaks]; for (int i = 0; i < numbreaks; i++) { columnBreaks[i] = IntegerHelper.getInt(data[pos], data[pos + 1]); pos += 6; } } /** * Constructs the dimensions from the raw data * * @param t the raw data * @param biff7 an indicator to initialise this record for biff 7 format */ public VerticalPageBreaksRecord(Record t, Biff7 biff7) { super(t); byte[] data = t.getData(); int numbreaks = IntegerHelper.getInt(data[0], data[1]); int pos = 2; columnBreaks = new int[numbreaks]; for (int i = 0; i < numbreaks; i++) { columnBreaks[i] = IntegerHelper.getInt(data[pos], data[pos + 1]); pos += 2; } } /** * Gets the row breaks * * @return the row breaks on the current sheet */ public int[] getColumnBreaks() { return columnBreaks; } } jexcelapi/src/jxl/read/biff/CodepageRecord.java0000750000175000017500000000312511207000610021616 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2004 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.common.Logger; import jxl.biff.IntegerHelper; import jxl.biff.RecordData; /** * A codepage record */ class CodepageRecord extends RecordData { /** * The logger */ private static Logger logger = Logger.getLogger(CodepageRecord.class); /** * The character encoding */ private int characterSet; /** * Constructor * * @param t the record */ public CodepageRecord(Record t) { super(t); byte[] data = t.getData(); characterSet = IntegerHelper.getInt(data[0], data[1]); } /** * Accessor for the encoding * * @return the character encoding */ public int getCharacterSet() { return characterSet; } } jexcelapi/src/jxl/read/biff/DefaultRowHeightRecord.java0000750000175000017500000000313111207000610023311 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.biff.IntegerHelper; import jxl.biff.RecordData; /** * Contains the default column width for cells in this sheet */ class DefaultRowHeightRecord extends RecordData { /** * The default row height, in 1/20ths of a point */ private int height; /** * Constructs the def col width from the raw data * * @param t the raw data */ public DefaultRowHeightRecord(Record t) { super(t); byte[] data = t.getData(); if (data.length > 2) { height = IntegerHelper.getInt(data[2], data[3]); } } /** * Accessor for the default height * * @return the height */ public int getHeight() { return height; } } jexcelapi/src/jxl/read/biff/ProtectRecord.java0000750000175000017500000000306711207000612021536 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.biff.IntegerHelper; import jxl.biff.RecordData; /** * A record detailing whether the sheet is protected */ class ProtectRecord extends RecordData { /** * Protected flag */ private boolean prot; /** * Constructs this object from the raw data * * @param t the raw data */ ProtectRecord(Record t) { super(t); byte[] data = getRecord().getData(); int protflag = IntegerHelper.getInt(data[0], data[1]); prot = (protflag == 1); } /** * Returns the protected flag * * @return TRUE if this is protected, FALSE otherwise */ boolean isProtected() { return prot; } } jexcelapi/src/jxl/read/biff/GuttersRecord.java0000750000175000017500000000331711207000610021547 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2007 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.biff.IntegerHelper; import jxl.biff.RecordData; /** * The gutters record */ public class GuttersRecord extends RecordData { private int width; private int height; private int rowOutlineLevel; private int columnOutlineLevel; /** * Constructs this object from the raw data * * @param r the raw data */ public GuttersRecord(Record r) { super(r); byte[] data = getRecord().getData(); width = IntegerHelper.getInt(data[0], data[1]); height = IntegerHelper.getInt(data[2], data[3]); rowOutlineLevel = IntegerHelper.getInt(data[4], data[5]); columnOutlineLevel = IntegerHelper.getInt(data[6], data[7]); } int getRowOutlineLevel() { return rowOutlineLevel; } int getColumnOutlineLevel() { return columnOutlineLevel; } } jexcelapi/src/jxl/read/biff/#!ediff-merge!#4368ILU#0000750000175000017500000000652511207000610021363 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.biff.IntegerHelper; import jxl.biff.RecordData; import jxl.biff.Type; /** * Contains the display info data which affects the entire columns */ public class ColumnInfoRecord extends RecordData { /** * The raw data */ private byte[] data; /** * The start for which to apply the format information */ private int startColumn; /** * The end column for which to apply the format information */ private int endColumn; /** * The index to the XF record, which applies to each cell in this column */ private int xfIndex; /** * The width of the column in 1/256 of a character */ private int width; /** * A hidden flag */ private boolean hidden; /** * Constructor which creates this object from the binary data * * @param t the record */ ColumnInfoRecord(Record t) { super(Type.COLINFO); data = t.getData(); startColumn = IntegerHelper.getInt(data[0], data[1]); endColumn = IntegerHelper.getInt(data[2], data[3]); width = IntegerHelper.getInt(data[4], data[5]); xfIndex = IntegerHelper.getInt(data[6], data[7]); int options = IntegerHelper.getInt(data[8], data[9]); hidden = ((options & 0x1) != 0); } /** * Accessor for the start column of this range * * @return the start column index */ public int getStartColumn() { return startColumn; } /** * Accessor for the end column of this range * * @return the end column index */ public int getEndColumn() { return endColumn; } /** * Accessor for the column format index * * @return the format index */ public int getXFIndex() { return xfIndex; } <<<<<<< variant A >>>>>>> variant B /** Accessor for the column's outline level * * @return the column's outline level * * 20070227DR */ public int getOutlineLevel() { return outlineLevel; } /** Accessor for whether the column is collapsed * * @return the column's collapsed state * * 20070227DR */ public boolean getCollapsed() { return collapsed; } ======= end /** * Accessor for the width of the column * * @return the width */ public int getWidth() { return width; } /** * Accessor for the hidden flag. Used when copying sheets * * @return TRUE if the columns are hidden, FALSE otherwise */ public boolean getHidden() { return hidden; } } jexcelapi/src/jxl/read/biff/NameRecord.java0000750000175000017500000003322211207000612020772 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import java.util.ArrayList; import jxl.common.Assert; import jxl.common.Logger; import jxl.WorkbookSettings; import jxl.biff.BuiltInName; import jxl.biff.IntegerHelper; import jxl.biff.RecordData; import jxl.biff.StringHelper; /** * Holds an excel name record, and the details of the cells/ranges it refers * to */ public class NameRecord extends RecordData { /** * The logger */ private static Logger logger = Logger.getLogger(NameRecord.class); /** * The name */ private String name; /** * The built in name */ private BuiltInName builtInName; /** * The 0-based index in the name table */ private int index; /** * The 0-based index sheet reference for a record name * 0 is for a global reference */ private int sheetRef = 0; /** * Indicates whether this is a biff8 name record. Used during copying */ private boolean isbiff8; /** * Dummy indicators for overloading the constructor */ private static class Biff7 {}; public static Biff7 biff7 = new Biff7(); // Constants which refer to the name type private static final int commandMacro = 0xc; private static final int builtIn = 0x20; // Constants which refer to the parse tokens after the string private static final int cellReference = 0x3a; private static final int areaReference = 0x3b; private static final int subExpression = 0x29; private static final int union = 0x10; /** * A nested class to hold range information */ public class NameRange { /** * The first column */ private int columnFirst; /** * The first row */ private int rowFirst; /** * The last column */ private int columnLast; /** * The last row */ private int rowLast; /** * The first sheet */ private int externalSheet; /** * Constructor * * @param s1 the sheet * @param c1 the first column * @param r1 the first row * @param c2 the last column * @param r2 the last row */ NameRange(int s1, int c1, int r1, int c2, int r2) { columnFirst = c1; rowFirst = r1; columnLast = c2; rowLast = r2; externalSheet = s1; } /** * Accessor for the first column * * @return the index of the first column */ public int getFirstColumn() { return columnFirst; } /** * Accessor for the first row * * @return the index of the first row */ public int getFirstRow() { return rowFirst; } /** * Accessor for the last column * * @return the index of the last column */ public int getLastColumn() { return columnLast; } /** * Accessor for the last row * * @return the index of the last row */ public int getLastRow() { return rowLast; } /** * Accessor for the first sheet * * @return the index of the external sheet */ public int getExternalSheet() { return externalSheet; } } /** * The ranges referenced by this name */ private ArrayList ranges; /** * Constructs this object from the raw data * * @param t the raw data * @param ws the workbook settings * @param ind the index in the name table */ NameRecord(Record t, WorkbookSettings ws, int ind) { super(t); index = ind; isbiff8 = true; try { ranges = new ArrayList(); byte[] data = getRecord().getData(); int option = IntegerHelper.getInt(data[0], data[1]); int length = data[3]; sheetRef = IntegerHelper.getInt(data[8],data[9]); if ((option & builtIn) != 0) { builtInName = BuiltInName.getBuiltInName(data[15]); } else { name = StringHelper.getString(data, length, 15, ws); } if ((option & commandMacro) != 0) { // This is a command macro, so it has no cell references return; } int pos = length + 15; if (data[pos] == cellReference) { int sheet = IntegerHelper.getInt(data[pos + 1], data[pos + 2]); int row = IntegerHelper.getInt(data[pos + 3], data[pos + 4]); int columnMask = IntegerHelper.getInt(data[pos + 5], data[pos + 6]); int column = columnMask & 0xff; // Check that we are not dealing with offsets Assert.verify((columnMask & 0xc0000) == 0); NameRange r = new NameRange(sheet, column, row, column, row); ranges.add(r); } else if (data[pos] == areaReference) { int sheet1 = 0; int r1 = 0; int columnMask = 0; int c1 = 0; int r2 = 0; int c2 = 0; NameRange range = null; while (pos < data.length) { sheet1 = IntegerHelper.getInt(data[pos + 1], data[pos + 2]); r1 = IntegerHelper.getInt(data[pos + 3], data[pos + 4]); r2 = IntegerHelper.getInt(data[pos + 5], data[pos + 6]); columnMask = IntegerHelper.getInt(data[pos + 7], data[pos + 8]); c1 = columnMask & 0xff; // Check that we are not dealing with offsets Assert.verify((columnMask & 0xc0000) == 0); columnMask = IntegerHelper.getInt(data[pos + 9], data[pos + 10]); c2 = columnMask & 0xff; // Check that we are not dealing with offsets Assert.verify((columnMask & 0xc0000) == 0); range = new NameRange(sheet1, c1, r1, c2, r2); ranges.add(range); pos += 11; } } else if (data[pos] == subExpression) { int sheet1 = 0; int r1 = 0; int columnMask = 0; int c1 = 0; int r2 = 0; int c2 = 0; NameRange range = null; // Consume unnecessary parsed tokens if (pos < data.length && data[pos] != cellReference && data[pos] != areaReference) { if (data[pos] == subExpression) { pos += 3; } else if (data[pos] == union) { pos += 1; } } while (pos < data.length) { sheet1 = IntegerHelper.getInt(data[pos + 1], data[pos + 2]); r1 = IntegerHelper.getInt(data[pos + 3], data[pos + 4]); r2 = IntegerHelper.getInt(data[pos + 5], data[pos + 6]); columnMask = IntegerHelper.getInt(data[pos + 7], data[pos + 8]); c1 = columnMask & 0xff; // Check that we are not dealing with offsets Assert.verify((columnMask & 0xc0000) == 0); columnMask = IntegerHelper.getInt(data[pos + 9], data[pos + 10]); c2 = columnMask & 0xff; // Check that we are not dealing with offsets Assert.verify((columnMask & 0xc0000) == 0); range = new NameRange(sheet1, c1, r1, c2, r2); ranges.add(range); pos += 11; // Consume unnecessary parsed tokens if (pos < data.length && data[pos] != cellReference && data[pos] != areaReference) { if (data[pos] == subExpression) { pos += 3; } else if (data[pos] == union) { pos += 1; } } } } else { String n = name != null ? name : builtInName.getName(); logger.warn("Cannot read name ranges for " + n + " - setting to empty"); NameRange range = new NameRange(0,0,0,0,0); ranges.add(range); } } catch (Throwable t1) { // Generate a warning // Names are really a nice to have, and we don't want to halt the // reading process for functionality that probably won't be used logger.warn("Cannot read name"); name = "ERROR"; } } /** * Constructs this object from the raw data * * @param t the raw data * @param ws the workbook settings * @param ind the index in the name table * @param dummy dummy parameter to indicate a biff7 workbook */ NameRecord(Record t, WorkbookSettings ws, int ind, Biff7 dummy) { super(t); index = ind; isbiff8 = false; try { ranges = new ArrayList(); byte[] data = getRecord().getData(); int length = data[3]; sheetRef = IntegerHelper.getInt(data[8], data[9]); name = StringHelper.getString(data, length, 14, ws); int pos = length + 14; if (pos >= data.length) { // There appears to be nothing after the name, so return return; } if (data[pos] == cellReference) { int sheet = IntegerHelper.getInt(data[pos + 11], data[pos + 12]); int row = IntegerHelper.getInt(data[pos + 15], data[pos + 16]); int column = data[pos + 17]; NameRange r = new NameRange(sheet, column, row, column, row); ranges.add(r); } else if (data[pos] == areaReference) { int sheet1 = 0; int r1 = 0; int c1 = 0; int r2 = 0; int c2 = 0; NameRange range = null; while (pos < data.length) { sheet1 = IntegerHelper.getInt(data[pos + 11], data[pos + 12]); r1 = IntegerHelper.getInt(data[pos + 15], data[pos + 16]); r2 = IntegerHelper.getInt(data[pos + 17], data[pos + 18]); c1 = data[pos + 19]; c2 = data[pos + 20]; range = new NameRange(sheet1, c1, r1, c2, r2); ranges.add(range); pos += 21; } } else if (data[pos] == subExpression) { int sheet1 = 0; int sheet2 = 0; int r1 = 0; int c1 = 0; int r2 = 0; int c2 = 0; NameRange range = null; // Consume unnecessary parsed tokens if (pos < data.length && data[pos] != cellReference && data[pos] != areaReference) { if (data[pos] == subExpression) { pos += 3; } else if (data[pos] == union) { pos += 1; } } while (pos < data.length) { sheet1 = IntegerHelper.getInt(data[pos + 11], data[pos + 12]); r1 = IntegerHelper.getInt(data[pos + 15], data[pos + 16]); r2 = IntegerHelper.getInt(data[pos + 17], data[pos + 18]); c1 = data[pos + 19]; c2 = data[pos + 20]; range = new NameRange(sheet1, c1, r1, c2, r2); ranges.add(range); pos += 21; // Consume unnecessary parsed tokens if (pos < data.length && data[pos] != cellReference && data[pos] != areaReference) { if (data[pos] == subExpression) { pos += 3; } else if (data[pos] == union) { pos += 1; } } } } } catch (Throwable t1) { // Generate a warning // Names are really a nice to have, and we don't want to halt the // reading process for functionality that probably won't be used logger.warn("Cannot read name."); name = "ERROR"; } } /** * Gets the name * * @return the strings */ public String getName() { return name; } /** * Gets the built in name * * @return the built in name */ public BuiltInName getBuiltInName() { return builtInName; } /** * Gets the array of ranges for this name. This method is public as it is * used from the writable side when copying ranges * * @return the ranges */ public NameRange[] getRanges() { NameRange[] nr = new NameRange[ranges.size()]; return (NameRange[]) ranges.toArray(nr); } /** * Accessor for the index into the name table * * @return the 0-based index into the name table */ int getIndex() { return index; } /** * The 0-based index sheet reference for a record name * 0 is for a global reference * * @return the sheet reference for name formula */ public int getSheetRef() { return sheetRef; } /** * Set the index sheet reference for a record name * 0 is for a global reference */ public void setSheetRef(int i) { sheetRef = i; } /** * Called when copying a sheet. Just returns the raw data * * @return the raw data */ public byte[] getData() { return getRecord().getData(); } /** * Called when copying to determine whether this is a biff8 name * * @return TRUE if this is a biff8 name record, FALSE otherwise */ public boolean isBiff8() { return isbiff8; } /** * Queries whether this is a global name or not * * @return TRUE if this is a global name, FALSE otherwise */ public boolean isGlobal() { return sheetRef == 0; } } jexcelapi/src/jxl/read/biff/BOFRecord.java0000750000175000017500000000771211207000610020523 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.common.Logger; import jxl.biff.IntegerHelper; import jxl.biff.RecordData; /** * A Beginning Of File record, found at the commencement of all substreams * within a biff8 file */ public class BOFRecord extends RecordData { /** * The logger */ private static Logger logger = Logger.getLogger(BOFRecord.class); /** * The code used for biff8 files */ private static final int Biff8 = 0x600; /** * The code used for biff8 files */ private static final int Biff7 = 0x500; /** * The code used for workbook globals */ private static final int WorkbookGlobals = 0x5; /** * The code used for worksheets */ private static final int Worksheet = 0x10; /** * The code used for charts */ private static final int Chart = 0x20; /** * The code used for macro sheets */ private static final int MacroSheet = 0x40; /** * The biff version of this substream */ private int version; /** * The type of this substream */ private int substreamType; /** * Constructs this object from the raw data * * @param t the raw data */ BOFRecord(Record t) { super(t); byte[] data = getRecord().getData(); version = IntegerHelper.getInt(data[0], data[1]); substreamType = IntegerHelper.getInt(data[2], data[3]); } /** * Interrogates this object to see if it is a biff8 substream * * @return TRUE if this substream is biff8, false otherwise */ public boolean isBiff8() { return version == Biff8; } /** * Interrogates this object to see if it is a biff7 substream * * @return TRUE if this substream is biff7, false otherwise */ public boolean isBiff7() { return version == Biff7; } /** * Interrogates this substream to see if it represents the commencement of * the workbook globals substream * * @return TRUE if this is the commencement of a workbook globals substream, * FALSE otherwise */ boolean isWorkbookGlobals() { return substreamType == WorkbookGlobals; } /** * Interrogates the substream to see if it is the commencement of a worksheet * * @return TRUE if this substream is the beginning of a worksheet, FALSE * otherwise */ public boolean isWorksheet() { return substreamType == Worksheet; } /** * Interrogates the substream to see if it is the commencement of a worksheet * * @return TRUE if this substream is the beginning of a worksheet, FALSE * otherwise */ public boolean isMacroSheet() { return substreamType == MacroSheet; } /** * Interrogates the substream to see if it is a chart * * @return TRUE if this substream is the beginning of a worksheet, FALSE * otherwise */ public boolean isChart() { return substreamType == Chart; } /** * Gets the length of the data portion of this record * Used to adjust when reading sheets which contain just a chart * @return the length of the data portion of this record */ int getLength() { return getRecord().getLength(); } } jexcelapi/src/jxl/read/biff/CentreRecord.java0000750000175000017500000000301511207000610021325 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2005 Andrew Khan, Adam Caldwell * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.biff.IntegerHelper; import jxl.biff.RecordData; /** * Record which indicates the whether the horizontal center option has been set */ class CentreRecord extends RecordData { /** * The centre flag */ private boolean centre; /** * Constructor * * @param t the record to constructfrom */ public CentreRecord(Record t) { super(t); byte[] data = getRecord().getData(); centre = IntegerHelper.getInt(data[0], data[1]) != 0; } /** * Accessor for the centre flag * * @return Returns the centre flag. */ public boolean isCentre() { return centre; } } jexcelapi/src/jxl/read/biff/Record.java0000750000175000017500000000757611207000612020206 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import java.util.ArrayList; import jxl.common.Logger; import jxl.biff.IntegerHelper; import jxl.biff.Type; /** * A container for the raw record data within a biff file */ public final class Record { /** * The logger */ private static final Logger logger = Logger.getLogger(Record.class); /** * The excel biff code */ private int code; /** * The data type */ private Type type; /** * The length of this record */ private int length; /** * A pointer to the beginning of the actual data */ private int dataPos; /** * A handle to the excel 97 file */ private File file; /** * The raw data within this record */ private byte[] data; /** * Any continue records */ private ArrayList continueRecords; /** * Constructor * * @param offset the offset in the raw file * @param f the excel 97 biff file * @param d the data record */ Record(byte[] d, int offset, File f) { code = IntegerHelper.getInt(d[offset], d[offset + 1]); length = IntegerHelper.getInt(d[offset + 2], d[offset + 3]); file = f; file.skip(4); dataPos = f.getPos(); file.skip(length); type = Type.getType(code); } /** * Gets the biff type * * @return the biff type */ public Type getType() { return type; } /** * Gets the length of the record * * @return the length of the record */ public int getLength() { return length; } /** * Gets the data portion of the record * * @return the data portion of the record */ public byte[] getData() { if (data == null) { data = file.read(dataPos, length); } // copy in any data from the continue records if (continueRecords != null) { int size = 0; byte[][] contData = new byte[continueRecords.size()][]; for (int i = 0; i < continueRecords.size(); i++) { Record r = (Record) continueRecords.get(i); contData[i] = r.getData(); byte[] d2 = contData[i]; size += d2.length; } byte[] d3 = new byte[data.length + size]; System.arraycopy(data, 0, d3, 0, data.length); int pos = data.length; for (int i = 0; i < contData.length; i++) { byte[] d2 = contData[i]; System.arraycopy(d2, 0, d3, pos, d2.length); pos += d2.length; } data = d3; } return data; } /** * The excel 97 code * * @return the excel code */ public int getCode() { return code; } /** * In the case of dodgy records, this method may be called to forcibly * set the type in order to continue processing * * @param t the forcibly overridden type */ void setType(Type t) { type = t; } /** * Adds a continue record to this data * * @param d the continue record */ public void addContinueRecord(Record d) { if (continueRecords == null) { continueRecords = new ArrayList(); } continueRecords.add(d); } } jexcelapi/src/jxl/read/biff/SortRecord.java0000750000175000017500000001023011207000612021033 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2004 Andrew Khan, Al Mantei * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.biff.RecordData; import jxl.biff.StringHelper; import jxl.biff.Type; /** * A storage area for the last Sort dialog box area */ public class SortRecord extends RecordData { private int col1Size; private int col2Size; private int col3Size; private String col1Name; private String col2Name; private String col3Name; private byte optionFlags; private boolean sortColumns = false; private boolean sortKey1Desc = false; private boolean sortKey2Desc = false; private boolean sortKey3Desc = false; private boolean sortCaseSensitive = false; /** * Constructs this object from the raw data * * @param r the raw data */ public SortRecord(Record r) { super(Type.SORT); byte[] data = r.getData(); optionFlags = data[0]; sortColumns = ((optionFlags & 0x01) != 0); sortKey1Desc = ((optionFlags & 0x02) != 0); sortKey2Desc = ((optionFlags & 0x04) != 0); sortKey3Desc = ((optionFlags & 0x08) != 0); sortCaseSensitive = ((optionFlags & 0x10) != 0); // data[1] contains sort list index - not implemented... col1Size = data[2]; col2Size = data[3]; col3Size = data[4]; int curPos = 5; if (data[curPos++] == 0x00) { col1Name = new String(data, curPos, col1Size); curPos += col1Size; } else { col1Name = StringHelper.getUnicodeString(data, col1Size, curPos); curPos += col1Size * 2; } if (col2Size > 0) { if (data[curPos++] == 0x00) { col2Name = new String(data, curPos, col2Size); curPos += col2Size; } else { col2Name = StringHelper.getUnicodeString(data, col2Size, curPos); curPos += col2Size * 2; } } else { col2Name = ""; } if (col3Size > 0) { if (data[curPos++] == 0x00) { col3Name = new String(data, curPos, col3Size); curPos += col3Size; } else { col3Name = StringHelper.getUnicodeString(data, col3Size, curPos); curPos += col3Size * 2; } } else { col3Name = ""; } } /** * Accessor for the 1st Sort Column Name * * @return the 1st Sort Column Name */ public String getSortCol1Name() { return col1Name; } /** * Accessor for the 2nd Sort Column Name * * @return the 2nd Sort Column Name */ public String getSortCol2Name() { return col2Name; } /** * Accessor for the 3rd Sort Column Name * * @return the 3rd Sort Column Name */ public String getSortCol3Name() { return col3Name; } /** * Accessor for the Sort by Columns flag * * @return the Sort by Columns flag */ public boolean getSortColumns() { return sortColumns; } /** * Accessor for the Sort Column 1 Descending flag * * @return the Sort Column 1 Descending flag */ public boolean getSortKey1Desc() { return sortKey1Desc; } /** * Accessor for the Sort Column 2 Descending flag * * @return the Sort Column 2 Descending flag */ public boolean getSortKey2Desc() { return sortKey2Desc; } /** * Accessor for the Sort Column 3 Descending flag * * @return the Sort Column 3 Descending flag */ public boolean getSortKey3Desc() { return sortKey3Desc; } /** * Accessor for the Sort Case Sensitivity flag * * @return the Sort Case Secsitivity flag */ public boolean getSortCaseSensitive() { return sortCaseSensitive; } } jexcelapi/src/jxl/read/biff/NumberValue.java0000750000175000017500000001207711207000612021205 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import java.text.DecimalFormat; import java.text.NumberFormat; import jxl.CellFeatures; import jxl.CellType; import jxl.NumberCell; import jxl.biff.FormattingRecords; import jxl.format.CellFormat; /** * A numerical cell value, initialized indirectly from a multiple biff record * rather than directly from the binary data */ class NumberValue implements NumberCell, CellFeaturesAccessor { /** * The row containing this number */ private int row; /** * The column containing this number */ private int column; /** * The value of this number */ private double value; /** * The cell format */ private NumberFormat format; /** * The raw cell format */ private CellFormat cellFormat; /** * The cell features */ private CellFeatures features; /** * The index to the XF Record */ private int xfIndex; /** * A handle to the formatting records */ private FormattingRecords formattingRecords; /** * A flag to indicate whether this object's formatting things have * been initialized */ private boolean initialized; /** * A handle to the sheet */ private SheetImpl sheet; /** * The format in which to return this number as a string */ private static DecimalFormat defaultFormat = new DecimalFormat("#.###"); /** * Constructs this number * * @param r the zero based row * @param c the zero base column * @param val the value * @param xfi the xf index * @param fr the formatting records * @param si the sheet */ public NumberValue(int r, int c, double val, int xfi, FormattingRecords fr, SheetImpl si) { row = r; column = c; value = val; format = defaultFormat; xfIndex = xfi; formattingRecords = fr; sheet = si; initialized = false; } /** * Sets the format for the number based on the Excel spreadsheets' format. * This is called from SheetImpl when it has been definitely established * that this cell is a number and not a date * * @param f the format */ final void setNumberFormat(NumberFormat f) { if (f != null) { format = f; } } /** * Accessor for the row * * @return the zero based row */ public final int getRow() { return row; } /** * Accessor for the column * * @return the zero based column */ public final int getColumn() { return column; } /** * Accessor for the value * * @return the value */ public double getValue() { return value; } /** * Accessor for the contents as a string * * @return the value as a string */ public String getContents() { return format.format(value); } /** * Accessor for the cell type * * @return the cell type */ public CellType getType() { return CellType.NUMBER; } /** * Gets the cell format * * @return the cell format */ public CellFormat getCellFormat() { if (!initialized) { cellFormat = formattingRecords.getXFRecord(xfIndex); initialized = true; } return cellFormat; } /** * Determines whether or not this cell has been hidden * * @return TRUE if this cell has been hidden, FALSE otherwise */ public boolean isHidden() { ColumnInfoRecord cir = sheet.getColumnInfo(column); if (cir != null && cir.getWidth() == 0) { return true; } RowRecord rr = sheet.getRowInfo(row); if (rr != null && (rr.getRowHeight() == 0 || rr.isCollapsed())) { return true; } return false; } /** * Gets the NumberFormat used to format this cell. This is the java * equivalent of the Excel format * * @return the NumberFormat used to format the cell */ public NumberFormat getNumberFormat() { return format; } /** * Accessor for the cell features * * @return the cell features or NULL if this cell doesn't have any */ public CellFeatures getCellFeatures() { return features; } /** * Sets the cell features * * @param cf the cell features */ public void setCellFeatures(CellFeatures cf) { features = cf; } } jexcelapi/src/jxl/read/biff/MulBlankCell.java0000750000175000017500000001031311207000612021254 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.common.Logger; import jxl.Cell; import jxl.CellFeatures; import jxl.CellType; import jxl.biff.FormattingRecords; import jxl.format.CellFormat; /** * A blank cell value, initialized indirectly from a multiple biff record * rather than directly from the binary data */ class MulBlankCell implements Cell, CellFeaturesAccessor { /** * The logger */ private static Logger logger = Logger.getLogger(MulBlankCell.class); /** * The row containing this blank */ private int row; /** * The column containing this blank */ private int column; /** * The raw cell format */ private CellFormat cellFormat; /** * The index to the XF Record */ private int xfIndex; /** * A handle to the formatting records */ private FormattingRecords formattingRecords; /** * A flag to indicate whether this object's formatting things have * been initialized */ private boolean initialized; /** * A handle to the sheet */ private SheetImpl sheet; /** * The cell features */ private CellFeatures features; /** * Constructs this cell * * @param r the zero based row * @param c the zero base column * @param xfi the xf index * @param fr the formatting records * @param si the sheet */ public MulBlankCell(int r, int c, int xfi, FormattingRecords fr, SheetImpl si) { row = r; column = c; xfIndex = xfi; formattingRecords = fr; sheet = si; initialized = false; } /** * Accessor for the row * * @return the zero based row */ public final int getRow() { return row; } /** * Accessor for the column * * @return the zero based column */ public final int getColumn() { return column; } /** * Accessor for the contents as a string * * @return the value as a string */ public String getContents() { return ""; } /** * Accessor for the cell type * * @return the cell type */ public CellType getType() { return CellType.EMPTY; } /** * Gets the cell format for this cell * * @return the cell format for these cells */ public CellFormat getCellFormat() { if (!initialized) { cellFormat = formattingRecords.getXFRecord(xfIndex); initialized = true; } return cellFormat; } /** * Determines whether or not this cell has been hidden * * @return TRUE if this cell has been hidden, FALSE otherwise */ public boolean isHidden() { ColumnInfoRecord cir = sheet.getColumnInfo(column); if (cir != null && cir.getWidth() == 0) { return true; } RowRecord rr = sheet.getRowInfo(row); if (rr != null && (rr.getRowHeight() == 0 || rr.isCollapsed())) { return true; } return false; } /** * Accessor for the cell features * * @return the cell features or NULL if this cell doesn't have any */ public CellFeatures getCellFeatures() { return features; } /** * Sets the cell features during the reading process * * @param cf the cell features */ public void setCellFeatures(CellFeatures cf) { if (features != null) { logger.warn("current cell features not null - overwriting"); } features = cf; } } jexcelapi/src/jxl/read/biff/BiffRecordReader.java0000750000175000017500000000363311207000610022104 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; /** * Serves up Record objects from a biff file. This object is used by the * demo programs BiffDump and ... only and has no influence whatsoever on * the JExcelApi reading and writing of excel sheets */ public class BiffRecordReader { /** * The biff file */ private File file; /** * The current record retrieved */ private Record record; /** * Constructor * * @param f the biff file */ public BiffRecordReader(File f) { file = f; } /** * Sees if there are any more records to read * * @return TRUE if there are more records, FALSE otherwise */ public boolean hasNext() { return file.hasNext(); } /** * Gets the next record * * @return the next record */ public Record next() { record = file.next(); return record; } /** * Gets the position of the current record in the biff file * * @return the position */ public int getPos() { return file.getPos() - record.getLength() - 4; } } jexcelapi/src/jxl/read/biff/MulRKRecord.java0000750000175000017500000000663611207000612021115 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.common.Logger; import jxl.biff.IntegerHelper; import jxl.biff.RecordData; /** * Contains an array of RK numbers */ class MulRKRecord extends RecordData { /** * The logger */ private static Logger logger = Logger.getLogger(MulRKRecord.class); /** * The row containing these numbers */ private int row; /** * The first column these rk number occur on */ private int colFirst; /** * The last column these rk numbers occur on */ private int colLast; /** * The number of rk numbers contained in this record */ private int numrks; /** * The array of rk numbers */ private int[] rknumbers; /** * The array of xf indices */ private int[] xfIndices; /** * Constructs the rk numbers from the raw data * * @param t the raw data */ public MulRKRecord(Record t) { super(t); byte[] data = getRecord().getData(); int length = getRecord().getLength(); row = IntegerHelper.getInt(data[0], data[1]); colFirst = IntegerHelper.getInt(data[2], data[3]); colLast = IntegerHelper.getInt(data[length - 2], data[length - 1]); numrks = colLast - colFirst + 1; rknumbers = new int[numrks]; xfIndices = new int[numrks]; readRks(data); } /** * Reads the rks from the raw data * * @param data the raw data */ private void readRks(byte[] data) { int pos = 4; int rk; for (int i = 0; i < numrks; i++) { xfIndices[i] = IntegerHelper.getInt(data[pos], data[pos + 1]); rk = IntegerHelper.getInt (data[pos + 2], data[pos + 3], data[pos + 4], data[pos + 5]); rknumbers[i] = rk; pos += 6; } } /** * Accessor for the row * * @return the row of containing these rk numbers */ public int getRow() { return row; } /** * The first column containing the rk numbers * * @return the first column */ public int getFirstColumn() { return colFirst; } /** * Accessor for the number of rk values * * @return the number of rk values */ public int getNumberOfColumns() { return numrks; } /** * Returns a specific rk number * * @param index the rk number to return * @return the rk number in bits */ public int getRKNumber(int index) { return rknumbers[index]; } /** * Return a specific formatting index * * @param index the index of the cell in this group * @return the xf index */ public int getXFIndex(int index) { return xfIndices[index]; } } jexcelapi/src/jxl/read/biff/BottomMarginRecord.java0000750000175000017500000000224311207000610022511 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.biff.Type; /** * Record for the left margin settings */ class BottomMarginRecord extends MarginRecord { /** * Constructor * * @param r the record */ BottomMarginRecord(Record r) { super(Type.BOTTOMMARGIN, r); } } jexcelapi/src/jxl/read/biff/ErrorRecord.java0000750000175000017500000000440711207000610021204 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.CellType; import jxl.ErrorCell; import jxl.biff.FormattingRecords; /** * A cell containing an error code. This will usually be the result * of some error during the calculation of a formula */ class ErrorRecord extends CellValue implements ErrorCell { /** * The error code if this cell evaluates to an error, otherwise zer0 */ private int errorCode; /** * Constructs this object * * @param t the raw data * @param fr the formatting records * @param si the sheet */ public ErrorRecord(Record t, FormattingRecords fr, SheetImpl si) { super(t, fr, si); byte[] data = getRecord().getData(); errorCode = data[6]; } /** * Interface method which gets the error code for this cell. If this cell * does not represent an error, then it returns 0. Always use the * method isError() to determine this prior to calling this method * * @return the error code if this cell contains an error, 0 otherwise */ public int getErrorCode() { return errorCode; } /** * Returns the numerical value as a string * * @return The numerical value of the formula as a string */ public String getContents() { return "ERROR " + errorCode; } /** * Returns the cell type * * @return The cell type */ public CellType getType() { return CellType.ERROR; } } jexcelapi/src/jxl/read/biff/PasswordException.java0000750000175000017500000000232411207000612022433 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; /** * A properly typed exception in case consumers of the API specifically * wish to handle the case when the workbook is password protected */ public class PasswordException extends BiffException { /** * Constructor */ public PasswordException() { super(passwordProtected); } } jexcelapi/src/jxl/read/biff/BooleanRecord.java0000750000175000017500000000610211207000610021464 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.common.Assert; import jxl.BooleanCell; import jxl.CellType; import jxl.biff.FormattingRecords; /** * A boolean cell last calculated value */ class BooleanRecord extends CellValue implements BooleanCell { /** * Indicates whether this cell contains an error or a boolean */ private boolean error; /** * The boolean value of this cell. If this cell represents an error, * this will be false */ private boolean value; /** * Constructs this object from the raw data * * @param t the raw data * @param fr the formatting records * @param si the sheet */ public BooleanRecord(Record t, FormattingRecords fr, SheetImpl si) { super(t, fr, si); error = false; value = false; byte[] data = getRecord().getData(); error = (data[7] == 1); if (!error) { value = data[6] == 1 ? true : false; } } /** * Interface method which queries whether this cell contains an error. * Returns TRUE if it does, otherwise returns FALSE. * * @return TRUE if this cell is an error, FALSE otherwise */ public boolean isError() { return error; } /** * Interface method which Gets the boolean value stored in this cell. If * this cell contains an error, then returns FALSE. Always query this cell * type using the accessor method isError() prior to calling this method * * @return TRUE if this cell contains TRUE, FALSE if it contains FALSE or * an error code */ public boolean getValue() { return value; } /** * Returns the numerical value as a string * * @return The numerical value of the formula as a string */ public String getContents() { Assert.verify(!isError()); // return Boolean.toString(value) - only available in 1.4 or later return (new Boolean(value)).toString(); } /** * Returns the cell type * * @return The cell type */ public CellType getType() { return CellType.BOOLEAN; } /** * A special case which overrides the method in the subclass to get * hold of the raw data * * @return the record */ public Record getRecord() { return super.getRecord(); } } jexcelapi/src/jxl/read/biff/BlankCell.java0000750000175000017500000000326711207000610020606 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.read.biff; import jxl.CellType; import jxl.biff.FormattingRecords; /** * A blank cell. Despite the fact that this cell has no contents, it * has formatting information applied to it */ public class BlankCell extends CellValue { /** * Constructs this object from the raw data * * @param t the raw data * @param fr the available formats * @param si the sheet */ BlankCell(Record t, FormattingRecords fr, SheetImpl si) { super(t, fr, si); } /** * Returns the contents of this cell as an empty string * * @return the value formatted into a string */ public String getContents() { return ""; } /** * Accessor for the cell type * * @return the cell type */ public CellType getType() { return CellType.EMPTY; } } jexcelapi/src/jxl/CellFeatures.java0000750000175000017500000000420011232351556017520 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2004 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl; import jxl.biff.BaseCellFeatures; /** * Container for any additional cell features */ public class CellFeatures extends BaseCellFeatures { /** * Constructor */ public CellFeatures() { super(); } /** * Copy constructor * * @param cf cell to copy */ protected CellFeatures(CellFeatures cf) { super(cf); } /** * Accessor for the cell comment * * @return the cell comment, or NULL if this cell doesn't have * a comment associated with it */ public String getComment() { return super.getComment(); } /** * Gets the data validation list * * @return the data validation list */ public String getDataValidationList() { return super.getDataValidationList(); } /** * Gets the range of cells to which the data validation applies. If the * validation applies to just this cell, this will be reflected in the * returned range * * @return the range to which the same validation extends, or NULL if this * cell doesn't have a validation */ public Range getSharedDataValidationRange() { return super.getSharedDataValidationRange(); } } jexcelapi/src/jxl/DateFormulaCell.java0000750000175000017500000000215111207000610020130 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl; /** * A mixin interface for date formulas, which combines the interfaces * for formulas and for dates */ public interface DateFormulaCell extends DateCell, FormulaCell { } jexcelapi/src/jxl/Workbook.java0000750000175000017500000003201511262601525016741 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import jxl.read.biff.BiffException; import jxl.read.biff.File; import jxl.read.biff.PasswordException; import jxl.read.biff.WorkbookParser; import jxl.write.WritableWorkbook; import jxl.write.biff.WritableWorkbookImpl; /** * Represents a Workbook. Contains the various factory methods and provides * a variety of accessors which provide access to the work sheets. */ public abstract class Workbook { /** * The current version of the software */ private static final String VERSION = "2.6.12"; /** * The constructor */ protected Workbook() { } /** * Gets the sheets within this workbook. Use of this method for * large worksheets can cause performance problems. * * @return an array of the individual sheets */ public abstract Sheet[] getSheets(); /** * Gets the sheet names * * @return an array of strings containing the sheet names */ public abstract String[] getSheetNames(); /** * Gets the specified sheet within this workbook * As described in the accompanying technical notes, each call * to getSheet forces a reread of the sheet (for memory reasons). * Therefore, do not make unnecessary calls to this method. Furthermore, * do not hold unnecessary references to Sheets in client code, as * this will prevent the garbage collector from freeing the memory * * @param index the zero based index of the reQuired sheet * @return The sheet specified by the index * @exception IndexOutOfBoundException when index refers to a non-existent * sheet */ public abstract Sheet getSheet(int index) throws IndexOutOfBoundsException; /** * Gets the sheet with the specified name from within this workbook. * As described in the accompanying technical notes, each call * to getSheet forces a reread of the sheet (for memory reasons). * Therefore, do not make unnecessary calls to this method. Furthermore, * do not hold unnecessary references to Sheets in client code, as * this will prevent the garbage collector from freeing the memory * * @param name the sheet name * @return The sheet with the specified name, or null if it is not found */ public abstract Sheet getSheet(String name); /** * Accessor for the software version * * @return the version */ public static String getVersion() { return VERSION; } /** * Returns the number of sheets in this workbook * * @return the number of sheets in this workbook */ public abstract int getNumberOfSheets(); /** * Gets the named cell from this workbook. If the name refers to a * range of cells, then the cell on the top left is returned. If * the name cannot be found, null is returned. * This is a convenience function to quickly access the contents * of a single cell. If you need further information (such as the * sheet or adjacent cells in the range) use the functionally * richer method, findByName which returns a list of ranges * * @param name the name of the cell/range to search for * @return the cell in the top left of the range if found, NULL * otherwise */ public abstract Cell findCellByName(String name); /** * Returns the cell for the specified location eg. "Sheet1!A4". * This is identical to using the CellReferenceHelper with its * associated performance overheads, consequently it should * be use sparingly * * @param loc the cell to retrieve * @return the cell at the specified location */ public abstract Cell getCell(String loc); /** * Gets the named range from this workbook. The Range object returns * contains all the cells from the top left to the bottom right * of the range. * If the named range comprises an adjacent range, * the Range[] will contain one object; for non-adjacent * ranges, it is necessary to return an array of length greater than * one. * If the named range contains a single cell, the top left and * bottom right cell will be the same cell * * @param name the name of the cell/range to search for * @return the range of cells, or NULL if the range does not exist */ public abstract Range[] findByName(String name); /** * Gets the named ranges * * @return the list of named cells within the workbook */ public abstract String[] getRangeNames(); /** * Determines whether the sheet is protected * * @return TRUE if the workbook is protected, FALSE otherwise */ public abstract boolean isProtected(); /** * Parses the excel file. * If the workbook is password protected a PasswordException is thrown * in case consumers of the API wish to handle this in a particular way * * @exception BiffException * @exception PasswordException */ protected abstract void parse() throws BiffException, PasswordException; /** * Closes this workbook, and frees makes any memory allocated available * for garbage collection */ public abstract void close(); /** * A factory method which takes in an excel file and reads in the contents. * * @exception IOException * @exception BiffException * @param file the excel 97 spreadsheet to parse * @return a workbook instance */ public static Workbook getWorkbook(java.io.File file) throws IOException, BiffException { return getWorkbook(file, new WorkbookSettings()); } /** * A factory method which takes in an excel file and reads in the contents. * * @exception IOException * @exception BiffException * @param file the excel 97 spreadsheet to parse * @param ws the settings for the workbook * @return a workbook instance */ public static Workbook getWorkbook(java.io.File file, WorkbookSettings ws) throws IOException, BiffException { FileInputStream fis = new FileInputStream(file); // Always close down the input stream, regardless of whether or not the // file can be parsed. Thanks to Steve Hahn for this File dataFile = null; try { dataFile = new File(fis, ws); } catch (IOException e) { fis.close(); throw e; } catch (BiffException e) { fis.close(); throw e; } fis.close(); Workbook workbook = new WorkbookParser(dataFile, ws); workbook.parse(); return workbook; } /** * A factory method which takes in an excel file and reads in the contents. * * @param is an open stream which is the the excel 97 spreadsheet to parse * @return a workbook instance * @exception IOException * @exception BiffException */ public static Workbook getWorkbook(InputStream is) throws IOException, BiffException { return getWorkbook(is, new WorkbookSettings()); } /** * A factory method which takes in an excel file and reads in the contents. * * @param is an open stream which is the the excel 97 spreadsheet to parse * @param ws the settings for the workbook * @return a workbook instance * @exception IOException * @exception BiffException */ public static Workbook getWorkbook(InputStream is, WorkbookSettings ws) throws IOException, BiffException { File dataFile = new File(is, ws); Workbook workbook = new WorkbookParser(dataFile, ws); workbook.parse(); return workbook; } /** * Creates a writable workbook with the given file name * * @param file the workbook to copy * @return a writable workbook * @exception IOException */ public static WritableWorkbook createWorkbook(java.io.File file) throws IOException { return createWorkbook(file, new WorkbookSettings()); } /** * Creates a writable workbook with the given file name * * @param file the file to copy from * @param ws the global workbook settings * @return a writable workbook * @exception IOException */ public static WritableWorkbook createWorkbook(java.io.File file, WorkbookSettings ws) throws IOException { FileOutputStream fos = new FileOutputStream(file); WritableWorkbook w = new WritableWorkbookImpl(fos, true, ws); return w; } /** * Creates a writable workbook with the given filename as a copy of * the workbook passed in. Once created, the contents of the writable * workbook may be modified * * @param file the output file for the copy * @param in the workbook to copy * @return a writable workbook * @exception IOException */ public static WritableWorkbook createWorkbook(java.io.File file, Workbook in) throws IOException { return createWorkbook(file, in, new WorkbookSettings()); } /** * Creates a writable workbook with the given filename as a copy of * the workbook passed in. Once created, the contents of the writable * workbook may be modified * * @param file the output file for the copy * @param in the workbook to copy * @param ws the configuration for this workbook * @return a writable workbook */ public static WritableWorkbook createWorkbook(java.io.File file, Workbook in, WorkbookSettings ws) throws IOException { FileOutputStream fos = new FileOutputStream(file); WritableWorkbook w = new WritableWorkbookImpl(fos, in, true, ws); return w; } /** * Creates a writable workbook as a copy of * the workbook passed in. Once created, the contents of the writable * workbook may be modified * * @param os the stream to write to * @param in the workbook to copy * @return a writable workbook * @exception IOException */ public static WritableWorkbook createWorkbook(OutputStream os, Workbook in) throws IOException { return createWorkbook(os, in, ((WorkbookParser) in).getSettings()); } /** * Creates a writable workbook as a copy of * the workbook passed in. Once created, the contents of the writable * workbook may be modified * * @param os the output stream to write to * @param in the workbook to copy * @param ws the configuration for this workbook * @return a writable workbook * @exception IOException */ public static WritableWorkbook createWorkbook(OutputStream os, Workbook in, WorkbookSettings ws) throws IOException { WritableWorkbook w = new WritableWorkbookImpl(os, in, false, ws); return w; } /** * Creates a writable workbook. When the workbook is closed, * it will be streamed directly to the output stream. In this * manner, a generated excel spreadsheet can be passed from * a servlet to the browser over HTTP * * @param os the output stream * @return the writable workbook * @exception IOException */ public static WritableWorkbook createWorkbook(OutputStream os) throws IOException { return createWorkbook(os, new WorkbookSettings()); } /** * Creates a writable workbook. When the workbook is closed, * it will be streamed directly to the output stream. In this * manner, a generated excel spreadsheet can be passed from * a servlet to the browser over HTTP * * @param os the output stream * @param ws the configuration for this workbook * @return the writable workbook * @exception IOException */ public static WritableWorkbook createWorkbook(OutputStream os, WorkbookSettings ws) throws IOException { WritableWorkbook w = new WritableWorkbookImpl(os, false, ws); return w; } } jexcelapi/src/jxl/biff/0000750000175000017500000000000011270605332015202 5ustar drazzibdrazzibjexcelapi/src/jxl/biff/ContinueRecord.java0000750000175000017500000000375111207000612020767 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2004 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; import jxl.read.biff.Record; /** * A continue record - only used explicitly in special circumstances, as * the general continuation record is handled directly by the records */ public class ContinueRecord extends WritableRecordData { /** * The data */ private byte[] data; /** * Constructor * * @param t the raw bytes */ public ContinueRecord(Record t) { super(t); data = t.getData(); } /** * Constructor invoked when creating continue records * * @param d the data */ public ContinueRecord(byte[] d) { super(Type.CONTINUE); data = d; } /** * Accessor for the binary data - used when copying * * @return the binary data */ public byte[] getData() { return data; } /** * Accessor for the record. Used when forcibly changing this record * into another type, notably a drawing record, as sometimes Excel appears * to switch to writing Continue records instead of MsoDrawing records * * @return the record */ public Record getRecord() { return super.getRecord(); } } jexcelapi/src/jxl/biff/AutoFilterInfoRecord.java0000750000175000017500000000300311207000612022063 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2007 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; import jxl.common.Logger; import jxl.read.biff.Record; /** * Range information for conditional formatting */ public class AutoFilterInfoRecord extends WritableRecordData { // The logger private static Logger logger = Logger.getLogger(AutoFilterInfoRecord.class); /** * The data */ private byte[] data; /** * Constructor */ public AutoFilterInfoRecord(Record t) { super(t); data = getRecord().getData(); } /** * Retrieves the data for output to binary file * * @return the data to be written */ public byte[] getData() { return data; } } jexcelapi/src/jxl/biff/BuiltInFormat.java0000750000175000017500000001252211207000612020557 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; import jxl.format.Format; /** * The excel string for the various built in formats. Used to present * the cell format information back to the user * * The difference between this class and the various format object contained * in the jxl.write package is that this object contains the Excel strings, * not their java equivalents */ final class BuiltInFormat implements Format, DisplayFormat { /** * The excel format string */ private String formatString; /** * The index */ private int formatIndex; /** * Constructor * * @param s the format string * @param i the format index */ private BuiltInFormat(String s, int i) { formatIndex = i; formatString = s; } /** * Accesses the excel format string which is applied to the cell * Note that this is the string that excel uses, and not the java * equivalent * * @return the cell format string */ public String getFormatString() { return formatString; } /** * Accessor for the index style of this format * * @return the index for this format */ public int getFormatIndex() { return formatIndex; } /** * Accessor to see whether this format has been initialized * * @return TRUE if initialized, FALSE otherwise */ public boolean isInitialized() { return true; } /** * Initializes this format with the specified index number * * @param pos the position of this format record in the workbook */ public void initialize(int pos) { } /** * Accessor to determine whether or not this format is built in * * @return TRUE if this format is a built in format, FALSE otherwise */ public boolean isBuiltIn() { return true; } /** * Equals method * * @return TRUE if the two built in formats are equal, FALSE otherwise */ public boolean equals(Object o) { if (o == this) { return true; } if (!(o instanceof BuiltInFormat)) { return false; } BuiltInFormat bif = (BuiltInFormat) o; return (formatIndex == bif.formatIndex); } /** * The list of built in formats */ public static BuiltInFormat[] builtIns = new BuiltInFormat[0x32]; // Populate the built ins static { builtIns[0x0] = new BuiltInFormat("", 0); builtIns[0x1] = new BuiltInFormat("0", 1); builtIns[0x2] = new BuiltInFormat("0.00", 2); builtIns[0x3] = new BuiltInFormat("#,##0", 3); builtIns[0x4] = new BuiltInFormat("#,##0.00", 4); builtIns[0x5] = new BuiltInFormat("($#,##0_);($#,##0)", 5); builtIns[0x6] = new BuiltInFormat("($#,##0_);[Red]($#,##0)", 6); builtIns[0x7] = new BuiltInFormat("($#,##0_);[Red]($#,##0)", 7); builtIns[0x8] = new BuiltInFormat("($#,##0.00_);[Red]($#,##0.00)", 8); builtIns[0x9] = new BuiltInFormat("0%", 9); builtIns[0xa] = new BuiltInFormat("0.00%", 10); builtIns[0xb] = new BuiltInFormat("0.00E+00", 11); builtIns[0xc] = new BuiltInFormat("# ?/?", 12); builtIns[0xd] = new BuiltInFormat("# ??/??", 13); builtIns[0xe] = new BuiltInFormat("dd/mm/yyyy", 14); builtIns[0xf] = new BuiltInFormat("d-mmm-yy", 15); builtIns[0x10] = new BuiltInFormat("d-mmm", 16); builtIns[0x11] = new BuiltInFormat("mmm-yy", 17); builtIns[0x12] = new BuiltInFormat("h:mm AM/PM", 18); builtIns[0x13] = new BuiltInFormat("h:mm:ss AM/PM", 19); builtIns[0x14] = new BuiltInFormat("h:mm", 20); builtIns[0x15] = new BuiltInFormat("h:mm:ss", 21); builtIns[0x16] = new BuiltInFormat("m/d/yy h:mm", 22); builtIns[0x25] = new BuiltInFormat("(#,##0_);(#,##0)", 0x25); builtIns[0x26] = new BuiltInFormat("(#,##0_);[Red](#,##0)", 0x26); builtIns[0x27] = new BuiltInFormat("(#,##0.00_);(#,##0.00)", 0x27); builtIns[0x28] = new BuiltInFormat("(#,##0.00_);[Red](#,##0.00)", 0x28); builtIns[0x29] = new BuiltInFormat ("_(*#,##0_);_(*(#,##0);_(*\"-\"_);(@_)", 0x29); builtIns[0x2a] = new BuiltInFormat ("_($*#,##0_);_($*(#,##0);_($*\"-\"_);(@_)", 0x2a); builtIns[0x2b] = new BuiltInFormat ("_(* #,##0.00_);_(* (#,##0.00);_(* \"-\"??_);(@_)", 0x2b); builtIns[0x2c] = new BuiltInFormat ("_($* #,##0.00_);_($* (#,##0.00);_($* \"-\"??_);(@_)", 0x2c); builtIns[0x2d] = new BuiltInFormat("mm:ss", 0x2d); builtIns[0x2e] = new BuiltInFormat("[h]mm:ss", 0x2e); builtIns[0x2f] = new BuiltInFormat("mm:ss.0", 0x2f); builtIns[0x30] = new BuiltInFormat("##0.0E+0", 0x30); builtIns[0x31] = new BuiltInFormat("@", 0x31); } } jexcelapi/src/jxl/biff/FormulaData.java0000750000175000017500000000263511207000612020243 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; import jxl.Cell; import jxl.biff.formula.FormulaException; /** * Interface which is used for copying formulas from a read only * to a writable spreadsheet */ public interface FormulaData extends Cell { /** * Gets the raw bytes for the formula. This will include the * parsed tokens array EXCLUDING the standard cell information * (row, column, xfindex) * * @return the raw record data * @exception FormulaException */ public byte[] getFormulaData() throws FormulaException; } jexcelapi/src/jxl/biff/WorkbookMethods.java0000750000175000017500000000343411207000612021163 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; import jxl.Sheet; /** * An interface containing some common workbook methods. This so that * objects which are re-used for both readable and writable workbooks * can still make the same method calls on a workbook */ public interface WorkbookMethods { /** * Gets the specified sheet within this workbook * * @param index the zero based index of the required sheet * @return The sheet specified by the index */ public Sheet getReadSheet(int index); /** * Gets the name at the specified index * * @param index the index into the name table * @return the name of the cell * @exception NameRangeException */ public String getName(int index) throws NameRangeException; /** * Gets the index of the name record for the name * * @param name the name * @return the index in the name table */ public int getNameIndex(String name); } jexcelapi/src/jxl/biff/#DataValidationParseException.java#0000750000175000017500000000330111207000612023677 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2009 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; import jxl.JXLException; /** * A properly typed exception in case consumers of the API specifically * wish to handle the case when the workbook is password protected */ public class DataValidationParseException extends JXLException { private int col1; private int col2; private int row1; private int row2; /** * Constructor */ public DataValidationParseException(String msg, int c1, int r1, int c2, int r2) { super(msg); col1 = c1; col2 = c2; row1 = r1; row2 = r2; } public String getMessage() { return super.getMessage() + " for cells " + CellReferenceHelper.getCellReference(col1, row2)+ "-" + CellReferenceHelper.getCellReference(col2, row2); } } jexcelapi/src/jxl/biff/drawing/0000750000175000017500000000000011270605332016635 5ustar drazzibdrazzibjexcelapi/src/jxl/biff/drawing/#Button.java#0000750000175000017500000004164111207000612021060 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.drawing; import java.io.IOException; import jxl.common.Assert; import jxl.common.Logger; import jxl.WorkbookSettings; import jxl.biff.ContinueRecord; import jxl.biff.IntegerHelper; import jxl.biff.StringHelper; import jxl.write.biff.File; /** * Contains the various biff records used to copy a Button (from the * Form toolbox) between workbook */ public class Button implements DrawingGroupObject { /** * The logger */ private static Logger logger = Logger.getLogger(Button.class); /** * The spContainer that was read in */ private EscherContainer readSpContainer; /** * The spContainer that was generated */ private EscherContainer spContainer; /** * The MsoDrawingRecord associated with the drawing */ private MsoDrawingRecord msoDrawingRecord; /** * The ObjRecord associated with the drawing */ private ObjRecord objRecord; /** * Initialized flag */ private boolean initialized = false; /** * The object id, assigned by the drawing group */ private int objectId; /** * The blip id */ private int blipId; /** * The shape id */ private int shapeId; /** * The column */ private int column; /** * The row position of the image */ private int row; /** * The width of the image in cells */ private double width; /** * The height of the image in cells */ private double height; /** * The number of places this drawing is referenced */ private int referenceCount; /** * The top level escher container */ private EscherContainer escherData; /** * Where this image came from (read, written or a copy) */ private Origin origin; /** * The drawing group for all the images */ private DrawingGroup drawingGroup; /** * The drawing data */ private DrawingData drawingData; /** * The type of this drawing object */ private ShapeType type; /** * The drawing position on the sheet */ private int drawingNumber; /** * An mso drawing record, which sometimes appears */ private MsoDrawingRecord mso; /** * The text object record */ private TextObjectRecord txo; /** * Text data from the first continue record */ private ContinueRecord text; /** * Formatting data from the second continue record */ private ContinueRecord formatting; /** * The comment text */ private String commentText; /** * The workbook settings */ private WorkbookSettings workbookSettings; /** * Constructor used when reading images * * @param msodr the drawing record * @param obj the object record * @param dd the drawing data for all drawings on this sheet * @param dg the drawing group * @param ws the workbook settings */ public Button(MsoDrawingRecord msodr, ObjRecord obj, DrawingData dd, DrawingGroup dg, WorkbookSettings ws) { drawingGroup = dg; msoDrawingRecord = msodr; drawingData = dd; objRecord = obj; initialized = false; workbookSettings = ws; origin = Origin.READ; drawingData.addData(msoDrawingRecord.getData()); drawingNumber = drawingData.getNumDrawings() - 1; drawingGroup.addDrawing(this); Assert.verify(msoDrawingRecord != null && objRecord != null); initialize(); } /** * Copy constructor used to copy drawings from read to write * * @param dgo the drawing group object * @param dg the drawing group * @param ws the workbook settings */ public Button(DrawingGroupObject dgo, DrawingGroup dg, WorkbookSettings ws) { Button d = (Button) dgo; Assert.verify(d.origin == Origin.READ); msoDrawingRecord = d.msoDrawingRecord; objRecord = d.objRecord; initialized = false; origin = Origin.READ; drawingData = d.drawingData; drawingGroup = dg; drawingNumber = d.drawingNumber; drawingGroup.addDrawing(this); mso = d.mso; txo = d.txo; text = d.text; formatting = d.formatting; workbookSettings = ws; } /** * Initializes the member variables from the Escher stream data */ private void initialize() { readSpContainer = drawingData.getSpContainer(drawingNumber); Assert.verify(readSpContainer != null); EscherRecord[] children = readSpContainer.getChildren(); Sp sp = (Sp) readSpContainer.getChildren()[0]; objectId = objRecord.getObjectId(); shapeId = sp.getShapeId(); type = ShapeType.getType(sp.getShapeType()); if (type == ShapeType.UNKNOWN) { logger.warn("Unknown shape type"); } ClientAnchor clientAnchor = null; for (int i = 0; i < children.length && clientAnchor == null; i++) { if (children[i].getType() == EscherRecordType.CLIENT_ANCHOR) { clientAnchor = (ClientAnchor) children[i]; } } if (clientAnchor == null) { logger.warn("Client anchor not found"); } else { column = (int) clientAnchor.getX1() - 1; row = (int) clientAnchor.getY1() + 1; } initialized = true; } /** * Sets the object id. Invoked by the drawing group when the object is * added to id * * @param objid the object id * @param bip the blip id * @param sid the shape id */ public final void setObjectId(int objid, int bip, int sid) { objectId = objid; blipId = bip; shapeId = sid; if (origin == Origin.READ) { origin = Origin.READ_WRITE; } } /** * Accessor for the object id * * @return the object id */ public final int getObjectId() { if (!initialized) { initialize(); } return objectId; } /** * Accessor for the shape id * * @return the object id */ public final int getShapeId() { if (!initialized) { initialize(); } return shapeId; } /** * Accessor for the blip id * * @return the blip id */ public final int getBlipId() { if (!initialized) { initialize(); } return blipId; } /** * Gets the drawing record which was read in * * @return the drawing record */ public MsoDrawingRecord getMsoDrawingRecord() { return msoDrawingRecord; } /** * Creates the main Sp container for the drawing * * @return the SP container */ public EscherContainer getSpContainer() { if (!initialized) { initialize(); } if (origin == Origin.READ) { return getReadSpContainer(); } Assert.verify(false); /* if (spContainer == null) { spContainer = new SpContainer(); Sp sp = new Sp(type, shapeId, 2560); spContainer.add(sp); Opt opt = new Opt(); opt.addProperty(344, false, false, 0); // ? opt.addProperty(385, false, false, 134217808); // fill colour opt.addProperty(387, false, false, 134217808); // background colour opt.addProperty(959, false, false, 131074); // hide spContainer.add(opt); ClientAnchor clientAnchor = new ClientAnchor(column + 1.3, Math.max(0, row - 0.6), column+3, row + 4); spContainer.add(clientAnchor); ClientData clientData = new ClientData(); spContainer.add(clientData); ClientTextBox clientTextBox = new ClientTextBox(); spContainer.add(clientTextBox); } */ return spContainer; } /** * Sets the drawing group for this drawing. Called by the drawing group * when this drawing is added to it * * @param dg the drawing group */ public void setDrawingGroup(DrawingGroup dg) { drawingGroup = dg; } /** * Accessor for the drawing group * * @return the drawing group */ public DrawingGroup getDrawingGroup() { return drawingGroup; } /** * Gets the origin of this drawing * * @return where this drawing came from */ public Origin getOrigin() { return origin; } /** * Accessor for the reference count on this drawing * * @return the reference count */ public int getReferenceCount() { return referenceCount; } /** * Sets the new reference count on the drawing * * @param r the new reference count */ public void setReferenceCount(int r) { referenceCount = r; } /** * Accessor for the column of this drawing * * @return the column */ public double getX() { if (!initialized) { initialize(); } return column; } /** * Sets the column position of this drawing. Used when inserting/removing * columns from the spreadsheet * * @param x the column */ public void setX(double x) { if (origin == Origin.READ) { if (!initialized) { initialize(); } origin = Origin.READ_WRITE; } column = (int) x; } /** * Accessor for the row of this drawing * * @return the row */ public double getY() { if (!initialized) { initialize(); } return row; } /** * Accessor for the row of the drawing * * @param y the row */ public void setY(double y) { if (origin == Origin.READ) { if (!initialized) { initialize(); } origin = Origin.READ_WRITE; } row = (int) y; } /** * Accessor for the width of this drawing * * @return the number of columns spanned by this image */ public double getWidth() { if (!initialized) { initialize(); } return width; } /** * Accessor for the width * * @param w the number of columns to span */ public void setWidth(double w) { if (origin == Origin.READ) { if (!initialized) { initialize(); } origin = Origin.READ_WRITE; } width = w; } /** * Accessor for the height of this drawing * * @return the number of rows spanned by this image */ public double getHeight() { if (!initialized) { initialize(); } return height; } /** * Accessor for the height of this drawing * * @param h the number of rows spanned by this image */ public void setHeight(double h) { if (origin == Origin.READ) { if (!initialized) { initialize(); } origin = Origin.READ_WRITE; } height = h; } /** * Gets the SpContainer that was read in * * @return the read sp container */ private EscherContainer getReadSpContainer() { if (!initialized) { initialize(); } return readSpContainer; } /** * Accessor for the image data * * @return the image data */ public byte[] getImageData() { Assert.verify(origin == Origin.READ || origin == Origin.READ_WRITE); if (!initialized) { initialize(); } return drawingGroup.getImageData(blipId); } /** * Accessor for the type * * @return the type */ public ShapeType getType() { return type; } /** * Sets the text object * * @param t the text object record */ public void setTextObject(TextObjectRecord t) { txo = t; } /** * Sets the text data * * @param t continuation record */ public void setText(ContinueRecord t) { text = t; } /** * Sets the formatting * * @param t continue record */ public void setFormatting(ContinueRecord t) { formatting = t; } /** * Accessor for the image data * * @return the image data */ public byte[] getImageBytes() { Assert.verify(false); return null; } /** * Accessor for the image file path. Normally this is the absolute path * of a file on the directory system, but if this drawing was constructed * using an byte[] then the blip id is returned * * @return the image file path, or the blip id */ public String getImageFilePath() { Assert.verify(false); return null; } /** * The drawing record * * @param d the drawing record */ public void addMso(MsoDrawingRecord d) { mso = d; drawingData.addRawData(mso.getData()); } /** * Writes out any additional records * * @param outputFile the output file * @exception IOException */ public void writeAdditionalRecords(File outputFile) throws IOException { if (origin == Origin.READ) { outputFile.write(objRecord); if (mso != null) { outputFile.write(mso); } outputFile.write(txo); outputFile.write(text); if (formatting != null) { outputFile.write(formatting); } return; } Assert.verify(false); // Create the obj record ObjRecord objrec = new ObjRecord(objectId, ObjRecord.EXCELNOTE); outputFile.write(objrec); // Create the mso data record. Write the text box record again, // although it is already included in the SpContainer ClientTextBox textBox = new ClientTextBox(); MsoDrawingRecord msod = new MsoDrawingRecord(textBox.getData()); outputFile.write(msod); TextObjectRecord tor = new TextObjectRecord(getText()); outputFile.write(tor); // Data for the first continue record byte[] textData = new byte[commentText.length() * 2 + 1]; textData[0] = 0x1; // unicode indicator StringHelper.getUnicodeBytes(commentText, textData, 1); //StringHelper.getBytes(commentText, textData, 1); ContinueRecord textContinue = new ContinueRecord(textData); outputFile.write(textContinue); // Data for the formatting runs byte[] frData = new byte[16]; // First txo run (the user) IntegerHelper.getTwoBytes(0, frData, 0); // index to the first character IntegerHelper.getTwoBytes(0, frData, 2); // index to the font(default) // Mandatory last txo run IntegerHelper.getTwoBytes(commentText.length(), frData, 8); IntegerHelper.getTwoBytes(0, frData, 10); // index to the font(default) ContinueRecord frContinue = new ContinueRecord(frData); outputFile.write(frContinue); } /** * Writes any records that need to be written after all the drawing group * objects have been written * * @param outputFile the output file */ public void writeTailRecords(File outputFile) { } /** * Accessor for the row. As buttons are not associated with a cell, * does nothing here * * @return the row number */ public int getRow() { return 0; } /** * Accessor for the column. As buttons are not associated with a cell, * does nothing here * * @return the column number */ public int getColumn() { return 0; } /** * Accessor for the text on the button * * @return the button text */ public String getText() { if (commentText == null) { Assert.verify(text != null); byte[] td = text.getData(); if (td[0] == 0) { commentText = StringHelper.getString (td, td.length - 1, 1, workbookSettings); } else { commentText = StringHelper.getUnicodeString (td, (td.length - 1) / 2, 1); } } return commentText; } /** * Hashing algorithm * * @return the hash code */ public int hashCode() { return commentText.hashCode(); } /** * Called when the comment text is changed during the sheet copy process * * @param t the new text */ public void setButtonText(String t) { commentText = t; if (origin == Origin.READ) { origin = Origin.READ_WRITE; } } /** * Accessor for the first drawing on the sheet. This is used when * copying unmodified sheets to indicate that this drawing contains * the first time Escher gubbins * * @return TRUE if this MSORecord is the first drawing on the sheet */ public boolean isFirst() { return mso.isFirst(); } /** * Queries whether this object is a form object. Form objects have their * drawings records spread over TXO and CONTINUE records and * require special handling * * @return TRUE if this is a form object, FALSE otherwise */ public boolean isFormObject() { return true; } } jexcelapi/src/jxl/biff/drawing/ClientTextBox.java0000750000175000017500000000302011207000612022220 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.drawing; import jxl.common.Logger; /** * ??? */ class ClientTextBox extends EscherAtom { /** * The logger */ private static Logger logger = Logger.getLogger(ClientTextBox.class); /** * The raw data */ private byte[] data; /** * Constructor * * @param erd */ public ClientTextBox(EscherRecordData erd) { super(erd); } /** * Constructor */ public ClientTextBox() { super(EscherRecordType.CLIENT_TEXT_BOX); } /** * Accessor for the raw data * * @return */ byte[] getData() { data = new byte[0]; return setHeaderData(data); } } jexcelapi/src/jxl/biff/drawing/EscherRecordType.java0000750000175000017500000000663111207000612022711 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.drawing; /** * Enumeration class for Escher record types */ final class EscherRecordType { /** * The code of the item within the escher stream */ private int value; /** * All escher types */ private static EscherRecordType[] types = new EscherRecordType[0]; /** * Constructor * * @param val the escher record value */ private EscherRecordType(int val) { value = val; EscherRecordType[] newtypes = new EscherRecordType[types.length + 1]; System.arraycopy(types, 0, newtypes, 0, types.length); newtypes[types.length] = this; types = newtypes; } /** * Accessor for the escher record value * * @return the escher record value */ public int getValue() { return value; } /** * Accessor to get the item from a particular value * * @param val the escher record value * @return the type corresponding to val, or UNKNOWN if a match could not * be found */ public static EscherRecordType getType(int val) { EscherRecordType type = UNKNOWN; for (int i = 0; i < types.length; i++) { if (val == types[i].value) { type = types[i]; break; } } return type; } public static final EscherRecordType UNKNOWN = new EscherRecordType(0x0); public static final EscherRecordType DGG_CONTAINER = new EscherRecordType(0xf000); public static final EscherRecordType BSTORE_CONTAINER = new EscherRecordType(0xf001); public static final EscherRecordType DG_CONTAINER = new EscherRecordType(0xf002); public static final EscherRecordType SPGR_CONTAINER = new EscherRecordType(0xf003); public static final EscherRecordType SP_CONTAINER = new EscherRecordType(0xf004); public static final EscherRecordType DGG = new EscherRecordType(0xf006); public static final EscherRecordType BSE = new EscherRecordType(0xf007); public static final EscherRecordType DG = new EscherRecordType(0xf008); public static final EscherRecordType SPGR = new EscherRecordType(0xf009); public static final EscherRecordType SP = new EscherRecordType(0xf00a); public static final EscherRecordType OPT = new EscherRecordType(0xf00b); public static final EscherRecordType CLIENT_ANCHOR = new EscherRecordType(0xf010); public static final EscherRecordType CLIENT_DATA = new EscherRecordType(0xf011); public static final EscherRecordType CLIENT_TEXT_BOX = new EscherRecordType(0xf00d); public static final EscherRecordType SPLIT_MENU_COLORS = new EscherRecordType(0xf11e); } jexcelapi/src/jxl/biff/drawing/ClientAnchor.java0000750000175000017500000001110211207000612022035 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.drawing; import jxl.common.Logger; import jxl.biff.IntegerHelper; /** * The client anchor record */ class ClientAnchor extends EscherAtom { /** * The logger */ private static final Logger logger = Logger.getLogger(ClientAnchor.class); /** * The binary data */ private byte[] data; /** * The properties */ private int properties; /** * The x1 position */ private double x1; /** * The y1 position */ private double y1; /** * The x2 position */ private double x2; /** * The y2 position */ private double y2; /** * Constructor * * @param erd the escher record data */ public ClientAnchor(EscherRecordData erd) { super(erd); byte[] bytes = getBytes(); // The properties properties = IntegerHelper.getInt(bytes[0], bytes[1]); // The x1 cell int x1Cell = IntegerHelper.getInt(bytes[2], bytes[3]); int x1Fraction = IntegerHelper.getInt(bytes[4], bytes[5]); x1 = x1Cell + (double) x1Fraction / (double) 1024; // The y1 cell int y1Cell = IntegerHelper.getInt(bytes[6], bytes[7]); int y1Fraction = IntegerHelper.getInt(bytes[8], bytes[9]); y1 = y1Cell + (double) y1Fraction / (double) 256; // The x2 cell int x2Cell = IntegerHelper.getInt(bytes[10], bytes[11]); int x2Fraction = IntegerHelper.getInt(bytes[12], bytes[13]); x2 = x2Cell + (double) x2Fraction / (double) 1024; // The y1 cell int y2Cell = IntegerHelper.getInt(bytes[14], bytes[15]); int y2Fraction = IntegerHelper.getInt(bytes[16], bytes[17]); y2 = y2Cell + (double) y2Fraction / (double) 256; } /** * Constructor * * @param x1 the x1 position * @param y1 the y1 position * @param x2 the x2 position * @param y2 the y2 position * @param props the anchor properties */ public ClientAnchor(double x1, double y1, double x2, double y2, int props) { super(EscherRecordType.CLIENT_ANCHOR); this.x1 = x1; this.y1 = y1; this.x2 = x2; this.y2 = y2; properties = props; } /** * Gets the client anchor data * * @return the data */ byte[] getData() { data = new byte[18]; IntegerHelper.getTwoBytes(properties, data, 0); // The x1 cell IntegerHelper.getTwoBytes((int) x1, data, 2); // The x1 fraction into the cell 0-1024 int x1fraction = (int) ((x1 - (int) x1) * 1024); IntegerHelper.getTwoBytes(x1fraction, data, 4); // The y1 cell IntegerHelper.getTwoBytes((int) y1, data, 6); // The y1 fraction into the cell 0-256 int y1fraction = (int) ((y1 - (int) y1) * 256); IntegerHelper.getTwoBytes(y1fraction, data, 8); // The x2 cell IntegerHelper.getTwoBytes((int) x2, data, 10); // The x2 fraction into the cell 0-1024 int x2fraction = (int) ((x2 - (int) x2) * 1024); IntegerHelper.getTwoBytes(x2fraction, data, 12); // The y2 cell IntegerHelper.getTwoBytes((int) y2, data, 14); // The y2 fraction into the cell 0-256 int y2fraction = (int) ((y2 - (int) y2) * 256); IntegerHelper.getTwoBytes(y2fraction, data, 16); return setHeaderData(data); } /** * Accessor for the x1 position * * @return the x1 position */ double getX1() { return x1; } /** * Accessor for the y1 position * * @return the y1 position */ double getY1() { return y1; } /** * Accessor for the x2 position * * @return the x2 position */ double getX2() { return x2; } /** * Accessor for the y2 position * * @return the y2 position */ double getY2() { return y2; } /** * Accessor for the anchor properties */ int getProperties() { return properties; } } jexcelapi/src/jxl/biff/drawing/EscherAtom.java0000750000175000017500000000344511207000612021531 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.drawing; import jxl.common.Logger; /** * Class for atoms. This may be instantiated as is for unknown/uncared about * atoms, or subclassed if we have some semantic interest in the contents */ class EscherAtom extends EscherRecord { /** * The logger */ private static Logger logger = Logger.getLogger(EscherAtom.class); /** * Constructor * * @param erd the escher record data */ public EscherAtom(EscherRecordData erd) { super(erd); } /** * Constructor * * @param type the type */ protected EscherAtom(EscherRecordType type) { super(type); } /** * Gets the data for writing * * @return the data */ byte[] getData() { logger.warn("escher atom getData called on object of type " + getClass().getName() + " code " + Integer.toString(getType().getValue(), 16)); return null; } } jexcelapi/src/jxl/biff/drawing/Opt.java0000750000175000017500000001341211263145355020254 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.drawing; import java.util.ArrayList; import java.util.Iterator; import jxl.common.Logger; import jxl.biff.IntegerHelper; import jxl.biff.StringHelper; /** * An options record in the escher stream */ class Opt extends EscherAtom { /** * The logger */ private static Logger logger = Logger.getLogger(Opt.class); /** * The binary data */ private byte[] data; /** * The number of properties */ private int numProperties; /** * The list of properties */ private ArrayList properties; /** * Properties enumeration inner class */ final static class Property { int id; boolean blipId; boolean complex; int value; String stringValue; /** * Constructor * * @param i the property id * @param bl the blip id * @param co complex flag * @param v the value */ public Property(int i, boolean bl, boolean co, int v) { id = i; blipId = bl; complex = co; value = v; } /** * Constructor * * @param i the property id * @param bl the blip id * @param co complex flag * @param v the value * @param s the property string */ public Property(int i, boolean bl, boolean co, int v, String s) { id = i; blipId = bl; complex = co; value = v; stringValue = s; } } /** * Constructor * * @param erd the escher record data */ public Opt(EscherRecordData erd) { super(erd); numProperties = getInstance(); readProperties(); } /** * Reads the properties */ private void readProperties() { properties = new ArrayList(); int pos = 0; byte[] bytes = getBytes(); for (int i = 0; i < numProperties; i++) { int val = IntegerHelper.getInt(bytes[pos], bytes[pos + 1]); int id = val & 0x3fff; int value = IntegerHelper.getInt(bytes[pos + 2], bytes[pos + 3], bytes[pos + 4], bytes[pos + 5]); Property p = new Property(id, (val & 0x4000) != 0, (val & 0x8000) != 0, value); pos += 6; properties.add(p); } for (Iterator i = properties.iterator(); i.hasNext();) { Property p = (Property) i.next(); if (p.complex) { p.stringValue = StringHelper.getUnicodeString(bytes, p.value / 2, pos); pos += p.value; } } } /** * Constructor */ public Opt() { super(EscherRecordType.OPT); properties = new ArrayList(); setVersion(3); } /** * Accessor for the binary data * * @return the binary data */ byte[] getData() { numProperties = properties.size(); setInstance(numProperties); data = new byte[numProperties * 6]; int pos = 0; // Add in the root data for (Iterator i = properties.iterator(); i.hasNext();) { Property p = (Property) i.next(); int val = p.id & 0x3fff; if (p.blipId) { val |= 0x4000; } if (p.complex) { val |= 0x8000; } IntegerHelper.getTwoBytes(val, data, pos); IntegerHelper.getFourBytes(p.value, data, pos + 2); pos += 6; } // Add in any complex data for (Iterator i = properties.iterator(); i.hasNext();) { Property p = (Property) i.next(); if (p.complex && p.stringValue != null) { byte[] newData = new byte[data.length + p.stringValue.length() * 2]; System.arraycopy(data, 0, newData, 0, data.length); StringHelper.getUnicodeBytes(p.stringValue, newData, data.length); data = newData; } } return setHeaderData(data); } /** * Adds a property into the options * * @param id the property id * @param blip the blip id * @param complex whether it's a complex property * @param val the value */ void addProperty(int id, boolean blip, boolean complex, int val) { Property p = new Property(id, blip, complex, val); properties.add(p); } /** * Adds a property into the options * * @param id the property id * @param blip the blip id * @param complex whether it's a complex property * @param val the value * @param s the value string */ void addProperty(int id, boolean blip, boolean complex, int val, String s) { Property p = new Property(id, blip, complex, val, s); properties.add(p); } /** * Accessor for the property * * @param id the property id * @return the property */ Property getProperty(int id) { boolean found = false; Property p = null; for (Iterator i = properties.iterator(); i.hasNext() && !found;) { p = (Property) i.next(); if (p.id == id) { found = true; } } return found ? p : null; } } jexcelapi/src/jxl/biff/drawing/Spgr.java0000750000175000017500000000266711207000612020417 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.drawing; /** * The SpGr escher atom */ class Spgr extends EscherAtom { /** * The binary data */ private byte[] data; /** * Constructor * * @param erd the raw escher record data */ public Spgr(EscherRecordData erd) { super(erd); } /** * Constructor */ public Spgr() { super(EscherRecordType.SPGR); setVersion(1); data = new byte[16]; } /** * Gets the binary data * * @return the binary data */ byte[] getData() { return setHeaderData(data); } } jexcelapi/src/jxl/biff/drawing/SpContainer.java0000750000175000017500000000242511207000612021721 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.drawing; /** * Shape contianer - Contains the data for this particular shape */ class SpContainer extends EscherContainer { /** * Constructor */ public SpContainer() { super(EscherRecordType.SP_CONTAINER); } /** * Constructor * * @param erd the escher record data */ public SpContainer(EscherRecordData erd) { super(erd); } } jexcelapi/src/jxl/biff/drawing/Drawing.java0000750000175000017500000006043711207000612021076 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.drawing; import java.io.FileInputStream; import java.io.IOException; import jxl.common.Assert; import jxl.common.Logger; import jxl.common.LengthUnit; import jxl.common.LengthConverter; import jxl.Image; import jxl.Sheet; import jxl.CellView; import jxl.write.biff.File; /** * Contains the various biff records used to insert a drawing into a * worksheet */ public class Drawing implements DrawingGroupObject, Image { /** * The logger */ private static Logger logger = Logger.getLogger(Drawing.class); /** * The spContainer that was read in */ private EscherContainer readSpContainer; /** * The MsoDrawingRecord associated with the drawing */ private MsoDrawingRecord msoDrawingRecord; /** * The ObjRecord associated with the drawing */ private ObjRecord objRecord; /** * Initialized flag */ private boolean initialized = false; /** * The file containing the image */ private java.io.File imageFile; /** * The raw image data, used instead of an image file */ private byte[] imageData; /** * The object id, assigned by the drawing group */ private int objectId; /** * The blip id */ private int blipId; /** * The column position of the image */ private double x; /** * The row position of the image */ private double y; /** * The width of the image in cells */ private double width; /** * The height of the image in cells */ private double height; /** * The number of places this drawing is referenced */ private int referenceCount; /** * The top level escher container */ private EscherContainer escherData; /** * Where this image came from (read, written or a copy) */ private Origin origin; /** * The drawing group for all the images */ private DrawingGroup drawingGroup; /** * The drawing data */ private DrawingData drawingData; /** * The type of this drawing object */ private ShapeType type; /** * The shape id */ private int shapeId; /** * The drawing position on the sheet */ private int drawingNumber; /** * A reference to the sheet containing this drawing. Used to calculate * the drawing dimensions in pixels */ private Sheet sheet; /** * Reader for the raw image data */ private PNGReader pngReader; /** * The client anchor properties */ private ImageAnchorProperties imageAnchorProperties; // Enumeration type for the image anchor properties protected static class ImageAnchorProperties { private int value; private static ImageAnchorProperties[] o = new ImageAnchorProperties[0]; ImageAnchorProperties(int v) { value = v; ImageAnchorProperties[] oldArray = o; o = new ImageAnchorProperties[oldArray.length + 1]; System.arraycopy(oldArray, 0, o, 0, oldArray.length); o[oldArray.length] = this; } int getValue() { return value; } static ImageAnchorProperties getImageAnchorProperties(int val) { ImageAnchorProperties iap = MOVE_AND_SIZE_WITH_CELLS; int pos = 0; while (pos < o.length) { if (o[pos].getValue()== val) { iap = o[pos]; break; } else { pos++; } } return iap; } } // The image anchor properties public static ImageAnchorProperties MOVE_AND_SIZE_WITH_CELLS = new ImageAnchorProperties(1); public static ImageAnchorProperties MOVE_WITH_CELLS = new ImageAnchorProperties(2); public static ImageAnchorProperties NO_MOVE_OR_SIZE_WITH_CELLS = new ImageAnchorProperties(3); /** * The default font size for columns */ private static final double DEFAULT_FONT_SIZE = 10; /** * Constructor used when reading images * * @param mso the drawing record * @param obj the object record * @param dd the drawing data for all drawings on this sheet * @param dg the drawing group */ public Drawing(MsoDrawingRecord mso, ObjRecord obj, DrawingData dd, DrawingGroup dg, Sheet s) { drawingGroup = dg; msoDrawingRecord = mso; drawingData = dd; objRecord = obj; sheet = s; initialized = false; origin = Origin.READ; drawingData.addData(msoDrawingRecord.getData()); drawingNumber = drawingData.getNumDrawings() - 1; drawingGroup.addDrawing(this); Assert.verify(mso != null && obj != null); initialize(); } /** * Copy constructor used to copy drawings from read to write * * @param dgo the drawing group object * @param dg the drawing group */ protected Drawing(DrawingGroupObject dgo, DrawingGroup dg) { Drawing d = (Drawing) dgo; Assert.verify(d.origin == Origin.READ); msoDrawingRecord = d.msoDrawingRecord; objRecord = d.objRecord; initialized = false; origin = Origin.READ; drawingData = d.drawingData; drawingGroup = dg; drawingNumber = d.drawingNumber; drawingGroup.addDrawing(this); } /** * Constructor invoked when writing the images * * @param x the column * @param y the row * @param w the width in cells * @param h the height in cells * @param image the image file */ public Drawing(double x, double y, double w, double h, java.io.File image) { imageFile = image; initialized = true; origin = Origin.WRITE; this.x = x; this.y = y; this.width = w; this.height = h; referenceCount = 1; imageAnchorProperties = MOVE_WITH_CELLS; type = ShapeType.PICTURE_FRAME; } /** * Constructor invoked when writing the images * * @param x the column * @param y the row * @param w the width in cells * @param h the height in cells * @param image the image data */ public Drawing(double x, double y, double w, double h, byte[] image) { imageData = image; initialized = true; origin = Origin.WRITE; this.x = x; this.y = y; this.width = w; this.height = h; referenceCount = 1; imageAnchorProperties = MOVE_WITH_CELLS; type = ShapeType.PICTURE_FRAME; } /** * Initializes the member variables from the Escher stream data */ private void initialize() { readSpContainer = drawingData.getSpContainer(drawingNumber); Assert.verify(readSpContainer != null); EscherRecord[] children = readSpContainer.getChildren(); Sp sp = (Sp) readSpContainer.getChildren()[0]; shapeId = sp.getShapeId(); objectId = objRecord.getObjectId(); type = ShapeType.getType(sp.getShapeType()); if (type == ShapeType.UNKNOWN) { logger.warn("Unknown shape type"); } Opt opt = (Opt) readSpContainer.getChildren()[1]; if (opt.getProperty(260) != null) { blipId = opt.getProperty(260).value; } if (opt.getProperty(261) != null) { imageFile = new java.io.File(opt.getProperty(261).stringValue); } else { if (type == ShapeType.PICTURE_FRAME) { logger.warn("no filename property for drawing"); imageFile = new java.io.File(Integer.toString(blipId)); } } ClientAnchor clientAnchor = null; for (int i = 0; i < children.length && clientAnchor == null; i++) { if (children[i].getType() == EscherRecordType.CLIENT_ANCHOR) { clientAnchor = (ClientAnchor) children[i]; } } if (clientAnchor == null) { logger.warn("client anchor not found"); } else { x = clientAnchor.getX1(); y = clientAnchor.getY1(); width = clientAnchor.getX2() - x; height = clientAnchor.getY2() - y; imageAnchorProperties = ImageAnchorProperties.getImageAnchorProperties (clientAnchor.getProperties()); } if (blipId == 0) { logger.warn("linked drawings are not supported"); } initialized = true; } /** * Accessor for the image file * * @return the image file */ public java.io.File getImageFile() { return imageFile; } /** * Accessor for the image file path. Normally this is the absolute path * of a file on the directory system, but if this drawing was constructed * using an byte[] then the blip id is returned * * @return the image file path, or the blip id */ public String getImageFilePath() { if (imageFile == null) { // return the blip id, if it exists return blipId != 0 ? Integer.toString(blipId) : "__new__image__"; } return imageFile.getPath(); } /** * Sets the object id. Invoked by the drawing group when the object is * added to id * * @param objid the object id * @param bip the blip id * @param sid the shape id */ public final void setObjectId(int objid, int bip, int sid) { objectId = objid; blipId = bip; shapeId = sid; if (origin == Origin.READ) { origin = Origin.READ_WRITE; } } /** * Accessor for the object id * * @return the object id */ public final int getObjectId() { if (!initialized) { initialize(); } return objectId; } /** * Accessor for the shape id * * @return the shape id */ public int getShapeId() { if (!initialized) { initialize(); } return shapeId; } /** * Accessor for the blip id * * @return the blip id */ public final int getBlipId() { if (!initialized) { initialize(); } return blipId; } /** * Gets the drawing record which was read in * * @return the drawing record */ public MsoDrawingRecord getMsoDrawingRecord() { return msoDrawingRecord; } /** * Creates the main Sp container for the drawing * * @return the SP container */ public EscherContainer getSpContainer() { if (!initialized) { initialize(); } if (origin == Origin.READ) { return getReadSpContainer(); } SpContainer spContainer = new SpContainer(); Sp sp = new Sp(type, shapeId, 2560); spContainer.add(sp); Opt opt = new Opt(); opt.addProperty(260, true, false, blipId); if (type == ShapeType.PICTURE_FRAME) { String filePath = imageFile != null ? imageFile.getPath() : ""; opt.addProperty(261, true, true, filePath.length() * 2, filePath); opt.addProperty(447, false, false, 65536); opt.addProperty(959, false, false, 524288); spContainer.add(opt); } ClientAnchor clientAnchor = new ClientAnchor (x, y, x + width, y + height, imageAnchorProperties.getValue()); spContainer.add(clientAnchor); ClientData clientData = new ClientData(); spContainer.add(clientData); return spContainer; } /** * Sets the drawing group for this drawing. Called by the drawing group * when this drawing is added to it * * @param dg the drawing group */ public void setDrawingGroup(DrawingGroup dg) { drawingGroup = dg; } /** * Accessor for the drawing group * * @return the drawing group */ public DrawingGroup getDrawingGroup() { return drawingGroup; } /** * Gets the origin of this drawing * * @return where this drawing came from */ public Origin getOrigin() { return origin; } /** * Accessor for the reference count on this drawing * * @return the reference count */ public int getReferenceCount() { return referenceCount; } /** * Sets the new reference count on the drawing * * @param r the new reference count */ public void setReferenceCount(int r) { referenceCount = r; } /** * Accessor for the column of this drawing * * @return the column */ public double getX() { if (!initialized) { initialize(); } return x; } /** * Sets the column position of this drawing * * @param x the column */ public void setX(double x) { if (origin == Origin.READ) { if (!initialized) { initialize(); } origin = Origin.READ_WRITE; } this.x = x; } /** * Accessor for the row of this drawing * * @return the row */ public double getY() { if (!initialized) { initialize(); } return y; } /** * Accessor for the row of the drawing * * @param y the row */ public void setY(double y) { if (origin == Origin.READ) { if (!initialized) { initialize(); } origin = Origin.READ_WRITE; } this.y = y; } /** * Accessor for the width of this drawing * * @return the number of columns spanned by this image */ public double getWidth() { if (!initialized) { initialize(); } return width; } /** * Accessor for the width * * @param w the number of columns to span */ public void setWidth(double w) { if (origin == Origin.READ) { if (!initialized) { initialize(); } origin = Origin.READ_WRITE; } width = w; } /** * Accessor for the height of this drawing * * @return the number of rows spanned by this image */ public double getHeight() { if (!initialized) { initialize(); } return height; } /** * Accessor for the height of this drawing * * @param h the number of rows spanned by this image */ public void setHeight(double h) { if (origin == Origin.READ) { if (!initialized) { initialize(); } origin = Origin.READ_WRITE; } height = h; } /** * Gets the SpContainer that was read in * * @return the read sp container */ private EscherContainer getReadSpContainer() { if (!initialized) { initialize(); } return readSpContainer; } /** * Accessor for the image data * * @return the image data */ public byte[] getImageData() { Assert.verify(origin == Origin.READ || origin == Origin.READ_WRITE); if (!initialized) { initialize(); } return drawingGroup.getImageData(blipId); } /** * Accessor for the image data * * @return the image data */ public byte[] getImageBytes() throws IOException { if (origin == Origin.READ || origin == Origin.READ_WRITE) { return getImageData(); } Assert.verify(origin == Origin.WRITE); if (imageFile == null) { Assert.verify(imageData != null); return imageData; } byte[] data = new byte[(int) imageFile.length()]; FileInputStream fis = new FileInputStream(imageFile); fis.read(data, 0, data.length); fis.close(); return data; } /** * Accessor for the type * * @return the type */ public ShapeType getType() { return type; } /** * Writes any other records associated with this drawing group object * * @param outputFile the output file * @exception IOException */ public void writeAdditionalRecords(File outputFile) throws IOException { if (origin == Origin.READ) { outputFile.write(objRecord); return; } // Create the obj record ObjRecord objrec = new ObjRecord(objectId, ObjRecord.PICTURE); outputFile.write(objrec); } /** * Writes any records that need to be written after all the drawing group * objects have been written * Does nothing here * * @param outputFile the output file */ public void writeTailRecords(File outputFile) throws IOException { // does nothing } /** * Interface method * * @return the column number at which the image is positioned */ public double getColumn() { return getX(); } /** * Interface method * * @return the row number at which the image is positions */ public double getRow() { return getY(); } /** * Accessor for the first drawing on the sheet. This is used when * copying unmodified sheets to indicate that this drawing contains * the first time Escher gubbins * * @return TRUE if this MSORecord is the first drawing on the sheet */ public boolean isFirst() { return msoDrawingRecord.isFirst(); } /** * Queries whether this object is a form object. Form objects have their * drawings records spread over TXO and CONTINUE records and * require special handling * * @return TRUE if this is a form object, FALSE otherwise */ public boolean isFormObject() { return false; } /** * Removes a row * * @param r the row to be removed */ public void removeRow(int r) { if (y > r) { setY(r); } } /** * Accessor for the image dimensions. See technotes for Bill's explanation * of the calculation logic * * @return approximate drawing size in pixels */ private double getWidthInPoints() { if (sheet == null) { logger.warn("calculating image width: sheet is null"); return 0; } // The start and end row numbers int firstCol = (int) x; int lastCol = (int) Math.ceil(x + width) - 1; // **** MAGIC NUMBER ALERT *** // multiply the point size of the font by 0.59 to give the point size // I know of no explanation for this yet, other than that it seems to // give the right answer // Get the width of the image within the first col, allowing for // fractional offsets CellView cellView = sheet.getColumnView(firstCol); int firstColWidth = cellView.getSize(); double firstColImageWidth = (1 - (x - firstCol)) * firstColWidth; double pointSize = (cellView.getFormat() != null) ? cellView.getFormat().getFont().getPointSize() : DEFAULT_FONT_SIZE; double firstColWidthInPoints = firstColImageWidth * 0.59 * pointSize / 256; // Get the height of the image within the last row, allowing for // fractional offsets int lastColWidth = 0; double lastColImageWidth = 0; double lastColWidthInPoints = 0; if (lastCol != firstCol) { cellView = sheet.getColumnView(lastCol); lastColWidth = cellView.getSize(); lastColImageWidth = (x + width - lastCol) * lastColWidth; pointSize = (cellView.getFormat() != null) ? cellView.getFormat().getFont().getPointSize() : DEFAULT_FONT_SIZE; lastColWidthInPoints = lastColImageWidth * 0.59 * pointSize / 256; } // Now get all the columns in between double width = 0; for (int i = 0 ; i < lastCol - firstCol - 1 ; i++) { cellView = sheet.getColumnView(firstCol + 1 +i); pointSize = (cellView.getFormat() != null) ? cellView.getFormat().getFont().getPointSize() : DEFAULT_FONT_SIZE; width += cellView.getSize() * 0.59 * pointSize / 256; } // Add on the first and last row contributions to get the height in twips double widthInPoints = width + firstColWidthInPoints + lastColWidthInPoints; return widthInPoints; } /** * Accessor for the image dimensions. See technotes for Bill's explanation * of the calculation logic * * @return approximate drawing size in pixels */ private double getHeightInPoints() { if (sheet == null) { logger.warn("calculating image height: sheet is null"); return 0; } // The start and end row numbers int firstRow = (int) y; int lastRow = (int) Math.ceil(y + height) - 1; // Get the height of the image within the first row, allowing for // fractional offsets int firstRowHeight = sheet.getRowView(firstRow).getSize(); double firstRowImageHeight = (1 - (y - firstRow)) * firstRowHeight; // Get the height of the image within the last row, allowing for // fractional offsets int lastRowHeight = 0; double lastRowImageHeight = 0; if (lastRow != firstRow) { lastRowHeight = sheet.getRowView(lastRow).getSize(); lastRowImageHeight = (y + height - lastRow) * lastRowHeight; } // Now get all the rows in between double height = 0; for (int i = 0 ; i < lastRow - firstRow - 1 ; i++) { height += sheet.getRowView(firstRow + 1 + i).getSize(); } // Add on the first and last row contributions to get the height in twips double heightInTwips = height + firstRowHeight + lastRowHeight; // Now divide by the magic number to converts twips into pixels and // return the value double heightInPoints = heightInTwips / 20.0; return heightInPoints; } /** * Get the width of this image as rendered within Excel * * @param unit the unit of measurement * @return the width of the image within Excel */ public double getWidth(LengthUnit unit) { double widthInPoints = getWidthInPoints(); return widthInPoints * LengthConverter.getConversionFactor (LengthUnit.POINTS, unit); } /** * Get the height of this image as rendered within Excel * * @param unit the unit of measurement * @return the height of the image within Excel */ public double getHeight(LengthUnit unit) { double heightInPoints = getHeightInPoints(); return heightInPoints * LengthConverter.getConversionFactor (LengthUnit.POINTS, unit); } /** * Gets the width of the image. Note that this is the width of the * underlying image, and does not take into account any size manipulations * that may have occurred when the image was added into Excel * * @return the image width in pixels */ public int getImageWidth() { return getPngReader().getWidth(); } /** * Gets the height of the image. Note that this is the height of the * underlying image, and does not take into account any size manipulations * that may have occurred when the image was added into Excel * * @return the image width in pixels */ public int getImageHeight() { return getPngReader().getHeight(); } /** * Gets the horizontal resolution of the image, if that information * is available. * * @return the number of dots per unit specified, if available, 0 otherwise */ public double getHorizontalResolution(LengthUnit unit) { int res = getPngReader().getHorizontalResolution(); return res / LengthConverter.getConversionFactor(LengthUnit.METRES, unit); } /** * Gets the vertical resolution of the image, if that information * is available. * * @return the number of dots per unit specified, if available, 0 otherwise */ public double getVerticalResolution(LengthUnit unit) { int res = getPngReader().getVerticalResolution(); return res / LengthConverter.getConversionFactor(LengthUnit.METRES, unit); } private PNGReader getPngReader() { if (pngReader != null) { return pngReader; } byte[] imdata = null; if (origin == Origin.READ || origin == Origin.READ_WRITE) { imdata = getImageData(); } else { try { imdata = getImageBytes(); } catch (IOException e) { logger.warn("Could not read image file"); imdata = new byte[0]; } } pngReader = new PNGReader(imdata); pngReader.read(); return pngReader; } /** * Accessor for the anchor properties */ protected void setImageAnchor(ImageAnchorProperties iap) { imageAnchorProperties = iap; if (origin == Origin.READ) { origin = Origin.READ_WRITE; } } /** * Accessor for the anchor properties */ protected ImageAnchorProperties getImageAnchor() { if (!initialized) { initialize(); } return imageAnchorProperties; } } jexcelapi/src/jxl/biff/drawing/DggContainer.java0000750000175000017500000000214711207000612022041 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.drawing; /** * Container for Dgg objects */ class DggContainer extends EscherContainer { /** * Constructor */ public DggContainer() { super(EscherRecordType.DGG_CONTAINER); } } jexcelapi/src/jxl/biff/drawing/DgContainer.java0000750000175000017500000000213111207000612021663 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.drawing; /** * A Dg Container */ class DgContainer extends EscherContainer { /** * Constructor */ public DgContainer() { super(EscherRecordType.DG_CONTAINER); } } jexcelapi/src/jxl/biff/drawing/SplitMenuColors.java0000750000175000017500000000334311207000612022576 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.drawing; /** * Split menu colours escher record */ class SplitMenuColors extends EscherAtom { /** * The binary data */ private byte[] data; /** * Constructor * * @param erd escher record data */ public SplitMenuColors(EscherRecordData erd) { super(erd); } /** * Constructor */ public SplitMenuColors() { super(EscherRecordType.SPLIT_MENU_COLORS); setVersion(0); setInstance(4); data = new byte[] {(byte) 0x0d, (byte) 0x00, (byte) 0x00, (byte) 0x08, (byte) 0x0c, (byte) 0x00, (byte) 0x00, (byte) 0x08, (byte) 0x17, (byte) 0x00, (byte) 0x00, (byte) 0x08, (byte) 0xf7, (byte) 0x00, (byte) 0x00, (byte) 0x10}; } /** * The binary data * * @return the binary data */ byte[] getData() { return setHeaderData(data); } } jexcelapi/src/jxl/biff/drawing/Comment.java0000750000175000017500000004364711207000612021111 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.drawing; import java.io.IOException; import jxl.common.Assert; import jxl.common.Logger; import jxl.WorkbookSettings; import jxl.biff.ContinueRecord; import jxl.biff.IntegerHelper; import jxl.biff.StringHelper; import jxl.write.biff.File; /** * Contains the various biff records used to insert a cell note into a * worksheet */ public class Comment implements DrawingGroupObject { /** * The logger */ private static Logger logger = Logger.getLogger(Comment.class); /** * The spContainer that was read in */ private EscherContainer readSpContainer; /** * The spContainer that was generated */ private EscherContainer spContainer; /** * The MsoDrawingRecord associated with the drawing */ private MsoDrawingRecord msoDrawingRecord; /** * The ObjRecord associated with the drawing */ private ObjRecord objRecord; /** * Initialized flag */ private boolean initialized = false; /** * The object id, assigned by the drawing group */ private int objectId; /** * The blip id */ private int blipId; /** * The shape id */ private int shapeId; /** * The column */ private int column; /** * The row position of the image */ private int row; /** * The width of the image in cells */ private double width; /** * The height of the image in cells */ private double height; /** * The number of places this drawing is referenced */ private int referenceCount; /** * The top level escher container */ private EscherContainer escherData; /** * Where this image came from (read, written or a copy) */ private Origin origin; /** * The drawing group for all the images */ private DrawingGroup drawingGroup; /** * The drawing data */ private DrawingData drawingData; /** * The type of this drawing object */ private ShapeType type; /** * The drawing position on the sheet */ private int drawingNumber; /** * An mso drawing record, which sometimes appears */ private MsoDrawingRecord mso; /** * The text object record */ private TextObjectRecord txo; /** * The note record */ private NoteRecord note; /** * Text data from the first continue record */ private ContinueRecord text; /** * Formatting data from the second continue record */ private ContinueRecord formatting; /** * The comment text */ private String commentText; /** * The workbook settings */ private WorkbookSettings workbookSettings; /** * Constructor used when reading images * * @param msorec the drawing record * @param obj the object record * @param dd the drawing data for all drawings on this sheet * @param dg the drawing group * @param ws the workbook settings */ public Comment(MsoDrawingRecord msorec, ObjRecord obj, DrawingData dd, DrawingGroup dg, WorkbookSettings ws) { drawingGroup = dg; msoDrawingRecord = msorec; drawingData = dd; objRecord = obj; initialized = false; workbookSettings = ws; origin = Origin.READ; drawingData.addData(msoDrawingRecord.getData()); drawingNumber = drawingData.getNumDrawings() - 1; drawingGroup.addDrawing(this); Assert.verify(msoDrawingRecord != null && objRecord != null); if (!initialized) { initialize(); } } /** * Copy constructor used to copy drawings from read to write * * @param dgo the drawing group object * @param dg the drawing group * @param ws the workbook settings */ /*protected*/ public Comment(DrawingGroupObject dgo, DrawingGroup dg, WorkbookSettings ws) { Comment d = (Comment) dgo; Assert.verify(d.origin == Origin.READ); msoDrawingRecord = d.msoDrawingRecord; objRecord = d.objRecord; initialized = false; origin = Origin.READ; drawingData = d.drawingData; drawingGroup = dg; drawingNumber = d.drawingNumber; drawingGroup.addDrawing(this); mso = d.mso; txo = d.txo; text = d.text; formatting = d.formatting; note = d.note; width = d.width; height = d.height; workbookSettings = ws; } /** * Constructor invoked when writing the images * * @param txt the comment text * @param c the column * @param r the row */ public Comment(String txt, int c, int r) { initialized = true; origin = Origin.WRITE; column = c; row = r; referenceCount = 1; type = ShapeType.TEXT_BOX; commentText = txt; width = 3; height = 4; } /** * Initializes the member variables from the Escher stream data */ private void initialize() { readSpContainer = drawingData.getSpContainer(drawingNumber); Assert.verify(readSpContainer != null); EscherRecord[] children = readSpContainer.getChildren(); Sp sp = (Sp) readSpContainer.getChildren()[0]; objectId = objRecord.getObjectId(); shapeId = sp.getShapeId(); type = ShapeType.getType(sp.getShapeType()); if (type == ShapeType.UNKNOWN) { logger.warn("Unknown shape type"); } ClientAnchor clientAnchor = null; for (int i = 0; i < children.length && clientAnchor == null; i++) { if (children[i].getType() == EscherRecordType.CLIENT_ANCHOR) { clientAnchor = (ClientAnchor) children[i]; } } if (clientAnchor == null) { logger.warn("client anchor not found"); } else { column = (int) clientAnchor.getX1() - 1; row = (int) clientAnchor.getY1() + 1; width = clientAnchor.getX2() - clientAnchor.getX1(); height = clientAnchor.getY2() - clientAnchor.getY1(); } initialized = true; } /** * Sets the object id. Invoked by the drawing group when the object is * added to id * * @param objid the object id * @param bip the blip id * @param sid the shape id */ public final void setObjectId(int objid, int bip, int sid) { objectId = objid; blipId = bip; shapeId = sid; if (origin == Origin.READ) { origin = Origin.READ_WRITE; } } /** * Accessor for the object id * * @return the object id */ public final int getObjectId() { if (!initialized) { initialize(); } return objectId; } /** * Accessor for the shape id * * @return the object id */ public final int getShapeId() { if (!initialized) { initialize(); } return shapeId; } /** * Accessor for the blip id * * @return the blip id */ public final int getBlipId() { if (!initialized) { initialize(); } return blipId; } /** * Gets the drawing record which was read in * * @return the drawing record */ public MsoDrawingRecord getMsoDrawingRecord() { return msoDrawingRecord; } /** * Creates the main Sp container for the drawing * * @return the SP container */ public EscherContainer getSpContainer() { if (!initialized) { initialize(); } if (origin == Origin.READ) { return getReadSpContainer(); } if (spContainer == null) { spContainer = new SpContainer(); Sp sp = new Sp(type, shapeId, 2560); spContainer.add(sp); Opt opt = new Opt(); opt.addProperty(344, false, false, 0); // ? opt.addProperty(385, false, false, 134217808); // fill colour opt.addProperty(387, false, false, 134217808); // background colour opt.addProperty(959, false, false, 131074); // hide spContainer.add(opt); ClientAnchor clientAnchor = new ClientAnchor(column + 1.3, Math.max(0, row - 0.6), column + 1.3 + width, row + height, 0x1); spContainer.add(clientAnchor); ClientData clientData = new ClientData(); spContainer.add(clientData); ClientTextBox clientTextBox = new ClientTextBox(); spContainer.add(clientTextBox); } return spContainer; } /** * Sets the drawing group for this drawing. Called by the drawing group * when this drawing is added to it * * @param dg the drawing group */ public void setDrawingGroup(DrawingGroup dg) { drawingGroup = dg; } /** * Accessor for the drawing group * * @return the drawing group */ public DrawingGroup getDrawingGroup() { return drawingGroup; } /** * Gets the origin of this drawing * * @return where this drawing came from */ public Origin getOrigin() { return origin; } /** * Accessor for the reference count on this drawing * * @return the reference count */ public int getReferenceCount() { return referenceCount; } /** * Sets the new reference count on the drawing * * @param r the new reference count */ public void setReferenceCount(int r) { referenceCount = r; } /** * Accessor for the column of this drawing * * @return the column */ public double getX() { if (!initialized) { initialize(); } return column; } /** * Sets the column position of this drawing. Used when inserting/removing * columns from the spreadsheet * * @param x the column */ public void setX(double x) { if (origin == Origin.READ) { if (!initialized) { initialize(); } origin = Origin.READ_WRITE; } column = (int) x; } /** * Accessor for the row of this drawing * * @return the row */ public double getY() { if (!initialized) { initialize(); } return row; } /** * Accessor for the row of the drawing * * @param y the row */ public void setY(double y) { if (origin == Origin.READ) { if (!initialized) { initialize(); } origin = Origin.READ_WRITE; } row = (int) y; } /** * Accessor for the width of this drawing * * @return the number of columns spanned by this image */ public double getWidth() { if (!initialized) { initialize(); } return width; } /** * Accessor for the width * * @param w the number of columns to span */ public void setWidth(double w) { if (origin == Origin.READ) { if (!initialized) { initialize(); } origin = Origin.READ_WRITE; } width = w; } /** * Accessor for the height of this drawing * * @return the number of rows spanned by this image */ public double getHeight() { if (!initialized) { initialize(); } return height; } /** * Accessor for the height of this drawing * * @param h the number of rows spanned by this image */ public void setHeight(double h) { if (origin == Origin.READ) { if (!initialized) { initialize(); } origin = Origin.READ_WRITE; } height = h; } /** * Gets the SpContainer that was read in * * @return the read sp container */ private EscherContainer getReadSpContainer() { if (!initialized) { initialize(); } return readSpContainer; } /** * Accessor for the image data * * @return the image data */ public byte[] getImageData() { Assert.verify(origin == Origin.READ || origin == Origin.READ_WRITE); if (!initialized) { initialize(); } return drawingGroup.getImageData(blipId); } /** * Accessor for the type * * @return the type */ public ShapeType getType() { return type; } /** * Sets the text object * * @param t the text object */ public void setTextObject(TextObjectRecord t) { txo = t; } /** * Sets the note object * * @param t the note record */ public void setNote(NoteRecord t) { note = t; } /** * Sets the text data * * @param t the text data */ public void setText(ContinueRecord t) { text = t; } /** * Sets the formatting * * @param t the formatting record */ public void setFormatting(ContinueRecord t) { formatting = t; } /** * Accessor for the image data * * @return the image data */ public byte[] getImageBytes() { Assert.verify(false); return null; } /** * Accessor for the image file path. Normally this is the absolute path * of a file on the directory system, but if this drawing was constructed * using an byte[] then the blip id is returned * * @return the image file path, or the blip id */ public String getImageFilePath() { Assert.verify(false); return null; } /** * Adds an mso record to this object * * @param d the mso record */ public void addMso(MsoDrawingRecord d) { mso = d; drawingData.addRawData(mso.getData()); } /** * Writes out the additional comment records * * @param outputFile the output file * @exception IOException */ public void writeAdditionalRecords(File outputFile) throws IOException { if (origin == Origin.READ) { outputFile.write(objRecord); if (mso != null) { outputFile.write(mso); } outputFile.write(txo); outputFile.write(text); if (formatting != null) { outputFile.write(formatting); } return; } // Create the obj record ObjRecord objrec = new ObjRecord(objectId, ObjRecord.EXCELNOTE); outputFile.write(objrec); // Create the mso data record. Write the text box record again, // although it is already included in the SpContainer ClientTextBox textBox = new ClientTextBox(); MsoDrawingRecord msod = new MsoDrawingRecord(textBox.getData()); outputFile.write(msod); TextObjectRecord txorec = new TextObjectRecord(getText()); outputFile.write(txorec); // Data for the first continue record byte[] textData = new byte[commentText.length() * 2 + 1]; textData[0] = 0x1; // unicode indicator StringHelper.getUnicodeBytes(commentText, textData, 1); //StringHelper.getBytes(commentText, textData, 1); ContinueRecord textContinue = new ContinueRecord(textData); outputFile.write(textContinue); // Data for the formatting runs byte[] frData = new byte[16]; // First txo run (the user) IntegerHelper.getTwoBytes(0, frData, 0); // index to the first character IntegerHelper.getTwoBytes(0, frData, 2); // index to the font(default) // Mandatory last txo run IntegerHelper.getTwoBytes(commentText.length(), frData, 8); IntegerHelper.getTwoBytes(0, frData, 10); // index to the font(default) ContinueRecord frContinue = new ContinueRecord(frData); outputFile.write(frContinue); } /** * Writes any records that need to be written after all the drawing group * objects have been written * Writes out all the note records * * @param outputFile the output file * @exception IOException */ public void writeTailRecords(File outputFile) throws IOException { if (origin == Origin.READ) { outputFile.write(note); return; } // The note record NoteRecord noteRecord = new NoteRecord(column, row, objectId); outputFile.write(noteRecord); } /** * Accessor for the row * * @return the row */ public int getRow() { return note.getRow(); } /** * Accessor for the column * * @return the column */ public int getColumn() { return note.getColumn(); } /** * Accessor for the comment text * * @return the comment text */ public String getText() { if (commentText == null) { Assert.verify(text != null); byte[] td = text.getData(); if (td[0] == 0) { commentText = StringHelper.getString (td, td.length - 1, 1, workbookSettings); } else { commentText = StringHelper.getUnicodeString (td, (td.length - 1) / 2, 1); } } return commentText; } /** * Hashing algorithm * * @return the hash code */ public int hashCode() { return commentText.hashCode(); } /** * Called when the comment text is changed during the sheet copy process * * @param t the new text */ public void setCommentText(String t) { commentText = t; if (origin == Origin.READ) { origin = Origin.READ_WRITE; } } /** * Accessor for the first drawing on the sheet. This is used when * copying unmodified sheets to indicate that this drawing contains * the first time Escher gubbins * * @return TRUE if this MSORecord is the first drawing on the sheet */ public boolean isFirst() { return msoDrawingRecord.isFirst(); } /** * Queries whether this object is a form object. Form objects have their * drawings records spread over several records and require special handling * * @return TRUE if this is a form object, FALSE otherwise */ public boolean isFormObject() { return true; } } jexcelapi/src/jxl/biff/drawing/Chunk.java0000750000175000017500000000240411207000612020541 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2006 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.drawing; class Chunk { private int pos; private int length; private ChunkType type; private byte[] data; public Chunk(int p, int l, ChunkType ct, byte[] d) { pos = p; length = l; type = ct; data = new byte[length]; System.arraycopy(d, pos, data, 0, length); } public byte[] getData() { return data; } } jexcelapi/src/jxl/biff/drawing/DrawingGroupObject.java0000750000175000017500000001216611207000612023236 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.drawing; import java.io.IOException; import jxl.write.biff.File; /** * Interface for the various object types that can be added to a drawing * group */ public interface DrawingGroupObject { /** * Sets the object id. Invoked by the drawing group when the object is * added to id * * @param objid the object id * @param bip the blip id * @param sid the shape id */ void setObjectId(int objid, int bip, int sid); /** * Accessor for the object id * * @return the object id */ int getObjectId(); /** * Accessor for the blip id * * @return the blip id */ int getBlipId(); /** * Accessor for the shape id * * @return the shape id */ public int getShapeId(); /** * Gets the drawing record which was read in * * @return the drawing record */ MsoDrawingRecord getMsoDrawingRecord(); /** * Creates the main Sp container for the drawing * * @return the SP container */ public EscherContainer getSpContainer(); /** * Sets the drawing group for this drawing. Called by the drawing group * when this drawing is added to it * * @param dg the drawing group */ void setDrawingGroup(DrawingGroup dg); /** * Accessor for the drawing group * * @return the drawing group */ DrawingGroup getDrawingGroup(); /** * Gets the origin of this drawing * * @return where this drawing came from */ Origin getOrigin(); /** * Accessor for the reference count on this drawing * * @return the reference count */ int getReferenceCount(); /** * Sets the new reference count on the drawing * * @param r the new reference count */ void setReferenceCount(int r); /** * Accessor for the column of this drawing * * @return the column */ public double getX(); /** * Sets the column position of this drawing * * @param x the column */ public void setX(double x); /** * Accessor for the row of this drawing * * @return the row */ public double getY(); /** * Accessor for the row of the drawing * * @param y the row */ public void setY(double y); /** * Accessor for the width of this drawing * * @return the number of columns spanned by this image */ public double getWidth(); /** * Accessor for the width * * @param w the number of columns to span */ public void setWidth(double w); /** * Accessor for the height of this drawing * * @return the number of rows spanned by this image */ public double getHeight(); /** * Accessor for the height of this drawing * * @param h the number of rows spanned by this image */ public void setHeight(double h); /** * Accessor for the type * * @return the type */ ShapeType getType(); /** * Accessor for the image data * * @return the image data */ public byte[] getImageData(); /** * Accessor for the image data * * @return the image data */ public byte[] getImageBytes() throws IOException; /** * Accessor for the image file path. Normally this is the absolute path * of a file on the directory system, but if this drawing was constructed * using an byte[] then the blip id is returned * * @return the image file path, or the blip id */ String getImageFilePath(); /** * Writes any other records associated with this drawing group object */ public void writeAdditionalRecords(File outputFile) throws IOException; /** * Writes any records that need to be written after all the drawing group * objects have been written */ public void writeTailRecords(File outputFile) throws IOException; /** * Accessor for the first drawing on the sheet. This is used when * copying unmodified sheets to indicate that this drawing contains * the first time Escher gubbins * * @return TRUE if this MSORecord is the first drawing on the sheet */ public boolean isFirst(); /** * Queries whether this object is a form object. Form objects have their * drawings records spread over TXO and CONTINUE records and * require special handling * * @return TRUE if this is a form object, FALSE otherwise */ public boolean isFormObject(); } jexcelapi/src/jxl/biff/drawing/Origin.java0000750000175000017500000000233611207000612020724 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2004 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.drawing; /** * Enumeration type for the origin of a drawing object */ public final class Origin { /** * Constructor */ private Origin() { } public static final Origin READ = new Origin(); public static final Origin WRITE = new Origin(); public static final Origin READ_WRITE = new Origin(); } jexcelapi/src/jxl/biff/drawing/BlipStoreEntry.java0000750000175000017500000001176211207000612022425 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.drawing; import java.io.IOException; import jxl.common.Assert; import jxl.common.Logger; import jxl.biff.IntegerHelper; /** * The data for this blip store entry. Typically this is the raw image data */ class BlipStoreEntry extends EscherAtom { /** * The logger */ private static Logger logger = Logger.getLogger(BlipStoreEntry.class); /** * The type of the blip */ private BlipType type; /** * The image data read in */ private byte[] data; /** * The length of the image data */ private int imageDataLength; /** * The reference count on this blip */ private int referenceCount; /** * Flag to indicate that this entry was specified by the API, and not * read in */ private boolean write; /** * The start of the image data within this blip entry */ private static final int IMAGE_DATA_OFFSET = 61; /** * Constructor * * @param erd the escher record data */ public BlipStoreEntry(EscherRecordData erd) { super(erd); type = BlipType.getType(getInstance()); write = false; byte[] bytes = getBytes(); referenceCount = IntegerHelper.getInt(bytes[24], bytes[25], bytes[26], bytes[27]); } /** * Constructor * * @param d the drawing * @exception IOException */ public BlipStoreEntry(Drawing d) throws IOException { super(EscherRecordType.BSE); type = BlipType.PNG; setVersion(2); setInstance(type.getValue()); byte[] imageData = d.getImageBytes(); imageDataLength = imageData.length; data = new byte[imageDataLength + IMAGE_DATA_OFFSET]; System.arraycopy(imageData, 0, data, IMAGE_DATA_OFFSET, imageDataLength); referenceCount = d.getReferenceCount(); write = true; } /** * Accessor for the blip type * * @return the blip type */ public BlipType getBlipType() { return type; } /** * Gets the data for this blip so that it can be written out * * @return the data for the blip */ public byte[] getData() { if (write) { // Drawing has been specified by API // Type on win32 data[0] = (byte) type.getValue(); // Type on MacOs data[1] = (byte) type.getValue(); // The blip identifier // IntegerHelper.getTwoBytes(0xfce1, data, 2); // Unused tags - 18 bytes // System.arraycopy(stuff, 0, data, 2, stuff.length); // The size of the file IntegerHelper.getFourBytes(imageDataLength + 8 + 17, data, 20); // The reference count on the blip IntegerHelper.getFourBytes(referenceCount, data, 24); // Offset in the delay stream IntegerHelper.getFourBytes(0, data, 28); // Usage byte data[32] = (byte) 0; // Length of the blip name data[33] = (byte) 0; // Last two bytes unused data[34] = (byte) 0x7e; data[35] = (byte) 0x01; // The blip itself data[36] = (byte) 0; data[37] = (byte) 0x6e; // The blip identifier IntegerHelper.getTwoBytes(0xf01e, data, 38); // The length of the blip. This is the length of the image file plus // 16 bytes IntegerHelper.getFourBytes(imageDataLength + 17, data, 40); // Unknown stuff // System.arraycopy(stuff, 0, data, 44, stuff.length); } else { // drawing has been read in data = getBytes(); } return setHeaderData(data); } /** * Reduces the reference count in this blip. Called when a drawing is * removed */ void dereference() { referenceCount--; Assert.verify(referenceCount >= 0); } /** * Accessor for the reference count on the blip * * @return the reference count on the blip */ int getReferenceCount() { return referenceCount; } /** * Accessor for the image data. * * @return the image data */ byte[] getImageData() { byte[] allData = getBytes(); byte[] imageData = new byte[allData.length - IMAGE_DATA_OFFSET]; System.arraycopy(allData, IMAGE_DATA_OFFSET, imageData, 0, imageData.length); return imageData; } } jexcelapi/src/jxl/biff/drawing/EscherDisplay.java0000750000175000017500000001324511263324714022253 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2005 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.drawing; import java.io.BufferedWriter; import java.io.IOException; /** * Class used to display a complete hierarchically organized Escher stream * The whole thing is dumped to System.out * * This class is only used as a debugging tool */ public class EscherDisplay { /** * The escher stream */ private EscherStream stream; /** * The writer */ private BufferedWriter writer; /** * Constructor * * @param s the stream * @param bw the writer */ public EscherDisplay(EscherStream s, BufferedWriter bw) { stream = s; writer = bw; } /** * Display the formatted escher stream * * @exception IOException */ public void display() throws IOException { EscherRecordData er = new EscherRecordData(stream, 0); EscherContainer ec = new EscherContainer(er); displayContainer(ec, 0); } /** * Displays the escher container as text * * @param ec the escher container * @param level the indent level * @exception IOException */ private void displayContainer(EscherContainer ec, int level) throws IOException { displayRecord(ec, level); // Display the contents of the container level++; EscherRecord[] children = ec.getChildren(); for (int i = 0; i < children.length; i++) { EscherRecord er = children[i]; if (er.getEscherData().isContainer()) { displayContainer((EscherContainer) er, level); } else { displayRecord(er, level); } } } /** * Displays an escher record * * @param er the record to display * @param level the amount of indentation * @exception IOException */ private void displayRecord(EscherRecord er, int level) throws IOException { indent(level); EscherRecordType type = er.getType(); // Display the code writer.write(Integer.toString(type.getValue(), 16)); writer.write(" - "); // Display the name if (type == EscherRecordType.DGG_CONTAINER) { writer.write("Dgg Container"); writer.newLine(); } else if (type == EscherRecordType.BSTORE_CONTAINER) { writer.write("BStore Container"); writer.newLine(); } else if (type == EscherRecordType.DG_CONTAINER) { writer.write("Dg Container"); writer.newLine(); } else if (type == EscherRecordType.SPGR_CONTAINER) { writer.write("Spgr Container"); writer.newLine(); } else if (type == EscherRecordType.SP_CONTAINER) { writer.write("Sp Container"); writer.newLine(); } else if (type == EscherRecordType.DGG) { writer.write("Dgg"); writer.newLine(); } else if (type == EscherRecordType.BSE) { writer.write("Bse"); writer.newLine(); } else if (type == EscherRecordType.DG) { Dg dg = new Dg(er.getEscherData()); writer.write("Dg: drawing id " + dg.getDrawingId() + " shape count " + dg.getShapeCount()); writer.newLine(); } else if (type == EscherRecordType.SPGR) { writer.write("Spgr"); writer.newLine(); } else if (type == EscherRecordType.SP) { Sp sp = new Sp(er.getEscherData()); writer.write("Sp: shape id " + sp.getShapeId() + " shape type " + sp.getShapeType()); writer.newLine(); } else if (type == EscherRecordType.OPT) { Opt opt = new Opt(er.getEscherData()); Opt.Property p260 = opt.getProperty(260); Opt.Property p261 = opt.getProperty(261); writer.write("Opt (value, stringValue): "); if (p260 != null) { writer.write("260: " + p260.value + ", " + p260.stringValue + ";"); } if (p261 != null) { writer.write("261: " + p261.value + ", " + p261.stringValue + ";"); } writer.newLine(); } else if (type == EscherRecordType.CLIENT_ANCHOR) { writer.write("Client Anchor"); writer.newLine(); } else if (type == EscherRecordType.CLIENT_DATA) { writer.write("Client Data"); writer.newLine(); } else if (type == EscherRecordType.CLIENT_TEXT_BOX) { writer.write("Client Text Box"); writer.newLine(); } else if (type == EscherRecordType.SPLIT_MENU_COLORS) { writer.write("Split Menu Colors"); writer.newLine(); } else { writer.write("???"); writer.newLine(); } } /** * Indents to the amount specified by the level * * @param level the level * @exception IOException */ private void indent(int level) throws IOException { for (int i = 0; i < level * 2; i++) { writer.write(' '); } } } jexcelapi/src/jxl/biff/drawing/MsoDrawingGroupRecord.java0000750000175000017500000000334311207000612023722 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2001 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.drawing; import jxl.biff.Type; import jxl.biff.WritableRecordData; import jxl.read.biff.Record; /** * A record which merely holds the MSODRAWINGGROUP data. Used when copying * files which contain images */ public class MsoDrawingGroupRecord extends WritableRecordData { /** * The binary data */ private byte[] data; /** * Constructs this object from the raw data * * @param t the raw data */ public MsoDrawingGroupRecord(Record t) { super(t); data = t.getData(); } /** * Constructor * * @param d the data */ MsoDrawingGroupRecord(byte[] d) { super(Type.MSODRAWINGGROUP); data = d; } /** * Expose the protected function to the SheetImpl in this package * * @return the raw record data */ public byte[] getData() { return data; } } jexcelapi/src/jxl/biff/drawing/Dg.java0000750000175000017500000000466411263324152020047 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.drawing; import jxl.biff.IntegerHelper; /** * The Drawing Group */ class Dg extends EscherAtom { /** * The data */ private byte[] data; /** * The id of this drawing */ private int drawingId; /** * The number of shapes */ private int shapeCount; /** * The seed for drawing ids */ private int seed; /** * Constructor invoked when reading in an escher stream * * @param erd the escher record */ public Dg(EscherRecordData erd) { super(erd); drawingId = getInstance(); byte[] bytes = getBytes(); shapeCount = IntegerHelper.getInt(bytes[0], bytes[1], bytes[2], bytes[3]); seed = IntegerHelper.getInt(bytes[4], bytes[5], bytes[6], bytes[7]); } /** * Constructor invoked when writing out an escher stream * * @param numDrawings the number of drawings */ public Dg(int numDrawings) { super(EscherRecordType.DG); drawingId = 1; shapeCount = numDrawings + 1; seed = 1024 + shapeCount + 1; setInstance(drawingId); } /** * Gets the drawing id * * @return the drawing id */ public int getDrawingId() { return drawingId; } /** * Gets the shape count * * @return the shape count */ int getShapeCount() { return shapeCount; } /** * Used to generate the drawing data * * @return the data */ byte[] getData() { data = new byte[8]; IntegerHelper.getFourBytes(shapeCount, data, 0); IntegerHelper.getFourBytes(seed, data, 4); return setHeaderData(data); } } jexcelapi/src/jxl/biff/drawing/EscherRecordData.java0000750000175000017500000001417711207000612022645 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.drawing; import jxl.common.Logger; import jxl.biff.IntegerHelper; /** * A single record from an Escher stream. Basically this a container for * the header data for each Escher record */ final class EscherRecordData { /** * The logger */ private static Logger logger = Logger.getLogger(EscherRecordData.class); /** * The byte position of this record in the escher stream */ private int pos; /** * The instance value */ private int instance; /** * The version value */ private int version; /** * The record id */ private int recordId; /** * The length of the record, excluding the 8 byte header */ private int length; /** * The length of the stream */ private int streamLength; /** * Indicates whether this record is a container */ private boolean container; /** * The type of this record */ private EscherRecordType type; /** * A handle back to the drawing group, which contains the entire escher * stream byte data */ private EscherStream escherStream; /** * Constructor * * @param dg the escher stream data * @param p the current position in the stream */ public EscherRecordData(EscherStream dg, int p) { escherStream = dg; pos = p; byte[] data = escherStream.getData(); streamLength = data.length; // First two bytes contain instance and version int value = IntegerHelper.getInt(data[pos], data[pos + 1]); // Instance value is the first 12 bits instance = (value & 0xfff0) >> 4; // Version is the last four bits version = value & 0xf; // Bytes 2 and 3 are the record id recordId = IntegerHelper.getInt(data[pos + 2], data[pos + 3]); // Length is bytes 4,5,6 and 7 length = IntegerHelper.getInt(data[pos + 4], data[pos + 5], data[pos + 6], data[pos + 7]); if (version == 0x0f) { container = true; } else { container = false; } } /** * Constructor * * @param t the type of the escher record */ public EscherRecordData(EscherRecordType t) { type = t; recordId = type.getValue(); } /** * Determines whether this record is a container * * @return TRUE if this is a container, FALSE otherwise */ public boolean isContainer() { return container; } /** * Accessor for the length, excluding the 8 byte header * * @return the length excluding the 8 byte header */ public int getLength() { return length; } /** * Accessor for the record id * * @return the record id */ public int getRecordId() { return recordId; } /** * Accessor for the drawing group stream * * @return the drawing group stream */ EscherStream getDrawingGroup() { return escherStream; } /** * Gets the position in the stream * * @return the position in the stream */ int getPos() { return pos; } /** * Gets the escher type of this record * * @return the escher type */ EscherRecordType getType() { if (type == null) { type = EscherRecordType.getType(recordId); } return type; } /** * Gets the instance value * * @return the instance value */ int getInstance() { return instance; } /** * Sets whether or not this is a container - called when writing * out an escher stream * * @param c TRUE if this is a container, FALSE otherwise */ void setContainer(boolean c) { container = c; } /** * Called from the subclass when writing to set the instance value * * @param inst the instance */ void setInstance(int inst) { instance = inst; } /** * Called when writing to set the length of this record * * @param l the length */ void setLength(int l) { length = l; } /** * Called when writing to set the version of this record * * @param v the version */ void setVersion(int v) { version = v; } /** * Adds the 8 byte header data on the value data passed in, returning * the modified data * * @param d the value data * @return the value data with the header information */ byte[] setHeaderData(byte[] d) { byte[] data = new byte[d.length + 8]; System.arraycopy(d, 0, data, 8, d.length); if (container) { version = 0x0f; } // First two bytes contain instance and version int value = instance << 4; value |= version; IntegerHelper.getTwoBytes(value, data, 0); // Bytes 2 and 3 are the record id IntegerHelper.getTwoBytes(recordId, data, 2); // Length is bytes 4,5,6 and 7 IntegerHelper.getFourBytes(d.length, data, 4); return data; } /** * Accessor for the header stream * * @return the escher stream */ EscherStream getEscherStream() { return escherStream; } /** * Gets the data that was read in, excluding the header data * * @return the value data that was read in */ byte[] getBytes() { byte[] d = new byte[length]; System.arraycopy(escherStream.getData(), pos + 8, d, 0, length); return d; } /** * Accessor for the stream length * * @return the stream length */ int getStreamLength() { return streamLength; } } jexcelapi/src/jxl/biff/drawing/ShapeType.java0000750000175000017500000000427711207000612021405 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2004 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.drawing; /** * Enumerations for the shape type */ final class ShapeType { /** * The value */ private int value; /** * The list of shape types */ private static ShapeType[] types = new ShapeType[0]; /** * Constructor * * @param v the value */ ShapeType(int v) { value = v; ShapeType[] old = types; types = new ShapeType[types.length + 1]; System.arraycopy(old, 0, types, 0, old.length); types[old.length] = this; } /** * Gets the shape type given the value * * @param v the value * @return the shape type for the value */ static ShapeType getType(int v) { ShapeType st = UNKNOWN; boolean found = false; for (int i = 0; i < types.length && !found; i++) { if (types[i].value == v) { found = true; st = types[i]; } } return st; } /** * Accessor for the value * * @return the value */ public int getValue() { return value; } public static final ShapeType MIN = new ShapeType(0); public static final ShapeType PICTURE_FRAME = new ShapeType(75); public static final ShapeType HOST_CONTROL = new ShapeType(201); public static final ShapeType TEXT_BOX = new ShapeType(202); public static final ShapeType UNKNOWN = new ShapeType(-1); } jexcelapi/src/jxl/biff/drawing/PNGReader.java0000750000175000017500000001030211207000612021234 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2006 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.drawing; import java.io.File; import java.io.FileInputStream; import java.util.Arrays; public class PNGReader { private byte[] pngData; private Chunk ihdr; private Chunk phys; private int pixelWidth; private int pixelHeight; private int verticalResolution; private int horizontalResolution; private int resolutionUnit; private static byte[] PNG_MAGIC_NUMBER = new byte[] {(byte) 0x89, (byte) 0x50, (byte) 0x4e, (byte) 0x47, (byte) 0x0d, (byte) 0x0a, (byte) 0x1a, (byte) 0x0a}; public PNGReader(byte[] data) { pngData = data; } void read() { // Verify the magic data byte[] header = new byte[PNG_MAGIC_NUMBER.length]; System.arraycopy(pngData, 0, header, 0, header.length); boolean pngFile = Arrays.equals(PNG_MAGIC_NUMBER, header); if (!pngFile) { return; } int pos = 8; while (pos < pngData.length) { int length = getInt(pngData[pos], pngData[pos+1], pngData[pos+2], pngData[pos+3]); ChunkType chunkType = ChunkType.getChunkType(pngData[pos+4], pngData[pos+5], pngData[pos+6], pngData[pos+7]); if (chunkType == ChunkType.IHDR) { ihdr = new Chunk(pos + 8, length, chunkType, pngData); } else if (chunkType == ChunkType.PHYS) { phys = new Chunk(pos + 8, length, chunkType, pngData); } pos += length + 12; } // Get the width and height from the ihdr byte[] ihdrData = ihdr.getData(); pixelWidth = getInt(ihdrData[0], ihdrData[1], ihdrData[2], ihdrData[3]); pixelHeight = getInt(ihdrData[4], ihdrData[5], ihdrData[6], ihdrData[7]); if (phys != null) { byte[] physData = phys.getData(); resolutionUnit = physData[8]; horizontalResolution = getInt(physData[0], physData[1], physData[2], physData[3]); verticalResolution = getInt(physData[4], physData[5], physData[6], physData[7]); } } // Gets the big-Endian integer private int getInt(byte d1, byte d2, byte d3, byte d4) { int i1 = d1 & 0xff; int i2 = d2 & 0xff; int i3 = d3 & 0xff; int i4 = d4 & 0xff; int val = i1 << 24 | i2 << 16 | i3 << 8 | i4; return val; } public int getHeight() { return pixelHeight; } public int getWidth() { return pixelWidth; } public int getHorizontalResolution() { // only return if the resolution unit is in metres return resolutionUnit == 1 ? horizontalResolution : 0; } public int getVerticalResolution() { // only return if the resolution unit is in metres return resolutionUnit == 1 ? verticalResolution : 0; } public static void main(String args[]) { try { File f = new File(args[0]); int size = (int) f.length(); byte[] data = new byte[size]; FileInputStream fis = new FileInputStream(f); fis.read(data); fis.close(); PNGReader reader = new PNGReader(data); reader.read(); } catch (Throwable t) { t.printStackTrace(); } } } jexcelapi/src/jxl/biff/drawing/EscherStream.java0000750000175000017500000000217411207000612022062 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2004 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.drawing; /** * Interface implemented by records which contain escher byte streams */ interface EscherStream { /** * Method to access the escher data * * @return the escher data */ byte[] getData(); } jexcelapi/src/jxl/biff/drawing/NoteRecord.java0000750000175000017500000000640611207000612021543 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2004 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.drawing; import jxl.common.Logger; import jxl.biff.IntegerHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; import jxl.read.biff.Record; /** * A Note (TXO) record which contains the information for comments */ public class NoteRecord extends WritableRecordData { /** * The logger */ private static Logger logger = Logger.getLogger(NoteRecord.class); /** * The raw drawing data which was read in */ private byte[] data; /** * The row */ private int row; /** * The column */ private int column; /** * The object id */ private int objectId; /** * Constructs this object from the raw data * * @param t the raw data */ public NoteRecord(Record t) { super(t); data = getRecord().getData(); row = IntegerHelper.getInt(data[0], data[1]); column = IntegerHelper.getInt(data[2], data[3]); objectId = IntegerHelper.getInt(data[6], data[7]); } /** * Constructor * * @param d the drawing data */ public NoteRecord(byte[] d) { super(Type.NOTE); data = d; } /** * Constructor used when writing a Note * * @param c the column * @param r the row * @param id the object id */ public NoteRecord(int c, int r, int id) { super(Type.NOTE); row = r; column = c; objectId = id; } /** * Expose the protected function to the SheetImpl in this package * * @return the raw record data */ public byte[] getData() { if (data != null) { return data; } String author = ""; data = new byte[8 + author.length() + 4]; // the row IntegerHelper.getTwoBytes(row, data, 0); // the column IntegerHelper.getTwoBytes(column, data, 2); // the object id IntegerHelper.getTwoBytes(objectId, data, 6); // the length of the string IntegerHelper.getTwoBytes(author.length(), data, 8); // the string // StringHelper.getBytes(author, data, 11); // data[data.length-1]=(byte)0x24; return data; } /** * Accessor for the row * * @return the row */ int getRow() { return row; } /** * Accessor for the column * * @return the column */ int getColumn() { return column; } /** * Accessor for the object id * * @return the object id */ public int getObjectId() { return objectId; } } jexcelapi/src/jxl/biff/drawing/BlipType.java0000750000175000017500000000601411207000612021222 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.drawing; /** * Enumeration for the BLIP type */ final class BlipType { /** * The blip type code */ private int value; /** * The blip type description */ private String desc; /** * All blip types */ private static BlipType[] types = new BlipType[0]; /** * Constructor * * @param val the code * @param d the description */ private BlipType(int val, String d) { value = val; desc = d; BlipType[] newtypes = new BlipType[types.length + 1]; System.arraycopy(types, 0, newtypes, 0, types.length); newtypes[types.length] = this; types = newtypes; } /** * Accessor for the description * * @return the description */ public String getDescription() { return desc; } /** * Accessor for the value * * @return the value */ public int getValue() { return value; } /** * Gets the blip type given the value * * @param val get the value * @return the blip type */ public static BlipType getType(int val) { BlipType type = UNKNOWN; for (int i = 0; i < types.length; i++) { if (types[i].value == val) { type = types[i]; break; } } return type; } public static final BlipType ERROR = new BlipType(0, "Error"); // An error occured during loading public static final BlipType UNKNOWN = new BlipType(1, "Unknown"); // An unknown blip type public static final BlipType EMF = new BlipType(2, "EMF"); // Windows Enhanced Metafile public static final BlipType WMF = new BlipType(3, "WMF"); // Windows Metafile public static final BlipType PICT = new BlipType(4, "PICT"); // Macintosh PICT public static final BlipType JPEG = new BlipType(5, "JPEG"); // JFIF public static final BlipType PNG = new BlipType(6, "PNG"); // PNG public static final BlipType DIB = new BlipType(7, "DIB"); // Windows DIB public static final BlipType FIRST_CLIENT = new BlipType(32, "FIRST"); // First client defined blip type public static final BlipType LAST_CLIENT = new BlipType(255, "LAST"); // Last client defined blip type } jexcelapi/src/jxl/biff/drawing/ObjRecord.java0000750000175000017500000002412411263076056021366 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2001 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.drawing; import jxl.common.Assert; import jxl.common.Logger; import jxl.biff.IntegerHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; import jxl.read.biff.Record; /** * A record which merely holds the OBJ data. Used when copying files which * contain images */ public class ObjRecord extends WritableRecordData { /** * The logger */ private static final Logger logger = Logger.getLogger(ObjRecord.class); /** * The object type */ private ObjType type; /** * Indicates whether this record was read in */ private boolean read; /** * The object id */ private int objectId; /** * Object type enumeration */ private static final class ObjType { public int value; public String desc; private static ObjType[] types = new ObjType[0]; ObjType(int v, String d) { value = v; desc = d; ObjType[] oldtypes = types; types = new ObjType[types.length + 1]; System.arraycopy(oldtypes, 0, types, 0, oldtypes.length); types[oldtypes.length] = this; } public String toString() { return desc; } public static ObjType getType(int val) { ObjType retval = UNKNOWN; for (int i = 0; i < types.length && retval == UNKNOWN; i++) { if (types[i].value == val) { retval = types[i]; } } return retval; } } // The object types public static final ObjType GROUP = new ObjType(0x0, "Group"); public static final ObjType LINE = new ObjType(0x01, "Line"); public static final ObjType RECTANGLE = new ObjType(0x02, "Rectangle"); public static final ObjType OVAL = new ObjType(0x03, "Oval"); public static final ObjType ARC = new ObjType(0x04, "Arc"); public static final ObjType CHART = new ObjType(0x05, "Chart"); public static final ObjType TEXT = new ObjType(0x06, "Text"); public static final ObjType BUTTON = new ObjType(0x07, "Button"); public static final ObjType PICTURE = new ObjType(0x08, "Picture"); public static final ObjType POLYGON = new ObjType(0x09, "Polygon"); public static final ObjType CHECKBOX = new ObjType(0x0b, "Checkbox"); public static final ObjType OPTION = new ObjType(0x0c, "Option"); public static final ObjType EDITBOX = new ObjType(0x0d, "Edit Box"); public static final ObjType LABEL = new ObjType(0x0e, "Label"); public static final ObjType DIALOGUEBOX = new ObjType(0x0f, "Dialogue Box"); public static final ObjType SPINBOX = new ObjType(0x10, "Spin Box"); public static final ObjType SCROLLBAR = new ObjType(0x11, "Scrollbar"); public static final ObjType LISTBOX = new ObjType(0x12, "List Box"); public static final ObjType GROUPBOX = new ObjType(0x13, "Group Box"); public static final ObjType COMBOBOX = new ObjType(0x14, "Combo Box"); public static final ObjType MSOFFICEDRAWING = new ObjType (0x1e, "MS Office Drawing"); public static final ObjType FORMCONTROL = new ObjType (0x14, "Form Combo Box"); public static final ObjType EXCELNOTE = new ObjType (0x19, "Excel Note"); public static final ObjType UNKNOWN = new ObjType(0xff, "Unknown"); // Field sub records private static final int COMMON_DATA_LENGTH = 22; private static final int CLIPBOARD_FORMAT_LENGTH = 6; private static final int PICTURE_OPTION_LENGTH = 6; private static final int NOTE_STRUCTURE_LENGTH = 26; private static final int COMBOBOX_STRUCTURE_LENGTH = 44; private static final int END_LENGTH = 4; /** * Constructs this object from the raw data * * @param t the raw data */ public ObjRecord(Record t) { super(t); byte[] data = t.getData(); int objtype = IntegerHelper.getInt(data[4], data[5]); read = true; type = ObjType.getType(objtype); if (type == UNKNOWN) { logger.warn("unknown object type code " + objtype); } objectId = IntegerHelper.getInt(data[6], data[7]); } /** * Constructor * * @param objId the object id * @param t the object type */ ObjRecord(int objId, ObjType t) { super(Type.OBJ); objectId = objId; type = t; } /** * Expose the protected function to the SheetImpl in this package * * @return the raw record data */ public byte[] getData() { if (read) { return getRecord().getData(); } if (type == PICTURE || type == CHART) { return getPictureData(); } else if (type == EXCELNOTE) { return getNoteData(); } else if (type == COMBOBOX) { return getComboBoxData(); } else { Assert.verify(false); } return null; } /** * Gets the ObjRecord subrecords for a picture * * @return the binary data for the picture */ private byte[] getPictureData() { int dataLength = COMMON_DATA_LENGTH + CLIPBOARD_FORMAT_LENGTH + PICTURE_OPTION_LENGTH + END_LENGTH; int pos = 0; byte[] data = new byte[dataLength]; // The jxl.common.data // record id IntegerHelper.getTwoBytes(0x15, data, pos); // record length IntegerHelper.getTwoBytes(COMMON_DATA_LENGTH - 4, data, pos + 2); // object type IntegerHelper.getTwoBytes(type.value, data, pos + 4); // object id IntegerHelper.getTwoBytes(objectId, data, pos + 6); // the options IntegerHelper.getTwoBytes(0x6011, data, pos + 8); pos += COMMON_DATA_LENGTH; // The clipboard format // record id IntegerHelper.getTwoBytes(0x7, data, pos); // record length IntegerHelper.getTwoBytes(CLIPBOARD_FORMAT_LENGTH - 4, data, pos + 2); // the data IntegerHelper.getTwoBytes(0xffff, data, pos + 4); pos += CLIPBOARD_FORMAT_LENGTH; // Picture option flags // record id IntegerHelper.getTwoBytes(0x8, data, pos); // record length IntegerHelper.getTwoBytes(PICTURE_OPTION_LENGTH - 4, data, pos + 2); // the data IntegerHelper.getTwoBytes(0x1, data, pos + 4); pos += CLIPBOARD_FORMAT_LENGTH; // End record id IntegerHelper.getTwoBytes(0x0, data, pos); // record length IntegerHelper.getTwoBytes(END_LENGTH - 4, data, pos + 2); // the data pos += END_LENGTH; return data; } /** * Gets the ObjRecord subrecords for a note * * @return the note data */ private byte[] getNoteData() { int dataLength = COMMON_DATA_LENGTH + NOTE_STRUCTURE_LENGTH + END_LENGTH; int pos = 0; byte[] data = new byte[dataLength]; // The jxl.common.data // record id IntegerHelper.getTwoBytes(0x15, data, pos); // record length IntegerHelper.getTwoBytes(COMMON_DATA_LENGTH - 4, data, pos + 2); // object type IntegerHelper.getTwoBytes(type.value, data, pos + 4); // object id IntegerHelper.getTwoBytes(objectId, data, pos + 6); // the options IntegerHelper.getTwoBytes(0x4011, data, pos + 8); pos += COMMON_DATA_LENGTH; // The note structure // record id IntegerHelper.getTwoBytes(0xd, data, pos); // record length IntegerHelper.getTwoBytes(NOTE_STRUCTURE_LENGTH - 4, data, pos + 2); // the data pos += NOTE_STRUCTURE_LENGTH; // End // record id IntegerHelper.getTwoBytes(0x0, data, pos); // record length IntegerHelper.getTwoBytes(END_LENGTH - 4, data, pos + 2); // the data pos += END_LENGTH; return data; } /** * Gets the ObjRecord subrecords for a combo box * * @return returns the binary data for a combo box */ private byte[] getComboBoxData() { int dataLength = COMMON_DATA_LENGTH + COMBOBOX_STRUCTURE_LENGTH + END_LENGTH; int pos = 0; byte[] data = new byte[dataLength]; // The jxl.common.data // record id IntegerHelper.getTwoBytes(0x15, data, pos); // record length IntegerHelper.getTwoBytes(COMMON_DATA_LENGTH - 4, data, pos + 2); // object type IntegerHelper.getTwoBytes(type.value, data, pos + 4); // object id IntegerHelper.getTwoBytes(objectId, data, pos + 6); // the options IntegerHelper.getTwoBytes(0x0, data, pos + 8); pos += COMMON_DATA_LENGTH; // The combo box structure // record id IntegerHelper.getTwoBytes(0xc, data, pos); // record length IntegerHelper.getTwoBytes(0x14, data, pos + 2); // the data data[pos + 14] = 0x01; data[pos + 16] = 0x04; data[pos + 20] = 0x10; data[pos + 24] = 0x13; data[pos + 26] = (byte) 0xee; data[pos + 27] = 0x1f; data[pos + 30] = 0x04; data[pos + 34] = 0x01; data[pos + 35] = 0x06; data[pos + 38] = 0x02; data[pos + 40] = 0x08; data[pos + 42] = 0x40; pos += COMBOBOX_STRUCTURE_LENGTH; // End // record id IntegerHelper.getTwoBytes(0x0, data, pos); // record length IntegerHelper.getTwoBytes(END_LENGTH - 4, data, pos + 2); // the data pos += END_LENGTH; return data; } /** * Expose the protected function to the SheetImpl in this package * * @return the raw record data */ public Record getRecord() { return super.getRecord(); } /** * Accessor for the object type * * @return the object type */ public ObjType getType() { return type; } /** * Accessor for the object id * * @return accessor for the object id */ public int getObjectId() { return objectId; } } jexcelapi/src/jxl/biff/drawing/EscherRecord.java0000750000175000017500000001005711207000612022044 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.drawing; import jxl.common.Logger; /** * The base class for all escher records. This class contains * the jxl.common.header data and is basically a wrapper for the EscherRecordData * object */ abstract class EscherRecord { /** * The logger */ private static Logger logger = Logger.getLogger(EscherRecord.class); /** * The escher data */ private EscherRecordData data; //protected EscherRecordData data; /** * The length of the escher header on all records */ protected static final int HEADER_LENGTH = 8; /** * Constructor * * @param erd the data */ protected EscherRecord(EscherRecordData erd) { data = erd; } /** * Constructor * * @param type the type */ protected EscherRecord(EscherRecordType type) { data = new EscherRecordData(type); } /** * Identifies whether this item is a container * * @param cont TRUE if this is a container, FALSE otherwise */ protected void setContainer(boolean cont) { data.setContainer(cont); } /** * Gets the entire length of the record, including the header * * @return the length of the record, including the header data */ public int getLength() { return data.getLength() + HEADER_LENGTH; } /** * Accessor for the escher stream * * @return the escher stream */ protected final EscherStream getEscherStream() { return data.getEscherStream(); } /** * The position of this escher record in the stream * * @return the position */ protected final int getPos() { return data.getPos(); } /** * Accessor for the instance * * @return the instance */ protected final int getInstance() { return data.getInstance(); } /** * Sets the instance number when writing out the escher data * * @param i the instance */ protected final void setInstance(int i) { data.setInstance(i); } /** * Sets the version when writing out the escher data * * @param v the version */ protected final void setVersion (int v) { data.setVersion(v); } /** * Accessor for the escher type * * @return the type */ public EscherRecordType getType() { return data.getType(); } /** * Abstract method used to retrieve the generated escher data when writing * out image information * * @return the escher data */ abstract byte[] getData(); /** * Prepends the standard header data to the first eight bytes of the array * and returns it * * @param d the data * @return the binary data */ final byte[] setHeaderData(byte[] d) { return data.setHeaderData(d); } /** * Gets the data that was read in, excluding the header data * * @return the bytes read in, excluding the header data */ byte[] getBytes() { return data.getBytes(); } /** * Accessor for the stream length * * @return the stream length */ protected int getStreamLength() { return data.getStreamLength(); } /** * Used by the EscherDisplay class to retrieve the data * * @return the data */ protected EscherRecordData getEscherData() { return data; } } jexcelapi/src/jxl/biff/drawing/TextObjectRecord.java0000750000175000017500000000561711207000612022714 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2004 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.drawing; import jxl.common.Logger; import jxl.biff.IntegerHelper; import jxl.biff.Type; import jxl.biff.WritableRecordData; import jxl.read.biff.Record; /** * A TextObject (TXO) record which contains the information for comments */ public class TextObjectRecord extends WritableRecordData { /** * The logger */ private static Logger logger = Logger.getLogger(TextObjectRecord.class); /** * The raw drawing data which was read in */ private byte[] data; /** * The text */ private int textLength; /** * Constructor invoked when writing out this object * * @param t the text string */ TextObjectRecord(String t) { super(Type.TXO); textLength = t.length(); } /** * Constructs this object from the raw data * * @param t the raw data */ public TextObjectRecord(Record t) { super(t); data = getRecord().getData(); textLength = IntegerHelper.getInt(data[10], data[11]); } /** * Constructor * * @param d the drawing data */ public TextObjectRecord(byte[] d) { super(Type.TXO); data = d; } /** * Gets the text length. Used to determine if there is any data held * in the following continue records * * @return the length of the text */ public int getTextLength() { return textLength; } /** * Expose the protected function to the SheetImpl in this package * * @return the raw record data */ public byte[] getData() { if (data != null) { return data; } data = new byte[18]; // the options int options = 0; options |= (0x1 << 1); // horizontal alignment - left options |= (0x1 << 4); // vertical alignment - top options |= (0x1 << 9); // lock text IntegerHelper.getTwoBytes(options, data, 0); // the rotation // no rotation // Length of text IntegerHelper.getTwoBytes(textLength, data, 10); // Length of formatting runs IntegerHelper.getTwoBytes(0x10, data, 12); return data; } } jexcelapi/src/jxl/biff/drawing/Chart.java0000750000175000017500000001526411207000612020542 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.drawing; import jxl.common.Assert; import jxl.common.Logger; import jxl.WorkbookSettings; import jxl.biff.ByteData; import jxl.biff.IndexMapping; import jxl.biff.IntegerHelper; import jxl.biff.Type; import jxl.read.biff.File; /** * Contains the various biff records used to insert a chart into a * worksheet */ public class Chart implements ByteData, EscherStream { /** * The logger */ private static final Logger logger = Logger.getLogger(Chart.class); /** * The MsoDrawingRecord associated with the chart */ private MsoDrawingRecord msoDrawingRecord; /** * The ObjRecord associated with the chart */ private ObjRecord objRecord; /** * The start pos of the chart bof stream in the data file */ private int startpos; /** * The start pos of the chart bof stream in the data file */ private int endpos; /** * A handle to the Excel file */ private File file; /** * The drawing data */ private DrawingData drawingData; /** * The drawing number */ private int drawingNumber; /** * The chart byte data */ private byte[] data; /** * Flag which indicates that the byte data has been initialized */ private boolean initialized; /** * The workbook settings */ private WorkbookSettings workbookSettings; /** * Constructor * * @param mso a MsoDrawingRecord value * @param obj an ObjRecord value * @param dd the drawing data * @param sp an int value * @param ep an int value * @param f a File value * @param ws the workbook settings */ public Chart(MsoDrawingRecord mso, ObjRecord obj, DrawingData dd, int sp, int ep, File f, WorkbookSettings ws) { msoDrawingRecord = mso; objRecord = obj; startpos = sp; endpos = ep; file = f; workbookSettings = ws; // msoDrawingRecord is null if the entire sheet consists of just the // chart. In this case, as there is only one drawing on the page, // it isn't necessary to add to the drawing data record anyway if (msoDrawingRecord != null) { drawingData = dd; drawingData.addData(msoDrawingRecord.getRecord().getData()); drawingNumber = drawingData.getNumDrawings() - 1; } initialized = false; // Note: mso and obj values can be null if we are creating a chart // which takes up an entire worksheet. Check that both are null or both // not null though Assert.verify((mso != null && obj != null) || (mso == null && obj == null)); } /** * Gets the entire binary record for the chart as a chunk of binary data * * @return the bytes */ public byte[] getBytes() { if (!initialized) { initialize(); } return data; } /** * Implementation of the EscherStream method * * @return the data */ public byte[] getData() { return msoDrawingRecord.getRecord().getData(); } /** * Initializes the charts byte data */ private void initialize() { data = file.read(startpos, endpos - startpos); initialized = true; } /** * Rationalizes the sheet's xf index mapping * @param xfMapping the index mapping for XFRecords * @param fontMapping the index mapping for fonts * @param formatMapping the index mapping for formats */ public void rationalize(IndexMapping xfMapping, IndexMapping fontMapping, IndexMapping formatMapping) { if (!initialized) { initialize(); } // Read through the array, looking for the data types // This is a total hack bodge for now - it will eventually need to be // integrated properly int pos = 0; int code = 0; int length = 0; Type type = null; while (pos < data.length) { code = IntegerHelper.getInt(data[pos], data[pos + 1]); length = IntegerHelper.getInt(data[pos + 2], data[pos + 3]); type = Type.getType(code); if (type == Type.FONTX) { int fontind = IntegerHelper.getInt(data[pos + 4], data[pos + 5]); IntegerHelper.getTwoBytes(fontMapping.getNewIndex(fontind), data, pos + 4); } else if (type == Type.FBI) { int fontind = IntegerHelper.getInt(data[pos + 12], data[pos + 13]); IntegerHelper.getTwoBytes(fontMapping.getNewIndex(fontind), data, pos + 12); } else if (type == Type.IFMT) { int formind = IntegerHelper.getInt(data[pos + 4], data[pos + 5]); IntegerHelper.getTwoBytes(formatMapping.getNewIndex(formind), data, pos + 4); } else if (type == Type.ALRUNS) { int numRuns = IntegerHelper.getInt(data[pos + 4], data[pos + 5]); int fontPos = pos + 6; for (int i = 0 ; i < numRuns; i++) { int fontind = IntegerHelper.getInt(data[fontPos + 2], data[fontPos + 3]); IntegerHelper.getTwoBytes(fontMapping.getNewIndex(fontind), data, fontPos + 2); fontPos += 4; } } pos += length + 4; } } /** * Gets the SpContainer containing the charts drawing information * * @return the spContainer */ EscherContainer getSpContainer() { EscherContainer spContainer = drawingData.getSpContainer(drawingNumber); return spContainer; } /** * Accessor for the mso drawing record * * @return the drawing record */ MsoDrawingRecord getMsoDrawingRecord() { return msoDrawingRecord; } /** * Accessor for the obj record * * @return the obj record */ ObjRecord getObjRecord() { return objRecord; } } jexcelapi/src/jxl/biff/drawing/MsoDrawingRecord.java0000750000175000017500000000520411207000612022703 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2001 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.drawing; import jxl.common.Logger; import jxl.biff.Type; import jxl.biff.WritableRecordData; import jxl.read.biff.Record; /** * A record which merely holds the MSODRAWING data. Used when copying files * which contain images */ public class MsoDrawingRecord extends WritableRecordData { /** * The logger */ private static Logger logger = Logger.getLogger(MsoDrawingRecord.class); /** * Flag to indicate whether this is the first drawing on the sheet * - needed for copying */ private boolean first; /** * The raw drawing data which was read in */ private byte[] data; /** * Constructs this object from the raw data * * @param t the raw data */ public MsoDrawingRecord(Record t) { super(t); data = getRecord().getData(); first = false; } /** * Constructor * * @param d the drawing data */ public MsoDrawingRecord(byte[] d) { super(Type.MSODRAWING); data = d; first = false; } /** * Expose the protected function * * @return the raw record data */ public byte[] getData() { return data; } /** * Expose the protected function to the SheetImpl in this package * * @return the raw record data */ public Record getRecord() { return super.getRecord(); } /** * Sets the flag to indicate that this is the first drawing on the sheet */ public void setFirst() { first = true; } /** * Accessor for the first drawing on the sheet. This is used when * copying unmodified sheets to indicate that this drawing contains * the first time Escher gubbins * * @return TRUE if this MSORecord is the first drawing on the sheet */ public boolean isFirst() { return first; } } jexcelapi/src/jxl/biff/drawing/EscherContainer.java0000750000175000017500000001176511207000612022557 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.drawing; import java.util.ArrayList; import java.util.Iterator; import jxl.common.Logger; /** * An escher container. This record may contain other escher containers or * atoms */ class EscherContainer extends EscherRecord { /** * The logger */ private static Logger logger = Logger.getLogger(EscherContainer.class); /** * Initialized flag */ private boolean initialized; /** * The children of this container */ private ArrayList children; /** * Constructor * * @param erd the raw data */ public EscherContainer(EscherRecordData erd) { super(erd); initialized = false; children = new ArrayList(); } /** * Constructor used when writing out escher data * * @param type the type */ protected EscherContainer(EscherRecordType type) { super(type); setContainer(true); children = new ArrayList(); } /** * Accessor for the children of this container * * @return the children */ public EscherRecord[] getChildren() { if (!initialized) { initialize(); } Object[] ca = children.toArray(new EscherRecord[children.size()]); return (EscherRecord[]) ca; } /** * Adds a child to this container * * @param child the item to add */ public void add(EscherRecord child) { children.add(child); } /** * Removes a child from this container * * @param child the item to remove */ public void remove(EscherRecord child) { boolean result = children.remove(child); } /** * Initialization */ private void initialize() { int curpos = getPos() + HEADER_LENGTH; int endpos = Math.min(getPos() + getLength(), getStreamLength()); EscherRecord newRecord = null; while (curpos < endpos) { EscherRecordData erd = new EscherRecordData(getEscherStream(), curpos); EscherRecordType type = erd.getType(); if (type == EscherRecordType.DGG) { newRecord = new Dgg(erd); } else if (type == EscherRecordType.DG) { newRecord = new Dg(erd); } else if (type == EscherRecordType.BSTORE_CONTAINER) { newRecord = new BStoreContainer(erd); } else if (type == EscherRecordType.SPGR_CONTAINER) { newRecord = new SpgrContainer(erd); } else if (type == EscherRecordType.SP_CONTAINER) { newRecord = new SpContainer(erd); } else if (type == EscherRecordType.SPGR) { newRecord = new Spgr(erd); } else if (type == EscherRecordType.SP) { newRecord = new Sp(erd); } else if (type == EscherRecordType.CLIENT_ANCHOR) { newRecord = new ClientAnchor(erd); } else if (type == EscherRecordType.CLIENT_DATA) { newRecord = new ClientData(erd); } else if (type == EscherRecordType.BSE) { newRecord = new BlipStoreEntry(erd); } else if (type == EscherRecordType.OPT) { newRecord = new Opt(erd); } else if (type == EscherRecordType.SPLIT_MENU_COLORS) { newRecord = new SplitMenuColors(erd); } else if (type == EscherRecordType.CLIENT_TEXT_BOX) { newRecord = new ClientTextBox(erd); } else { newRecord = new EscherAtom(erd); } children.add(newRecord); curpos += newRecord.getLength(); } initialized = true; } /** * Gets the data for this container (and all of its children recursively * * @return the binary data */ byte[] getData() { if (!initialized) { initialize(); } byte[] data = new byte[0]; for (Iterator i = children.iterator(); i.hasNext();) { EscherRecord er = (EscherRecord) i.next(); byte[] childData = er.getData(); if (childData != null) { byte[] newData = new byte[data.length + childData.length]; System.arraycopy(data, 0, newData, 0, data.length); System.arraycopy(childData, 0, newData, data.length, childData.length); data = newData; } } return setHeaderData(data); } } jexcelapi/src/jxl/biff/drawing/DrawingGroup.java0000750000175000017500000003505411207000612022110 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2004 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.drawing; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import jxl.common.Assert; import jxl.common.Logger; import jxl.read.biff.Record; import jxl.write.biff.File; /** * This class contains the Excel picture data in Escher format for the * entire workbook */ public class DrawingGroup implements EscherStream { /** * The logger */ private static Logger logger = Logger.getLogger(DrawingGroup.class); /** * The escher data read in from file */ private byte[] drawingData; /** * The top level escher container */ private EscherContainer escherData; /** * The Bstore container, which contains all the drawing data */ private BStoreContainer bstoreContainer; /** * The initialized flag */ private boolean initialized; /** * The list of user added drawings */ private ArrayList drawings; /** * The number of blips */ private int numBlips; /** * The number of charts */ private int numCharts; /** * The number of shape ids used on the second Dgg cluster */ private int drawingGroupId; /** * Flag which indicates that at least one of the drawings has been omitted * from the worksheet */ private boolean drawingsOmitted; /** * The origin of this drawing group */ private Origin origin; /** * A hash map of images keyed on the file path, containing the * reference count */ private HashMap imageFiles; /** * A count of the next available object id */ private int maxObjectId; /** * The maximum shape id so far encountered */ private int maxShapeId; /** * Constructor * * @param o the origin of this drawing group */ public DrawingGroup(Origin o) { origin = o; initialized = o == Origin.WRITE ? true : false; drawings = new ArrayList(); imageFiles = new HashMap(); drawingsOmitted = false; maxObjectId = 1; maxShapeId = 1024; } /** * Copy constructor * Uses a shallow copy for most things, since as soon as anything * is changed, the drawing group is invalidated and all the data blocks * regenerated * * @param dg the drawing group to copy */ public DrawingGroup(DrawingGroup dg) { drawingData = dg.drawingData; escherData = dg.escherData; bstoreContainer = dg.bstoreContainer; initialized = dg.initialized; drawingData = dg.drawingData; escherData = dg.escherData; bstoreContainer = dg.bstoreContainer; numBlips = dg.numBlips; numCharts = dg.numCharts; drawingGroupId = dg.drawingGroupId; drawingsOmitted = dg.drawingsOmitted; origin = dg.origin; imageFiles = (HashMap) dg.imageFiles.clone(); maxObjectId = dg.maxObjectId; maxShapeId = dg.maxShapeId; // Create this as empty, because all drawings will get added later // as part of the sheet copy process drawings = new ArrayList(); } /** /** * Adds in a drawing group record to this drawing group. The binary * data is extracted from the drawing group and added to a single * byte array * * @param mso the drawing group record to add */ public void add(MsoDrawingGroupRecord mso) { addData(mso.getData()); } /** * Adds a continue record to this drawing group. the binary data is * extracted and appended to the byte array * * @param cont the continue record */ public void add(Record cont) { addData(cont.getData()); } /** * Adds the mso record data to the drawing data * * @param msodata the raw mso data */ private void addData(byte[] msodata) { if (drawingData == null) { drawingData = new byte[msodata.length]; System.arraycopy(msodata, 0, drawingData, 0, msodata.length); return; } // Grow the array byte[] newdata = new byte[drawingData.length + msodata.length]; System.arraycopy(drawingData, 0, newdata, 0, drawingData.length); System.arraycopy(msodata, 0, newdata, drawingData.length, msodata.length); drawingData = newdata; } /** * Adds a drawing to the drawing group * * @param d the drawing to add */ final void addDrawing(DrawingGroupObject d) { drawings.add(d); maxObjectId = Math.max(maxObjectId, d.getObjectId()); maxShapeId = Math.max(maxShapeId, d.getShapeId()); } /** * Adds a chart to the drawing group * * @param c the chart */ public void add(Chart c) { numCharts++; } /** * Adds a drawing from the public, writable interface * * @param d the drawing to add */ public void add(DrawingGroupObject d) { if (origin == Origin.READ) { origin = Origin.READ_WRITE; BStoreContainer bsc = getBStoreContainer(); // force initialization Dgg dgg = (Dgg) escherData.getChildren()[0]; drawingGroupId = dgg.getCluster(1).drawingGroupId - numBlips - 1; numBlips = bsc != null ? bsc.getNumBlips() : 0; if (bsc != null) { Assert.verify(numBlips == bsc.getNumBlips()); } } if (!(d instanceof Drawing)) { // Assign a new object id and add it to the list // drawings.add(d); maxObjectId++; maxShapeId++; d.setDrawingGroup(this); d.setObjectId(maxObjectId, numBlips + 1, maxShapeId); if (drawings.size() > maxObjectId) { logger.warn("drawings length " + drawings.size() + " exceeds the max object id " + maxObjectId); } // numBlips++; return; } Drawing drawing = (Drawing) d; // See if this is referenced elsewhere Drawing refImage = (Drawing) imageFiles.get(d.getImageFilePath()); if (refImage == null) { // There are no other references to this drawing, so assign // a new object id and put it on the hash map maxObjectId++; maxShapeId++; drawings.add(drawing); drawing.setDrawingGroup(this); drawing.setObjectId(maxObjectId, numBlips + 1, maxShapeId); numBlips++; imageFiles.put(drawing.getImageFilePath(), drawing); } else { // This drawing is used elsewhere in the workbook. Increment the // reference count on the drawing, and set the object id of the drawing // passed in refImage.setReferenceCount(refImage.getReferenceCount() + 1); drawing.setDrawingGroup(this); drawing.setObjectId(refImage.getObjectId(), refImage.getBlipId(), refImage.getShapeId()); } } /** * Interface method to remove a drawing from the group * * @param d the drawing to remove */ public void remove(DrawingGroupObject d) { // Unless there are real images or some such, it is possible that // a BStoreContainer will not be present. In that case simply return if (getBStoreContainer() == null) { return; } if (origin == Origin.READ) { origin = Origin.READ_WRITE; numBlips = getBStoreContainer().getNumBlips(); Dgg dgg = (Dgg) escherData.getChildren()[0]; drawingGroupId = dgg.getCluster(1).drawingGroupId - numBlips - 1; } // Get the blip EscherRecord[] children = getBStoreContainer().getChildren(); BlipStoreEntry bse = (BlipStoreEntry) children[d.getBlipId() - 1]; bse.dereference(); if (bse.getReferenceCount() == 0) { // Remove the blip getBStoreContainer().remove(bse); // Adjust blipId on the other blips for (Iterator i = drawings.iterator(); i.hasNext();) { DrawingGroupObject drawing = (DrawingGroupObject) i.next(); if (drawing.getBlipId() > d.getBlipId()) { drawing.setObjectId(drawing.getObjectId(), drawing.getBlipId() - 1, drawing.getShapeId()); } } numBlips--; } } /** * Initializes the drawing data from the escher record read in */ private void initialize() { EscherRecordData er = new EscherRecordData(this, 0); Assert.verify(er.isContainer()); escherData = new EscherContainer(er); Assert.verify(escherData.getLength() == drawingData.length); Assert.verify(escherData.getType() == EscherRecordType.DGG_CONTAINER); initialized = true; } /** * Gets hold of the BStore container from the Escher data * * @return the BStore container */ private BStoreContainer getBStoreContainer() { if (bstoreContainer == null) { if (!initialized) { initialize(); } EscherRecord[] children = escherData.getChildren(); if (children.length > 1 && children[1].getType() == EscherRecordType.BSTORE_CONTAINER) { bstoreContainer = (BStoreContainer) children[1]; } } return bstoreContainer; } /** * Gets hold of the binary data * * @return the data */ public byte[] getData() { return drawingData; } /** * Writes the drawing group to the output file * * @param outputFile the file to write to * @exception IOException */ public void write(File outputFile) throws IOException { if (origin == Origin.WRITE) { DggContainer dggContainer = new DggContainer(); Dgg dgg = new Dgg(numBlips + numCharts + 1, numBlips); dgg.addCluster(1, 0); dgg.addCluster(numBlips + 1, 0); dggContainer.add(dgg); int drawingsAdded = 0; BStoreContainer bstoreCont = new BStoreContainer(); // Create a blip entry for each drawing for (Iterator i = drawings.iterator(); i.hasNext();) { Object o = i.next(); if (o instanceof Drawing) { Drawing d = (Drawing) o; BlipStoreEntry bse = new BlipStoreEntry(d); bstoreCont.add(bse); drawingsAdded++; } } if (drawingsAdded > 0) { bstoreCont.setNumBlips(drawingsAdded); dggContainer.add(bstoreCont); } Opt opt = new Opt(); dggContainer.add(opt); SplitMenuColors splitMenuColors = new SplitMenuColors(); dggContainer.add(splitMenuColors); drawingData = dggContainer.getData(); } else if (origin == Origin.READ_WRITE) { DggContainer dggContainer = new DggContainer(); Dgg dgg = new Dgg(numBlips + numCharts + 1, numBlips); dgg.addCluster(1, 0); dgg.addCluster(drawingGroupId + numBlips + 1, 0); dggContainer.add(dgg); BStoreContainer bstoreCont = new BStoreContainer(); bstoreCont.setNumBlips(numBlips); // Create a blip entry for each drawing that was read in BStoreContainer readBStoreContainer = getBStoreContainer(); if (readBStoreContainer != null) { EscherRecord[] children = readBStoreContainer.getChildren(); for (int i = 0; i < children.length; i++) { BlipStoreEntry bse = (BlipStoreEntry) children[i]; bstoreCont.add(bse); } } // Create a blip entry for each drawing that has been added for (Iterator i = drawings.iterator(); i.hasNext();) { DrawingGroupObject dgo = (DrawingGroupObject) i.next(); if (dgo instanceof Drawing) { Drawing d = (Drawing) dgo; if (d.getOrigin() == Origin.WRITE) { BlipStoreEntry bse = new BlipStoreEntry(d); bstoreCont.add(bse); } } } dggContainer.add(bstoreCont); Opt opt = new Opt(); opt.addProperty(191, false, false, 524296); opt.addProperty(385, false, false, 134217737); opt.addProperty(448, false, false, 134217792); dggContainer.add(opt); SplitMenuColors splitMenuColors = new SplitMenuColors(); dggContainer.add(splitMenuColors); drawingData = dggContainer.getData(); } MsoDrawingGroupRecord msodg = new MsoDrawingGroupRecord(drawingData); outputFile.write(msodg); } /** * Accessor for the number of blips in the drawing group * * @return the number of blips */ final int getNumberOfBlips() { return numBlips; } /** * Gets the drawing data for the given blip id. Called by the Drawing * object * * @param blipId the blipId * @return the drawing data */ byte[] getImageData(int blipId) { numBlips = getBStoreContainer().getNumBlips(); Assert.verify(blipId <= numBlips); Assert.verify(origin == Origin.READ || origin == Origin.READ_WRITE); // Get the blip EscherRecord[] children = getBStoreContainer().getChildren(); BlipStoreEntry bse = (BlipStoreEntry) children[blipId - 1]; return bse.getImageData(); } /** * Indicates that at least one of the drawings has been omitted from * the worksheet * @param mso the mso record * @param obj the obj record */ public void setDrawingsOmitted(MsoDrawingRecord mso, ObjRecord obj) { drawingsOmitted = true; if (obj != null) { maxObjectId = Math.max(maxObjectId, obj.getObjectId()); } } /** * Accessor for the drawingsOmitted flag * * @return TRUE if a drawing has been omitted, FALSE otherwise */ public boolean hasDrawingsOmitted() { return drawingsOmitted; } /** * Updates this with the appropriate data from the drawing group passed in * This is called during the copy process: this is first initialised as * an empty object, but during the copy, the source DrawingGroup may * change. After the copy process, this method is then called to update * the relevant fields. Unfortunately, the copy process required the * presence of a drawing group * * @param dg the drawing group containing the updated data */ public void updateData(DrawingGroup dg) { drawingsOmitted = dg.drawingsOmitted; maxObjectId = dg.maxObjectId; maxShapeId = dg.maxShapeId; } } jexcelapi/src/jxl/biff/drawing/Sp.java0000750000175000017500000000513411263144254020073 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.drawing; import jxl.common.Logger; import jxl.biff.IntegerHelper; /** * The Sp escher atom */ class Sp extends EscherAtom { /** * The logger */ private static Logger logger = Logger.getLogger(Sp.class); /** * The binary data */ private byte[] data; /** * The shape type */ private int shapeType; /** * The shape id */ private int shapeId; /** * The Sp persistence flags */ private int persistenceFlags; /** * Constructor * * @param erd the entity record data */ public Sp(EscherRecordData erd) { super(erd); shapeType = getInstance(); byte[] bytes = getBytes(); shapeId = IntegerHelper.getInt(bytes[0], bytes[1], bytes[2], bytes[3]); persistenceFlags = IntegerHelper.getInt(bytes[4], bytes[5], bytes[6], bytes[7]); } /** * Constructor - used when writing * * @param st the shape type * @param sid the shape id * @param p persistence flags */ public Sp(ShapeType st, int sid, int p) { super(EscherRecordType.SP); setVersion(2); shapeType = st.getValue(); shapeId = sid; persistenceFlags = p; setInstance(shapeType); } /** * Accessor for the shape id * * @return the shape id */ int getShapeId() { return shapeId; } /** * Accessor for the shape type * * @return the shape type */ int getShapeType() { return shapeType; } /** * Gets the data * * @return the binary data */ byte[] getData() { data = new byte[8]; IntegerHelper.getFourBytes(shapeId, data, 0); IntegerHelper.getFourBytes(persistenceFlags, data, 4); return setHeaderData(data); } } jexcelapi/src/jxl/biff/drawing/SheetDrawingWriter.java0000750000175000017500000003304211207000612023254 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2004 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.drawing; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import jxl.common.Logger; import jxl.WorkbookSettings; import jxl.biff.IntegerHelper; import jxl.write.biff.File; /** * Handles the writing out of the different charts and images on a sheet. * Called by the SheetWriter object */ public class SheetDrawingWriter { /** * The logger */ private static Logger logger = Logger.getLogger(SheetDrawingWriter.class); /** * The drawings on the sheet */ private ArrayList drawings; /** * Flag indicating whether the drawings on the sheet were modified */ private boolean drawingsModified; /** * The charts on the sheet */ private Chart[] charts; /** * The workbook settings */ private WorkbookSettings workbookSettings; /** * Constructor * * @param ws the workbook settings */ public SheetDrawingWriter(WorkbookSettings ws) { charts = new Chart[0]; } /** * The drawings on the sheet * * @param dr the list of drawings * @param mod flag indicating whether the drawings have been tampered with */ public void setDrawings(ArrayList dr, boolean mod) { drawings = dr; drawingsModified = mod; } /** * Writes out the MsoDrawing records and Obj records for each image * and chart on the sheet * * @param outputFile the output file * @exception IOException */ public void write(File outputFile) throws IOException { // If there are no drawings or charts on this sheet then exit if (drawings.size() == 0 && charts.length == 0) { return; } // See if any drawing has been modified boolean modified = drawingsModified; int numImages = drawings.size(); for (Iterator i = drawings.iterator(); i.hasNext() && !modified;) { DrawingGroupObject d = (DrawingGroupObject) i.next(); if (d.getOrigin() != Origin.READ) { modified = true; } } // If the drawing order has been muddled at all, then we'll need // to regenerate the Escher drawing data if (numImages > 0 && !modified) { DrawingGroupObject d2 = (DrawingGroupObject) drawings.get(0); if (!d2.isFirst()) { modified = true; } } // Check to see if this sheet consists of just a single chart. If so // there is no MsoDrawingRecord, so write out the data and exit if (numImages == 0 && charts.length == 1 && charts[0].getMsoDrawingRecord() == null) { modified = false; // this sheet has not been modified } // If no drawing has been modified, then simply write them straight out // again and exit if (!modified) { writeUnmodified(outputFile); return; } Object[] spContainerData = new Object[numImages + charts.length]; int length = 0; EscherContainer firstSpContainer = null; // Get all the spContainer byte data from the drawings // and store in an array for (int i = 0; i < numImages; i++) { DrawingGroupObject drawing = (DrawingGroupObject) drawings.get(i); EscherContainer spc = drawing.getSpContainer(); if (spc != null) { byte[] data = spc.getData(); spContainerData[i] = data; if (i == 0) { firstSpContainer = spc; } else { length += data.length; } } } // Get all the spContainer bytes from the charts and add to the array for (int i = 0; i < charts.length; i++) { EscherContainer spContainer = charts[i].getSpContainer(); byte[] data = spContainer.getBytes(); //use getBytes instead of getData data = spContainer.setHeaderData(data); spContainerData[i + numImages] = data; if (i == 0 && numImages == 0) { firstSpContainer = spContainer; } else { length += data.length; } } // Put the generalised stuff around the first item DgContainer dgContainer = new DgContainer(); Dg dg = new Dg(numImages + charts.length); dgContainer.add(dg); SpgrContainer spgrContainer = new SpgrContainer(); SpContainer spContainer = new SpContainer(); Spgr spgr = new Spgr(); spContainer.add(spgr); Sp sp = new Sp(ShapeType.MIN, 1024, 5); spContainer.add(sp); spgrContainer.add(spContainer); spgrContainer.add(firstSpContainer); dgContainer.add(spgrContainer); byte[] firstMsoData = dgContainer.getData(); // Adjust the length of the DgContainer int len = IntegerHelper.getInt(firstMsoData[4], firstMsoData[5], firstMsoData[6], firstMsoData[7]); IntegerHelper.getFourBytes(len + length, firstMsoData, 4); // Adjust the length of the SpgrContainer len = IntegerHelper.getInt(firstMsoData[28], firstMsoData[29], firstMsoData[30], firstMsoData[31]); IntegerHelper.getFourBytes(len + length, firstMsoData, 28); // Now write out each MsoDrawing record // First MsoRecord // test hack for form objects, to remove the ClientTextBox record // from the end of the SpContainer if (numImages > 0 && ((DrawingGroupObject) drawings.get(0)).isFormObject()) { byte[] msodata2 = new byte[firstMsoData.length - 8]; System.arraycopy(firstMsoData, 0, msodata2, 0, msodata2.length); firstMsoData = msodata2; } MsoDrawingRecord msoDrawingRecord = new MsoDrawingRecord(firstMsoData); outputFile.write(msoDrawingRecord); if (numImages > 0) { DrawingGroupObject firstDrawing = (DrawingGroupObject) drawings.get(0); firstDrawing.writeAdditionalRecords(outputFile); } else { // first image is a chart Chart chart = charts[0]; ObjRecord objRecord = chart.getObjRecord(); outputFile.write(objRecord); outputFile.write(chart); } // Now do all the others for (int i = 1; i < spContainerData.length; i++) { byte[] bytes = (byte[]) spContainerData[i]; // test hack for form objects, to remove the ClientTextBox record // from the end of the SpContainer if (i < numImages && ((DrawingGroupObject) drawings.get(i)).isFormObject()) { byte[] bytes2 = new byte[bytes.length - 8]; System.arraycopy(bytes, 0, bytes2, 0, bytes2.length); bytes = bytes2; } msoDrawingRecord = new MsoDrawingRecord(bytes); outputFile.write(msoDrawingRecord); if (i < numImages) { // Write anything else the object needs DrawingGroupObject d = (DrawingGroupObject) drawings.get(i); d.writeAdditionalRecords(outputFile); } else { Chart chart = charts[i - numImages]; ObjRecord objRecord = chart.getObjRecord(); outputFile.write(objRecord); outputFile.write(chart); } } // Write any tail records that need to be written for (Iterator i = drawings.iterator(); i.hasNext();) { DrawingGroupObject dgo2 = (DrawingGroupObject) i.next(); dgo2.writeTailRecords(outputFile); } } /** * Writes out the drawings and the charts if nothing has been modified * * @param outputFile the output file * @exception IOException */ private void writeUnmodified(File outputFile) throws IOException { if (charts.length == 0 && drawings.size() == 0) { // No drawings or charts return; } else if (charts.length == 0 && drawings.size() != 0) { // If there are no charts, then write out the drawings and return for (Iterator i = drawings.iterator(); i.hasNext();) { DrawingGroupObject d = (DrawingGroupObject) i.next(); outputFile.write(d.getMsoDrawingRecord()); d.writeAdditionalRecords(outputFile); } for (Iterator i = drawings.iterator(); i.hasNext();) { DrawingGroupObject d = (DrawingGroupObject) i.next(); d.writeTailRecords(outputFile); } return; } else if (drawings.size() == 0 && charts.length != 0) { // If there are no drawings, then write out the charts and return Chart curChart = null; for (int i = 0; i < charts.length; i++) { curChart = charts[i]; if (curChart.getMsoDrawingRecord() != null) { outputFile.write(curChart.getMsoDrawingRecord()); } if (curChart.getObjRecord() != null) { outputFile.write(curChart.getObjRecord()); } outputFile.write(curChart); } return; } // There are both charts and drawings - the output // drawing group records will need // to be re-jigged in order to write the drawings out first, then the // charts int numDrawings = drawings.size(); int length = 0; EscherContainer[] spContainers = new EscherContainer[numDrawings + charts.length]; boolean[] isFormObject = new boolean[numDrawings + charts.length]; for (int i = 0; i < numDrawings; i++) { DrawingGroupObject d = (DrawingGroupObject) drawings.get(i); spContainers[i] = d.getSpContainer(); if (i > 0) { length += spContainers[i].getLength(); } if (d.isFormObject()) { isFormObject[i] = true; } } for (int i = 0; i < charts.length; i++) { spContainers[i + numDrawings] = charts[i].getSpContainer(); length += spContainers[i + numDrawings].getLength(); } // Put the generalised stuff around the first item DgContainer dgContainer = new DgContainer(); Dg dg = new Dg(numDrawings + charts.length); dgContainer.add(dg); SpgrContainer spgrContainer = new SpgrContainer(); SpContainer spContainer = new SpContainer(); Spgr spgr = new Spgr(); spContainer.add(spgr); Sp sp = new Sp(ShapeType.MIN, 1024, 5); spContainer.add(sp); spgrContainer.add(spContainer); spgrContainer.add(spContainers[0]); dgContainer.add(spgrContainer); byte[] firstMsoData = dgContainer.getData(); // Adjust the length of the DgContainer int len = IntegerHelper.getInt(firstMsoData[4], firstMsoData[5], firstMsoData[6], firstMsoData[7]); IntegerHelper.getFourBytes(len + length, firstMsoData, 4); // Adjust the length of the SpgrContainer len = IntegerHelper.getInt(firstMsoData[28], firstMsoData[29], firstMsoData[30], firstMsoData[31]); IntegerHelper.getFourBytes(len + length, firstMsoData, 28); // Now write out each MsoDrawing record and object record // Hack to remove the last eight bytes (text box escher record) // from the container if (isFormObject[0] == true) { byte[] cbytes = new byte[firstMsoData.length - 8]; System.arraycopy(firstMsoData, 0, cbytes, 0, cbytes.length); firstMsoData = cbytes; } // First MsoRecord MsoDrawingRecord msoDrawingRecord = new MsoDrawingRecord(firstMsoData); outputFile.write(msoDrawingRecord); DrawingGroupObject dgo = (DrawingGroupObject) drawings.get(0); dgo.writeAdditionalRecords(outputFile); // Now do all the others for (int i = 1; i < spContainers.length; i++) { byte[] bytes = spContainers[i].getBytes(); byte[] bytes2 = spContainers[i].setHeaderData(bytes); // Hack to remove the last eight bytes (text box escher record) // from the container if (isFormObject[i] == true) { byte[] cbytes = new byte[bytes2.length - 8]; System.arraycopy(bytes2, 0, cbytes, 0, cbytes.length); bytes2 = cbytes; } msoDrawingRecord = new MsoDrawingRecord(bytes2); outputFile.write(msoDrawingRecord); if (i < numDrawings) { dgo = (DrawingGroupObject) drawings.get(i); dgo.writeAdditionalRecords(outputFile); } else { Chart chart = charts[i - numDrawings]; ObjRecord objRecord = chart.getObjRecord(); outputFile.write(objRecord); outputFile.write(chart); } } // Write any tail records that need to be written for (Iterator i = drawings.iterator(); i.hasNext();) { DrawingGroupObject dgo2 = (DrawingGroupObject) i.next(); dgo2.writeTailRecords(outputFile); } } /** * Sets the charts on the sheet * * @param ch the charts */ public void setCharts(Chart[] ch) { charts = ch; } /** * Accessor for the charts on the sheet * * @return the charts */ public Chart[] getCharts() { return charts; } } jexcelapi/src/jxl/biff/drawing/ChunkType.java0000750000175000017500000000432111207000612021403 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2006 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.drawing; import java.util.Arrays; /** * Enumeration for the various chunk types */ class ChunkType { private byte[] id; private String name; private static ChunkType[] chunkTypes = new ChunkType[0]; private ChunkType(int d1, int d2, int d3, int d4, String n) { id = new byte[] {(byte) d1, (byte) d2, (byte) d3, (byte) d4}; name = n; ChunkType[] ct = new ChunkType[chunkTypes.length + 1]; System.arraycopy(chunkTypes, 0, ct, 0, chunkTypes.length); ct[chunkTypes.length] = this; chunkTypes = ct; } public String getName() { return name; } public static ChunkType getChunkType(byte d1, byte d2, byte d3, byte d4) { byte[] cmp = new byte[] {d1, d2, d3, d4}; boolean found = false; ChunkType chunk = ChunkType.UNKNOWN; for (int i = 0; i < chunkTypes.length && !found ; i++) { if (Arrays.equals(chunkTypes[i].id, cmp)) { chunk = chunkTypes[i]; found = true; } } return chunk; } public static ChunkType IHDR = new ChunkType(0x49, 0x48, 0x44, 0x52,"IHDR"); public static ChunkType IEND = new ChunkType(0x49, 0x45, 0x4e, 0x44,"IEND"); public static ChunkType PHYS = new ChunkType(0x70, 0x48, 0x59, 0x73,"pHYs"); public static ChunkType UNKNOWN = new ChunkType(0xff, 0xff, 0xff, 0xff, "UNKNOWN"); } jexcelapi/src/jxl/biff/drawing/DrawingDataException.java0000750000175000017500000000261211207000612023536 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2006 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.drawing; /** * Checked exception thrown when the drawing data is corrupt eg. when * the drawing number exceeds the number of SpContainers. This exception * is handled within the drawing package, and usually causes drawings to be * disabled for the remainder of the workbook */ public class DrawingDataException extends RuntimeException { private static String message = "Drawing number exceeds available SpContainers"; DrawingDataException() { super(message); } } jexcelapi/src/jxl/biff/drawing/CheckBox.java0000750000175000017500000003552611207000612021172 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2009 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.drawing; import java.io.IOException; import jxl.common.Assert; import jxl.common.Logger; import jxl.WorkbookSettings; import jxl.biff.ContinueRecord; import jxl.write.biff.File; /** * Contains the various biff records used to copy a CheckBox (from the * Form toolbox) between workbook */ public class CheckBox implements DrawingGroupObject { /** * The logger */ private static Logger logger = Logger.getLogger(CheckBox.class); /** * The spContainer that was read in */ private EscherContainer readSpContainer; /** * The spContainer that was generated */ private EscherContainer spContainer; /** * The MsoDrawingRecord associated with the drawing */ private MsoDrawingRecord msoDrawingRecord; /** * The ObjRecord associated with the drawing */ private ObjRecord objRecord; /** * Initialized flag */ private boolean initialized = false; /** * The object id, assigned by the drawing group */ private int objectId; /** * The blip id */ private int blipId; /** * The shape id */ private int shapeId; /** * The column */ private int column; /** * The row position of the image */ private int row; /** * The width of the image in cells */ private double width; /** * The height of the image in cells */ private double height; /** * The number of places this drawing is referenced */ private int referenceCount; /** * The top level escher container */ private EscherContainer escherData; /** * Where this image came from (read, written or a copy) */ private Origin origin; /** * The drawing group for all the images */ private DrawingGroup drawingGroup; /** * The drawing data */ private DrawingData drawingData; /** * The type of this drawing object */ private ShapeType type; /** * The drawing position on the sheet */ private int drawingNumber; /** * An mso drawing record, which sometimes appears */ private MsoDrawingRecord mso; /** * The text object record */ private TextObjectRecord txo; /** * Text data from the first continue record */ private ContinueRecord text; /** * Formatting data from the second continue record */ private ContinueRecord formatting; /** * The workbook settings */ private WorkbookSettings workbookSettings; /** * Constructor used when reading images * * @param mso the drawing record * @param obj the object record * @param dd the drawing data for all drawings on this sheet * @param dg the drawing group * @param ws the workbook settings */ public CheckBox(MsoDrawingRecord mso, ObjRecord obj, DrawingData dd, DrawingGroup dg, WorkbookSettings ws) { drawingGroup = dg; msoDrawingRecord = mso; drawingData = dd; objRecord = obj; initialized = false; workbookSettings = ws; origin = Origin.READ; drawingData.addData(msoDrawingRecord.getData()); drawingNumber = drawingData.getNumDrawings() - 1; drawingGroup.addDrawing(this); Assert.verify(mso != null && obj != null); initialize(); } /** * Copy constructor used to copy drawings from read to write * * @param dgo the drawing group object * @param dg the drawing group * @param ws the workbook settings */ public CheckBox(DrawingGroupObject dgo, DrawingGroup dg, WorkbookSettings ws) { CheckBox d = (CheckBox) dgo; Assert.verify(d.origin == Origin.READ); msoDrawingRecord = d.msoDrawingRecord; objRecord = d.objRecord; initialized = false; origin = Origin.READ; drawingData = d.drawingData; drawingGroup = dg; drawingNumber = d.drawingNumber; drawingGroup.addDrawing(this); mso = d.mso; txo = d.txo; text = d.text; formatting = d.formatting; workbookSettings = ws; } /** * Constructor invoked when writing images */ public CheckBox() { initialized = true; origin = Origin.WRITE; referenceCount = 1; type = ShapeType.HOST_CONTROL; } /** * Initializes the member variables from the Escher stream data */ private void initialize() { readSpContainer = drawingData.getSpContainer(drawingNumber); Assert.verify(readSpContainer != null); EscherRecord[] children = readSpContainer.getChildren(); Sp sp = (Sp) readSpContainer.getChildren()[0]; objectId = objRecord.getObjectId(); shapeId = sp.getShapeId(); type = ShapeType.getType(sp.getShapeType()); if (type == ShapeType.UNKNOWN) { logger.warn("Unknown shape type"); } ClientAnchor clientAnchor = null; for (int i = 0; i < children.length && clientAnchor == null; i++) { if (children[i].getType() == EscherRecordType.CLIENT_ANCHOR) { clientAnchor = (ClientAnchor) children[i]; } } if (clientAnchor == null) { logger.warn("Client anchor not found"); } else { column = (int) clientAnchor.getX1(); row = (int) clientAnchor.getY1(); } initialized = true; } /** * Sets the object id. Invoked by the drawing group when the object is * added to id * * @param objid the object id * @param bip the blip id * @param sid the shape id */ public final void setObjectId(int objid, int bip, int sid) { objectId = objid; blipId = bip; shapeId = sid; if (origin == Origin.READ) { origin = Origin.READ_WRITE; } } /** * Accessor for the object id * * @return the object id */ public final int getObjectId() { if (!initialized) { initialize(); } return objectId; } /** * Accessor for the shape id * * @return the object id */ public final int getShapeId() { if (!initialized) { initialize(); } return shapeId; } /** * Accessor for the blip id * * @return the blip id */ public final int getBlipId() { if (!initialized) { initialize(); } return blipId; } /** * Gets the drawing record which was read in * * @return the drawing record */ public MsoDrawingRecord getMsoDrawingRecord() { return msoDrawingRecord; } /** * Creates the main Sp container for the drawing * * @return the SP container */ public EscherContainer getSpContainer() { if (!initialized) { initialize(); } if (origin == Origin.READ) { return getReadSpContainer(); } SpContainer spc = new SpContainer(); Sp sp = new Sp(type, shapeId, 2560); spc.add(sp); Opt opt = new Opt(); opt.addProperty(127, false, false, 17039620); opt.addProperty(191, false, false, 524296); opt.addProperty(511, false, false, 524288); opt.addProperty(959, false, false, 131072); // opt.addProperty(260, true, false, blipId); // opt.addProperty(261, false, false, 36); spc.add(opt); ClientAnchor clientAnchor = new ClientAnchor(column, row, column + 1, row + 1, 0x1); spc.add(clientAnchor); ClientData clientData = new ClientData(); spc.add(clientData); return spc; } /** * Sets the drawing group for this drawing. Called by the drawing group * when this drawing is added to it * * @param dg the drawing group */ public void setDrawingGroup(DrawingGroup dg) { drawingGroup = dg; } /** * Accessor for the drawing group * * @return the drawing group */ public DrawingGroup getDrawingGroup() { return drawingGroup; } /** * Gets the origin of this drawing * * @return where this drawing came from */ public Origin getOrigin() { return origin; } /** * Accessor for the reference count on this drawing * * @return the reference count */ public int getReferenceCount() { return referenceCount; } /** * Sets the new reference count on the drawing * * @param r the new reference count */ public void setReferenceCount(int r) { referenceCount = r; } /** * Accessor for the column of this drawing * * @return the column */ public double getX() { if (!initialized) { initialize(); } return column; } /** * Sets the column position of this drawing. Used when inserting/removing * columns from the spreadsheet * * @param x the column */ public void setX(double x) { if (origin == Origin.READ) { if (!initialized) { initialize(); } origin = Origin.READ_WRITE; } column = (int) x; } /** * Accessor for the row of this drawing * * @return the row */ public double getY() { if (!initialized) { initialize(); } return row; } /** * Accessor for the row of the drawing * * @param y the row */ public void setY(double y) { if (origin == Origin.READ) { if (!initialized) { initialize(); } origin = Origin.READ_WRITE; } row = (int) y; } /** * Accessor for the width of this drawing * * @return the number of columns spanned by this image */ public double getWidth() { if (!initialized) { initialize(); } return width; } /** * Accessor for the width * * @param w the number of columns to span */ public void setWidth(double w) { if (origin == Origin.READ) { if (!initialized) { initialize(); } origin = Origin.READ_WRITE; } width = w; } /** * Accessor for the height of this drawing * * @return the number of rows spanned by this image */ public double getHeight() { if (!initialized) { initialize(); } return height; } /** * Accessor for the height of this drawing * * @param h the number of rows spanned by this image */ public void setHeight(double h) { if (origin == Origin.READ) { if (!initialized) { initialize(); } origin = Origin.READ_WRITE; } height = h; } /** * Gets the SpContainer that was read in * * @return the read sp container */ private EscherContainer getReadSpContainer() { if (!initialized) { initialize(); } return readSpContainer; } /** * Accessor for the image data * * @return the image data */ public byte[] getImageData() { Assert.verify(origin == Origin.READ || origin == Origin.READ_WRITE); if (!initialized) { initialize(); } return drawingGroup.getImageData(blipId); } /** * Accessor for the type * * @return the type */ public ShapeType getType() { return type; } /** * Accessor for the image data * * @return the image data */ public byte[] getImageBytes() { Assert.verify(false); return null; } /** * Accessor for the image file path. Normally this is the absolute path * of a file on the directory system, but if this drawing was constructed * using an byte[] then the blip id is returned * * @return the image file path, or the blip id */ public String getImageFilePath() { Assert.verify(false); return null; } /** * Writes out the additional records for a combo box * * @param outputFile the output file * @exception IOException */ public void writeAdditionalRecords(File outputFile) throws IOException { if (origin == Origin.READ) { outputFile.write(objRecord); if (mso != null) { outputFile.write(mso); } outputFile.write(txo); outputFile.write(text); if (formatting != null) { outputFile.write(formatting); } return; } // Create the obj record ObjRecord objrec = new ObjRecord(objectId, ObjRecord.CHECKBOX); outputFile.write(objrec); logger.warn("Writing of additional records for checkboxes not " + "implemented"); } /** * Writes any records that need to be written after all the drawing group * objects have been written * Writes out all the note records * * @param outputFile the output file */ public void writeTailRecords(File outputFile) { } /** * Accessor for the row * * @return the row */ public int getRow() { return 0; } /** * Accessor for the column * * @return the column */ public int getColumn() { return 0; } /** * Hashing algorithm * * @return the hash code */ public int hashCode() { return getClass().getName().hashCode(); } /** * Accessor for the first drawing on the sheet. This is used when * copying unmodified sheets to indicate that this drawing contains * the first time Escher gubbins * * @return TRUE if this MSORecord is the first drawing on the sheet */ public boolean isFirst() { return msoDrawingRecord.isFirst(); } /** * Queries whether this object is a form object. Form objects have their * drawings records spread over TXO and CONTINUE records and * require special handling * * @return TRUE if this is a form object, FALSE otherwise */ public boolean isFormObject() { return false; } /** * Sets the text object * * @param t the text object record */ public void setTextObject(TextObjectRecord t) { txo = t; } /** * Sets the text data * * @param t continuation record */ public void setText(ContinueRecord t) { text = t; } /** * Sets the formatting * * @param t continue record */ public void setFormatting(ContinueRecord t) { formatting = t; } /** * The drawing record * * @param d the drawing record */ public void addMso(MsoDrawingRecord d) { mso = d; drawingData.addRawData(mso.getData()); } } jexcelapi/src/jxl/biff/drawing/Drawing2.java0000750000175000017500000003131411207000612021150 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2006 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.drawing; import java.io.FileInputStream; import java.io.IOException; import jxl.common.Assert; import jxl.common.Logger; import jxl.write.biff.File; /** * Contains the various biff records used to insert a drawing into a * worksheet. This type of image does not have an associated object * record */ public class Drawing2 implements DrawingGroupObject { /** * The logger */ private static Logger logger = Logger.getLogger(Drawing.class); /** * The spContainer that was read in */ private EscherContainer readSpContainer; /** * The MsoDrawingRecord associated with the drawing */ private MsoDrawingRecord msoDrawingRecord; /** * Initialized flag */ private boolean initialized = false; /** * The file containing the image */ private java.io.File imageFile; /** * The raw image data, used instead of an image file */ private byte[] imageData; /** * The object id, assigned by the drawing group */ private int objectId; /** * The blip id */ private int blipId; /** * The column position of the image */ private double x; /** * The row position of the image */ private double y; /** * The width of the image in cells */ private double width; /** * The height of the image in cells */ private double height; /** * The number of places this drawing is referenced */ private int referenceCount; /** * The top level escher container */ private EscherContainer escherData; /** * Where this image came from (read, written or a copy) */ private Origin origin; /** * The drawing group for all the images */ private DrawingGroup drawingGroup; /** * The drawing data */ private DrawingData drawingData; /** * The type of this drawing object */ private ShapeType type; /** * The shape id */ private int shapeId; /** * The drawing position on the sheet */ private int drawingNumber; /** * Constructor used when reading images * * @param mso the drawing record * @param dd the drawing data for all drawings on this sheet * @param dg the drawing group */ public Drawing2(MsoDrawingRecord mso, DrawingData dd, DrawingGroup dg) { drawingGroup = dg; msoDrawingRecord = mso; drawingData = dd; initialized = false; origin = Origin.READ; // there is no drawing number associated with this drawing drawingData.addRawData(msoDrawingRecord.getData()); drawingGroup.addDrawing(this); Assert.verify(mso != null); initialize(); } /** * Copy constructor used to copy drawings from read to write * * @param dgo the drawing group object * @param dg the drawing group */ protected Drawing2(DrawingGroupObject dgo, DrawingGroup dg) { Drawing2 d = (Drawing2) dgo; Assert.verify(d.origin == Origin.READ); msoDrawingRecord = d.msoDrawingRecord; initialized = false; origin = Origin.READ; drawingData = d.drawingData; drawingGroup = dg; drawingNumber = d.drawingNumber; drawingGroup.addDrawing(this); } /** * Constructor invoked when writing the images * * @param x the column * @param y the row * @param w the width in cells * @param h the height in cells * @param image the image file */ public Drawing2(double x, double y, double w, double h, java.io.File image) { imageFile = image; initialized = true; origin = Origin.WRITE; this.x = x; this.y = y; this.width = w; this.height = h; referenceCount = 1; type = ShapeType.PICTURE_FRAME; } /** * Constructor invoked when writing the images * * @param x the column * @param y the row * @param w the width in cells * @param h the height in cells * @param image the image data */ public Drawing2(double x, double y, double w, double h, byte[] image) { imageData = image; initialized = true; origin = Origin.WRITE; this.x = x; this.y = y; this.width = w; this.height = h; referenceCount = 1; type = ShapeType.PICTURE_FRAME; } /** * Initializes the member variables from the Escher stream data */ private void initialize() { initialized = true; } /** * Sets the object id. Invoked by the drawing group when the object is * added to id * * @param objid the object id * @param bip the blip id * @param sid the shape id */ public final void setObjectId(int objid, int bip, int sid) { objectId = objid; blipId = bip; shapeId = sid; if (origin == Origin.READ) { origin = Origin.READ_WRITE; } } /** * Accessor for the object id * * @return the object id */ public final int getObjectId() { if (!initialized) { initialize(); } return objectId; } /** * Accessor for the shape id * * @return the shape id */ public int getShapeId() { if (!initialized) { initialize(); } return shapeId; } /** * Accessor for the blip id * * @return the blip id */ public final int getBlipId() { if (!initialized) { initialize(); } return blipId; } /** * Gets the drawing record which was read in * * @return the drawing record */ public MsoDrawingRecord getMsoDrawingRecord() { return msoDrawingRecord; } /** * Creates the main Sp container for the drawing * * @return the SP container */ public EscherContainer getSpContainer() { if (!initialized) { initialize(); } Assert.verify(origin == Origin.READ); return getReadSpContainer(); } /** * Sets the drawing group for this drawing. Called by the drawing group * when this drawing is added to it * * @param dg the drawing group */ public void setDrawingGroup(DrawingGroup dg) { drawingGroup = dg; } /** * Accessor for the drawing group * * @return the drawing group */ public DrawingGroup getDrawingGroup() { return drawingGroup; } /** * Gets the origin of this drawing * * @return where this drawing came from */ public Origin getOrigin() { return origin; } /** * Accessor for the reference count on this drawing * * @return the reference count */ public int getReferenceCount() { return referenceCount; } /** * Sets the new reference count on the drawing * * @param r the new reference count */ public void setReferenceCount(int r) { referenceCount = r; } /** * Accessor for the column of this drawing * * @return the column */ public double getX() { if (!initialized) { initialize(); } return x; } /** * Sets the column position of this drawing * * @param x the column */ public void setX(double x) { if (origin == Origin.READ) { if (!initialized) { initialize(); } origin = Origin.READ_WRITE; } this.x = x; } /** * Accessor for the row of this drawing * * @return the row */ public double getY() { if (!initialized) { initialize(); } return y; } /** * Accessor for the row of the drawing * * @param y the row */ public void setY(double y) { if (origin == Origin.READ) { if (!initialized) { initialize(); } origin = Origin.READ_WRITE; } this.y = y; } /** * Accessor for the width of this drawing * * @return the number of columns spanned by this image */ public double getWidth() { if (!initialized) { initialize(); } return width; } /** * Accessor for the width * * @param w the number of columns to span */ public void setWidth(double w) { if (origin == Origin.READ) { if (!initialized) { initialize(); } origin = Origin.READ_WRITE; } width = w; } /** * Accessor for the height of this drawing * * @return the number of rows spanned by this image */ public double getHeight() { if (!initialized) { initialize(); } return height; } /** * Accessor for the height of this drawing * * @param h the number of rows spanned by this image */ public void setHeight(double h) { if (origin == Origin.READ) { if (!initialized) { initialize(); } origin = Origin.READ_WRITE; } height = h; } /** * Gets the SpContainer that was read in * * @return the read sp container */ private EscherContainer getReadSpContainer() { if (!initialized) { initialize(); } return readSpContainer; } /** * Accessor for the image data * * @return the image data */ public byte[] getImageData() { Assert.verify(false); Assert.verify(origin == Origin.READ || origin == Origin.READ_WRITE); if (!initialized) { initialize(); } return drawingGroup.getImageData(blipId); } /** * Accessor for the image data * * @return the image data */ public byte[] getImageBytes() throws IOException { Assert.verify(false); if (origin == Origin.READ || origin == Origin.READ_WRITE) { return getImageData(); } Assert.verify(origin == Origin.WRITE); if (imageFile == null) { Assert.verify(imageData != null); return imageData; } byte[] data = new byte[(int) imageFile.length()]; FileInputStream fis = new FileInputStream(imageFile); fis.read(data, 0, data.length); fis.close(); return data; } /** * Accessor for the type * * @return the type */ public ShapeType getType() { return type; } /** * Writes any other records associated with this drawing group object * * @param outputFile the output file * @exception IOException */ public void writeAdditionalRecords(File outputFile) throws IOException { // no records to write } /** * Writes any records that need to be written after all the drawing group * objects have been written * Does nothing here * * @param outputFile the output file * @exception IOException */ public void writeTailRecords(File outputFile) throws IOException { // does nothing } /** * Interface method * * @return the column number at which the image is positioned */ public double getColumn() { return getX(); } /** * Interface method * * @return the row number at which the image is positions */ public double getRow() { return getY(); } /** * Accessor for the first drawing on the sheet. This is used when * copying unmodified sheets to indicate that this drawing contains * the first time Escher gubbins * * @return TRUE if this MSORecord is the first drawing on the sheet */ public boolean isFirst() { return msoDrawingRecord.isFirst(); } /** * Queries whether this object is a form object. Form objects have their * drawings records spread over TXO and CONTINUE records and * require special handling * * @return TRUE if this is a form object, FALSE otherwise */ public boolean isFormObject() { return false; } /** * Removes a row * * @param r the row to be removed */ public void removeRow(int r) { if (y > r) { setY(r); } } /** * Accessor for the image file path. Normally this is the absolute path * of a file on the directory system, but if this drawing was constructed * using an byte[] then the blip id is returned * * @return the image file path, or the blip id */ public String getImageFilePath() { Assert.verify(false); return null; } } jexcelapi/src/jxl/biff/drawing/DrawingData.java0000750000175000017500000001324611267106345021704 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2004 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.drawing; import java.util.ArrayList; import jxl.common.Assert; import jxl.common.Logger; /** * Class used to concatenate all the data for the various drawing objects * into one continuous stream */ public class DrawingData implements EscherStream { /** * The logger */ private static Logger logger = Logger.getLogger(DrawingData.class); /** * The drawing data */ private byte[] drawingData; /** * The number of drawings */ private int numDrawings; /** * Initialized flag */ private boolean initialized; /** * The spgr container. The contains the SpContainer for each drawing */ private EscherRecord[] spContainers; /** * Constructor */ public DrawingData() { numDrawings = 0; drawingData = null; initialized = false; } /** * Initialization */ private void initialize() { EscherRecordData er = new EscherRecordData(this, 0); Assert.verify(er.isContainer()); EscherContainer dgContainer = new EscherContainer(er); EscherRecord[] children = dgContainer.getChildren(); children = dgContainer.getChildren(); // Dg dg = (Dg) children[0]; EscherContainer spgrContainer = null; for (int i = 0; i < children.length && spgrContainer == null; i++) { EscherRecord child = children[i]; if (child.getType() == EscherRecordType.SPGR_CONTAINER) { spgrContainer = (EscherContainer) child; } } Assert.verify(spgrContainer != null); EscherRecord[] spgrChildren = spgrContainer.getChildren(); // See if any of the spgrChildren are SpgrContainer boolean nestedContainers = false; for (int i = 0; i < spgrChildren.length && !nestedContainers; i++) { if (spgrChildren[i].getType() == EscherRecordType.SPGR_CONTAINER) { nestedContainers = true; } } // If there are no nested containers, simply set the spContainer list // to be the list of children if (!nestedContainers) { spContainers = spgrChildren; } else { // Go through the hierarchy and dig out all the Sp containers ArrayList sps = new ArrayList(); getSpContainers(spgrContainer, sps); spContainers = new EscherRecord[sps.size()]; spContainers = (EscherRecord[]) sps.toArray(spContainers); } initialized = true; } /** * Gets the sp container from the internal data * * @param spgrContainer the spgr container * @param sps the list of sp records */ private void getSpContainers(EscherContainer spgrContainer, ArrayList sps) { EscherRecord[] spgrChildren = spgrContainer.getChildren(); for (int i = 0; i < spgrChildren.length; i++) { if (spgrChildren[i].getType() == EscherRecordType.SP_CONTAINER) { sps.add(spgrChildren[i]); } else if (spgrChildren[i].getType() == EscherRecordType.SPGR_CONTAINER) { getSpContainers((EscherContainer) spgrChildren[i], sps); } else { logger.warn("Spgr Containers contains a record other than Sp/Spgr " + "containers"); } } } /** * Adds the byte stream to the drawing data * * @param data the data to add */ public void addData(byte[] data) { addRawData(data); numDrawings++; } /** * Adds the data to the array without incrementing the drawing number. * This is used by comments, which for some bizarre and inexplicable * reason split out the data * * @param data the data to add */ public void addRawData(byte[] data) { if (drawingData == null) { drawingData = data; return; } // Resize the array byte[] newArray = new byte[drawingData.length + data.length]; System.arraycopy(drawingData, 0, newArray, 0, drawingData.length); System.arraycopy(data, 0, newArray, drawingData.length, data.length); drawingData = newArray; // Dirty up this object initialized = false; } /** * Accessor for the number of drawings * * @return the current count of drawings */ final int getNumDrawings() { return numDrawings; } /** * Gets the sp container for the specified drawing number * * @param drawingNum the drawing number for which to return the spContainer * @return the spcontainer */ EscherContainer getSpContainer(int drawingNum) { if (!initialized) { initialize(); } if ( (drawingNum + 1) >= spContainers.length) { throw new DrawingDataException(); } EscherContainer spContainer = (EscherContainer) spContainers[drawingNum + 1]; Assert.verify(spContainer != null); return spContainer; } /** * Gets the data which was read in for the drawings * * @return the drawing data */ public byte[] getData() { return drawingData; } } jexcelapi/src/jxl/biff/drawing/Dgg.java0000750000175000017500000001121311207000612020170 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.drawing; import java.util.ArrayList; import jxl.common.Logger; import jxl.biff.IntegerHelper; /** * Dgg record */ class Dgg extends EscherAtom { /** * The logger */ private static Logger logger = Logger.getLogger(Dgg.class); /** * The binary data */ private byte[] data; /** * The number of clusters */ private int numClusters; /** * The maximum shape id */ private int maxShapeId; /** * The number of shapes saved */ private int shapesSaved; /** * The number of drawings saved */ private int drawingsSaved; /** * The clusters */ private ArrayList clusters; /** * The cluster structure */ static final class Cluster { /** * The drawing group id */ int drawingGroupId; /** * The something or other */ int shapeIdsUsed; /** * Constructor * * @param dgId the drawing group id * @param sids the sids */ Cluster(int dgId, int sids) { drawingGroupId = dgId; shapeIdsUsed = sids; } } /** * Constructor * * @param erd the read in data */ public Dgg(EscherRecordData erd) { super(erd); clusters = new ArrayList(); byte[] bytes = getBytes(); maxShapeId = IntegerHelper.getInt (bytes[0], bytes[1], bytes[2], bytes[3]); numClusters = IntegerHelper.getInt (bytes[4], bytes[5], bytes[6], bytes[7]); shapesSaved = IntegerHelper.getInt (bytes[8], bytes[9], bytes[10], bytes[11]); drawingsSaved = IntegerHelper.getInt (bytes[12], bytes[13], bytes[14], bytes[15]); int pos = 16; for (int i = 0; i < numClusters; i++) { int dgId = IntegerHelper.getInt(bytes[pos], bytes[pos + 1]); int sids = IntegerHelper.getInt(bytes[pos + 2], bytes[pos + 3]); Cluster c = new Cluster(dgId, sids); clusters.add(c); pos += 4; } } /** * Constructor * * @param numShapes the number of shapes * @param numDrawings the number of drawings */ public Dgg(int numShapes, int numDrawings) { super(EscherRecordType.DGG); shapesSaved = numShapes; drawingsSaved = numDrawings; clusters = new ArrayList(); } /** * Adds a cluster to this record * * @param dgid the id * @param sids the sid */ void addCluster(int dgid, int sids) { Cluster c = new Cluster(dgid, sids); clusters.add(c); } /** * Gets the data for writing out * * @return the binary data */ byte[] getData() { numClusters = clusters.size(); data = new byte[16 + numClusters * 4]; // The max shape id IntegerHelper.getFourBytes(1024 + shapesSaved, data, 0); // The number of clusters IntegerHelper.getFourBytes(numClusters, data, 4); // The number of shapes saved IntegerHelper.getFourBytes(shapesSaved, data, 8); // The number of drawings saved // IntegerHelper.getFourBytes(drawingsSaved, data, 12); IntegerHelper.getFourBytes(1, data, 12); int pos = 16; for (int i = 0; i < numClusters; i++) { Cluster c = (Cluster) clusters.get(i); IntegerHelper.getTwoBytes(c.drawingGroupId, data, pos); IntegerHelper.getTwoBytes(c.shapeIdsUsed, data, pos + 2); pos += 4; } return setHeaderData(data); } /** * Accessor for the number of shapes saved * * @return the number of shapes saved */ int getShapesSaved() { return shapesSaved; } /** * Accessor for the number of drawings saved * * @return the number of drawings saved */ int getDrawingsSaved() { return drawingsSaved; } /** * Accessor for a particular cluster * * @param i the cluster number * @return the cluster */ Cluster getCluster(int i) { return (Cluster) clusters.get(i); } } jexcelapi/src/jxl/biff/drawing/ComboBox.java0000750000175000017500000003272211207000612021207 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2006 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.drawing; import java.io.IOException; import jxl.common.Assert; import jxl.common.Logger; import jxl.WorkbookSettings; import jxl.write.biff.File; /** * Contains the various biff records used to copy a ComboBox (from the * Form toolbox) between workbook */ public class ComboBox implements DrawingGroupObject { /** * The logger */ private static Logger logger = Logger.getLogger(ComboBox.class); /** * The spContainer that was read in */ private EscherContainer readSpContainer; /** * The spContainer that was generated */ private EscherContainer spContainer; /** * The MsoDrawingRecord associated with the drawing */ private MsoDrawingRecord msoDrawingRecord; /** * The ObjRecord associated with the drawing */ private ObjRecord objRecord; /** * Initialized flag */ private boolean initialized = false; /** * The object id, assigned by the drawing group */ private int objectId; /** * The blip id */ private int blipId; /** * The shape id */ private int shapeId; /** * The column */ private int column; /** * The row position of the image */ private int row; /** * The width of the image in cells */ private double width; /** * The height of the image in cells */ private double height; /** * The number of places this drawing is referenced */ private int referenceCount; /** * The top level escher container */ private EscherContainer escherData; /** * Where this image came from (read, written or a copy) */ private Origin origin; /** * The drawing group for all the images */ private DrawingGroup drawingGroup; /** * The drawing data */ private DrawingData drawingData; /** * The type of this drawing object */ private ShapeType type; /** * The drawing position on the sheet */ private int drawingNumber; /** * The workbook settings */ private WorkbookSettings workbookSettings; /** * Constructor used when reading images * * @param mso the drawing record * @param obj the object record * @param dd the drawing data for all drawings on this sheet * @param dg the drawing group * @param ws the workbook settings */ public ComboBox(MsoDrawingRecord mso, ObjRecord obj, DrawingData dd, DrawingGroup dg, WorkbookSettings ws) { drawingGroup = dg; msoDrawingRecord = mso; drawingData = dd; objRecord = obj; initialized = false; workbookSettings = ws; origin = Origin.READ; drawingData.addData(msoDrawingRecord.getData()); drawingNumber = drawingData.getNumDrawings() - 1; drawingGroup.addDrawing(this); Assert.verify(mso != null && obj != null); initialize(); } /** * Copy constructor used to copy drawings from read to write * * @param dgo the drawing group object * @param dg the drawing group * @param ws the workbook settings */ public ComboBox(DrawingGroupObject dgo, DrawingGroup dg, WorkbookSettings ws) { ComboBox d = (ComboBox) dgo; Assert.verify(d.origin == Origin.READ); msoDrawingRecord = d.msoDrawingRecord; objRecord = d.objRecord; initialized = false; origin = Origin.READ; drawingData = d.drawingData; drawingGroup = dg; drawingNumber = d.drawingNumber; drawingGroup.addDrawing(this); workbookSettings = ws; } /** * Constructor invoked when writing images */ public ComboBox() { initialized = true; origin = Origin.WRITE; referenceCount = 1; type = ShapeType.HOST_CONTROL; } /** * Initializes the member variables from the Escher stream data */ private void initialize() { readSpContainer = drawingData.getSpContainer(drawingNumber); Assert.verify(readSpContainer != null); EscherRecord[] children = readSpContainer.getChildren(); Sp sp = (Sp) readSpContainer.getChildren()[0]; objectId = objRecord.getObjectId(); shapeId = sp.getShapeId(); type = ShapeType.getType(sp.getShapeType()); if (type == ShapeType.UNKNOWN) { logger.warn("Unknown shape type"); } ClientAnchor clientAnchor = null; for (int i = 0; i < children.length && clientAnchor == null; i++) { if (children[i].getType() == EscherRecordType.CLIENT_ANCHOR) { clientAnchor = (ClientAnchor) children[i]; } } if (clientAnchor == null) { logger.warn("Client anchor not found"); } else { column = (int) clientAnchor.getX1(); row = (int) clientAnchor.getY1(); } initialized = true; } /** * Sets the object id. Invoked by the drawing group when the object is * added to id * * @param objid the object id * @param bip the blip id * @param sid the shape id */ public final void setObjectId(int objid, int bip, int sid) { objectId = objid; blipId = bip; shapeId = sid; if (origin == Origin.READ) { origin = Origin.READ_WRITE; } } /** * Accessor for the object id * * @return the object id */ public final int getObjectId() { if (!initialized) { initialize(); } return objectId; } /** * Accessor for the shape id * * @return the object id */ public final int getShapeId() { if (!initialized) { initialize(); } return shapeId; } /** * Accessor for the blip id * * @return the blip id */ public final int getBlipId() { if (!initialized) { initialize(); } return blipId; } /** * Gets the drawing record which was read in * * @return the drawing record */ public MsoDrawingRecord getMsoDrawingRecord() { return msoDrawingRecord; } /** * Creates the main Sp container for the drawing * * @return the SP container */ public EscherContainer getSpContainer() { if (!initialized) { initialize(); } if (origin == Origin.READ) { return getReadSpContainer(); } SpContainer spc = new SpContainer(); Sp sp = new Sp(type, shapeId, 2560); spc.add(sp); Opt opt = new Opt(); opt.addProperty(127, false, false, 17039620); opt.addProperty(191, false, false, 524296); opt.addProperty(511, false, false, 524288); opt.addProperty(959, false, false, 131072); // opt.addProperty(260, true, false, blipId); // opt.addProperty(261, false, false, 36); spc.add(opt); ClientAnchor clientAnchor = new ClientAnchor(column, row, column + 1, row + 1, 0x1); spc.add(clientAnchor); ClientData clientData = new ClientData(); spc.add(clientData); return spc; } /** * Sets the drawing group for this drawing. Called by the drawing group * when this drawing is added to it * * @param dg the drawing group */ public void setDrawingGroup(DrawingGroup dg) { drawingGroup = dg; } /** * Accessor for the drawing group * * @return the drawing group */ public DrawingGroup getDrawingGroup() { return drawingGroup; } /** * Gets the origin of this drawing * * @return where this drawing came from */ public Origin getOrigin() { return origin; } /** * Accessor for the reference count on this drawing * * @return the reference count */ public int getReferenceCount() { return referenceCount; } /** * Sets the new reference count on the drawing * * @param r the new reference count */ public void setReferenceCount(int r) { referenceCount = r; } /** * Accessor for the column of this drawing * * @return the column */ public double getX() { if (!initialized) { initialize(); } return column; } /** * Sets the column position of this drawing. Used when inserting/removing * columns from the spreadsheet * * @param x the column */ public void setX(double x) { if (origin == Origin.READ) { if (!initialized) { initialize(); } origin = Origin.READ_WRITE; } column = (int) x; } /** * Accessor for the row of this drawing * * @return the row */ public double getY() { if (!initialized) { initialize(); } return row; } /** * Accessor for the row of the drawing * * @param y the row */ public void setY(double y) { if (origin == Origin.READ) { if (!initialized) { initialize(); } origin = Origin.READ_WRITE; } row = (int) y; } /** * Accessor for the width of this drawing * * @return the number of columns spanned by this image */ public double getWidth() { if (!initialized) { initialize(); } return width; } /** * Accessor for the width * * @param w the number of columns to span */ public void setWidth(double w) { if (origin == Origin.READ) { if (!initialized) { initialize(); } origin = Origin.READ_WRITE; } width = w; } /** * Accessor for the height of this drawing * * @return the number of rows spanned by this image */ public double getHeight() { if (!initialized) { initialize(); } return height; } /** * Accessor for the height of this drawing * * @param h the number of rows spanned by this image */ public void setHeight(double h) { if (origin == Origin.READ) { if (!initialized) { initialize(); } origin = Origin.READ_WRITE; } height = h; } /** * Gets the SpContainer that was read in * * @return the read sp container */ private EscherContainer getReadSpContainer() { if (!initialized) { initialize(); } return readSpContainer; } /** * Accessor for the image data * * @return the image data */ public byte[] getImageData() { Assert.verify(origin == Origin.READ || origin == Origin.READ_WRITE); if (!initialized) { initialize(); } return drawingGroup.getImageData(blipId); } /** * Accessor for the type * * @return the type */ public ShapeType getType() { return type; } /** * Accessor for the image data * * @return the image data */ public byte[] getImageBytes() { Assert.verify(false); return null; } /** * Accessor for the image file path. Normally this is the absolute path * of a file on the directory system, but if this drawing was constructed * using an byte[] then the blip id is returned * * @return the image file path, or the blip id */ public String getImageFilePath() { Assert.verify(false); return null; } /** * Writes out the additional records for a combo box * * @param outputFile the output file * @exception IOException */ public void writeAdditionalRecords(File outputFile) throws IOException { if (origin == Origin.READ) { outputFile.write(objRecord); return; } // Create the obj record ObjRecord objrec = new ObjRecord(objectId, ObjRecord.COMBOBOX); outputFile.write(objrec); } /** * Writes any records that need to be written after all the drawing group * objects have been written * Writes out all the note records * * @param outputFile the output file */ public void writeTailRecords(File outputFile) { } /** * Accessor for the row * * @return the row */ public int getRow() { return 0; } /** * Accessor for the column * * @return the column */ public int getColumn() { return 0; } /** * Hashing algorithm * * @return the hash code */ public int hashCode() { return getClass().getName().hashCode(); } /** * Accessor for the first drawing on the sheet. This is used when * copying unmodified sheets to indicate that this drawing contains * the first time Escher gubbins * * @return TRUE if this MSORecord is the first drawing on the sheet */ public boolean isFirst() { return msoDrawingRecord.isFirst(); } /** * Queries whether this object is a form object. Form objects have their * drawings records spread over TXO and CONTINUE records and * require special handling * * @return TRUE if this is a form object, FALSE otherwise */ public boolean isFormObject() { return false; } } jexcelapi/src/jxl/biff/drawing/SpgrContainer.java0000750000175000017500000000265411207000612022256 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.drawing; import jxl.common.Logger; /** * An Spgr container record in an escher stream */ class SpgrContainer extends EscherContainer { /** * The logger */ private static final Logger logger = Logger.getLogger(SpgrContainer.class); /** * Constructor used when writing */ public SpgrContainer() { super(EscherRecordType.SPGR_CONTAINER); } /** * Constructor * * @param erd the escher record data read in */ public SpgrContainer(EscherRecordData erd) { super(erd); } } jexcelapi/src/jxl/biff/drawing/ClientData.java0000750000175000017500000000305311207000612021502 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.drawing; import jxl.common.Logger; /** * The client data */ class ClientData extends EscherAtom { /** * The logger */ private static Logger logger = Logger.getLogger(ClientData.class); /** * The raw data */ private byte[] data; /** * Constructor * * @param erd the record data */ public ClientData(EscherRecordData erd) { super(erd); } /** * Constructor */ public ClientData() { super(EscherRecordType.CLIENT_DATA); } /** * Accessor for the raw data * * @return the binary data */ byte[] getData() { data = new byte[0]; return setHeaderData(data); } } jexcelapi/src/jxl/biff/drawing/BStoreContainer.java0000750000175000017500000000433511207000612022537 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.drawing; import jxl.common.Logger; /** * A BStoreContainer escher record */ class BStoreContainer extends EscherContainer { /** * The logger */ private static Logger logger = Logger.getLogger(BStoreContainer.class); /** * The number of blips inside this container */ private int numBlips; /** * Constructor used to instantiate this object when reading from an * escher stream * * @param erd the escher data */ public BStoreContainer(EscherRecordData erd) { super(erd); numBlips = getInstance(); } /** * Constructor used when writing out an escher record */ public BStoreContainer() { super(EscherRecordType.BSTORE_CONTAINER); } /** * Sets the number of drawings in this container * * @param count the number of blips */ void setNumBlips(int count) { numBlips = count; setInstance(numBlips); } /** * Accessor for the number of blips * * @return the number of blips */ public int getNumBlips() { return numBlips; } /** * Accessor for the drawing * * @param i the index number of the drawing to return * @return the drawing */ public BlipStoreEntry getDrawing(int i) { EscherRecord[] children = getChildren(); BlipStoreEntry bse = (BlipStoreEntry) children[i]; return bse; } } jexcelapi/src/jxl/biff/drawing/Button.java0000750000175000017500000004170611207000612020754 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.drawing; import java.io.IOException; import jxl.common.Assert; import jxl.common.Logger; import jxl.WorkbookSettings; import jxl.biff.ContinueRecord; import jxl.biff.IntegerHelper; import jxl.biff.StringHelper; import jxl.write.biff.File; /** * Contains the various biff records used to copy a Button (from the * Form toolbox) between workbook */ public class Button implements DrawingGroupObject { /** * The logger */ private static Logger logger = Logger.getLogger(Button.class); /** * The spContainer that was read in */ private EscherContainer readSpContainer; /** * The spContainer that was generated */ private EscherContainer spContainer; /** * The MsoDrawingRecord associated with the drawing */ private MsoDrawingRecord msoDrawingRecord; /** * The ObjRecord associated with the drawing */ private ObjRecord objRecord; /** * Initialized flag */ private boolean initialized = false; /** * The object id, assigned by the drawing group */ private int objectId; /** * The blip id */ private int blipId; /** * The shape id */ private int shapeId; /** * The column */ private int column; /** * The row position of the image */ private int row; /** * The width of the image in cells */ private double width; /** * The height of the image in cells */ private double height; /** * The number of places this drawing is referenced */ private int referenceCount; /** * The top level escher container */ private EscherContainer escherData; /** * Where this image came from (read, written or a copy) */ private Origin origin; /** * The drawing group for all the images */ private DrawingGroup drawingGroup; /** * The drawing data */ private DrawingData drawingData; /** * The type of this drawing object */ private ShapeType type; /** * The drawing position on the sheet */ private int drawingNumber; /** * An mso drawing record, which sometimes appears */ private MsoDrawingRecord mso; /** * The text object record */ private TextObjectRecord txo; /** * Text data from the first continue record */ private ContinueRecord text; /** * Formatting data from the second continue record */ private ContinueRecord formatting; /** * The comment text */ private String commentText; /** * The workbook settings */ private WorkbookSettings workbookSettings; /** * Constructor used when reading images * * @param msodr the drawing record * @param obj the object record * @param dd the drawing data for all drawings on this sheet * @param dg the drawing group * @param ws the workbook settings */ public Button(MsoDrawingRecord msodr, ObjRecord obj, DrawingData dd, DrawingGroup dg, WorkbookSettings ws) { drawingGroup = dg; msoDrawingRecord = msodr; drawingData = dd; objRecord = obj; initialized = false; workbookSettings = ws; origin = Origin.READ; drawingData.addData(msoDrawingRecord.getData()); drawingNumber = drawingData.getNumDrawings() - 1; drawingGroup.addDrawing(this); Assert.verify(msoDrawingRecord != null && objRecord != null); initialize(); } /** * Copy constructor used to copy drawings from read to write * * @param dgo the drawing group object * @param dg the drawing group * @param ws the workbook settings */ public Button(DrawingGroupObject dgo, DrawingGroup dg, WorkbookSettings ws) { Button d = (Button) dgo; Assert.verify(d.origin == Origin.READ); msoDrawingRecord = d.msoDrawingRecord; objRecord = d.objRecord; initialized = false; origin = Origin.READ; drawingData = d.drawingData; drawingGroup = dg; drawingNumber = d.drawingNumber; drawingGroup.addDrawing(this); mso = d.mso; txo = d.txo; text = d.text; formatting = d.formatting; workbookSettings = ws; } /** * Initializes the member variables from the Escher stream data */ private void initialize() { readSpContainer = drawingData.getSpContainer(drawingNumber); Assert.verify(readSpContainer != null); EscherRecord[] children = readSpContainer.getChildren(); Sp sp = (Sp) readSpContainer.getChildren()[0]; objectId = objRecord.getObjectId(); shapeId = sp.getShapeId(); type = ShapeType.getType(sp.getShapeType()); if (type == ShapeType.UNKNOWN) { logger.warn("Unknown shape type"); } ClientAnchor clientAnchor = null; for (int i = 0; i < children.length && clientAnchor == null; i++) { if (children[i].getType() == EscherRecordType.CLIENT_ANCHOR) { clientAnchor = (ClientAnchor) children[i]; } } if (clientAnchor == null) { logger.warn("Client anchor not found"); } else { column = (int) clientAnchor.getX1() - 1; row = (int) clientAnchor.getY1() + 1; } initialized = true; } /** * Sets the object id. Invoked by the drawing group when the object is * added to id * * @param objid the object id * @param bip the blip id * @param sid the shape id */ public final void setObjectId(int objid, int bip, int sid) { objectId = objid; blipId = bip; shapeId = sid; if (origin == Origin.READ) { origin = Origin.READ_WRITE; } } /** * Accessor for the object id * * @return the object id */ public final int getObjectId() { if (!initialized) { initialize(); } return objectId; } /** * Accessor for the shape id * * @return the object id */ public final int getShapeId() { if (!initialized) { initialize(); } return shapeId; } /** * Accessor for the blip id * * @return the blip id */ public final int getBlipId() { if (!initialized) { initialize(); } return blipId; } /** * Gets the drawing record which was read in * * @return the drawing record */ public MsoDrawingRecord getMsoDrawingRecord() { return msoDrawingRecord; } /** * Creates the main Sp container for the drawing * * @return the SP container */ public EscherContainer getSpContainer() { if (!initialized) { initialize(); } if (origin == Origin.READ) { return getReadSpContainer(); } Assert.verify(false); /* if (spContainer == null) { spContainer = new SpContainer(); Sp sp = new Sp(type, shapeId, 2560); spContainer.add(sp); Opt opt = new Opt(); opt.addProperty(344, false, false, 0); // ? opt.addProperty(385, false, false, 134217808); // fill colour opt.addProperty(387, false, false, 134217808); // background colour opt.addProperty(959, false, false, 131074); // hide spContainer.add(opt); ClientAnchor clientAnchor = new ClientAnchor(column + 1.3, Math.max(0, row - 0.6), column+3, row + 4); spContainer.add(clientAnchor); ClientData clientData = new ClientData(); spContainer.add(clientData); ClientTextBox clientTextBox = new ClientTextBox(); spContainer.add(clientTextBox); } */ return spContainer; } /** * Sets the drawing group for this drawing. Called by the drawing group * when this drawing is added to it * * @param dg the drawing group */ public void setDrawingGroup(DrawingGroup dg) { drawingGroup = dg; } /** * Accessor for the drawing group * * @return the drawing group */ public DrawingGroup getDrawingGroup() { return drawingGroup; } /** * Gets the origin of this drawing * * @return where this drawing came from */ public Origin getOrigin() { return origin; } /** * Accessor for the reference count on this drawing * * @return the reference count */ public int getReferenceCount() { return referenceCount; } /** * Sets the new reference count on the drawing * * @param r the new reference count */ public void setReferenceCount(int r) { referenceCount = r; } /** * Accessor for the column of this drawing * * @return the column */ public double getX() { if (!initialized) { initialize(); } return column; } /** * Sets the column position of this drawing. Used when inserting/removing * columns from the spreadsheet * * @param x the column */ public void setX(double x) { if (origin == Origin.READ) { if (!initialized) { initialize(); } origin = Origin.READ_WRITE; } column = (int) x; } /** * Accessor for the row of this drawing * * @return the row */ public double getY() { if (!initialized) { initialize(); } return row; } /** * Accessor for the row of the drawing * * @param y the row */ public void setY(double y) { if (origin == Origin.READ) { if (!initialized) { initialize(); } origin = Origin.READ_WRITE; } row = (int) y; } /** * Accessor for the width of this drawing * * @return the number of columns spanned by this image */ public double getWidth() { if (!initialized) { initialize(); } return width; } /** * Accessor for the width * * @param w the number of columns to span */ public void setWidth(double w) { if (origin == Origin.READ) { if (!initialized) { initialize(); } origin = Origin.READ_WRITE; } width = w; } /** * Accessor for the height of this drawing * * @return the number of rows spanned by this image */ public double getHeight() { if (!initialized) { initialize(); } return height; } /** * Accessor for the height of this drawing * * @param h the number of rows spanned by this image */ public void setHeight(double h) { if (origin == Origin.READ) { if (!initialized) { initialize(); } origin = Origin.READ_WRITE; } height = h; } /** * Gets the SpContainer that was read in * * @return the read sp container */ private EscherContainer getReadSpContainer() { if (!initialized) { initialize(); } return readSpContainer; } /** * Accessor for the image data * * @return the image data */ public byte[] getImageData() { Assert.verify(origin == Origin.READ || origin == Origin.READ_WRITE); if (!initialized) { initialize(); } return drawingGroup.getImageData(blipId); } /** * Accessor for the type * * @return the type */ public ShapeType getType() { return type; } /** * Sets the text object * * @param t the text object record */ public void setTextObject(TextObjectRecord t) { txo = t; } /** * Sets the text data * * @param t continuation record */ public void setText(ContinueRecord t) { text = t; } /** * Sets the formatting * * @param t continue record */ public void setFormatting(ContinueRecord t) { formatting = t; } /** * Accessor for the image data * * @return the image data */ public byte[] getImageBytes() { Assert.verify(false); return null; } /** * Accessor for the image file path. Normally this is the absolute path * of a file on the directory system, but if this drawing was constructed * using an byte[] then the blip id is returned * * @return the image file path, or the blip id */ public String getImageFilePath() { Assert.verify(false); return null; } /** * The drawing record * * @param d the drawing record */ public void addMso(MsoDrawingRecord d) { mso = d; drawingData.addRawData(mso.getData()); } /** * Writes out any additional records * * @param outputFile the output file * @exception IOException */ public void writeAdditionalRecords(File outputFile) throws IOException { if (origin == Origin.READ) { outputFile.write(objRecord); if (mso != null) { outputFile.write(mso); } outputFile.write(txo); outputFile.write(text); if (formatting != null) { outputFile.write(formatting); } return; } Assert.verify(false); // Create the obj record ObjRecord objrec = new ObjRecord(objectId, ObjRecord.EXCELNOTE); outputFile.write(objrec); // Create the mso data record. Write the text box record again, // although it is already included in the SpContainer ClientTextBox textBox = new ClientTextBox(); MsoDrawingRecord msod = new MsoDrawingRecord(textBox.getData()); outputFile.write(msod); TextObjectRecord tor = new TextObjectRecord(getText()); outputFile.write(tor); // Data for the first continue record byte[] textData = new byte[commentText.length() * 2 + 1]; textData[0] = 0x1; // unicode indicator StringHelper.getUnicodeBytes(commentText, textData, 1); //StringHelper.getBytes(commentText, textData, 1); ContinueRecord textContinue = new ContinueRecord(textData); outputFile.write(textContinue); // Data for the formatting runs byte[] frData = new byte[16]; // First txo run (the user) IntegerHelper.getTwoBytes(0, frData, 0); // index to the first character IntegerHelper.getTwoBytes(0, frData, 2); // index to the font(default) // Mandatory last txo run IntegerHelper.getTwoBytes(commentText.length(), frData, 8); IntegerHelper.getTwoBytes(0, frData, 10); // index to the font(default) ContinueRecord frContinue = new ContinueRecord(frData); outputFile.write(frContinue); } /** * Writes any records that need to be written after all the drawing group * objects have been written * Writes out all the note records * * @param outputFile the output file */ public void writeTailRecords(File outputFile) { } /** * Accessor for the row. As buttons are not associated with a cell, * does nothing here * * @return the row number */ public int getRow() { return 0; } /** * Accessor for the column. As buttons are not associated with a cell, * does nothing here * * @return the column number */ public int getColumn() { return 0; } /** * Accessor for the text on the button * * @return the button text */ public String getText() { if (commentText == null) { Assert.verify(text != null); byte[] td = text.getData(); if (td[0] == 0) { commentText = StringHelper.getString (td, td.length - 1, 1, workbookSettings); } else { commentText = StringHelper.getUnicodeString (td, (td.length - 1) / 2, 1); } } return commentText; } /** * Hashing algorithm * * @return the hash code */ public int hashCode() { return commentText.hashCode(); } /** * Called when the comment text is changed during the sheet copy process * * @param t the new text */ public void setButtonText(String t) { commentText = t; if (origin == Origin.READ) { origin = Origin.READ_WRITE; } } /** * Accessor for the first drawing on the sheet. This is used when * copying unmodified sheets to indicate that this drawing contains * the first time Escher gubbins * * @return TRUE if this MSORecord is the first drawing on the sheet */ public boolean isFirst() { return mso.isFirst(); } /** * Queries whether this object is a form object. Form objects have their * drawings records spread over TXO and CONTINUE records and * require special handling * * @return TRUE if this is a form object, FALSE otherwise */ public boolean isFormObject() { return true; } } jexcelapi/src/jxl/biff/DataValiditySettingsRecord.java0000750000175000017500000001367511234606732023330 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2004 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; import jxl.common.Assert; import jxl.common.Logger; import jxl.WorkbookSettings; import jxl.biff.WorkbookMethods; import jxl.biff.formula.ExternalSheet; import jxl.biff.formula.FormulaException; import jxl.read.biff.Record; /** * Data validity settings. Contains an individual Data validation (DV). * All the computationa work is delegated to the DVParser object */ public class DataValiditySettingsRecord extends WritableRecordData { /** * The logger */ private static Logger logger = Logger.getLogger(DataValiditySettingsRecord.class); /** * The binary data */ private byte[] data; /** * The reader */ private DVParser dvParser; /** * Handle to the workbook */ private WorkbookMethods workbook; /** * Handle to the externalSheet */ private ExternalSheet externalSheet; /** * Handle to the workbook settings */ private WorkbookSettings workbookSettings; /** * Handle to the data validation record */ private DataValidation dataValidation; /** * Constructor */ public DataValiditySettingsRecord(Record t, ExternalSheet es, WorkbookMethods wm, WorkbookSettings ws) { super(t); data = t.getData(); externalSheet = es; workbook = wm; workbookSettings = ws; } /** * Copy constructor */ DataValiditySettingsRecord(DataValiditySettingsRecord dvsr) { super(Type.DV); data = dvsr.getData(); } /** * Constructor used when copying sheets * * @param dvsr the record copied from a writable sheet */ DataValiditySettingsRecord(DataValiditySettingsRecord dvsr, ExternalSheet es, WorkbookMethods w, WorkbookSettings ws) { super(Type.DV); workbook = w; externalSheet = es; workbookSettings = ws; Assert.verify(w != null); Assert.verify(es != null); data = new byte[dvsr.data.length]; System.arraycopy(dvsr.data, 0, data, 0, data.length); } /** * Constructor called when the API creates a writable data validation * * @param dvsr the record copied from a writable sheet */ public DataValiditySettingsRecord(DVParser dvp) { super(Type.DV); dvParser = dvp; } /** * Initializes the dvParser */ private void initialize() { if (dvParser == null) { dvParser = new DVParser(data, externalSheet, workbook, workbookSettings); } } /** * Retrieves the data for output to binary file * * @return the data to be written */ public byte[] getData() { if (dvParser == null) { return data; } return dvParser.getData(); } /** * Inserts a row * * @param row the row to insert */ public void insertRow(int row) { if (dvParser == null) { initialize(); } dvParser.insertRow(row); } /** * Removes a row * * @param row the row to insert */ public void removeRow(int row) { if (dvParser == null) { initialize(); } dvParser.removeRow(row); } /** * Inserts a row * * @param col the row to insert */ public void insertColumn(int col) { if (dvParser == null) { initialize(); } dvParser.insertColumn(col); } /** * Removes a column * * @param col the row to insert */ public void removeColumn(int col) { if (dvParser == null) { initialize(); } dvParser.removeColumn(col); } /** * Accessor for first column * * @return the first column */ public int getFirstColumn() { if (dvParser == null) { initialize(); } return dvParser.getFirstColumn(); } /** * Accessor for the last column * * @return the last column */ public int getLastColumn() { if (dvParser == null) { initialize(); } return dvParser.getLastColumn(); } /** * Accessor for first row * * @return the first row */ public int getFirstRow() { if (dvParser == null) { initialize(); } return dvParser.getFirstRow(); } /** * Accessor for the last row * * @return the last row */ public int getLastRow() { if (dvParser == null) { initialize(); } return dvParser.getLastRow(); } /** * Sets the handle to the data validation record * * @param dv the data validation */ void setDataValidation(DataValidation dv) { dataValidation = dv; } /** * Gets the DVParser. This is used when doing a deep copy of cells * on the writable side of things */ DVParser getDVParser() { return dvParser; } public String getValidationFormula() { try { if (dvParser == null) { initialize(); } return dvParser.getValidationFormula(); } catch (FormulaException e) { logger.warn("Cannot read drop down range " + e.getMessage()); return ""; } } } jexcelapi/src/jxl/biff/RecordData.java0000750000175000017500000000343211207000612020050 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; import jxl.read.biff.Record; /** * The record data within a record */ public abstract class RecordData { /** * The raw data */ private Record record; /** * The Biff code for this record. This is set up when the record is * used for writing */ private int code; /** * Constructs this object from the raw data * * @param r the raw data */ protected RecordData(Record r) { record = r; code = r.getCode(); } /** * Constructor used by the writable records * * @param t the type */ protected RecordData(Type t) { code = t.value; } /** * Returns the raw data to its subclasses * * @return the raw data */ protected Record getRecord() { return record; } /** * Accessor for the code * * @return the code */ protected final int getCode() { return code; } } jexcelapi/src/jxl/biff/BuiltInName.java0000750000175000017500000000644611207000612020217 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2006 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; /** * Enumeration of built in names */ public class BuiltInName { /** * The name */ private String name; /** * The value */ private int value; /** * The list of name */ private static BuiltInName[] builtInNames = new BuiltInName[0]; /** * Constructor */ private BuiltInName(String n, int v) { name = n; value = v; BuiltInName[] oldnames = builtInNames; builtInNames = new BuiltInName[oldnames.length + 1]; System.arraycopy(oldnames, 0, builtInNames, 0, oldnames.length); builtInNames[oldnames.length] = this; } /** * Accessor for the name * * @return the name */ public String getName() { return name; } /** * Accessor for the value * * @return the value */ public int getValue() { return value; } /** * Gets the built in name for the value */ public static BuiltInName getBuiltInName(int val) { BuiltInName ret = FILTER_DATABASE; for (int i = 0 ; i < builtInNames.length; i++) { if (builtInNames[i].getValue() == val) { ret = builtInNames[i]; } } return ret; } // The list of built in names public static final BuiltInName CONSOLIDATE_AREA = new BuiltInName("Consolidate_Area", 0x0); public static final BuiltInName AUTO_OPEN = new BuiltInName("Auto_Open", 0x1); public static final BuiltInName AUTO_CLOSE = new BuiltInName("Auto_Open", 0x2); public static final BuiltInName EXTRACT = new BuiltInName("Extract", 0x3); public static final BuiltInName DATABASE = new BuiltInName("Database", 0x4); public static final BuiltInName CRITERIA = new BuiltInName("Criteria", 0x5); public static final BuiltInName PRINT_AREA = new BuiltInName("Print_Area", 0x6); public static final BuiltInName PRINT_TITLES = new BuiltInName("Print_Titles", 0x7); public static final BuiltInName RECORDER = new BuiltInName("Recorder", 0x8); public static final BuiltInName DATA_FORM = new BuiltInName("Data_Form", 0x9); public static final BuiltInName AUTO_ACTIVATE = new BuiltInName("Auto_Activate", 0xa); public static final BuiltInName AUTO_DEACTIVATE = new BuiltInName("Auto_Deactivate", 0xb); public static final BuiltInName SHEET_TITLE = new BuiltInName("Sheet_Title", 0xb); public static final BuiltInName FILTER_DATABASE = new BuiltInName("_FilterDatabase", 0xd); } jexcelapi/src/jxl/biff/FormatRecord.java0000750000175000017500000003560211207000612020433 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; import java.text.DateFormat; import java.text.DecimalFormat; import java.text.NumberFormat; import java.text.SimpleDateFormat; import jxl.common.Logger; import jxl.WorkbookSettings; import jxl.format.Format; import jxl.read.biff.Record; /** * A non-built in format record */ public class FormatRecord extends WritableRecordData implements DisplayFormat, Format { /** * The logger */ public static Logger logger = Logger.getLogger(FormatRecord.class); /** * Initialized flag */ private boolean initialized; /** * The raw data */ private byte[] data; /** * The index code */ private int indexCode; /** * The formatting string */ private String formatString; /** * Indicates whether this is a date formatting record */ private boolean date; /** * Indicates whether this a number formatting record */ private boolean number; /** * The format object */ private java.text.Format format; /** * The date strings to look for */ private static String[] dateStrings = new String[] { "dd", "mm", "yy", "hh", "ss", "m/", "/d" }; // Type to distinguish between biff7 and biff8 private static class BiffType { } public static final BiffType biff8 = new BiffType(); public static final BiffType biff7 = new BiffType(); /** * Constructor invoked when copying sheets * * @param fmt the format string * @param refno the index code */ FormatRecord(String fmt, int refno) { super(Type.FORMAT); formatString = fmt; indexCode = refno; initialized = true; } /** * Constructor used by writable formats */ protected FormatRecord() { super(Type.FORMAT); initialized = false; } /** * Copy constructor - can be invoked by public access * * @param fr the format to copy */ protected FormatRecord(FormatRecord fr) { super(Type.FORMAT); initialized = false; formatString = fr.formatString; date = fr.date; number = fr.number; // format = (java.text.Format) fr.format.clone(); } /** * Constructs this object from the raw data. Used when reading in a * format record * * @param t the raw data * @param ws the workbook settings * @param biffType biff type dummy overload */ public FormatRecord(Record t, WorkbookSettings ws, BiffType biffType) { super(t); byte[] data = getRecord().getData(); indexCode = IntegerHelper.getInt(data[0], data[1]); initialized = true; if (biffType == biff8) { int numchars = IntegerHelper.getInt(data[2], data[3]); if (data[4] == 0) { formatString = StringHelper.getString(data, numchars, 5, ws); } else { formatString = StringHelper.getUnicodeString(data, numchars, 5); } } else { int numchars = data[2]; byte[] chars = new byte[numchars]; System.arraycopy(data, 3, chars, 0, chars.length); formatString = new String(chars); } date = false; number = false; // First see if this is a date format for (int i = 0 ; i < dateStrings.length; i++) { String dateString = dateStrings[i]; if (formatString.indexOf(dateString) != -1 || formatString.indexOf(dateString.toUpperCase()) != -1) { date = true; break; } } // See if this is number format - look for the # or 0 characters if (!date) { if (formatString.indexOf('#') != -1 || formatString.indexOf('0') != -1 ) { number = true; } } } /** * Used to get the data when writing out the format record * * @return the raw data */ public byte[] getData() { data = new byte[formatString.length() * 2 + 3 + 2]; IntegerHelper.getTwoBytes(indexCode, data, 0); IntegerHelper.getTwoBytes(formatString.length(), data, 2); data[4] = (byte) 1; // unicode indicator StringHelper.getUnicodeBytes(formatString, data, 5); return data; } /** * Gets the format index of this record * * @return the format index of this record */ public int getFormatIndex() { return indexCode; } /** * Accessor to see whether this object is initialized or not. * * @return TRUE if this font record has been initialized, FALSE otherwise */ public boolean isInitialized() { return initialized; } /** * Sets the index of this record. Called from the FormattingRecords * object * * @param pos the position of this font in the workbooks font list */ public void initialize(int pos) { indexCode = pos; initialized = true; } /** * Replaces all instances of search with replace in the input. Used for * replacing microsoft number formatting characters with java equivalents * * @param input the format string * @param search the Excel character to be replaced * @param replace the java equivalent * @return the input string with the specified substring replaced */ protected final String replace(String input, String search, String replace) { String fmtstr = input; int pos = fmtstr.indexOf(search); while (pos != -1) { StringBuffer tmp = new StringBuffer(fmtstr.substring(0, pos)); tmp.append(replace); tmp.append(fmtstr.substring(pos + search.length())); fmtstr = tmp.toString(); pos = fmtstr.indexOf(search); } return fmtstr; } /** * Called by the immediate subclass to set the string * once the Java-Excel replacements have been done * * @param s the format string */ protected final void setFormatString(String s) { formatString = s; } /** * Sees if this format is a date format * * @return TRUE if this format is a date */ public final boolean isDate() { return date; } /** * Sees if this format is a number format * * @return TRUE if this format is a number */ public final boolean isNumber() { return number; } /** * Gets the java equivalent number format for the formatString * * @return The java equivalent of the number format for this object */ public final NumberFormat getNumberFormat() { if (format != null && format instanceof NumberFormat) { return (NumberFormat) format; } try { String fs = formatString; // Replace the Excel formatting characters with java equivalents fs = replace(fs, "E+", "E"); fs = replace(fs, "_)", ""); fs = replace(fs, "_", ""); fs = replace(fs, "[Red]", ""); fs = replace(fs, "\\", ""); format = new DecimalFormat(fs); } catch (IllegalArgumentException e) { // Something went wrong with the date format - fail silently // and return a default value format = new DecimalFormat("#.###"); } return (NumberFormat) format; } /** * Gets the java equivalent date format for the formatString * * @return The java equivalent of the date format for this object */ public final DateFormat getDateFormat() { if (format != null && format instanceof DateFormat) { return (DateFormat) format; } String fmt = formatString; // Replace the AM/PM indicator with an a int pos = fmt.indexOf("AM/PM"); while (pos != -1) { StringBuffer sb = new StringBuffer(fmt.substring(0, pos)); sb.append('a'); sb.append(fmt.substring(pos + 5)); fmt = sb.toString(); pos = fmt.indexOf("AM/PM"); } // Replace ss.0 with ss.SSS (necessary to always specify milliseconds // because of NT) pos = fmt.indexOf("ss.0"); while (pos != -1) { StringBuffer sb = new StringBuffer(fmt.substring(0, pos)); sb.append("ss.SSS"); // Keep going until we run out of zeros pos += 4; while (pos < fmt.length() && fmt.charAt(pos) == '0') { pos++; } sb.append(fmt.substring(pos)); fmt = sb.toString(); pos = fmt.indexOf("ss.0"); } // Filter out the backslashes StringBuffer sb = new StringBuffer(); for (int i = 0; i < fmt.length(); i++) { if (fmt.charAt(i) != '\\') { sb.append(fmt.charAt(i)); } } fmt = sb.toString(); // If the date format starts with anything inside square brackets then // filter tham out if (fmt.charAt(0) == '[') { int end = fmt.indexOf(']'); if (end != -1) { fmt = fmt.substring(end+1); } } // Get rid of some spurious characters that can creep in fmt = replace(fmt, ";@", ""); // We need to convert the month indicator m, to upper case when we // are dealing with dates char[] formatBytes = fmt.toCharArray(); for (int i = 0; i < formatBytes.length; i++) { if (formatBytes[i] == 'm') { // Firstly, see if the preceding character is also an m. If so, // copy that if (i > 0 && (formatBytes[i - 1] == 'm' || formatBytes[i - 1] == 'M')) { formatBytes[i] = formatBytes[i - 1]; } else { // There is no easy way out. We have to deduce whether this an // minute or a month? See which is closest out of the // letters H d s or y // First, h int minuteDist = Integer.MAX_VALUE; for (int j = i - 1; j > 0; j--) { if (formatBytes[j] == 'h') { minuteDist = i - j; break; } } for (int j = i + 1; j < formatBytes.length; j++) { if (formatBytes[j] == 'h') { minuteDist = Math.min(minuteDist, j - i); break; } } for (int j = i - 1; j > 0; j--) { if (formatBytes[j] == 'H') { minuteDist = i - j; break; } } for (int j = i + 1; j < formatBytes.length; j++) { if (formatBytes[j] == 'H') { minuteDist = Math.min(minuteDist, j - i); break; } } // Now repeat for s for (int j = i - 1; j > 0; j--) { if (formatBytes[j] == 's') { minuteDist = Math.min(minuteDist, i - j); break; } } for (int j = i + 1; j < formatBytes.length; j++) { if (formatBytes[j] == 's') { minuteDist = Math.min(minuteDist, j - i); break; } } // We now have the distance of the closest character which could // indicate the the m refers to a minute // Repeat for d and y int monthDist = Integer.MAX_VALUE; for (int j = i - 1; j > 0; j--) { if (formatBytes[j] == 'd') { monthDist = i - j; break; } } for (int j = i + 1; j < formatBytes.length; j++) { if (formatBytes[j] == 'd') { monthDist = Math.min(monthDist, j - i); break; } } // Now repeat for y for (int j = i - 1; j > 0; j--) { if (formatBytes[j] == 'y') { monthDist = Math.min(monthDist, i - j); break; } } for (int j = i + 1; j < formatBytes.length; j++) { if (formatBytes[j] == 'y') { monthDist = Math.min(monthDist, j - i); break; } } if (monthDist < minuteDist) { // The month indicator is closer, so convert to a capital M formatBytes[i] = Character.toUpperCase(formatBytes[i]); } else if ((monthDist == minuteDist) && (monthDist != Integer.MAX_VALUE)) { // They are equidistant. As a tie-breaker, take the formatting // character which precedes the m char ind = formatBytes[i - monthDist]; if (ind == 'y' || ind == 'd') { // The preceding item indicates a month measure, so convert formatBytes[i] = Character.toUpperCase(formatBytes[i]); } } } } } try { this.format = new SimpleDateFormat(new String(formatBytes)); } catch (IllegalArgumentException e) { // There was a spurious character - fail silently this.format = new SimpleDateFormat("dd MM yyyy hh:mm:ss"); } return (DateFormat) this.format; } /** * Gets the index code, for use as a hash value * * @return the ifmt code for this cell */ public int getIndexCode() { return indexCode; } /** * Gets the formatting string. * * @return the excel format string */ public String getFormatString() { return formatString; } /** * Indicates whether this formula is a built in * * @return FALSE */ public boolean isBuiltIn() { return false; } /** * Standard hash code method * @return the hash code value for this object */ public int hashCode() { return formatString.hashCode(); } /** * Standard equals method. This compares the contents of two * format records, and not their indexCodes, which are ignored * * @param o the object to compare * @return TRUE if the two objects are equal, FALSE otherwise */ public boolean equals(Object o) { if (o == this) { return true; } if (!(o instanceof FormatRecord)) { return false; } FormatRecord fr = (FormatRecord) o; // Initialized format comparison if (initialized && fr.initialized) { // Must be either a number or a date format if (date != fr.date || number != fr.number) { return false; } return formatString.equals(fr.formatString); } // Uninitialized format comparison return formatString.equals(fr.formatString); } } jexcelapi/src/jxl/biff/#RecordData.java#0000750000175000017500000000350111225606611020166 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; import jxl.read.biff.Record; /** * The record data within a record */ public abstract class RecordData { /** * The raw data */ private Record record; /** * Any continue records */ /** * The Biff code for this record. This is set up when the record is * used for writing */ private int code; /** * Constructs this object from the raw data * * @param r the raw data */ protected RecordData(Record r) { record = r; code = r.getCode(); } /** * Constructor used by the writable records * * @param t the type */ protected RecordData(Type t) { code = t.value; } /** * Returns the raw data to its subclasses * * @return the raw data */ protected Record getRecord() { return record; } /** * Accessor for the code * * @return the code */ protected final int getCode() { return code; } } jexcelapi/src/jxl/biff/StringHelper.java0000750000175000017500000001461611207000612020454 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; import java.io.UnsupportedEncodingException; import jxl.common.Logger; import jxl.WorkbookSettings; /** * Helper function to convert Java string objects to and from the byte * representations */ public final class StringHelper { /** * The logger */ private static Logger logger = Logger.getLogger(StringHelper.class); // Due to a a Sun bug in some versions of JVM 1.4, the UnicodeLittle // encoding doesn't always work. Making this a public static field // enables client code access to this (but in an undocumented and // unsupported fashion). Suggested alternative values for this // are "UTF-16LE" or "UnicodeLittleUnmarked" public static String UNICODE_ENCODING = "UnicodeLittle"; /** * Private default constructor to prevent instantiation */ private StringHelper() { } /** * Gets the bytes of the specified string. This will simply return the ASCII * values of the characters in the string * * @param s the string to convert into bytes * @return the ASCII values of the characters in the string * @deprecated */ public static byte[] getBytes(String s) { return s.getBytes(); } /** * Gets the bytes of the specified string. This will simply return the ASCII * values of the characters in the string * * @param s the string to convert into bytes * @return the ASCII values of the characters in the string */ public static byte[] getBytes(String s, WorkbookSettings ws) { try { return s.getBytes(ws.getEncoding()); } catch (UnsupportedEncodingException e) { // fail silently return null; } } /** * Converts the string into a little-endian array of Unicode bytes * * @param s the string to convert * @return the unicode values of the characters in the string */ public static byte[] getUnicodeBytes(String s) { try { byte[] b = s.getBytes(UNICODE_ENCODING); // Sometimes this method writes out the unicode // identifier if (b.length == (s.length() * 2 + 2)) { byte[] b2 = new byte[b.length - 2]; System.arraycopy(b, 2, b2, 0, b2.length); b = b2; } return b; } catch (UnsupportedEncodingException e) { // Fail silently return null; } } /** * Gets the ASCII bytes from the specified string and places them in the * array at the specified position * * @param pos the position at which to place the converted data * @param s the string to convert * @param d the byte array which will contain the converted string data */ public static void getBytes(String s, byte[] d, int pos) { byte[] b = getBytes(s); System.arraycopy(b, 0, d, pos, b.length); } /** * Inserts the unicode byte representation of the specified string into the * array passed in * * @param pos the position at which to insert the converted data * @param s the string to convert * @param d the byte array which will hold the string data */ public static void getUnicodeBytes(String s, byte[] d, int pos) { byte[] b = getUnicodeBytes(s); System.arraycopy(b, 0, d, pos, b.length); } /** * Gets a string from the data array using the character encoding for * this workbook * * @param pos The start position of the string * @param length The number of bytes to transform into a string * @param d The byte data * @param ws the workbook settings * @return the string built up from the raw bytes */ public static String getString(byte[] d, int length, int pos, WorkbookSettings ws) { if( length == 0 ) { return ""; // Reduces number of new Strings } try { return new String(d, pos, length, ws.getEncoding()); // byte[] b = new byte[length]; // System.arraycopy(d, pos, b, 0, length); // return new String(b, ws.getEncoding()); } catch (UnsupportedEncodingException e) { logger.warn(e.toString()); return ""; } } /** * Gets a string from the data array * * @param pos The start position of the string * @param length The number of characters to be converted into a string * @param d The byte data * @return the string built up from the unicode characters */ public static String getUnicodeString(byte[] d, int length, int pos) { try { byte[] b = new byte[length * 2]; System.arraycopy(d, pos, b, 0, length * 2); return new String(b, UNICODE_ENCODING); } catch (UnsupportedEncodingException e) { // Fail silently return ""; } } /** * Replaces all instances of search with replace in the input. * Even though later versions of java can use string.replace() * this is included Java 1.2 compatibility * * @param input the format string * @param search the Excel character to be replaced * @param replace the java equivalent * @return the input string with the specified substring replaced */ public static final String replace(String input, String search, String replace) { String fmtstr = input; int pos = fmtstr.indexOf(search); while (pos != -1) { StringBuffer tmp = new StringBuffer(fmtstr.substring(0, pos)); tmp.append(replace); tmp.append(fmtstr.substring(pos + search.length())); fmtstr = tmp.toString(); pos = fmtstr.indexOf(search, pos+replace.length()); } return fmtstr; } } jexcelapi/src/jxl/biff/HeaderFooter.java0000750000175000017500000004002711262604012020415 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2004 Andrew Khan, Eric Jung * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; import jxl.common.Logger; /** * Class which represents an Excel header or footer. Information for this * class came from Microsoft Knowledge Base Article 142136 * (previously Q142136). * * This class encapsulates three internal structures representing the header * or footer contents which appear on the left, right or central part of the * page */ public abstract class HeaderFooter { /** * The logger */ private static Logger logger = Logger.getLogger(HeaderFooter.class); // Codes to format text /** * Turns bold printing on or off */ private static final String BOLD_TOGGLE = "&B"; /** * Turns underline printing on or off */ private static final String UNDERLINE_TOGGLE = "&U"; /** * Turns italic printing on or off */ private static final String ITALICS_TOGGLE = "&I"; /** * Turns strikethrough printing on or off */ private static final String STRIKETHROUGH_TOGGLE = "&S"; /** * Turns double-underline printing on or off */ private static final String DOUBLE_UNDERLINE_TOGGLE = "&E"; /** * Turns superscript printing on or off */ private static final String SUPERSCRIPT_TOGGLE = "&X"; /** * Turns subscript printing on or off */ private static final String SUBSCRIPT_TOGGLE = "&Y"; /** * Turns outline printing on or off (Macintosh only) */ private static final String OUTLINE_TOGGLE = "&O"; /** * Turns shadow printing on or off (Macintosh only) */ private static final String SHADOW_TOGGLE = "&H"; /** * Left-aligns the characters that follow */ private static final String LEFT_ALIGN = "&L"; /** * Centres the characters that follow */ private static final String CENTRE = "&C"; /** * Right-aligns the characters that follow */ private static final String RIGHT_ALIGN = "&R"; // Codes to insert specific data /** * Prints the page number */ private static final String PAGENUM = "&P"; /** * Prints the total number of pages in the document */ private static final String TOTAL_PAGENUM = "&N"; /** * Prints the current date */ private static final String DATE = "&D"; /** * Prints the current time */ private static final String TIME = "&T"; /** * Prints the name of the workbook */ private static final String WORKBOOK_NAME = "&F"; /** * Prints the name of the worksheet */ private static final String WORKSHEET_NAME = "&A"; /** * The contents - a simple wrapper around a string buffer */ protected static class Contents { /** * The buffer containing the header/footer string */ private StringBuffer contents; /** * The constructor */ protected Contents() { contents = new StringBuffer(); } /** * Constructor used when reading worksheets. The string contains all * the formatting (but not alignment characters * * @param s the format string */ protected Contents(String s) { contents = new StringBuffer(s); } /** * Copy constructor * * @param copy the contents to copy */ protected Contents(Contents copy) { contents = new StringBuffer(copy.getContents()); } /** * Retrieves a Stringified * version of this object * * @return the header string */ protected String getContents() { return contents != null ? contents.toString() : ""; } /** * Internal method which appends the text to the string buffer * * @param txt */ private void appendInternal(String txt) { if (contents == null) { contents = new StringBuffer(); } contents.append(txt); } /** * Internal method which appends the text to the string buffer * * @param ch */ private void appendInternal(char ch) { if (contents == null) { contents = new StringBuffer(); } contents.append(ch); } /** * Appends the text to the string buffer * * @param txt */ protected void append(String txt) { appendInternal(txt); } /** * Turns bold printing on or off. Bold printing * is initially off. Text subsequently appended to * this object will be bolded until this method is * called again. */ protected void toggleBold() { appendInternal(BOLD_TOGGLE); } /** * Turns underline printing on or off. Underline printing * is initially off. Text subsequently appended to * this object will be underlined until this method is * called again. */ protected void toggleUnderline() { appendInternal(UNDERLINE_TOGGLE); } /** * Turns italics printing on or off. Italics printing * is initially off. Text subsequently appended to * this object will be italicized until this method is * called again. */ protected void toggleItalics() { appendInternal(ITALICS_TOGGLE); } /** * Turns strikethrough printing on or off. Strikethrough printing * is initially off. Text subsequently appended to * this object will be striked out until this method is * called again. */ protected void toggleStrikethrough() { appendInternal(STRIKETHROUGH_TOGGLE); } /** * Turns double-underline printing on or off. Double-underline printing * is initially off. Text subsequently appended to * this object will be double-underlined until this method is * called again. */ protected void toggleDoubleUnderline() { appendInternal(DOUBLE_UNDERLINE_TOGGLE); } /** * Turns superscript printing on or off. Superscript printing * is initially off. Text subsequently appended to * this object will be superscripted until this method is * called again. */ protected void toggleSuperScript() { appendInternal(SUPERSCRIPT_TOGGLE); } /** * Turns subscript printing on or off. Subscript printing * is initially off. Text subsequently appended to * this object will be subscripted until this method is * called again. */ protected void toggleSubScript() { appendInternal(SUBSCRIPT_TOGGLE); } /** * Turns outline printing on or off (Macintosh only). * Outline printing is initially off. Text subsequently appended * to this object will be outlined until this method is * called again. */ protected void toggleOutline() { appendInternal(OUTLINE_TOGGLE); } /** * Turns shadow printing on or off (Macintosh only). * Shadow printing is initially off. Text subsequently appended * to this object will be shadowed until this method is * called again. */ protected void toggleShadow() { appendInternal(SHADOW_TOGGLE); } /** * Sets the font of text subsequently appended to this * object.. Previously appended text is not affected. *

    * Note: no checking is performed to * determine if fontName is a valid font. * * @param fontName name of the font to use */ protected void setFontName(String fontName) { // Font name must be in quotations appendInternal("&\""); appendInternal(fontName); appendInternal('\"'); } /** * Sets the font size of text subsequently appended to this * object. Previously appended text is not affected. *

    * Valid point sizes are between 1 and 99 (inclusive). If * size is outside this range, this method returns false * and does not change font size. If size is within this * range, the font size is changed and true is returned. * * @param size The size in points. Valid point sizes are * between 1 and 99 (inclusive). * @return true if the font size was changed, false if font * size was not changed because 1 > size > 99. */ protected boolean setFontSize(int size) { if (size < 1 || size > 99) { return false; } // A two digit number should be used -- even if the // leading number is just a zero. String fontSize; if (size < 10) { // single-digit -- make two digit fontSize = "0" + size; } else { fontSize = Integer.toString(size); } appendInternal('&'); appendInternal(fontSize); return true; } /** * Appends the page number */ protected void appendPageNumber() { appendInternal(PAGENUM); } /** * Appends the total number of pages */ protected void appendTotalPages() { appendInternal(TOTAL_PAGENUM); } /** * Appends the current date */ protected void appendDate() { appendInternal(DATE); } /** * Appends the current time */ protected void appendTime() { appendInternal(TIME); } /** * Appends the workbook name */ protected void appendWorkbookName() { appendInternal(WORKBOOK_NAME); } /** * Appends the worksheet name */ protected void appendWorkSheetName() { appendInternal(WORKSHEET_NAME); } /** * Clears the contents of this portion */ protected void clear() { contents = null; } /** * Queries if the contents are empty * * @return TRUE if the contents are empty, FALSE otherwise */ protected boolean empty() { if (contents == null || contents.length() == 0) { return true; } else { return false; } } } /** * The left aligned header/footer contents */ private Contents left; /** * The right aligned header/footer contents */ private Contents right; /** * The centrally aligned header/footer contents */ private Contents centre; /** * Default constructor. */ protected HeaderFooter() { left = createContents(); right = createContents(); centre = createContents(); } /** * Copy constructor * * @param c the item to copy */ protected HeaderFooter(HeaderFooter hf) { left = createContents(hf.left); right = createContents(hf.right); centre = createContents(hf.centre); } /** * Constructor used when reading workbooks to separate the left, right * a central part of the strings into their constituent parts */ protected HeaderFooter(String s) { if (s == null || s.length() == 0) { left = createContents(); right = createContents(); centre = createContents(); return; } int leftPos = s.indexOf(LEFT_ALIGN); int rightPos = s.indexOf(RIGHT_ALIGN); int centrePos = s.indexOf(CENTRE); if (leftPos == -1 && rightPos == -1 && centrePos == -1) { // When no part is specified, it is the center part centre = createContents(s); } else { // Left part? if (leftPos != -1) { // We have a left part, find end of left part int endLeftPos= s.length(); if (centrePos > leftPos) { // Case centre part behind left part endLeftPos= centrePos; if (rightPos > leftPos && endLeftPos > rightPos) { // LRC case endLeftPos = rightPos; } else { // LCR case } } else { // Case centre part before left part if (rightPos > leftPos) { // LR case endLeftPos= rightPos; } else { // *L case // Left pos is last } } left = createContents(s.substring(leftPos + 2, endLeftPos)); } // Right part? if (rightPos != -1) { // Find end of right part int endRightPos= s.length(); if (centrePos > rightPos) { // centre part behind right part endRightPos= centrePos; if (leftPos > rightPos && endRightPos > leftPos) { // RLC case endRightPos= leftPos; } else { // RCL case } } else { if (leftPos > rightPos) { // RL case endRightPos= leftPos; } else { // *R case // Right pos is last } } right = createContents(s.substring(rightPos + 2, endRightPos)); } // Centre part? if (centrePos != -1) { // Find end of centre part int endCentrePos= s.length(); if (rightPos > centrePos) { // right part behind centre part endCentrePos= rightPos; if (leftPos > centrePos && endCentrePos > leftPos) { // CLR case endCentrePos= leftPos; } else { // CRL case } } else { if (leftPos > centrePos) { // CL case endCentrePos= leftPos; } else { // *C case // Centre pos is last } } centre = createContents(s.substring(centrePos + 2, endCentrePos)); } } if (left == null) { left = createContents(); } if (centre == null) { centre = createContents(); } if (right == null) { right = createContents(); } } /** * Retrieves a Stringified * version of this object * * @return the header string */ public String toString() { StringBuffer hf = new StringBuffer(); if (!left.empty()) { hf.append(LEFT_ALIGN); hf.append(left.getContents()); } if (!centre.empty()) { hf.append(CENTRE); hf.append(centre.getContents()); } if (!right.empty()) { hf.append(RIGHT_ALIGN); hf.append(right.getContents()); } return hf.toString(); } /** * Accessor for the contents which appear on the right hand side of the page * * @return the right aligned contents */ protected Contents getRightText() { return right; } /** * Accessor for the contents which in the centre of the page * * @return the centrally aligned contents */ protected Contents getCentreText() { return centre; } /** * Accessor for the contents which appear on the left hand side of the page * * @return the left aligned contents */ protected Contents getLeftText() { return left; } /** * Clears the contents of the header/footer */ protected void clear() { left.clear(); right.clear(); centre.clear(); } /** * Creates internal class of the appropriate type */ protected abstract Contents createContents(); /** * Creates internal class of the appropriate type */ protected abstract Contents createContents(String s); /** * Creates internal class of the appropriate type */ protected abstract Contents createContents(Contents c); } jexcelapi/src/jxl/biff/IndexMapping.java0000750000175000017500000000363511207000612020430 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; import jxl.common.Logger; /** * This class is a wrapper for a list of mappings between indices. * It is used when removing duplicate records and specifies the new * index for cells which have the duplicate format */ public final class IndexMapping { /** * The logger */ private static Logger logger = Logger.getLogger(IndexMapping.class); /** * The array of new indexes for an old one */ private int[] newIndices; /** * Constructor * * @param size the number of index numbers to be mapped */ public IndexMapping(int size) { newIndices = new int[size]; } /** * Sets a mapping * @param oldIndex the old index * @param newIndex the new index */ public void setMapping(int oldIndex, int newIndex) { newIndices[oldIndex] = newIndex; } /** * Gets the new cell format index * @param oldIndex the existing index number * @return the new index number */ public int getNewIndex(int oldIndex) { return newIndices[oldIndex]; } } jexcelapi/src/jxl/biff/DVParser.java0000750000175000017500000005731511262607514017556 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2004 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; import jxl.common.Assert; import jxl.common.Logger; import java.text.MessageFormat; import java.text.DecimalFormat; import java.util.Collection; import java.util.Iterator; import jxl.WorkbookSettings; import jxl.biff.formula.ExternalSheet; import jxl.biff.formula.FormulaException; import jxl.biff.formula.FormulaParser; import jxl.biff.formula.ParseContext; /** * Class which parses the binary data associated with Data Validity (DV) * setting */ public class DVParser { /** * The logger */ private static Logger logger = Logger.getLogger(DVParser.class); // DV Type public static class DVType { private int value; private String desc; private static DVType[] types = new DVType[0]; DVType(int v, String d) { value = v; desc = d; DVType[] oldtypes = types; types = new DVType[oldtypes.length+1]; System.arraycopy(oldtypes, 0, types, 0, oldtypes.length); types[oldtypes.length] = this; } static DVType getType(int v) { DVType found = null; for (int i = 0 ; i < types.length && found == null ; i++) { if (types[i].value == v) { found = types[i]; } } return found; } public int getValue() { return value; } public String getDescription() { return desc; } } // Error Style public static class ErrorStyle { private int value; private static ErrorStyle[] types = new ErrorStyle[0]; ErrorStyle(int v) { value = v; ErrorStyle[] oldtypes = types; types = new ErrorStyle[oldtypes.length+1]; System.arraycopy(oldtypes, 0, types, 0, oldtypes.length); types[oldtypes.length] = this; } static ErrorStyle getErrorStyle(int v) { ErrorStyle found = null; for (int i = 0 ; i < types.length && found == null ; i++) { if (types[i].value == v) { found = types[i]; } } return found; } public int getValue() { return value; } } // Conditions public static class Condition { private int value; private MessageFormat format; private static Condition[] types = new Condition[0]; Condition(int v, String pattern) { value = v; format = new MessageFormat(pattern); Condition[] oldtypes = types; types = new Condition[oldtypes.length+1]; System.arraycopy(oldtypes, 0, types, 0, oldtypes.length); types[oldtypes.length] = this; } static Condition getCondition(int v) { Condition found = null; for (int i = 0 ; i < types.length && found == null ; i++) { if (types[i].value == v) { found = types[i]; } } return found; } public int getValue() { return value; } public String getConditionString(String s1, String s2) { return format.format(new String[] {s1, s2}); } } // The values public static final DVType ANY = new DVType(0, "any"); public static final DVType INTEGER = new DVType(1, "int"); public static final DVType DECIMAL = new DVType(2, "dec"); public static final DVType LIST = new DVType(3, "list"); public static final DVType DATE = new DVType(4, "date"); public static final DVType TIME = new DVType(5, "time"); public static final DVType TEXT_LENGTH = new DVType(6, "strlen"); public static final DVType FORMULA = new DVType(7, "form"); // The error styles public static final ErrorStyle STOP = new ErrorStyle(0); public static final ErrorStyle WARNING = new ErrorStyle(1); public static final ErrorStyle INFO = new ErrorStyle(2); // The conditions public static final Condition BETWEEN = new Condition(0, "{0} <= x <= {1}"); public static final Condition NOT_BETWEEN = new Condition(1, "!({0} <= x <= {1}"); public static final Condition EQUAL = new Condition(2, "x == {0}"); public static final Condition NOT_EQUAL = new Condition(3, "x != {0}"); public static final Condition GREATER_THAN = new Condition(4, "x > {0}"); public static final Condition LESS_THAN = new Condition(5, "x < {0}"); public static final Condition GREATER_EQUAL = new Condition(6, "x >= {0}"); public static final Condition LESS_EQUAL = new Condition(7, "x <= {0}"); // The masks private static final int STRING_LIST_GIVEN_MASK = 0x80; private static final int EMPTY_CELLS_ALLOWED_MASK = 0x100; private static final int SUPPRESS_ARROW_MASK = 0x200; private static final int SHOW_PROMPT_MASK = 0x40000; private static final int SHOW_ERROR_MASK = 0x80000; // The decimal format private static DecimalFormat DECIMAL_FORMAT = new DecimalFormat("#.#"); // The maximum string length for a data validation list private static final int MAX_VALIDATION_LIST_LENGTH = 254; // The maximum number of rows and columns private static final int MAX_ROWS=0xffff; private static final int MAX_COLUMNS=0xff; /** * The type */ private DVType type; /** * The error style */ private ErrorStyle errorStyle; /** * The condition */ private Condition condition; /** * String list option */ private boolean stringListGiven; /** * Empty cells allowed */ private boolean emptyCellsAllowed; /** * Suppress arrow */ private boolean suppressArrow; /** * Show prompt */ private boolean showPrompt; /** * Show error */ private boolean showError; /** * The title of the prompt box */ private String promptTitle; /** * The title of the error box */ private String errorTitle; /** * The text of the prompt box */ private String promptText; /** * The text of the error box */ private String errorText; /** * The first formula */ private FormulaParser formula1; /** * The first formula string */ private String formula1String; /** * The second formula */ private FormulaParser formula2; /** * The second formula string */ private String formula2String; /** * The column number of the cell at the top left of the range */ private int column1; /** * The row number of the cell at the top left of the range */ private int row1; /** * The column index of the cell at the bottom right */ private int column2; /** * The row index of the cell at the bottom right */ private int row2; /** * Flag to indicate that this DV Parser is shared amongst a group * of cells */ private boolean extendedCellsValidation; /** * Flag indicated whether this has been copied */ private boolean copied; /** * Constructor */ public DVParser(byte[] data, ExternalSheet es, WorkbookMethods nt, WorkbookSettings ws) { Assert.verify(nt != null); copied = false; int options = IntegerHelper.getInt(data[0], data[1], data[2], data[3]); int typeVal = options & 0xf; type = DVType.getType(typeVal); int errorStyleVal = (options & 0x70) >> 4; errorStyle = ErrorStyle.getErrorStyle(errorStyleVal); int conditionVal = (options & 0xf00000) >> 20; condition = Condition.getCondition(conditionVal); stringListGiven = (options & STRING_LIST_GIVEN_MASK) != 0; emptyCellsAllowed = (options & EMPTY_CELLS_ALLOWED_MASK) != 0; suppressArrow = (options & SUPPRESS_ARROW_MASK) != 0; showPrompt = (options & SHOW_PROMPT_MASK) != 0; showError = (options & SHOW_ERROR_MASK) != 0; int pos = 4; int length = IntegerHelper.getInt(data[pos], data[pos+1]); if (length > 0 && data[pos + 2] == 0) { promptTitle = StringHelper.getString(data, length, pos + 3, ws); pos += length + 3; } else if (length > 0) { promptTitle = StringHelper.getUnicodeString(data, length, pos + 3); pos += length * 2 + 3; } else { pos += 3; } length = IntegerHelper.getInt(data[pos], data[pos+1]); if (length > 0 && data[pos + 2] == 0) { errorTitle = StringHelper.getString(data, length, pos + 3, ws); pos += length + 3; } else if (length > 0) { errorTitle = StringHelper.getUnicodeString(data, length, pos + 3); pos += length * 2 + 3; } else { pos += 3; } length = IntegerHelper.getInt(data[pos], data[pos+1]); if (length > 0 && data[pos + 2] == 0) { promptText = StringHelper.getString(data, length, pos + 3, ws); pos += length + 3; } else if (length > 0) { promptText = StringHelper.getUnicodeString(data, length, pos + 3); pos += length * 2 + 3; } else { pos += 3; } length = IntegerHelper.getInt(data[pos], data[pos+1]); if (length > 0 && data[pos + 2] == 0) { errorText = StringHelper.getString(data, length, pos + 3, ws); pos += length + 3; } else if (length > 0) { errorText = StringHelper.getUnicodeString(data, length, pos + 3); pos += length * 2 + 3; } else { pos += 3; } int formula1Length = IntegerHelper.getInt(data[pos], data[pos+1]); pos += 4; int formula1Pos = pos; pos += formula1Length; int formula2Length = IntegerHelper.getInt(data[pos], data[pos+1]); pos += 4; int formula2Pos = pos; pos += formula2Length; pos += 2; row1 = IntegerHelper.getInt(data[pos], data[pos+1]); pos += 2; row2 = IntegerHelper.getInt(data[pos], data[pos+1]); pos += 2; column1 = IntegerHelper.getInt(data[pos], data[pos+1]); pos += 2; column2 = IntegerHelper.getInt(data[pos], data[pos+1]); pos += 2; extendedCellsValidation = (row1 == row2 && column1 == column2) ? false : true; // Do the formulas try { // First, create a temporary blank cell for any formula relative // references EmptyCell tmprt = new EmptyCell(column1, row1); if (formula1Length != 0) { byte[] tokens = new byte[formula1Length]; System.arraycopy(data, formula1Pos, tokens, 0, formula1Length); formula1 = new FormulaParser(tokens, tmprt, es, nt,ws, ParseContext.DATA_VALIDATION); formula1.parse(); } if (formula2Length != 0) { byte[] tokens = new byte[formula2Length]; System.arraycopy(data, formula2Pos, tokens, 0, formula2Length); formula2 = new FormulaParser(tokens, tmprt, es, nt, ws, ParseContext.DATA_VALIDATION); formula2.parse(); } } catch (FormulaException e) { logger.warn(e.getMessage() + " for cells " + CellReferenceHelper.getCellReference(column1, row1)+ "-" + CellReferenceHelper.getCellReference(column2, row2)); } } /** * Constructor called when creating a data validation from the API */ public DVParser(Collection strings) { copied = false; type = LIST; errorStyle = STOP; condition = BETWEEN; extendedCellsValidation = false; // the options stringListGiven = true; emptyCellsAllowed = true; suppressArrow = false; showPrompt = true; showError = true; promptTitle = "\0"; errorTitle = "\0"; promptText = "\0"; errorText = "\0"; if (strings.size() == 0) { logger.warn("no validation strings - ignoring"); } Iterator i = strings.iterator(); StringBuffer formulaString = new StringBuffer(); formulaString.append(i.next().toString()); while (i.hasNext()) { formulaString.append('\0'); formulaString.append(' '); formulaString.append(i.next().toString()); } // If the formula string exceeds // the maximum validation list length, then truncate and stop there if (formulaString.length() > MAX_VALIDATION_LIST_LENGTH) { logger.warn("Validation list exceeds maximum number of characters - " + "truncating"); formulaString.delete(MAX_VALIDATION_LIST_LENGTH, formulaString.length()); } // Put the string in quotes formulaString.insert(0, '\"'); formulaString.append('\"'); formula1String = formulaString.toString(); } /** * Constructor called when creating a data validation from the API */ public DVParser(String namedRange) { // Handle the case for an empty string if (namedRange.length() == 0) { copied = false; type = FORMULA; errorStyle = STOP; condition = EQUAL; extendedCellsValidation = false; // the options stringListGiven = false; emptyCellsAllowed = false; suppressArrow = false; showPrompt = true; showError = true; promptTitle = "\0"; errorTitle = "\0"; promptText = "\0"; errorText = "\0"; formula1String = "\"\""; return; } copied = false; type = LIST; errorStyle = STOP; condition = BETWEEN; extendedCellsValidation = false; // the options stringListGiven = false; emptyCellsAllowed = true; suppressArrow = false; showPrompt = true; showError = true; promptTitle = "\0"; errorTitle = "\0"; promptText = "\0"; errorText = "\0"; formula1String = namedRange; } /** * Constructor called when creating a data validation from the API */ public DVParser(int c1, int r1, int c2, int r2) { copied = false; type = LIST; errorStyle = STOP; condition = BETWEEN; extendedCellsValidation = false; // the options stringListGiven = false; emptyCellsAllowed = true; suppressArrow = false; showPrompt = true; showError = true; promptTitle = "\0"; errorTitle = "\0"; promptText = "\0"; errorText = "\0"; StringBuffer formulaString = new StringBuffer(); CellReferenceHelper.getCellReference(c1,r1,formulaString); formulaString.append(':'); CellReferenceHelper.getCellReference(c2,r2,formulaString); formula1String = formulaString.toString(); } /** * Constructor called when creating a data validation from the API */ public DVParser(double val1, double val2, Condition c) { copied = false; type = DECIMAL; errorStyle = STOP; condition = c; extendedCellsValidation = false; // the options stringListGiven = false; emptyCellsAllowed = true; suppressArrow = false; showPrompt = true; showError = true; promptTitle = "\0"; errorTitle = "\0"; promptText = "\0"; errorText = "\0"; formula1String = DECIMAL_FORMAT.format(val1); if (!Double.isNaN(val2)) { formula2String = DECIMAL_FORMAT.format(val2); } } /** * Constructor called when doing a cell deep copy */ public DVParser(DVParser copy) { copied = true; type = copy.type; errorStyle = copy.errorStyle; condition = copy.condition; stringListGiven = copy.stringListGiven; emptyCellsAllowed = copy.emptyCellsAllowed; suppressArrow = copy.suppressArrow; showPrompt = copy.showPrompt; showError = copy.showError; promptTitle = copy.promptTitle; promptText = copy.promptText; errorTitle = copy.errorTitle; errorText = copy.errorText; extendedCellsValidation = copy.extendedCellsValidation; row1 = copy.row1; row2 = copy.row2; column1 = copy.column1; column2 = copy.column2; // Don't copy the formula parsers - just take their string equivalents if (copy.formula1String != null) { formula1String = copy.formula1String; formula2String = copy.formula2String; } else { try { formula1String = copy.formula1.getFormula(); formula2String = (copy.formula2 != null) ? copy.formula2.getFormula() : null; } catch (FormulaException e) { logger.warn("Cannot parse validation formula: " + e.getMessage()); } } // Don't copy the cell references - these will be added later } /** * Gets the data */ public byte[] getData() { // Compute the length of the data byte[] f1Bytes = formula1 != null ? formula1.getBytes() : new byte[0]; byte[] f2Bytes = formula2 != null ? formula2.getBytes() : new byte[0]; int dataLength = 4 + // the options promptTitle.length() * 2 + 3 + // the prompt title errorTitle.length() * 2 + 3 + // the error title promptText.length() * 2 + 3 + // the prompt text errorText.length() * 2 + 3 + // the error text f1Bytes.length + 2 + // first formula f2Bytes.length + 2 + // second formula + 4 + // unused bytes 10; // cell range byte[] data = new byte[dataLength]; // The position int pos = 0; // The options int options = 0; options |= type.getValue(); options |= errorStyle.getValue() << 4; options |= condition.getValue() << 20; if (stringListGiven) { options |= STRING_LIST_GIVEN_MASK; } if (emptyCellsAllowed) { options |= EMPTY_CELLS_ALLOWED_MASK; } if (suppressArrow) { options |= SUPPRESS_ARROW_MASK; } if (showPrompt) { options |= SHOW_PROMPT_MASK; } if (showError) { options |= SHOW_ERROR_MASK; } // The text IntegerHelper.getFourBytes(options, data, pos); pos += 4; IntegerHelper.getTwoBytes(promptTitle.length(), data, pos); pos += 2; data[pos] = (byte) 0x1; // unicode indicator pos++; StringHelper.getUnicodeBytes(promptTitle, data, pos); pos += promptTitle.length() * 2; IntegerHelper.getTwoBytes(errorTitle.length(), data, pos); pos += 2; data[pos] = (byte) 0x1; // unicode indicator pos++; StringHelper.getUnicodeBytes(errorTitle, data, pos); pos += errorTitle.length() * 2; IntegerHelper.getTwoBytes(promptText.length(), data, pos); pos += 2; data[pos] = (byte) 0x1; // unicode indicator pos++; StringHelper.getUnicodeBytes(promptText, data, pos); pos += promptText.length() * 2; IntegerHelper.getTwoBytes(errorText.length(), data, pos); pos += 2; data[pos] = (byte) 0x1; // unicode indicator pos++; StringHelper.getUnicodeBytes(errorText, data, pos); pos += errorText.length() * 2; // Formula 1 IntegerHelper.getTwoBytes(f1Bytes.length, data, pos); pos += 4; System.arraycopy(f1Bytes, 0, data, pos, f1Bytes.length); pos += f1Bytes.length; // Formula 2 IntegerHelper.getTwoBytes(f2Bytes.length, data, pos); pos += 4; System.arraycopy(f2Bytes, 0, data, pos, f2Bytes.length); pos += f2Bytes.length; // The cell ranges IntegerHelper.getTwoBytes(1, data, pos); pos += 2; IntegerHelper.getTwoBytes(row1, data, pos); pos += 2; IntegerHelper.getTwoBytes(row2, data, pos); pos += 2; IntegerHelper.getTwoBytes(column1, data, pos); pos += 2; IntegerHelper.getTwoBytes(column2, data, pos); pos += 2; return data; } /** * Inserts a row * * @param row the row to insert */ public void insertRow(int row) { if (formula1 != null) { formula1.rowInserted(0, row, true); } if (formula2 != null) { formula2.rowInserted(0, row, true); } if (row1 >= row) { row1++; } if (row2 >= row && row2 != MAX_ROWS) { row2++; } } /** * Inserts a column * * @param col the column to insert */ public void insertColumn(int col) { if (formula1 != null) { formula1.columnInserted(0, col, true); } if (formula2 != null) { formula2.columnInserted(0, col, true); } if (column1 >= col) { column1++; } if (column2 >= col && column2 != MAX_COLUMNS) { column2++; } } /** * Removes a row * * @param row the row to insert */ public void removeRow(int row) { if (formula1 != null) { formula1.rowRemoved(0, row, true); } if (formula2 != null) { formula2.rowRemoved(0, row, true); } if (row1 > row) { row1--; } if (row2 >= row) { row2--; } } /** * Removes a column * * @param col the row to remove */ public void removeColumn(int col) { if (formula1 != null) { formula1.columnRemoved(0, col, true); } if (formula2 != null) { formula2.columnRemoved(0, col, true); } if (column1 > col) { column1--; } if (column2 >= col && column2 != MAX_COLUMNS) { column2--; } } /** * Accessor for first column * * @return the first column */ public int getFirstColumn() { return column1; } /** * Accessor for the last column * * @return the last column */ public int getLastColumn() { return column2; } /** * Accessor for first row * * @return the first row */ public int getFirstRow() { return row1; } /** * Accessor for the last row * * @return the last row */ public int getLastRow() { return row2; } /** * Gets the formula present in the validation * * @return the validation formula as a string * @exception FormulaException */ String getValidationFormula() throws FormulaException { if (type == LIST) { return formula1.getFormula(); } String s1 = formula1.getFormula(); String s2 = formula2 != null ? formula2.getFormula() : null; return condition.getConditionString(s1, s2) + "; x " + type.getDescription(); } /** * Called by the cell value when the cell features are added to the sheet */ public void setCell(int col, int row, ExternalSheet es, WorkbookMethods nt, WorkbookSettings ws) throws FormulaException { // If this is part of an extended cells validation, then do nothing // as this will already have been called and parsed when the top left // cell was added if (extendedCellsValidation) { return; } row1 = row; row2 = row; column1 = col; column2 = col; formula1 = new FormulaParser(formula1String, es, nt, ws, ParseContext.DATA_VALIDATION); formula1.parse(); if (formula2String != null) { formula2 = new FormulaParser(formula2String, es, nt, ws, ParseContext.DATA_VALIDATION); formula2.parse(); } } /** * Indicates that the data validation extends across several more cells * * @param cols - the number of extra columns * @param rows - the number of extra rows */ public void extendCellValidation(int cols, int rows) { row2 = row1 + rows; column2 = column1 + cols; extendedCellsValidation = true; } /** * Accessor which indicates whether this validation applies across * multiple cels */ public boolean extendedCellsValidation() { return extendedCellsValidation; } public boolean copied() { return copied; } } jexcelapi/src/jxl/biff/NumFormatRecordsException.java0000750000175000017500000000250011207000612023144 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; /** * Excel places a constraint on the number of format records that * are allowed. This exception is thrown when that number is exceeded * This is a static exception and should be handled internally */ public class NumFormatRecordsException extends Exception { /** * Constructor */ public NumFormatRecordsException() { super("Internal error: max number of FORMAT records exceeded"); } } jexcelapi/src/jxl/biff/CellReferenceHelper.java0000750000175000017500000002026311234033732021710 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; import jxl.common.Logger; import jxl.biff.formula.ExternalSheet; /** * A helper to transform between excel cell references and * sheet:column:row notation * Because this function will be called when generating a string * representation of a formula, the cell reference will merely * be appened to the string buffer instead of returning a full * blooded string, for performance reasons */ public final class CellReferenceHelper { /** * The logger */ private static Logger logger = Logger.getLogger(CellReferenceHelper.class); /** * The character which indicates whether a reference is fixed */ private static final char fixedInd='$'; /** * The character which indicates the sheet name terminator */ private static final char sheetInd = '!'; /** * Constructor to prevent instantiation */ private CellReferenceHelper() { } /** * Gets the cell reference * * @param column * @param row * @param buf */ public static void getCellReference(int column, int row, StringBuffer buf) { // Put the column letter into the buffer getColumnReference(column, buf); // Add the row into the buffer buf.append(Integer.toString(row+1)); } /** * Overloaded method which prepends $ for absolute reference * * @param column * @param colabs TRUE if the column reference is absolute * @param row * @param rowabs TRUE if the row reference is absolute * @param buf */ public static void getCellReference(int column, boolean colabs, int row, boolean rowabs, StringBuffer buf) { if (colabs) { buf.append(fixedInd); } // Put the column letter into the buffer getColumnReference(column, buf); if (rowabs) { buf.append(fixedInd); } // Add the row into the buffer buf.append(Integer.toString(row+1)); } /** * Gets the column letter corresponding to the 0-based column number * * @param column the column number * @return the letter for that column number */ public static String getColumnReference(int column) { StringBuffer buf = new StringBuffer(); getColumnReference(column, buf); return buf.toString(); } /** * Gets the column letter corresponding to the 0-based column number * * @param column the column number * @param buf the string buffer in which to write the column letter */ public static void getColumnReference(int column, StringBuffer buf) { int v = column/26; int r = column%26; StringBuffer tmp = new StringBuffer(); while (v != 0) { char col = (char) ('A' + r) ; tmp.append(col); r = v%26 - 1; // subtract one because only rows >26 preceded by A v = v/26; } char col = (char) ('A' + r) ; tmp.append(col); // Insert into the proper string buffer in reverse order for (int i = tmp.length() - 1; i >= 0; i--) { buf.append(tmp.charAt(i)); } } /** * Gets the fully qualified cell reference given the column, row * external sheet reference etc * * @param sheet * @param column * @param row * @param workbook * @param buf */ public static void getCellReference (int sheet, int column, int row, ExternalSheet workbook, StringBuffer buf) { // Quotes are added by the WorkbookParser String name = workbook.getExternalSheetName(sheet); buf.append(StringHelper.replace(name, "\'", "\'\'")); buf.append(sheetInd); getCellReference(column, row, buf); } /** * Gets the fully qualified cell reference given the column, row * external sheet reference etc * * @param sheet * @param column * @param colabs TRUE if the column is an absolute reference * @param row * @param rowabs TRUE if the row is an absolute reference * @param workbook * @param buf */ public static void getCellReference (int sheet, int column, boolean colabs, int row, boolean rowabs, ExternalSheet workbook, StringBuffer buf) { // WorkbookParser now appends quotes and escapes apostrophes String name = workbook.getExternalSheetName(sheet); buf.append(name); buf.append(sheetInd); getCellReference(column, colabs, row, rowabs, buf); } /** * Gets the fully qualified cell reference given the column, row * external sheet reference etc * * @param sheet * @param column * @param row * @param workbook * @return the cell reference in the form 'Sheet 1'!A1 */ public static String getCellReference (int sheet, int column, int row, ExternalSheet workbook) { StringBuffer sb = new StringBuffer(); getCellReference(sheet, column, row, workbook, sb); return sb.toString(); } /** * Gets the cell reference for the specified column and row * * @param column * @param row * @return */ public static String getCellReference(int column, int row) { StringBuffer buf = new StringBuffer(); getCellReference(column, row, buf); return buf.toString(); } /** * Gets the columnn number of the string cell reference * * @param s the string to parse * @return the column portion of the cell reference */ public static int getColumn(String s) { int colnum = 0; int numindex = getNumberIndex(s); String s2 = s.toUpperCase(); int startPos = s.lastIndexOf(sheetInd) + 1; if (s.charAt(startPos) == fixedInd) { startPos++; } int endPos = numindex; if (s.charAt(numindex - 1) == fixedInd) { endPos--; } for (int i = startPos; i < endPos ; i++) { if (i != startPos) { colnum = (colnum+1) * 26; } colnum += (int) s2.charAt(i) - (int) 'A'; } return colnum; } /** * Gets the row number of the cell reference */ public static int getRow(String s) { try { return (Integer.parseInt(s.substring(getNumberIndex(s))) - 1); } catch (NumberFormatException e) { logger.warn(e, e); return 0xffff; } } /** * Finds the position where the first number occurs in the string */ private static int getNumberIndex(String s) { // Find the position of the first number boolean numberFound = false; int pos = s.lastIndexOf(sheetInd) + 1; char c = '\0'; while (!numberFound && pos < s.length() ) { c = s.charAt(pos); if (c >= '0' && c <= '9') { numberFound = true; } else { pos++; } } return pos; } /** * Sees if the column component is relative or not * * @param s * @return TRUE if the column is relative, FALSE otherwise */ public static boolean isColumnRelative(String s) { return s.charAt(0) != fixedInd; } /** * Sees if the row component is relative or not * * @param s * @return TRUE if the row is relative, FALSE otherwise */ public static boolean isRowRelative(String s) { return s.charAt(getNumberIndex(s) - 1) != fixedInd; } /** * Gets the sheet name from the cell reference string * * @param ref * @return the sheet reference */ public static String getSheet(String ref) { int sheetPos = ref.lastIndexOf(sheetInd); if (sheetPos == -1) { return ""; } return ref.substring(0, sheetPos); } } jexcelapi/src/jxl/biff/SheetRangeImpl.java0000750000175000017500000001527011207000612020712 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; import jxl.Cell; import jxl.Range; import jxl.Sheet; /** * Implementation class for the Range interface. This merely * holds the raw range information. This implementation is used * for ranges which are present on the current working sheet, so the * getSheetIndex merely returns -1 */ public class SheetRangeImpl implements Range { /** * A handle to the sheet containing this range */ private Sheet sheet; /** * The column number of the cell at the top left of the range */ private int column1; /** * The row number of the cell at the top left of the range */ private int row1; /** * The column index of the cell at the bottom right */ private int column2; /** * The row index of the cell at the bottom right */ private int row2; /** * Constructor * @param s the sheet containing the range * @param c1 the column number of the top left cell of the range * @param r1 the row number of the top left cell of the range * @param c2 the column number of the bottom right cell of the range * @param r2 the row number of the bottomr right cell of the range */ public SheetRangeImpl(Sheet s, int c1, int r1, int c2, int r2) { sheet = s; row1 = r1; row2 = r2; column1 = c1; column2 = c2; } /** * A copy constructor used for copying ranges between sheets * * @param c the range to copy from * @param s the writable sheet */ public SheetRangeImpl(SheetRangeImpl c, Sheet s) { sheet = s; row1 = c.row1; row2 = c.row2; column1 = c.column1; column2 = c.column2; } /** * Gets the cell at the top left of this range * * @return the cell at the top left */ public Cell getTopLeft() { // If the print area exceeds the bounds of the sheet, then handle // it here. The sheet implementation will give a NPE if (column1 >= sheet.getColumns() || row1 >= sheet.getRows()) { return new EmptyCell(column1,row1); } return sheet.getCell(column1, row1); } /** * Gets the cell at the bottom right of this range * * @return the cell at the bottom right */ public Cell getBottomRight() { // If the print area exceeds the bounds of the sheet, then handle // it here. The sheet implementation will give a NPE if (column2 >= sheet.getColumns() || row2 >= sheet.getRows()) { return new EmptyCell(column2,row2); } return sheet.getCell(column2, row2); } /** * Not supported. Returns -1, indicating that it refers to the current * sheet * * @return -1 */ public int getFirstSheetIndex() { return -1; } /** * Not supported. Returns -1, indicating that it refers to the current * sheet * * @return -1 */ public int getLastSheetIndex() { return -1; } /** * Sees whether there are any intersections between this range and the * range passed in. This method is used internally by the WritableSheet to * verify the integrity of merged cells, hyperlinks etc. Ranges are * only ever compared for the same sheet * * @param range the range to compare against * @return TRUE if the ranges intersect, FALSE otherwise */ public boolean intersects(SheetRangeImpl range) { if (range == this) { return true; } if (row2 < range.row1 || row1 > range.row2 || column2 < range.column1 || column1 > range.column2) { return false; } return true; } /** * To string method - primarily used during debugging * * @return the string version of this object */ public String toString() { StringBuffer sb = new StringBuffer(); CellReferenceHelper.getCellReference(column1, row1, sb); sb.append('-'); CellReferenceHelper.getCellReference(column2, row2, sb); return sb.toString(); } /** * A row has been inserted, so adjust the range objects accordingly * * @param r the row which has been inserted */ public void insertRow(int r) { if (r > row2) { return; } if (r <= row1) { row1++; } if (r <= row2) { row2++; } } /** * A column has been inserted, so adjust the range objects accordingly * * @param c the column which has been inserted */ public void insertColumn(int c) { if (c > column2) { return; } if (c <= column1) { column1++; } if (c <= column2) { column2++; } } /** * A row has been removed, so adjust the range objects accordingly * * @param r the row which has been inserted */ public void removeRow(int r) { if (r > row2) { return; } if (r < row1) { row1--; } if (r < row2) { row2--; } } /** * A column has been removed, so adjust the range objects accordingly * * @param c the column which has been removed */ public void removeColumn(int c) { if (c > column2) { return; } if (c < column1) { column1--; } if (c < column2) { column2--; } } /** * Standard hash code method * * @return the hash code */ public int hashCode() { return 0xffff ^ row1 ^ row2 ^ column1 ^ column2; } /** * Standard equals method * * @param o the object to compare * @return TRUE if the two objects are the same, FALSE otherwise */ public boolean equals(Object o) { if (o == this) { return true; } if (!(o instanceof SheetRangeImpl)) { return false; } SheetRangeImpl compare = (SheetRangeImpl) o; return (column1 == compare.column1 && column2 == compare.column2 && row1 == compare.row1 && row2 == compare.row2); } } jexcelapi/src/jxl/biff/CountryCode.java0000750000175000017500000001113011207000612020270 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2005 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; import jxl.common.Logger; /** * Enumeration type for the excel country codes */ public class CountryCode { /** * The logger */ private static Logger logger = Logger.getLogger(CountryCode.class); /** * The country code */ private int value; /** * The ISO 3166 two letter country mnemonic (as used by the Locale class) */ private String code; /** * The long description */ private String description; /** * The array of country codes */ private static CountryCode[] codes = new CountryCode[0]; /** * Constructor */ private CountryCode(int v, String c, String d) { value = v; code = c; description = d; CountryCode[] newcodes = new CountryCode[codes.length+1]; System.arraycopy(codes, 0, newcodes, 0, codes.length); newcodes[codes.length] = this; codes = newcodes; } /** * Constructor used to create an arbitrary code with a specified value. * Doesn't add the latest value to the static array */ private CountryCode(int v) { value = v; description = "Arbitrary"; code = "??"; } /** * Accessor for the excel value * * @return the excel value */ public int getValue() { return value; } /** * Accessor for the string * * @return the two character iso 3166 string */ public String getCode() { return code; } /** * Gets the country code for the given two character mnemonic string */ public static CountryCode getCountryCode(String s) { if (s == null || s.length() != 2) { logger.warn("Please specify two character ISO 3166 country code"); return USA; } CountryCode code = UNKNOWN; for (int i = 0 ; i < codes.length && code == UNKNOWN ; i++) { if (codes[i].code.equals(s)) { code = codes[i]; } } return code; } /** * Creates an arbitrary country code with the specified value. Used * when copying sheets, and the country code isn't initialized as part * of the static data below */ public static CountryCode createArbitraryCode(int i) { return new CountryCode(i); } // The country codes public final static CountryCode USA = new CountryCode(0x1, "US", "USA"); public final static CountryCode CANADA = new CountryCode(0x2, "CA", "Canada"); public final static CountryCode GREECE = new CountryCode(0x1e, "GR", "Greece"); public final static CountryCode NETHERLANDS = new CountryCode(0x1f, "NE", "Netherlands"); public final static CountryCode BELGIUM = new CountryCode(0x20, "BE", "Belgium"); public final static CountryCode FRANCE = new CountryCode(0x21, "FR", "France"); public final static CountryCode SPAIN = new CountryCode(0x22, "ES", "Spain"); public final static CountryCode ITALY = new CountryCode(0x27, "IT", "Italy"); public final static CountryCode SWITZERLAND = new CountryCode(0x29, "CH", "Switzerland"); public final static CountryCode UK = new CountryCode(0x2c, "UK", "United Kingdowm"); public final static CountryCode DENMARK = new CountryCode(0x2d, "DK", "Denmark"); public final static CountryCode SWEDEN = new CountryCode(0x2e, "SE", "Sweden"); public final static CountryCode NORWAY = new CountryCode(0x2f, "NO", "Norway"); public final static CountryCode GERMANY = new CountryCode(0x31, "DE", "Germany"); public final static CountryCode PHILIPPINES = new CountryCode(0x3f, "PH", "Philippines"); public final static CountryCode CHINA = new CountryCode(0x56, "CN", "China"); public final static CountryCode INDIA = new CountryCode(0x5b, "IN", "India"); public final static CountryCode UNKNOWN = new CountryCode(0xffff, "??", "Unknown"); } jexcelapi/src/jxl/biff/XCTRecord.java0000750000175000017500000000250411207000612017634 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2009 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; import jxl.read.biff.Record; /** * A record representing the XCT record */ public class XCTRecord extends WritableRecordData { /** * Constructor * * @param t the raw bytes */ public XCTRecord(Record t) { super(t); } /** * Accessor for the binary data - used when copying * * @return the binary data */ public byte[] getData() { return getRecord().getData(); } } jexcelapi/src/jxl/biff/CellReferenceHelper.java20000750000175000017500000001146311207000612021763 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; import jxl.biff.formula.ExternalSheet; /** * A helper to transform between excel cell references and * sheet:column:row notation * Because this function will be called when generating a string * representation of a formula, the cell reference will merely * be appened to the string buffer instead of returning a full * blooded string, for performance reasons */ public final class CellReferenceHelper { /** * The character which indicates whether a reference is fixed */ private static final char fixedInd='$'; /** * Constructor to prevent instantiation */ private CellReferenceHelper() { } public static void getCellReference(int column, int row, StringBuffer buf) { int v = column/26; int r = column%26; StringBuffer tmp = new StringBuffer(); while (v != 0) { char col = (char) ((int) 'A' + r) ; tmp.append(col); r = v%26 - 1; // subtract one because only rows >26 preceded by A v = v/26; } char col = (char) ((int) 'A' + r) ; tmp.append(col); // Insert into the proper string buffer in reverse order for (int i = tmp.length() - 1; i >= 0; i--) { buf.append(tmp.charAt(i)); } buf.append(Integer.toString(row+1)); } /** * Gets the fully qualified cell reference given the column, row * external sheet reference etc * * @param sheet * @param column * @param row * @param workbook * @param buf */ public static void getCellReference (int sheet, int column, int row, ExternalSheet workbook, StringBuffer buf) { buf.append(workbook.getExternalSheetName(sheet)); buf.append('!'); getCellReference(column, row, buf); } /** * Gets the cell reference for the specified column and row * * @param column * @param row * @return */ public static String getCellReference(int column, int row) { StringBuffer buf = new StringBuffer(); getCellReference(column, row, buf); return buf.toString(); } /** * Gets the columnn number of the string cell reference * * @param s the string to parse * @return the column portion of the cell reference */ public static int getColumn(String s) { int colnum = 0; int numindex = getNumberIndex(s); String s2 = s.toUpperCase(); int startPos = 0; if (s.charAt(0) == fixedInd) { startPos = 1; } int endPos = numindex; if (s.charAt(numindex - 1) == fixedInd) { endPos--; } for (int i = startPos; i < endPos ; i++) { if (i != startPos) { colnum = (colnum+1) * 26; } colnum += (int) s2.charAt(i) - (int) 'A'; } return colnum; } /** * Gets the row number of the cell reference */ public static int getRow(String s) { try { return (Integer.parseInt(s.substring(getNumberIndex(s))) - 1); } catch (NumberFormatException e) { System.err.println("Warning: " + e.toString()); return 0xffff; } } /** * Finds the position where the first number occurs in the string */ private static int getNumberIndex(String s) { // Find the position of the first number boolean numberFound = false; int pos = 0; char c = '\0'; while (!numberFound && pos < s.length() ) { c = s.charAt(pos); if (c >= '0' && c <= '9') { numberFound = true; } else { pos++; } } return pos; } /** * Sees if the column component is relative or not * * @param s * @return TRUE if the column is relative, FALSE otherwise */ public static boolean isColumnRelative(String s) { return s.charAt(0) != fixedInd; } /** * Sees if the row component is relative or not * * @param s * @return TRUE if the row is relative, FALSE otherwise */ public static boolean isRowRelative(String s) { return s.charAt(getNumberIndex(s) - 1) != fixedInd; } } jexcelapi/src/jxl/biff/ByteArray.java0000750000175000017500000000472511207000612017750 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2005 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; /** * A growable array of bytes */ public class ByteArray { /** * The array grow size */ private int growSize; /** * The current array */ private byte[] bytes; /** * The current position */ private int pos; // The default grow size private final static int defaultGrowSize = 1024; /** * Constructor */ public ByteArray() { this(defaultGrowSize); } /** * Constructor * * @param gs */ public ByteArray(int gs) { growSize = gs; bytes = new byte[defaultGrowSize]; pos = 0; } /** * Adds a byte onto the array * * @param b the byte */ public void add(byte b) { checkSize(1); bytes[pos] = b; pos++; } /** * Adds an array of bytes onto the array * * @param b the array of bytes */ public void add(byte[] b) { checkSize(b.length); System.arraycopy(b, 0, bytes, pos, b.length); pos += b.length; } /** * Gets the complete array * * @return the array */ public byte[] getBytes() { byte[] returnArray = new byte[pos]; System.arraycopy(bytes, 0, returnArray, 0, pos); return returnArray; } /** * Checks to see if there is sufficient space left on the array. If not, * then it grows the array * * @param sz the amount of bytes to add */ private void checkSize(int sz) { while (pos + sz >= bytes.length) { // Grow the array byte[] newArray = new byte[bytes.length + growSize]; System.arraycopy(bytes, 0, newArray, 0, pos); bytes = newArray; } } } jexcelapi/src/jxl/biff/DataValidation.java0000750000175000017500000002162011263061211020727 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2004 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import jxl.common.Assert; import jxl.common.Logger; import jxl.WorkbookSettings; import jxl.biff.formula.ExternalSheet; import jxl.write.biff.File; /** * Class which encapsulates a data validation. This encapsulates the * base DVAL record (DataValidityListRecord) and all the individual DV * (DataValiditySettingsRecord) records */ public class DataValidation { /** * The logger */ private static Logger logger = Logger.getLogger(DataValidation.class); /** * The data validity list */ private DataValidityListRecord validityList; /** * The list of data validity (DV) records */ private ArrayList validitySettings; /** * Handle to the workbook */ private WorkbookMethods workbook; /** * Handle to the external sheet */ private ExternalSheet externalSheet; /** * Handle to the workbook settings */ private WorkbookSettings workbookSettings; /** * The object id of the combo box used for drop downs */ private int comboBoxObjectId; /** * Indicates whether this was copied */ private boolean copied; public static final int DEFAULT_OBJECT_ID = 0xffffffff; private static final int MAX_NO_OF_VALIDITY_SETTINGS = 0xfffd; /** * Constructor */ public DataValidation(DataValidityListRecord dvlr) { validityList = dvlr; validitySettings = new ArrayList(validityList.getNumberOfSettings()); copied = false; } /** * Constructor used to create writable data validations */ public DataValidation(int objId, ExternalSheet es, WorkbookMethods wm, WorkbookSettings ws ) { workbook = wm; externalSheet = es; workbookSettings = ws; validitySettings = new ArrayList(); comboBoxObjectId = objId; copied = false; } /** * Copy constructor used to copy from read to write */ public DataValidation(DataValidation dv, ExternalSheet es, WorkbookMethods wm, WorkbookSettings ws ) { workbook = wm; externalSheet = es; workbookSettings = ws; copied = true; validityList = new DataValidityListRecord(dv.getDataValidityList()); validitySettings = new ArrayList(); DataValiditySettingsRecord[] settings = dv.getDataValiditySettings(); for (int i = 0; i < settings.length ; i++) { validitySettings.add(new DataValiditySettingsRecord(settings[i], externalSheet, workbook, workbookSettings)); } } /** * Adds a new settings object to this data validation */ public void add(DataValiditySettingsRecord dvsr) { validitySettings.add(dvsr); dvsr.setDataValidation(this); if (copied) { // adding a writable dv record to a copied validity list Assert.verify(validityList != null); validityList.dvAdded(); } } /** * Accessor for the validity list. Used when copying sheets */ public DataValidityListRecord getDataValidityList() { return validityList; } /** * Accessor for the validity settings. Used when copying sheets */ public DataValiditySettingsRecord[] getDataValiditySettings() { DataValiditySettingsRecord[] dvlr = new DataValiditySettingsRecord[0]; return (DataValiditySettingsRecord[]) validitySettings.toArray(dvlr); } /** * Writes out the data validation * * @exception IOException * @param outputFile the output file */ public void write(File outputFile) throws IOException { if (validitySettings.size() > MAX_NO_OF_VALIDITY_SETTINGS) { logger.warn("Maximum number of data validations exceeded - " + "truncating..."); validitySettings = new ArrayList (validitySettings.subList(0, MAX_NO_OF_VALIDITY_SETTINGS - 1)); Assert.verify(validitySettings.size() <= MAX_NO_OF_VALIDITY_SETTINGS); } if (validityList == null) { DValParser dvp = new DValParser(comboBoxObjectId, validitySettings.size()); validityList = new DataValidityListRecord(dvp); } if (!validityList.hasDVRecords()) { return; } outputFile.write(validityList); for (Iterator i = validitySettings.iterator(); i.hasNext() ; ) { DataValiditySettingsRecord dvsr = (DataValiditySettingsRecord) i.next(); outputFile.write(dvsr); } } /** * Inserts a row * * @param row the inserted row */ public void insertRow(int row) { for (Iterator i = validitySettings.iterator(); i.hasNext() ; ) { DataValiditySettingsRecord dv = (DataValiditySettingsRecord) i.next(); dv.insertRow(row); } } /** * Removes row * * @param row the row to be removed */ public void removeRow(int row) { for (Iterator i = validitySettings.iterator(); i.hasNext() ; ) { DataValiditySettingsRecord dv = (DataValiditySettingsRecord) i.next(); if (dv.getFirstRow() == row && dv.getLastRow() == row) { i.remove(); validityList.dvRemoved(); } else { dv.removeRow(row); } } } /** * Inserts a column * * @param col the inserted column */ public void insertColumn(int col) { for (Iterator i = validitySettings.iterator(); i.hasNext() ; ) { DataValiditySettingsRecord dv = (DataValiditySettingsRecord) i.next(); dv.insertColumn(col); } } /** * Removes a column * * @param col the inserted column */ public void removeColumn(int col) { for (Iterator i = validitySettings.iterator(); i.hasNext() ; ) { DataValiditySettingsRecord dv = (DataValiditySettingsRecord) i.next(); if (dv.getFirstColumn() == col && dv.getLastColumn() == col) { i.remove(); validityList.dvRemoved(); } else { dv.removeColumn(col); } } } /** * Removes the data validation for a specific cell * * @param col the column * @param row the row */ public void removeDataValidation (int col, int row) { for (Iterator i = validitySettings.iterator(); i.hasNext() ; ) { DataValiditySettingsRecord dv = (DataValiditySettingsRecord) i.next(); if (dv.getFirstColumn() == col && dv.getLastColumn() == col && dv.getFirstRow() == row && dv.getLastRow() == row) { i.remove(); validityList.dvRemoved(); break; } } } /** * Removes the data validation for a specific cell * * @param col1 the first column * @param row1 the first row */ public void removeSharedDataValidation (int col1, int row1, int col2, int row2) { for (Iterator i = validitySettings.iterator(); i.hasNext() ; ) { DataValiditySettingsRecord dv = (DataValiditySettingsRecord) i.next(); if (dv.getFirstColumn() == col1 && dv.getLastColumn() == col2 && dv.getFirstRow() == row1 && dv.getLastRow() == row2) { i.remove(); validityList.dvRemoved(); break; } } } /** * Used during the copy process to retrieve the validity settings for * a particular cell */ public DataValiditySettingsRecord getDataValiditySettings(int col, int row) { boolean found = false; DataValiditySettingsRecord foundRecord = null; for (Iterator i = validitySettings.iterator(); i.hasNext() && !found;) { DataValiditySettingsRecord dvsr = (DataValiditySettingsRecord) i.next(); if (dvsr.getFirstColumn() == col && dvsr.getFirstRow() == row) { found = true; foundRecord = dvsr; } } return foundRecord; } /** * Accessor for the combo box, used when copying sheets */ public int getComboBoxObjectId() { return comboBoxObjectId; } } jexcelapi/src/jxl/biff/ByteData.java0000750000175000017500000000234411207000612017536 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; /** * Interface which provides a method for transferring chunks of binary * data from one Excel file (read in) to another (written out) */ public interface ByteData { /** * Used when writing out records * * @return the full data to be included in the final compound file */ public byte[] getBytes(); } jexcelapi/src/jxl/biff/ConditionalFormatRangeRecord.java0000750000175000017500000001777711207000612023611 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2007 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; import jxl.common.Logger; import jxl.read.biff.Record; /** * Range information for conditional formatting */ public class ConditionalFormatRangeRecord extends WritableRecordData { // The logger private static Logger logger = Logger.getLogger(ConditionalFormatRangeRecord.class); /** * The enclosing range */ private Range enclosingRange; /** * The discrete ranges */ private Range[] ranges; /** * The number of ranges */ private int numRanges; /** * Initialized flag */ private boolean initialized; /** * Modified flag */ private boolean modified; /** * The data */ private byte[] data; private static class Range { public int firstRow; public int firstColumn; public int lastRow; public int lastColumn; public boolean modified; public Range() { modified = false; } /** * Inserts a blank column into this spreadsheet. If the column is out of * range of the columns in the sheet, then no action is taken * * @param col the column to insert */ public void insertColumn(int col) { if (col > lastColumn) { return; } if (col <= firstColumn) { firstColumn++; modified = true; } if (col <= lastColumn) { lastColumn++; modified = true; } } /** * Removes a column from this spreadsheet. If the column is out of range * of the columns in the sheet, then no action is taken * * @param col the column to remove */ public void removeColumn(int col) { if (col > lastColumn) { return; } if (col < firstColumn) { firstColumn--; modified = true; } if (col <= lastColumn) { lastColumn--; modified = true; } } /** * Removes a row from this spreadsheet. If the row is out of * range of the columns in the sheet, then no action is taken * * @param row the row to remove */ public void removeRow(int row) { if (row > lastRow) { return; } if (row < firstRow) { firstRow--; modified = true; } if (row <= lastRow) { lastRow--; modified = true; } } /** * Inserts a blank row into this spreadsheet. If the row is out of range * of the rows in the sheet, then no action is taken * * @param row the row to insert */ public void insertRow(int row) { if (row > lastRow) { return; } if (row <= firstRow) { firstRow++; modified = true; } if (row <= lastRow) { lastRow++; modified = true; } } } /** * Constructor */ public ConditionalFormatRangeRecord(Record t) { super(t); initialized = false; modified = false; data = getRecord().getData(); } /** * Initialization function */ private void initialize() { enclosingRange = new Range(); enclosingRange.firstRow = IntegerHelper.getInt(data[4], data[5]); enclosingRange.lastRow = IntegerHelper.getInt(data[6], data[7]); enclosingRange.firstColumn = IntegerHelper.getInt(data[8], data[9]); enclosingRange.lastColumn = IntegerHelper.getInt(data[10], data[11]); numRanges = IntegerHelper.getInt(data[12], data[13]); ranges = new Range[numRanges]; int pos = 14; for (int i = 0; i < numRanges; i++) { ranges[i] = new Range(); ranges[i].firstRow = IntegerHelper.getInt(data[pos], data[pos+1]); ranges[i].lastRow = IntegerHelper.getInt(data[pos+2], data[pos+3]); ranges[i].firstColumn = IntegerHelper.getInt(data[pos+4], data[pos+5]); ranges[i].lastColumn = IntegerHelper.getInt(data[pos+6], data[pos+7]); pos += 8; } initialized = true; } /** * Inserts a blank column into this spreadsheet. If the column is out of * range of the columns in the sheet, then no action is taken * * @param col the column to insert */ public void insertColumn(int col) { if (!initialized) { initialize(); } enclosingRange.insertColumn(col); if (enclosingRange.modified) { modified = true; } for (int i = 0 ; i < ranges.length ; i++) { ranges[i].insertColumn(col); if (ranges[i].modified) { modified = true; } } return; } /** * Inserts a blank column into this spreadsheet. If the column is out of * range of the columns in the sheet, then no action is taken * * @param col the column to insert */ public void removeColumn(int col) { if (!initialized) { initialize(); } enclosingRange.removeColumn(col); if (enclosingRange.modified) { modified = true; } for (int i = 0 ; i < ranges.length ; i++) { ranges[i].removeColumn(col); if (ranges[i].modified) { modified = true; } } return; } /** * Removes a row from this spreadsheet. If the row is out of * range of the columns in the sheet, then no action is taken * * @param row the row to remove */ public void removeRow(int row) { if (!initialized) { initialize(); } enclosingRange.removeRow(row); if (enclosingRange.modified) { modified = true; } for (int i = 0 ; i < ranges.length ; i++) { ranges[i].removeRow(row); if (ranges[i].modified) { modified = true; } } return; } /** * Inserts a blank row into this spreadsheet. If the row is out of range * of the rows in the sheet, then no action is taken * * @param row the row to insert */ public void insertRow(int row) { if (!initialized) { initialize(); } enclosingRange.insertRow(row); if (enclosingRange.modified) { modified = true; } for (int i = 0 ; i < ranges.length ; i++) { ranges[i].insertRow(row); if (ranges[i].modified) { modified = true; } } return; } /** * Retrieves the data for output to binary file * * @return the data to be written */ public byte[] getData() { if (!modified) { return data; } byte[] d = new byte[14 + ranges.length * 8]; // Copy in the original information System.arraycopy(data, 0, d, 0, 4); // Create the new range IntegerHelper.getTwoBytes(enclosingRange.firstRow, d, 4); IntegerHelper.getTwoBytes(enclosingRange.lastRow, d, 6); IntegerHelper.getTwoBytes(enclosingRange.firstColumn, d, 8); IntegerHelper.getTwoBytes(enclosingRange.lastColumn, d, 10); IntegerHelper.getTwoBytes(numRanges, d, 12); int pos = 14; for (int i = 0 ; i < ranges.length ; i++) { IntegerHelper.getTwoBytes(ranges[i].firstRow, d, pos); IntegerHelper.getTwoBytes(ranges[i].lastRow, d, pos+2); IntegerHelper.getTwoBytes(ranges[i].firstColumn, d, pos+4); IntegerHelper.getTwoBytes(ranges[i].lastColumn, d, pos+6); pos += 8; } return d; } } jexcelapi/src/jxl/biff/RangeImpl.java0000750000175000017500000000754211207000612017724 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; import jxl.common.Logger; import jxl.Cell; import jxl.Range; import jxl.Sheet; /** * Implementation class for the Range interface. This merely * holds the raw range information, and when the time comes, it * interrogates the workbook for the object. * This does not keep handles to the objects for performance reasons, * as this could impact garbage collection on larger spreadsheets */ public class RangeImpl implements Range { /** * The logger */ private static Logger logger = Logger.getLogger(RangeImpl.class); /** * A handle to the workbook */ private WorkbookMethods workbook; /** * The sheet index containing the column at the top left */ private int sheet1; /** * The column number of the cell at the top left of the range */ private int column1; /** * The row number of the cell at the top left of the range */ private int row1; /** * The sheet index of the cell at the bottom right */ private int sheet2; /** * The column index of the cell at the bottom right */ private int column2; /** * The row index of the cell at the bottom right */ private int row2; /** * Constructor * @param w the workbook * @param es the external sheet * @param s1 the sheet of the top left cell of the range * @param c1 the column number of the top left cell of the range * @param r1 the row number of the top left cell of the range * @param s2 the sheet of the bottom right cell * @param c2 the column number of the bottom right cell of the range * @param r2 the row number of the bottomr right cell of the range */ public RangeImpl(WorkbookMethods w, int s1, int c1, int r1, int s2, int c2, int r2) { workbook = w; sheet1 = s1; sheet2 = s2; row1 = r1; row2 = r2; column1 = c1; column2 = c2; } /** * Gets the cell at the top left of this range * * @return the cell at the top left */ public Cell getTopLeft() { Sheet s = workbook.getReadSheet(sheet1); if (column1 < s.getColumns() && row1 < s.getRows()) { return s.getCell(column1, row1); } else { return new EmptyCell(column1, row1); } } /** * Gets the cell at the bottom right of this range * * @return the cell at the bottom right */ public Cell getBottomRight() { Sheet s = workbook.getReadSheet(sheet2); if (column2 < s.getColumns() && row2 < s.getRows()) { return s.getCell(column2, row2); } else { return new EmptyCell(column2, row2); } } /** * Gets the index of the first sheet in the range * * @return the index of the first sheet in the range */ public int getFirstSheetIndex() { return sheet1; } /** * Gets the index of the last sheet in the range * * @return the index of the last sheet in the range */ public int getLastSheetIndex() { return sheet2; } } jexcelapi/src/jxl/biff/DisplayFormat.java0000750000175000017500000000341211207000612020614 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; /** * The interface implemented by the various number and date format styles. * The methods on this interface are called internally when generating a * spreadsheet */ public interface DisplayFormat { /** * Accessor for the index style of this format * * @return the index for this format */ public int getFormatIndex(); /** * Accessor to see whether this format has been initialized * * @return TRUE if initialized, FALSE otherwise */ public boolean isInitialized(); /** * Initializes this format with the specified index number * * @param pos the position of this format record in the workbook */ public void initialize(int pos); /** * Accessor to determine whether or not this format is built in * * @return TRUE if this format is a built in format, FALSE otherwise */ public boolean isBuiltIn(); } jexcelapi/src/jxl/biff/WorkspaceInformationRecord.java0000750000175000017500000000640611207000612023347 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; import jxl.common.Logger; import jxl.read.biff.Record; /** * A record detailing whether the sheet is protected */ public class WorkspaceInformationRecord extends WritableRecordData { // the logger private static Logger logger = Logger.getLogger(WorkspaceInformationRecord.class); /** * The options byte */ private int wsoptions; /** * The row outlines */ private boolean rowOutlines; /** * The column outlines */ private boolean columnOutlines; /** * The fit to pages flag */ private boolean fitToPages; // the masks private static final int FIT_TO_PAGES = 0x100; private static final int SHOW_ROW_OUTLINE_SYMBOLS = 0x400; private static final int SHOW_COLUMN_OUTLINE_SYMBOLS = 0x800; private static final int DEFAULT_OPTIONS = 0x4c1; /** * Constructs this object from the raw data * * @param t the raw data */ public WorkspaceInformationRecord(Record t) { super(t); byte[] data = getRecord().getData(); wsoptions = IntegerHelper.getInt(data[0], data[1]); fitToPages = (wsoptions | FIT_TO_PAGES) != 0; rowOutlines = (wsoptions | SHOW_ROW_OUTLINE_SYMBOLS) != 0; columnOutlines = (wsoptions | SHOW_COLUMN_OUTLINE_SYMBOLS) != 0; } /** * Constructs this object from the raw data */ public WorkspaceInformationRecord() { super(Type.WSBOOL); wsoptions = DEFAULT_OPTIONS; } /** * Gets the fit to pages flag * * @return TRUE if fit to pages is set */ public boolean getFitToPages() { return fitToPages; } /** * Sets the fit to page flag * * @param b fit to page indicator */ public void setFitToPages(boolean b) { fitToPages = b; } /** * Sets the outlines */ public void setRowOutlines(boolean ro) { rowOutlines = true; } /** * Sets the outlines */ public void setColumnOutlines(boolean ro) { rowOutlines = true; } /** * Gets the binary data for output to file * * @return the binary data */ public byte[] getData() { byte[] data = new byte[2]; if (fitToPages) { wsoptions |= FIT_TO_PAGES; } if (rowOutlines) { wsoptions |= SHOW_ROW_OUTLINE_SYMBOLS; } if (columnOutlines) { wsoptions |= SHOW_COLUMN_OUTLINE_SYMBOLS; } IntegerHelper.getTwoBytes(wsoptions, data, 0); return data; } } jexcelapi/src/jxl/biff/PaletteRecord.java0000750000175000017500000001255611207000612020604 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; import jxl.format.Colour; import jxl.format.RGB; import jxl.read.biff.Record; /** * A record representing the RGB colour palette */ public class PaletteRecord extends WritableRecordData { /** * The list of bespoke rgb colours used by this sheet */ private RGB[] rgbColours = new RGB[numColours]; /** * A dirty flag indicating that this palette has been tampered with * in some way */ private boolean dirty; /** * Flag indicating that the palette was read in */ private boolean read; /** * Initialized flag */ private boolean initialized; /** * The number of colours in the palette */ private static final int numColours = 56; /** * Constructor * * @param t the raw bytes */ public PaletteRecord(Record t) { super(t); initialized = false; dirty = false; read = true; } /** * Default constructor - used when there is no palette specified */ public PaletteRecord() { super(Type.PALETTE); initialized = true; dirty = false; read = false; // Initialize the array with all the default colours Colour[] colours = Colour.getAllColours(); for (int i = 0; i < colours.length; i++) { Colour c = colours[i]; setColourRGB(c, c.getDefaultRGB().getRed(), c.getDefaultRGB().getGreen(), c.getDefaultRGB().getBlue()); } } /** * Accessor for the binary data - used when copying * * @return the binary data */ public byte[] getData() { // Palette was read in, but has not been changed if (read && !dirty) { return getRecord().getData(); } byte[] data = new byte[numColours * 4 + 2]; int pos = 0; // Set the number of records IntegerHelper.getTwoBytes(numColours, data, pos); // Set the rgb content for (int i = 0; i < numColours; i++) { pos = i * 4 + 2; data[pos] = (byte) rgbColours[i].getRed(); data[pos + 1] = (byte) rgbColours[i].getGreen(); data[pos + 2] = (byte) rgbColours[i].getBlue(); } return data; } /** * Initialize the record data */ private void initialize() { byte[] data = getRecord().getData(); int numrecords = IntegerHelper.getInt(data[0], data[1]); for (int i = 0; i < numrecords; i++) { int pos = i * 4 + 2; int red = IntegerHelper.getInt(data[pos], (byte) 0); int green = IntegerHelper.getInt(data[pos + 1], (byte) 0); int blue = IntegerHelper.getInt(data[pos + 2], (byte) 0); rgbColours[i] = new RGB(red, green, blue); } initialized = true; } /** * Accessor for the dirty flag, which indicates if this palette has been * modified * * @return TRUE if the palette has been modified, FALSE if it is the default */ public boolean isDirty() { return dirty; } /** * Sets the RGB value for the specified colour for this workbook * * @param c the colour whose RGB value is to be overwritten * @param r the red portion to set (0-255) * @param g the green portion to set (0-255) * @param b the blue portion to set (0-255) */ public void setColourRGB(Colour c, int r, int g, int b) { // Only colours on the standard palette with values 8-64 are acceptable int pos = c.getValue() - 8; if (pos < 0 || pos >= numColours) { return; } if (!initialized) { initialize(); } // Force the colours into the range 0-255 r = setValueRange(r, 0, 0xff); g = setValueRange(g, 0, 0xff); b = setValueRange(b, 0, 0xff); rgbColours[pos] = new RGB(r, g, b); // Indicate that the palette has been modified dirty = true; } /** * Gets the colour RGB from the palette * * @param c the colour * @return an RGB structure */ public RGB getColourRGB(Colour c) { // Only colours on the standard palette with values 8-64 are acceptable int pos = c.getValue() - 8; if (pos < 0 || pos >= numColours) { return c.getDefaultRGB(); } if (!initialized) { initialize(); } return rgbColours[pos]; } /** * Forces the value passed in to be between the range passed in * * @param val the value to constrain * @param min the minimum acceptable value * @param max the maximum acceptable value * @return the constrained value */ private int setValueRange(int val, int min, int max) { val = Math.max(val, min); val = Math.min(val, max); return val; } } jexcelapi/src/jxl/biff/formula/0000750000175000017500000000000011270605356016655 5ustar drazzibdrazzibjexcelapi/src/jxl/biff/formula/StringOperator.java0000750000175000017500000001065011207000612022467 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; import java.util.Stack; import jxl.common.Assert; /** * Ambiguously defined operator, used as a place holder when parsing * string formulas. At this stage it could be either * a unary or binary operator - the string parser will deduce which and * create the appropriate type */ abstract class StringOperator extends Operator { /** * Constructor */ protected StringOperator() { super(); } /** * Gets the operands for this operator from the stack. Does nothing * here */ public void getOperands(Stack s) { Assert.verify(false); } /** * Gets the precedence for this operator. Does nothing here * * @return the operator precedence */ int getPrecedence() { Assert.verify(false); return 0; } /** * Gets the token representation of this item in RPN. Does nothing here * * @return the bytes applicable to this formula */ byte[] getBytes() { Assert.verify(false); return null; } /** * Gets the string representation of this item */ void getString(StringBuffer buf) { Assert.verify(false); } /** * Default behaviour is to do nothing * * @param colAdjust the amount to add on to each relative cell reference * @param rowAdjust the amount to add on to each relative row reference */ public void adjustRelativeCellReferences(int colAdjust, int rowAdjust) { Assert.verify(false); } /** * Default behaviour is to do nothing * * @param sheetIndex the sheet on which the column was inserted * @param col the column number which was inserted * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void columnInserted(int sheetIndex, int col, boolean currentSheet) { Assert.verify(false); } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the column was removed * @param col the column number which was removed * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void columnRemoved(int sheetIndex, int col, boolean currentSheet) { Assert.verify(false); } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the row was inserted * @param row the row number which was inserted * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void rowInserted(int sheetIndex, int row, boolean currentSheet) { Assert.verify(false); } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the row was removed * @param row the row number which was removed * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void rowRemoved(int sheetIndex, int row, boolean currentSheet) { Assert.verify(false); } /** * Abstract method which gets the binary version of this operator */ abstract Operator getBinaryOperator(); /** * Abstract method which gets the unary version of this operator */ abstract Operator getUnaryOperator(); } jexcelapi/src/jxl/biff/formula/Subtract.java0000750000175000017500000000303311207000612021271 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; /** * A cell reference in a formula */ class Subtract extends BinaryOperator implements ParsedThing { /** * Constructor */ public Subtract() { } public String getSymbol() { return "-"; } /** * Abstract method which gets the token for this operator * * @return the string symbol for this token */ Token getToken() { return Token.SUBTRACT; } /** * Gets the precedence for this operator. Operator precedents run from * 1 to 5, one being the highest, 5 being the lowest * * @return the operator precedence */ int getPrecedence() { return 4; } } jexcelapi/src/jxl/biff/formula/FunctionNames.java0000750000175000017500000000526211207000612022261 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; import java.util.HashMap; import java.util.Locale; import java.util.ResourceBundle; import jxl.common.Logger; /** * A class which contains the function names for the current workbook. The * function names can potentially vary from workbook to workbook depending * on the locale */ public class FunctionNames { /** * The logger class */ private static Logger logger = Logger.getLogger(FunctionNames.class); /** * A hash mapping keyed on the function and returning its locale specific * name */ private HashMap names; /** * A hash mapping keyed on the locale specific name and returning the * function */ private HashMap functions; /** * Constructor * * @param l the locale */ public FunctionNames(Locale l) { ResourceBundle rb = ResourceBundle.getBundle("functions", l); Function[] allfunctions = Function.getFunctions(); names = new HashMap(allfunctions.length); functions = new HashMap(allfunctions.length); // Iterate through all the functions, adding them to the hash maps Function f = null; String n = null; String propname = null; for (int i = 0; i < allfunctions.length; i++) { f = allfunctions[i]; propname = f.getPropertyName(); n = propname.length() != 0 ? rb.getString(propname) : null; if (n != null) { names.put(f, n); functions.put(n, f); } } } /** * Gets the function for the specified name * * @param s the string * @return the function */ Function getFunction(String s) { return (Function) functions.get(s); } /** * Gets the name for the function * * @param f the function * @return the string */ String getName(Function f) { return (String) names.get(f); } } jexcelapi/src/jxl/biff/formula/DoubleValue.java0000750000175000017500000000537111207000612021720 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; import jxl.common.Logger; import jxl.biff.DoubleHelper; /** * A cell reference in a formula */ class DoubleValue extends NumberValue implements ParsedThing { /** * The logger */ private static Logger logger = Logger.getLogger(DoubleValue.class); /** * The value of this double in the formula */ private double value; /** * Constructor */ public DoubleValue() { } /** * Constructor - invoked when writing an integer value that's out * of range for a short * * @param v the double value */ DoubleValue(double v) { value = v; } /** * Constructor for a double value when reading from a string * * @param s the string representation of this token */ public DoubleValue(String s) { try { value = Double.parseDouble(s); } catch (NumberFormatException e) { logger.warn(e, e); value = 0; } } /** * Reads the ptg data from the array starting at the specified position * * @param data the RPN array * @param pos the current position in the array, excluding the ptg identifier * @return the number of bytes read */ public int read(byte[] data, int pos) { value = DoubleHelper.getIEEEDouble(data, pos); return 8; } /** * Gets the token representation of this item in RPN * * @return the bytes applicable to this formula */ byte[] getBytes() { byte[] data = new byte[9]; data[0] = Token.DOUBLE.getCode(); DoubleHelper.getIEEEBytes(value, data, 1); return data; } /** * The double value * * @return the value */ public double getValue() { return value; } /** * If this formula was on an imported sheet, check that * cell references to another sheet are warned appropriately * Does nothing */ void handleImportedCellReferences() { } } jexcelapi/src/jxl/biff/formula/CellReference.java0000750000175000017500000001564211207000612022211 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; import jxl.common.Logger; import jxl.Cell; import jxl.biff.CellReferenceHelper; import jxl.biff.IntegerHelper; /** * A cell reference in a formula */ class CellReference extends Operand implements ParsedThing { /** * The logger */ private static Logger logger = Logger.getLogger(CellReference.class); /** * Indicates whether the column reference is relative or absolute */ private boolean columnRelative; /** * Indicates whether the row reference is relative or absolute */ private boolean rowRelative; /** * The column reference */ private int column; /** * The row reference */ private int row; /** * The cell containing the formula. Stored in order to determine * relative cell values */ private Cell relativeTo; /** * Constructor * * @param rt the cell containing the formula */ public CellReference(Cell rt) { relativeTo = rt; } /** * Constructor */ public CellReference() { } /** * Constructor invoked when parsing a text string * * @param s the string being parsed */ public CellReference(String s) { column = CellReferenceHelper.getColumn(s); row = CellReferenceHelper.getRow(s); columnRelative = CellReferenceHelper.isColumnRelative(s); rowRelative = CellReferenceHelper.isRowRelative(s); } /** * Reads the ptg data from the array starting at the specified position * * @param data the RPN array * @param pos the current position in the array, excluding the ptg identifier * @return the number of bytes read */ public int read(byte[] data, int pos) { row = IntegerHelper.getInt(data[pos], data[pos + 1]); int columnMask = IntegerHelper.getInt(data[pos + 2], data[pos + 3]); column = columnMask & 0x00ff; columnRelative = ((columnMask & 0x4000) != 0); rowRelative = ((columnMask & 0x8000) != 0); return 4; } /** * Accessor for the column * * @return the column */ public int getColumn() { return column; } /** * Accessor for the row * * @return the row */ public int getRow() { return row; } /** * Gets the cell reference as a string for this item * * @param buf the string buffer to populate */ public void getString(StringBuffer buf) { CellReferenceHelper.getCellReference(column, !columnRelative, row, !rowRelative, buf); } /** * Gets the token representation of this item in RPN * * @return the bytes applicable to this formula */ byte[] getBytes() { byte[] data = new byte[5]; data[0] = !useAlternateCode() ? Token.REF.getCode() : Token.REF.getCode2(); IntegerHelper.getTwoBytes(row, data, 1); int grcol = column; // Set the row/column relative bits if applicable if (rowRelative) { grcol |= 0x8000; } if (columnRelative) { grcol |= 0x4000; } IntegerHelper.getTwoBytes(grcol, data, 3); return data; } /** * Adjusts all the relative cell references in this formula by the * amount specified. Used when copying formulas * * @param colAdjust the amount to add on to each relative cell reference * @param rowAdjust the amount to add on to each relative row reference */ public void adjustRelativeCellReferences(int colAdjust, int rowAdjust) { if (columnRelative) { column += colAdjust; } if (rowRelative) { row += rowAdjust; } } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the column was inserted * @param col the column number which was inserted * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ public void columnInserted(int sheetIndex, int col, boolean currentSheet) { if (!currentSheet) { return; } if (column >= col) { column++; } } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the column was removed * @param col the column number which was removed * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void columnRemoved(int sheetIndex, int col, boolean currentSheet) { if (!currentSheet) { return; } if (column >= col) { column--; } } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the row was inserted * @param r the row number which was inserted * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void rowInserted(int sheetIndex, int r, boolean currentSheet) { if (!currentSheet) { return; } if (row >= r) { row++; } } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the row was removed * @param r the row number which was removed * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void rowRemoved(int sheetIndex, int r, boolean currentSheet) { if (!currentSheet) { return; } if (row >= r) { row--; } } /** * If this formula was on an imported sheet, check that * cell references to another sheet are warned appropriately * Flags the formula as invalid * Does nothing here */ void handleImportedCellReferences() { } } jexcelapi/src/jxl/biff/formula/ParseContext.java0000750000175000017500000000234011207000612022121 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; /** * Enumeration type for the context in which this formula is being parsed */ public class ParseContext { public static ParseContext DEFAULT = new ParseContext(); public static ParseContext DATA_VALIDATION = new ParseContext(); /** * Private constructor */ private ParseContext() { } } jexcelapi/src/jxl/biff/formula/Equal.java0000750000175000017500000000314711207000612020557 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; /** * A cell reference in a formula */ class Equal extends BinaryOperator implements ParsedThing { /** * Constructor */ public Equal() { } /** * Gets the string for this symbol * * @return the symbol string */ public String getSymbol() { return "="; } /** * Abstract method which gets the token for this operator * * @return the string symbol for this token */ Token getToken() { return Token.EQUAL; } /** * Gets the precedence for this operator. Operator precedents run from * 1 to 5, one being the highest, 5 being the lowest * * @return the operator precedence */ int getPrecedence() { return 5; } } jexcelapi/src/jxl/biff/formula/StringFormulaParser.java0000750000175000017500000003636011207000612023464 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; import java.io.IOException; import java.io.StringReader; import java.util.ArrayList; import java.util.Iterator; import java.util.Stack; import jxl.common.Logger; import jxl.WorkbookSettings; import jxl.biff.WorkbookMethods; /** * Parses a string formula into a parse tree */ class StringFormulaParser implements Parser { /** * The logger */ private static Logger logger = Logger.getLogger(StringFormulaParser.class); /** * The formula string passed to this object */ private String formula; /** * The parsed formula string, as retrieved from the parse tree */ private String parsedFormula; /** * The parse tree */ private ParseItem root; /** * The stack argument used when parsing a function in order to * pass multiple arguments back to the calling method */ private Stack arguments; /** * The workbook settings */ private WorkbookSettings settings; /** * A handle to the external sheet */ private ExternalSheet externalSheet; /** * A handle to the name table */ private WorkbookMethods nameTable; /** * The parse context */ private ParseContext parseContext; /** * Constructor * @param f * @param ws */ public StringFormulaParser(String f, ExternalSheet es, WorkbookMethods nt, WorkbookSettings ws, ParseContext pc) { formula = f; settings = ws; externalSheet = es; nameTable = nt; parseContext = pc; } /** * Parses the list of tokens * * @exception FormulaException */ public void parse() throws FormulaException { ArrayList tokens = getTokens(); Iterator i = tokens.iterator(); root = parseCurrent(i); } /** * Recursively parses the token array. Recursion is used in order * to evaluate parentheses and function arguments * * @param i an iterator of tokens * @return the root node of the current parse stack * @exception FormulaException if an error occurs */ private ParseItem parseCurrent(Iterator i) throws FormulaException { Stack stack = new Stack(); Stack operators = new Stack(); Stack args = null; // we usually don't need this boolean parenthesesClosed = false; ParseItem lastParseItem = null; while (i.hasNext() && !parenthesesClosed) { ParseItem pi = (ParseItem) i.next(); pi.setParseContext(parseContext); if (pi instanceof Operand) { handleOperand((Operand) pi, stack); } else if (pi instanceof StringFunction) { handleFunction((StringFunction) pi, i, stack); } else if (pi instanceof Operator) { Operator op = (Operator) pi; // See if the operator is a binary or unary operator // It is a unary operator either if the stack is empty, or if // the last thing off the stack was another operator if (op instanceof StringOperator) { StringOperator sop = (StringOperator) op; if (stack.isEmpty() || lastParseItem instanceof Operator) { op = sop.getUnaryOperator(); } else { op = sop.getBinaryOperator(); } } if (operators.empty()) { // nothing much going on, so do nothing for the time being operators.push(op); } else { Operator operator = (Operator) operators.peek(); // If the last operator has a higher precedence then add this to // the operator stack and wait if (op.getPrecedence() < operator.getPrecedence()) { operators.push(op); } else if (op.getPrecedence() == operator.getPrecedence() && op instanceof UnaryOperator) { // The operators are of equal precedence, but because it is a // unary operator the operand isn't available yet, so put it on // the stack operators.push(op); } else { // The operator is of a lower precedence so we can sort out // some of the items on the stack operators.pop(); // remove the operator from the stack operator.getOperands(stack); stack.push(operator); operators.push(op); } } } else if (pi instanceof ArgumentSeparator) { // Clean up any remaining items on this stack while (!operators.isEmpty()) { Operator o = (Operator) operators.pop(); o.getOperands(stack); stack.push(o); } // Add it to the argument stack. Create the argument stack // if necessary. Items will be stored on the argument stack in // reverse order if (args == null) { args = new Stack(); } args.push(stack.pop()); stack.clear(); } else if (pi instanceof OpenParentheses) { ParseItem pi2 = parseCurrent(i); Parenthesis p = new Parenthesis(); pi2.setParent(p); p.add(pi2); stack.push(p); } else if (pi instanceof CloseParentheses) { parenthesesClosed = true; } lastParseItem = pi; } while (!operators.isEmpty()) { Operator o = (Operator) operators.pop(); o.getOperands(stack); stack.push(o); } ParseItem rt = !stack.empty()? (ParseItem) stack.pop():null; // if the argument stack is not null, then add it to that stack // as well for good measure if (args != null && rt != null) { args.push(rt); } arguments = args; if (!stack.empty() || !operators.empty() ) { logger.warn("Formula " + formula + " has a non-empty parse stack"); } return rt; } /** * Gets the list of lexical tokens using the generated lexical analyzer * * @return the list of tokens * @exception FormulaException if an error occurs */ private ArrayList getTokens() throws FormulaException { ArrayList tokens = new ArrayList(); StringReader sr = new StringReader(formula); Yylex lex = new Yylex(sr); lex.setExternalSheet(externalSheet); lex.setNameTable(nameTable); try { ParseItem pi = lex.yylex(); while (pi != null) { tokens.add(pi); pi = lex.yylex(); } } catch (IOException e) { logger.warn(e.toString()); } catch (Error e) { throw new FormulaException(FormulaException.LEXICAL_ERROR, formula + " at char " + lex.getPos()); } return tokens; } /** * Gets the formula as a string. Uses the parse tree to do this, and * does not simply return whatever string was passed in */ public String getFormula() { if (parsedFormula == null) { StringBuffer sb = new StringBuffer(); root.getString(sb); parsedFormula = sb.toString(); } return parsedFormula; } /** * Gets the bytes for the formula * * @return the bytes in RPN */ public byte[] getBytes() { byte[] bytes = root.getBytes(); if (root.isVolatile()) { byte[] newBytes = new byte[bytes.length + 4]; System.arraycopy(bytes, 0, newBytes, 4, bytes.length); newBytes[0] = Token.ATTRIBUTE.getCode(); newBytes[1] = (byte) 0x1; bytes = newBytes; } return bytes; } /** * Handles the case when parsing a string when a token is a function * * @param sf the string function * @param i the token iterator * @param stack the parse tree stack * @exception FormulaException if an error occurs */ private void handleFunction(StringFunction sf, Iterator i, Stack stack) throws FormulaException { ParseItem pi2 = parseCurrent(i); // If the function is unknown, then throw an error if (sf.getFunction(settings) == Function.UNKNOWN) { throw new FormulaException(FormulaException.UNRECOGNIZED_FUNCTION); } // First check for possible optimized functions and possible // use of the Attribute token if (sf.getFunction(settings) == Function.SUM && arguments == null) { // this is handled by an attribute Attribute a = new Attribute(sf, settings); a.add(pi2); stack.push(a); return; } if (sf.getFunction(settings) == Function.IF) { // this is handled by an attribute Attribute a = new Attribute(sf, settings); // Add in the if conditions as a var arg function in // the correct order VariableArgFunction vaf = new VariableArgFunction(settings); int numargs = arguments.size(); for (int j = 0 ; j < numargs; j++) { ParseItem pi3 = (ParseItem) arguments.get(j); vaf.add(pi3); } a.setIfConditions(vaf); stack.push(a); return; } // Function cannot be optimized. See if it is a variable argument // function or not if (sf.getFunction(settings).getNumArgs() == 0xff) { // If the arg stack has not been initialized, it means // that there was only one argument, which is the // returned parse item if (arguments == null) { int numArgs = pi2 != null? 1:0; VariableArgFunction vaf = new VariableArgFunction (sf.getFunction(settings), numArgs, settings); if (pi2 != null) { vaf.add(pi2); } stack.push(vaf); } else { // Add the args to the function in the correct order int numargs = arguments.size(); VariableArgFunction vaf = new VariableArgFunction (sf.getFunction(settings), numargs, settings); ParseItem[] args = new ParseItem[numargs]; for (int j = 0 ; j < numargs; j++) { ParseItem pi3 = (ParseItem) arguments.pop(); args[numargs-j-1] = pi3; } for (int j = 0 ; j < args.length ; j++) { vaf.add(args[j]); } stack.push(vaf); arguments.clear(); arguments = null; } return; } // Function is a standard built in function BuiltInFunction bif = new BuiltInFunction(sf.getFunction(settings), settings); int numargs = sf.getFunction(settings).getNumArgs(); if (numargs == 1) { // only one item which is the returned ParseItem bif.add(pi2); } else { if ((arguments == null && numargs != 0) || (arguments != null && numargs != arguments.size())) { throw new FormulaException(FormulaException.INCORRECT_ARGUMENTS); } // multiple arguments so go to the arguments stack. // Unlike the variable argument function, the args are // stored in reverse order for (int j = 0; j < numargs ; j++) { ParseItem pi3 = (ParseItem) arguments.get(j); bif.add(pi3); } } stack.push(bif); } /** * Default behaviour is to do nothing * * @param colAdjust the amount to add on to each relative cell reference * @param rowAdjust the amount to add on to each relative row reference */ public void adjustRelativeCellReferences(int colAdjust, int rowAdjust) { root.adjustRelativeCellReferences(colAdjust, rowAdjust); } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the column was inserted * @param col the column number which was inserted * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ public void columnInserted(int sheetIndex, int col, boolean currentSheet) { root.columnInserted(sheetIndex, col, currentSheet); } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the column was removed * @param col the column number which was removed * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ public void columnRemoved(int sheetIndex, int col, boolean currentSheet) { root.columnRemoved(sheetIndex, col, currentSheet); } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the column was inserted * @param row the column number which was inserted * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ public void rowInserted(int sheetIndex, int row, boolean currentSheet) { root.rowInserted(sheetIndex, row, currentSheet); } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the column was removed * @param row the column number which was removed * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ public void rowRemoved(int sheetIndex, int row, boolean currentSheet) { root.rowRemoved(sheetIndex, row, currentSheet); } /** * Handles operands by pushing them onto the stack * * @param o operand * @param stack stack */ private void handleOperand(Operand o, Stack stack) { if (!(o instanceof IntegerValue)) { stack.push(o); return; } if (o instanceof IntegerValue) { IntegerValue iv = (IntegerValue) o; if (!iv.isOutOfRange()) { stack.push(iv); } else { // convert to a double DoubleValue dv = new DoubleValue(iv.getValue()); stack.push(dv); } } } /** * If this formula was on an imported sheet, check that * cell references to another sheet are warned appropriately * * @return TRUE if the formula is valid import, FALSE otherwise */ public boolean handleImportedCellReferences() { root.handleImportedCellReferences(); return root.isValid(); } } jexcelapi/src/jxl/biff/formula/Power.java0000750000175000017500000000302211207000612020574 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; /** * A cell reference in a formula */ class Power extends BinaryOperator implements ParsedThing { /** * Constructor */ public Power() { } public String getSymbol() { return "^"; } /** * Abstract method which gets the token for this operator * * @return the string symbol for this token */ Token getToken() { return Token.POWER; } /** * Gets the precedence for this operator. Operator precedents run from * 1 to 5, one being the highest, 5 being the lowest * * @return the operator precedence */ int getPrecedence() { return 1; } } jexcelapi/src/jxl/biff/formula/OpenParentheses.java0000750000175000017500000000221111207000612022602 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; /** * A dummy token used when parsing strings in order to indicate the * opening of some parenthesees */ class OpenParentheses extends StringParseItem { /** * Constructor */ public OpenParentheses() { } } jexcelapi/src/jxl/biff/formula/FormulaException.java0000750000175000017500000000567111207000612023000 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; import jxl.JXLException; /** * Exception thrown when parsing a formula */ public class FormulaException extends JXLException { /** * Inner class containing the message */ private static class FormulaMessage { /** * The message */ private String message; /** * Constructs this exception with the specified message * * @param m the message */ FormulaMessage(String m) { message = m; } /** * Accessor for the message * * @return the message */ public String getMessage() { return message; } } /** */ static final FormulaMessage UNRECOGNIZED_TOKEN = new FormulaMessage("Unrecognized token"); /** */ static final FormulaMessage UNRECOGNIZED_FUNCTION = new FormulaMessage("Unrecognized function"); /** */ public static final FormulaMessage BIFF8_SUPPORTED = new FormulaMessage("Only biff8 formulas are supported"); /** */ static final FormulaMessage LEXICAL_ERROR = new FormulaMessage("Lexical error: "); /** */ static final FormulaMessage INCORRECT_ARGUMENTS = new FormulaMessage("Incorrect arguments supplied to function"); /** */ static final FormulaMessage SHEET_REF_NOT_FOUND = new FormulaMessage("Could not find sheet"); /** */ static final FormulaMessage CELL_NAME_NOT_FOUND = new FormulaMessage("Could not find named cell"); /** * Constructs this exception with the specified message * * @param m the message */ public FormulaException(FormulaMessage m) { super(m.message); } /** * Constructs this exception with the specified message * * @param m the message * @param val the value */ public FormulaException(FormulaMessage m, int val) { super(m.message + " " + val); } /** * Constructs this exception with the specified message * * @param m the message * @param val the value */ public FormulaException(FormulaMessage m, String val) { super(m.message + " " + val); } } jexcelapi/src/jxl/biff/formula/Yylex.java0000750000175000017500000005661711270605356020654 0ustar drazzibdrazzib/* The following code was generated by JFlex 1.4.1 on 24/10/09 14:10 */ /********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; /** * This file is generated by JLex. Do not alter the contents of this file * because changes will be overridden */ import jxl.biff.WorkbookMethods; /** * This class is a scanner generated by * JFlex 1.4.1 * on 24/10/09 14:10 from the specification file * xlformula.flex */ class Yylex { /** This character denotes the end of file */ public static final int YYEOF = -1; /** initial size of the lookahead buffer */ private static final int ZZ_BUFFERSIZE = 16384; /** lexical states */ public static final int YYSTRING = 1; public static final int YYINITIAL = 0; /** * Translates characters to character classes */ private static final String ZZ_CMAP_PACKED = "\10\0\3\25\25\0\1\25\1\24\1\21\1\26\1\10\2\0\1\22"+ "\1\5\1\6\1\41\1\37\1\4\1\40\1\7\1\33\1\34\11\2"+ "\1\3\1\0\1\44\1\43\1\42\1\36\1\0\1\16\2\1\1\30"+ "\1\14\1\15\2\1\1\31\2\1\1\17\1\35\1\27\3\1\1\12"+ "\1\20\1\11\1\13\1\32\4\1\4\0\1\23\1\0\32\1\uff85\0"; /** * Translates characters to character classes */ private static final char [] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED); /** * Translates DFA states to action switch labels. */ private static final int [] ZZ_ACTION = zzUnpackAction(); private static final String ZZ_ACTION_PACKED_0 = "\1\0\1\1\1\2\1\3\1\4\1\5\1\6\1\7"+ "\1\0\2\2\1\10\1\0\1\11\1\0\1\12\1\13"+ "\1\14\1\15\1\16\1\17\1\20\1\1\1\21\1\2"+ "\1\22\1\0\1\23\1\0\1\2\3\0\2\2\5\0"+ "\1\24\1\25\1\26\1\2\1\0\1\27\1\0\1\22"+ "\2\0\1\30\1\0\2\2\10\0\1\27\1\0\1\31"+ "\1\0\1\32\10\0\1\33\2\0\1\31\2\0\1\34"+ "\4\0\1\35\3\0\1\35\1\0\1\36\1\0"; private static int [] zzUnpackAction() { int [] result = new int[94]; int offset = 0; offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result); return result; } private static int zzUnpackAction(String packed, int offset, int [] result) { int i = 0; /* index in packed string */ int j = offset; /* index in unpacked array */ int l = packed.length(); while (i < l) { int count = packed.charAt(i++); int value = packed.charAt(i++); do result[j++] = value; while (--count > 0); } return j; } /** * Translates a state to a row index in the transition table */ private static final int [] ZZ_ROWMAP = zzUnpackRowMap(); private static final String ZZ_ROWMAP_PACKED_0 = "\0\0\0\45\0\112\0\157\0\224\0\224\0\224\0\224"+ "\0\271\0\336\0\u0103\0\224\0\u0128\0\224\0\u014d\0\224"+ "\0\224\0\224\0\224\0\u0172\0\224\0\u0197\0\u01bc\0\224"+ "\0\u01e1\0\u0206\0\u022b\0\224\0\u0250\0\u0275\0\u029a\0\u02bf"+ "\0\u02e4\0\u0309\0\u032e\0\u0353\0\u0378\0\u039d\0\u03c2\0\u03e7"+ "\0\224\0\224\0\224\0\u040c\0\u0431\0\u0456\0\u047b\0\u04a0"+ "\0\u04c5\0\u04ea\0\u02bf\0\u050f\0\u0534\0\u0559\0\u057e\0\u05a3"+ "\0\u05c8\0\u05ed\0\u0612\0\u0637\0\u065c\0\u0681\0\224\0\u06a6"+ "\0\u06cb\0\u06cb\0\u040c\0\u06f0\0\u0715\0\u073a\0\u075f\0\u0784"+ "\0\u07a9\0\u07ce\0\u07f3\0\u0818\0\u0818\0\u083d\0\u0862\0\u0887"+ "\0\u08ac\0\224\0\u08d1\0\u08f6\0\u091b\0\u0940\0\u0965\0\u098a"+ "\0\u09af\0\u09d4\0\224\0\u09f9\0\u0a1e\0\u0a1e"; private static int [] zzUnpackRowMap() { int [] result = new int[94]; int offset = 0; offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result); return result; } private static int zzUnpackRowMap(String packed, int offset, int [] result) { int i = 0; /* index in packed string */ int j = offset; /* index in unpacked array */ int l = packed.length(); while (i < l) { int high = packed.charAt(i++) << 16; result[j++] = high | packed.charAt(i++); } return j; } /** * The transition table of the DFA */ private static final int [] ZZ_TRANS = zzUnpackTrans(); private static final String ZZ_TRANS_PACKED_0 = "\1\0\1\3\1\4\1\5\1\6\1\7\1\10\1\0"+ "\1\11\1\12\3\3\1\13\3\3\1\14\1\15\2\0"+ "\1\16\1\17\4\3\1\20\1\4\1\3\1\0\1\21"+ "\1\22\1\23\1\24\1\25\1\26\21\27\1\30\23\27"+ "\1\0\1\31\1\32\1\33\1\0\1\34\2\0\1\35"+ "\10\31\2\0\1\36\1\37\2\0\4\31\1\0\1\32"+ "\1\31\11\0\1\4\4\0\1\40\24\0\1\4\56\0"+ "\1\41\7\0\10\41\6\0\4\41\2\0\1\41\10\0"+ "\1\31\1\32\1\33\1\0\1\34\2\0\1\35\1\31"+ "\1\42\6\31\2\0\1\36\1\37\2\0\4\31\1\0"+ "\1\32\1\31\10\0\1\31\1\32\1\33\1\0\1\34"+ "\2\0\1\35\5\31\1\43\2\31\2\0\1\36\1\37"+ "\2\0\4\31\1\0\1\32\1\31\7\0\22\15\1\44"+ "\22\15\12\0\1\45\14\0\1\46\1\47\1\0\1\50"+ "\55\0\1\51\43\0\1\52\1\53\1\0\21\27\1\0"+ "\23\27\1\0\1\54\1\32\1\33\1\0\1\34\2\0"+ "\1\35\10\54\2\0\1\36\1\37\2\0\4\54\1\0"+ "\1\32\1\54\10\0\1\36\1\32\1\55\5\0\10\36"+ "\2\0\1\36\3\0\4\36\1\0\1\32\1\36\10\0"+ "\1\56\6\0\1\57\10\56\6\0\4\56\2\0\1\56"+ "\11\0\1\60\31\0\1\60\11\0\2\36\6\0\10\36"+ "\2\0\1\36\3\0\4\36\1\0\2\36\10\0\1\61"+ "\6\0\1\62\10\61\6\0\4\61\2\0\1\61\11\0"+ "\1\63\31\0\1\63\11\0\1\64\1\60\1\33\4\0"+ "\1\35\10\64\6\0\4\64\1\0\1\60\1\64\10\0"+ "\1\54\1\32\1\33\1\0\1\34\2\0\1\35\2\54"+ "\1\65\5\54\2\0\1\36\1\37\2\0\4\54\1\0"+ "\1\32\1\54\10\0\1\54\1\32\1\33\1\0\1\34"+ "\2\0\1\35\6\54\1\66\1\54\2\0\1\36\1\37"+ "\2\0\4\54\1\0\1\32\1\54\33\0\1\67\34\0"+ "\1\70\43\0\1\71\2\0\1\72\57\0\1\73\31\0"+ "\1\74\27\0\1\54\1\36\2\0\1\34\3\0\10\54"+ "\2\0\1\36\1\37\2\0\4\54\1\0\1\36\1\54"+ "\10\0\1\75\6\0\1\76\10\75\6\0\4\75\2\0"+ "\1\75\10\0\1\77\7\0\10\77\6\0\4\77\2\0"+ "\1\77\10\0\1\56\7\0\10\56\6\0\4\56\2\0"+ "\1\56\11\0\1\60\1\55\30\0\1\60\11\0\1\100"+ "\1\101\5\0\1\102\10\100\6\0\4\100\1\0\1\101"+ "\1\100\10\0\1\61\7\0\10\61\6\0\4\61\2\0"+ "\1\61\11\0\1\60\1\33\4\0\1\35\23\0\1\60"+ "\11\0\1\54\1\36\2\0\1\34\3\0\3\54\1\103"+ "\4\54\2\0\1\36\1\37\2\0\4\54\1\0\1\36"+ "\1\54\10\0\1\54\1\36\2\0\1\34\3\0\7\54"+ "\1\65\2\0\1\36\1\37\2\0\4\54\1\0\1\36"+ "\1\54\10\0\1\104\6\0\1\105\10\104\6\0\4\104"+ "\2\0\1\104\24\0\1\106\46\0\1\107\15\0\1\106"+ "\44\0\1\110\41\0\1\111\31\0\1\112\26\0\1\113"+ "\1\114\5\0\1\115\10\113\6\0\4\113\1\0\1\114"+ "\1\113\10\0\1\75\7\0\10\75\6\0\4\75\2\0"+ "\1\75\11\0\1\101\5\0\1\102\23\0\1\101\12\0"+ "\1\101\31\0\1\101\11\0\1\116\1\117\1\120\4\0"+ "\1\121\10\116\6\0\4\116\1\0\1\117\1\116\10\0"+ "\1\104\7\0\10\104\6\0\4\104\2\0\1\104\33\0"+ "\1\122\37\0\1\106\41\0\1\123\63\0\1\124\24\0"+ "\1\125\33\0\1\114\5\0\1\115\23\0\1\114\12\0"+ "\1\114\31\0\1\114\12\0\1\117\1\120\4\0\1\121"+ "\23\0\1\117\12\0\1\117\1\126\30\0\1\117\11\0"+ "\1\127\6\0\1\130\10\127\6\0\4\127\2\0\1\127"+ "\11\0\1\117\31\0\1\117\46\0\1\122\42\0\1\106"+ "\24\0\1\106\31\0\1\131\6\0\1\132\10\131\6\0"+ "\4\131\2\0\1\131\10\0\1\133\7\0\10\133\6\0"+ "\4\133\2\0\1\133\10\0\1\127\7\0\10\127\6\0"+ "\4\127\2\0\1\127\10\0\1\134\1\135\5\0\1\136"+ "\10\134\6\0\4\134\1\0\1\135\1\134\10\0\1\131"+ "\7\0\10\131\6\0\4\131\2\0\1\131\11\0\1\135"+ "\5\0\1\136\23\0\1\135\12\0\1\135\31\0\1\135"+ "\10\0"; private static int [] zzUnpackTrans() { int [] result = new int[2627]; int offset = 0; offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result); return result; } private static int zzUnpackTrans(String packed, int offset, int [] result) { int i = 0; /* index in packed string */ int j = offset; /* index in unpacked array */ int l = packed.length(); while (i < l) { int count = packed.charAt(i++); int value = packed.charAt(i++); value--; do result[j++] = value; while (--count > 0); } return j; } /* error codes */ private static final int ZZ_UNKNOWN_ERROR = 0; private static final int ZZ_NO_MATCH = 1; private static final int ZZ_PUSHBACK_2BIG = 2; /* error messages for the codes above */ private static final String ZZ_ERROR_MSG[] = { "Unkown internal scanner error", "Error: could not match input", "Error: pushback value was too large" }; /** * ZZ_ATTRIBUTE[aState] contains the attributes of state aState */ private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute(); private static final String ZZ_ATTRIBUTE_PACKED_0 = "\1\0\3\1\4\11\1\0\2\1\1\11\1\0\1\11"+ "\1\0\4\11\1\1\1\11\2\1\1\11\2\1\1\0"+ "\1\11\1\0\1\1\3\0\2\1\5\0\3\11\1\1"+ "\1\0\1\1\1\0\1\1\2\0\1\1\1\0\2\1"+ "\10\0\1\11\1\0\1\1\1\0\1\1\10\0\1\1"+ "\2\0\1\1\2\0\1\11\4\0\1\1\3\0\1\11"+ "\1\0\1\1\1\0"; private static int [] zzUnpackAttribute() { int [] result = new int[94]; int offset = 0; offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result); return result; } private static int zzUnpackAttribute(String packed, int offset, int [] result) { int i = 0; /* index in packed string */ int j = offset; /* index in unpacked array */ int l = packed.length(); while (i < l) { int count = packed.charAt(i++); int value = packed.charAt(i++); do result[j++] = value; while (--count > 0); } return j; } /** the input device */ private java.io.Reader zzReader; /** the current state of the DFA */ private int zzState; /** the current lexical state */ private int zzLexicalState = YYINITIAL; /** this buffer contains the current text to be matched and is the source of the yytext() string */ private char zzBuffer[] = new char[ZZ_BUFFERSIZE]; /** the textposition at the last accepting state */ private int zzMarkedPos; /** the textposition at the last state to be included in yytext */ private int zzPushbackPos; /** the current text position in the buffer */ private int zzCurrentPos; /** startRead marks the beginning of the yytext() string in the buffer */ private int zzStartRead; /** endRead marks the last character in the buffer, that has been read from input */ private int zzEndRead; /** number of newlines encountered up to the start of the matched text */ private int yyline; /** the number of characters up to the start of the matched text */ private int yychar; /** * the number of characters from the last newline up to the start of the * matched text */ private int yycolumn; /** * zzAtBOL == true <=> the scanner is currently at the beginning of a line */ private boolean zzAtBOL = true; /** zzAtEOF == true <=> the scanner is at the EOF */ private boolean zzAtEOF; /* user code: */ int getPos() { return yychar ; } private boolean emptyString; private ExternalSheet externalSheet; private WorkbookMethods nameTable; void setExternalSheet(ExternalSheet es) { externalSheet = es; } void setNameTable(WorkbookMethods nt) { nameTable = nt; } /** * Creates a new scanner * There is also a java.io.InputStream version of this constructor. * * @param in the java.io.Reader to read input from. */ Yylex(java.io.Reader in) { this.zzReader = in; } /** * Creates a new scanner. * There is also java.io.Reader version of this constructor. * * @param in the java.io.Inputstream to read input from. */ Yylex(java.io.InputStream in) { this(new java.io.InputStreamReader(in)); } /** * Unpacks the compressed character translation table. * * @param packed the packed character translation table * @return the unpacked character translation table */ private static char [] zzUnpackCMap(String packed) { char [] map = new char[0x10000]; int i = 0; /* index in packed string */ int j = 0; /* index in unpacked array */ while (i < 100) { int count = packed.charAt(i++); char value = packed.charAt(i++); do map[j++] = value; while (--count > 0); } return map; } /** * Refills the input buffer. * * @return false, iff there was new input. * * @exception java.io.IOException if any I/O-Error occurs */ private boolean zzRefill() throws java.io.IOException { /* first: make room (if you can) */ if (zzStartRead > 0) { System.arraycopy(zzBuffer, zzStartRead, zzBuffer, 0, zzEndRead-zzStartRead); /* translate stored positions */ zzEndRead-= zzStartRead; zzCurrentPos-= zzStartRead; zzMarkedPos-= zzStartRead; zzPushbackPos-= zzStartRead; zzStartRead = 0; } /* is the buffer big enough? */ if (zzCurrentPos >= zzBuffer.length) { /* if not: blow it up */ char newBuffer[] = new char[zzCurrentPos*2]; System.arraycopy(zzBuffer, 0, newBuffer, 0, zzBuffer.length); zzBuffer = newBuffer; } /* finally: fill the buffer with new input */ int numRead = zzReader.read(zzBuffer, zzEndRead, zzBuffer.length-zzEndRead); if (numRead < 0) { return true; } else { zzEndRead+= numRead; return false; } } /** * Closes the input stream. */ public final void yyclose() throws java.io.IOException { zzAtEOF = true; /* indicate end of file */ zzEndRead = zzStartRead; /* invalidate buffer */ if (zzReader != null) zzReader.close(); } /** * Resets the scanner to read from a new input stream. * Does not close the old reader. * * All internal variables are reset, the old input stream * cannot be reused (internal buffer is discarded and lost). * Lexical state is set to ZZ_INITIAL. * * @param reader the new input stream */ public final void yyreset(java.io.Reader reader) { zzReader = reader; zzAtBOL = true; zzAtEOF = false; zzEndRead = zzStartRead = 0; zzCurrentPos = zzMarkedPos = zzPushbackPos = 0; yyline = yychar = yycolumn = 0; zzLexicalState = YYINITIAL; } /** * Returns the current lexical state. */ public final int yystate() { return zzLexicalState; } /** * Enters a new lexical state * * @param newState the new lexical state */ public final void yybegin(int newState) { zzLexicalState = newState; } /** * Returns the text matched by the current regular expression. */ public final String yytext() { return new String( zzBuffer, zzStartRead, zzMarkedPos-zzStartRead ); } /** * Returns the character at position pos from the * matched text. * * It is equivalent to yytext().charAt(pos), but faster * * @param pos the position of the character to fetch. * A value from 0 to yylength()-1. * * @return the character at position pos */ public final char yycharat(int pos) { return zzBuffer[zzStartRead+pos]; } /** * Returns the length of the matched text region. */ public final int yylength() { return zzMarkedPos-zzStartRead; } /** * Reports an error that occured while scanning. * * In a wellformed scanner (no or only correct usage of * yypushback(int) and a match-all fallback rule) this method * will only be called with things that "Can't Possibly Happen". * If this method is called, something is seriously wrong * (e.g. a JFlex bug producing a faulty scanner etc.). * * Usual syntax/scanner level error handling should be done * in error fallback rules. * * @param errorCode the code of the errormessage to display */ private void zzScanError(int errorCode) { String message; try { message = ZZ_ERROR_MSG[errorCode]; } catch (ArrayIndexOutOfBoundsException e) { message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR]; } throw new Error(message); } /** * Pushes the specified amount of characters back into the input stream. * * They will be read again by then next call of the scanning method * * @param number the number of characters to be read again. * This number must not be greater than yylength()! */ public void yypushback(int number) { if ( number > yylength() ) zzScanError(ZZ_PUSHBACK_2BIG); zzMarkedPos -= number; } /** * Resumes scanning until the next regular expression is matched, * the end of input is encountered or an I/O-Error occurs. * * @return the next token * @exception java.io.IOException if any I/O-Error occurs */ public ParseItem yylex() throws java.io.IOException, jxl.biff.formula.FormulaException { int zzInput; int zzAction; // cached fields: int zzCurrentPosL; int zzMarkedPosL; int zzEndReadL = zzEndRead; char [] zzBufferL = zzBuffer; char [] zzCMapL = ZZ_CMAP; int [] zzTransL = ZZ_TRANS; int [] zzRowMapL = ZZ_ROWMAP; int [] zzAttrL = ZZ_ATTRIBUTE; while (true) { zzMarkedPosL = zzMarkedPos; yychar+= zzMarkedPosL-zzStartRead; boolean zzR = false; for (zzCurrentPosL = zzStartRead; zzCurrentPosL < zzMarkedPosL; zzCurrentPosL++) { switch (zzBufferL[zzCurrentPosL]) { case '\u000B': case '\u000C': case '\u0085': case '\u2028': case '\u2029': yyline++; zzR = false; break; case '\r': yyline++; zzR = true; break; case '\n': if (zzR) zzR = false; else { yyline++; } break; default: zzR = false; } } if (zzR) { // peek one character ahead if it is \n (if we have counted one line too much) boolean zzPeek; if (zzMarkedPosL < zzEndReadL) zzPeek = zzBufferL[zzMarkedPosL] == '\n'; else if (zzAtEOF) zzPeek = false; else { boolean eof = zzRefill(); zzEndReadL = zzEndRead; zzMarkedPosL = zzMarkedPos; zzBufferL = zzBuffer; if (eof) zzPeek = false; else zzPeek = zzBufferL[zzMarkedPosL] == '\n'; } if (zzPeek) yyline--; } zzAction = -1; zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL; zzState = zzLexicalState; zzForAction: { while (true) { if (zzCurrentPosL < zzEndReadL) zzInput = zzBufferL[zzCurrentPosL++]; else if (zzAtEOF) { zzInput = YYEOF; break zzForAction; } else { // store back cached positions zzCurrentPos = zzCurrentPosL; zzMarkedPos = zzMarkedPosL; boolean eof = zzRefill(); // get translated positions and possibly new buffer zzCurrentPosL = zzCurrentPos; zzMarkedPosL = zzMarkedPos; zzBufferL = zzBuffer; zzEndReadL = zzEndRead; if (eof) { zzInput = YYEOF; break zzForAction; } else { zzInput = zzBufferL[zzCurrentPosL++]; } } int zzNext = zzTransL[ zzRowMapL[zzState] + zzCMapL[zzInput] ]; if (zzNext == -1) break zzForAction; zzState = zzNext; int zzAttributes = zzAttrL[zzState]; if ( (zzAttributes & 1) == 1 ) { zzAction = zzState; zzMarkedPosL = zzCurrentPosL; if ( (zzAttributes & 8) == 8 ) break zzForAction; } } } // store back cached position zzMarkedPos = zzMarkedPosL; switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) { case 12: { return new Minus() ; } case 31: break; case 7: { return new CloseParentheses() ; } case 32: break; case 3: { return new IntegerValue(yytext()) ; } case 33: break; case 24: { return new DoubleValue(yytext()) ; } case 34: break; case 29: { return new ColumnRange3d(yytext(),externalSheet) ; } case 35: break; case 4: { return new RangeSeparator(); } case 36: break; case 10: { return new Divide() ; } case 37: break; case 25: { return new CellReference3d(yytext(),externalSheet) ; } case 38: break; case 26: { return new BooleanValue(yytext()); } case 39: break; case 15: { return new Equal() ; } case 40: break; case 17: { yybegin(YYINITIAL); if (emptyString) return new StringValue(""); } case 41: break; case 8: { emptyString = true; yybegin(YYSTRING); } case 42: break; case 21: { return new NotEqual() ; } case 43: break; case 22: { return new LessEqual() ; } case 44: break; case 16: { return new LessThan() ; } case 45: break; case 5: { return new ArgumentSeparator() ; } case 46: break; case 30: { return new Area3d(yytext(),externalSheet) ; } case 47: break; case 14: { return new GreaterThan() ; } case 48: break; case 18: { return new CellReference(yytext()) ; } case 49: break; case 20: { return new GreaterEqual() ; } case 50: break; case 27: { return new Area(yytext()) ; } case 51: break; case 23: { return new ColumnRange(yytext()); } case 52: break; case 1: { emptyString = false; return new StringValue(yytext()) ; } case 53: break; case 2: { return new NameRange(yytext(), nameTable); } case 54: break; case 19: { return new StringFunction(yytext()) ; } case 55: break; case 11: { return new Plus() ; } case 56: break; case 28: { return new ErrorConstant(yytext()); } case 57: break; case 9: { } case 58: break; case 13: { return new Multiply() ; } case 59: break; case 6: { return new OpenParentheses() ; } case 60: break; default: if (zzInput == YYEOF && zzStartRead == zzCurrentPos) { zzAtEOF = true; return null; } else { zzScanError(ZZ_NO_MATCH); } } } } } jexcelapi/src/jxl/biff/formula/ExternalSheet.java0000750000175000017500000000474011207000612022263 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; import jxl.read.biff.BOFRecord; /** * Interface which exposes the methods needed by formulas * to access external sheet records */ public interface ExternalSheet { /** * Gets the name of the external sheet specified by the index * * @param index the external sheet index * @return the name of the external sheet */ public String getExternalSheetName(int index); /** * Gets the index of the first external sheet for the name * * @param sheetName the name of the external sheet * @return the index of the external sheet with the specified name */ public int getExternalSheetIndex(String sheetName); /** * Gets the index of the first external sheet for the name * * @param index the external sheet index * @return the sheet index of the external sheet index */ public int getExternalSheetIndex(int index); /** * Gets the index of the last external sheet for the name * * @param sheetName the name of the external sheet * @return the index of the external sheet with the specified name */ public int getLastExternalSheetIndex(String sheetName); /** * Gets the index of the first external sheet for the name * * @param index the external sheet index * @return the sheet index of the external sheet index */ public int getLastExternalSheetIndex(int index); /** * Parsing of formulas is only supported for a subset of the available * biff version, so we need to test to see if this version is acceptable * * @return the BOF record */ public BOFRecord getWorkbookBof(); } jexcelapi/src/jxl/biff/formula/Parser.java0000750000175000017500000000751211207000612020744 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; /** * Interface used by the two different types of formula parser */ interface Parser { /** * Parses the formula * * @exception FormulaException if an error occurs */ public void parse() throws FormulaException; /** * Gets the string version of the formula * * @return the formula as a string */ public String getFormula(); /** * Gets the bytes for the formula. This takes into account any * token mapping necessary because of shared formulas * * @return the bytes in RPN */ public byte[] getBytes(); /** * Adjusts all the relative cell references in this formula by the * amount specified. * * @param colAdjust * @param rowAdjust */ public void adjustRelativeCellReferences(int colAdjust, int rowAdjust); /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the column was inserted * @param col the column number which was inserted * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ public void columnInserted(int sheetIndex, int col, boolean currentSheet); /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the column was removed * @param col the column number which was removed * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ public void columnRemoved(int sheetIndex, int col, boolean currentSheet); /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the column was inserted * @param row the column number which was inserted * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ public void rowInserted(int sheetIndex, int row, boolean currentSheet); /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the column was removed * @param row the column number which was removed * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ public void rowRemoved(int sheetIndex, int row, boolean currentSheet); /** * If this formula was on an imported sheet, check that * cell references to another sheet are warned appropriately * * @return TRUE if the formula is valid import, FALSE otherwise */ public boolean handleImportedCellReferences(); } jexcelapi/src/jxl/biff/formula/UnaryPlus.java0000750000175000017500000000341511207000612021450 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; /** * A cell reference in a formula */ class UnaryPlus extends UnaryOperator implements ParsedThing { /** * Constructor */ public UnaryPlus() { } public String getSymbol() { return "+"; } /** * Abstract method which gets the token for this operator * * @return the string symbol for this token */ Token getToken() { return Token.UNARY_PLUS; } /** * Gets the precedence for this operator. Operator precedents run from * 1 to 5, one being the highest, 5 being the lowest * * @return the operator precedence */ int getPrecedence() { return 2; } /** * If this formula was on an imported sheet, check that * cell references to another sheet are warned appropriately * Does nothing, as operators don't have cell references */ void handleImportedCellReferences() { } } jexcelapi/src/jxl/biff/formula/Union.java0000750000175000017500000000304211207000612020572 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2005 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; /** * A union of two cell ranges - the "," operator */ class Union extends BinaryOperator implements ParsedThing { /** * Constructor */ public Union() { } public String getSymbol() { return ","; } /** * Abstract method which gets the token for this operator * * @return the string symbol for this token */ Token getToken() { return Token.UNION; } /** * Gets the precedence for this operator. Operator precedents run from * 1 to 5, one being the highest, 5 being the lowest * * @return the operator precedence */ int getPrecedence() { return 4; } } jexcelapi/src/jxl/biff/formula/#CellReference3d.java#0000750000175000017500000001760511207000612022547 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; import jxl.common.Logger; import jxl.Cell; import jxl.biff.CellReferenceHelper; import jxl.biff.IntegerHelper; /** * A 3d cell reference in a formula */ class CellReference3d extends Operand implements ParsedThing { /** * The logger */ private static Logger logger = Logger.getLogger(CellReference3d.class); /** * Indicates whether the column reference is relative or absolute */ private boolean columnRelative; /** * Indicates whether the row reference is relative or absolute */ private boolean rowRelative; /** * The column reference */ private int column; /** * The row reference */ private int row; /** * The cell containing the formula. Stored in order to determine * relative cell values */ private Cell relativeTo; /** * The sheet which the reference is present on */ private int sheet; /** * A handle to the container of the external sheets ie. the workbook */ private ExternalSheet workbook; /** * Constructor * * @param rt the cell containing the formula * @param w the list of external sheets */ public CellReference3d(Cell rt, ExternalSheet w) { relativeTo = rt; workbook = w; } /** * Constructs this object from a string * * @param s the string * @param w the external sheet * @exception FormulaException */ public CellReference3d(String s, ExternalSheet w) throws FormulaException { workbook = w; columnRelative = true; rowRelative = true; // Get the cell details int sep = s.indexOf('!'); String cellString = s.substring(sep + 1); column = CellReferenceHelper.getColumn(cellString); row = CellReferenceHelper.getRow(cellString); // Get the sheet index String sheetName = s.substring(0, sep); logger.debug("Sheet name is " + sheetName); // Remove single quotes, if they exist if (sheetName.charAt(0) == '\'' && sheetName.charAt(sheetName.length() - 1) == '\'') { sheetName = sheetName.substring(1, sheetName.length() - 1); } sheet = w.getExternalSheetIndex(sheetName); if (sheet < 0) { throw new FormulaException(FormulaException.SHEET_REF_NOT_FOUND, sheetName); } } /** * Reads the ptg data from the array starting at the specified position * * @param data the RPN array * @param pos the current position in the array, excluding the ptg identifier * @return the number of bytes read */ public int read(byte[] data, int pos) { sheet = IntegerHelper.getInt(data[pos], data[pos + 1]); row = IntegerHelper.getInt(data[pos + 2], data[pos + 3]); int columnMask = IntegerHelper.getInt(data[pos + 4], data[pos + 5]); column = columnMask & 0x00ff; columnRelative = ((columnMask & 0x4000) != 0); rowRelative = ((columnMask & 0x8000) != 0); return 6; } /** * Accessor for the column * * @return the column number */ public int getColumn() { return column; } /** * Accessor for the row * * @return the row number */ public int getRow() { return row; } /** * Gets the string version of this cell reference * * @param buf the buffer to append to */ public void getString(StringBuffer buf) { CellReferenceHelper.getCellReference(sheet, column, !columnRelative, row, !rowRelative, workbook, buf); } /** * Gets the token representation of this item in RPN * * @return the bytes applicable to this formula */ byte[] getBytes() { byte[] data = new byte[7]; data[0] = Token.REF3D.getCode(); IntegerHelper.getTwoBytes(sheet, data, 1); IntegerHelper.getTwoBytes(row, data, 3); int grcol = column; // Set the row/column relative bits if applicable if (rowRelative) { grcol |= 0x8000; } if (columnRelative) { grcol |= 0x4000; } IntegerHelper.getTwoBytes(grcol, data, 5); return data; } /** * Adjusts all the relative cell references in this formula by the * amount specified. Used when copying formulas * * @param colAdjust the amount to add on to each relative cell reference * @param rowAdjust the amount to add on to each relative row reference */ public void adjustRelativeCellReferences(int colAdjust, int rowAdjust) { if (columnRelative) { column += colAdjust; } if (rowRelative) { row += rowAdjust; } } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the column was inserted * @param col the column number which was inserted * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ public void columnInserted(int sheetIndex, int col, boolean currentSheet) { if (sheetIndex != sheet) { return; } if (column >= col) { column++; } } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the column was removed * @param col the column number which was removed * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void columnRemoved(int sheetIndex, int col, boolean currentSheet) { if (sheetIndex != sheet) { return; } if (column >= col) { column--; } } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the row was inserted * @param r the row number which was inserted * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void rowInserted(int sheetIndex, int r, boolean currentSheet) { if (sheetIndex != sheet) { return; } if (row >= r) { row++; } } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the row was removed * @param r the row number which was removed * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void rowRemoved(int sheetIndex, int r, boolean currentSheet) { if (sheetIndex != sheet) { return; } if (row >= r) { row--; } } /** * If this formula was on an imported sheet, check that * cell references to another sheet are warned appropriately * Flags the formula as invalid */ void handleImportedCellReferences() { setInvalid(); } } jexcelapi/src/jxl/biff/formula/BuiltInFunction.java0000750000175000017500000001764211207000612022571 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; import java.util.Stack; import jxl.common.Assert; import jxl.common.Logger; import jxl.WorkbookSettings; import jxl.biff.IntegerHelper; /** * A built in function in a formula */ class BuiltInFunction extends Operator implements ParsedThing { /** * The logger */ private static Logger logger = Logger.getLogger(BuiltInFunction.class); /** * The function */ private Function function; /** * The workbook settings */ private WorkbookSettings settings; /** * Constructor * @param ws the workbook settings */ public BuiltInFunction(WorkbookSettings ws) { settings = ws; } /** * Constructor used when parsing a formula from a string * * @param f the function * @param ws the workbook settings */ public BuiltInFunction(Function f, WorkbookSettings ws) { function = f; settings = ws; } /** * Reads the ptg data from the array starting at the specified position * * @param data the RPN array * @param pos the current position in the array, excluding the ptg identifier * @return the number of bytes read */ public int read(byte[] data, int pos) { int index = IntegerHelper.getInt(data[pos], data[pos + 1]); function = Function.getFunction(index); Assert.verify(function != Function.UNKNOWN, "function code " + index); return 2; } /** * Gets the operands for this operator from the stack * * @param s the token stack */ public void getOperands(Stack s) { // parameters are in the correct order, god damn them ParseItem[] items = new ParseItem[function.getNumArgs()]; // modified in 2.4.3 for (int i = function.getNumArgs() - 1; i >= 0; i--) { ParseItem pi = (ParseItem) s.pop(); items[i] = pi; } for (int i = 0; i < function.getNumArgs(); i++) { add(items[i]); } } /** * Gets the string for this functions * * @param buf the buffer to append */ public void getString(StringBuffer buf) { buf.append(function.getName(settings)); buf.append('('); int numArgs = function.getNumArgs(); if (numArgs > 0) { ParseItem[] operands = getOperands(); // arguments are in the same order they were specified operands[0].getString(buf); for (int i = 1; i < numArgs; i++) { buf.append(','); operands[i].getString(buf); } } buf.append(')'); } /** * Adjusts all the relative cell references in this formula by the * amount specified. Used when copying formulas * * @param colAdjust the amount to add on to each relative cell reference * @param rowAdjust the amount to add on to each relative row reference */ public void adjustRelativeCellReferences(int colAdjust, int rowAdjust) { ParseItem[] operands = getOperands(); for (int i = 0; i < operands.length; i++) { operands[i].adjustRelativeCellReferences(colAdjust, rowAdjust); } } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the column was inserted * @param col the column number which was inserted * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void columnInserted(int sheetIndex, int col, boolean currentSheet) { ParseItem[] operands = getOperands(); for (int i = 0; i < operands.length; i++) { operands[i].columnInserted(sheetIndex, col, currentSheet); } } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the column was removed * @param col the column number which was removed * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void columnRemoved(int sheetIndex, int col, boolean currentSheet) { ParseItem[] operands = getOperands(); for (int i = 0; i < operands.length; i++) { operands[i].columnRemoved(sheetIndex, col, currentSheet); } } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the row was inserted * @param row the row number which was inserted * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void rowInserted(int sheetIndex, int row, boolean currentSheet) { ParseItem[] operands = getOperands(); for (int i = 0; i < operands.length; i++) { operands[i].rowInserted(sheetIndex, row, currentSheet); } } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the row was removed * @param row the row number which was removed * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void rowRemoved(int sheetIndex, int row, boolean currentSheet) { ParseItem[] operands = getOperands(); for (int i = 0; i < operands.length; i++) { operands[i].rowRemoved(sheetIndex, row, currentSheet); } } /** * If this formula was on an imported sheet, check that * cell references to another sheet are warned appropriately * Does nothing, as operators don't have cell references */ void handleImportedCellReferences() { ParseItem[] operands = getOperands(); for (int i = 0 ; i < operands.length ; i++) { operands[i].handleImportedCellReferences(); } } /** * Gets the token representation of this item in RPN * * @return the bytes applicable to this formula */ byte[] getBytes() { // Get the data for the operands ParseItem[] operands = getOperands(); byte[] data = new byte[0]; for (int i = 0; i < operands.length; i++) { byte[] opdata = operands[i].getBytes(); // Grow the array byte[] newdata = new byte[data.length + opdata.length]; System.arraycopy(data, 0, newdata, 0, data.length); System.arraycopy(opdata, 0, newdata, data.length, opdata.length); data = newdata; } // Add on the operator byte byte[] newdata = new byte[data.length + 3]; System.arraycopy(data, 0, newdata, 0, data.length); newdata[data.length] = !useAlternateCode() ? Token.FUNCTION.getCode() : Token.FUNCTION.getCode2(); IntegerHelper.getTwoBytes(function.getCode(), newdata, data.length + 1); return newdata; } /** * Gets the precedence for this operator. Operator precedents run from * 1 to 5, one being the highest, 5 being the lowest * * @return the operator precedence */ int getPrecedence() { return 3; } } jexcelapi/src/jxl/biff/formula/Area3d.java0000750000175000017500000002560411207000612020611 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; import jxl.common.Assert; import jxl.common.Logger; import jxl.biff.CellReferenceHelper; import jxl.biff.IntegerHelper; /** * A nested class to hold range information */ class Area3d extends Operand implements ParsedThing { /** * The logger */ private static Logger logger = Logger.getLogger(Area3d.class); /** * The sheet */ private int sheet; /** * The first column */ private int columnFirst; /** * The first row */ private int rowFirst; /** * The last column */ private int columnLast; /** * The last row */ private int rowLast; /** * Indicates whether the first column is relative */ private boolean columnFirstRelative; /** * Indicates whether the first row is relative */ private boolean rowFirstRelative; /** * Indicates whether the last column is relative */ private boolean columnLastRelative; /** * Indicates whether the last row is relative */ private boolean rowLastRelative; /** * A handle to the workbook */ private ExternalSheet workbook; /** * Constructor * * @param es the external sheet */ Area3d(ExternalSheet es) { workbook = es; } /** * Constructor invoked when parsing a string formula * * @param s the string to parse * @param es the external sheet * @exception FormulaException */ Area3d(String s, ExternalSheet es) throws FormulaException { workbook = es; int seppos = s.lastIndexOf(":"); Assert.verify(seppos != -1); String endcell = s.substring(seppos + 1); // Get the the start cell details int sep = s.indexOf('!'); String cellString = s.substring(sep + 1, seppos); columnFirst = CellReferenceHelper.getColumn(cellString); rowFirst = CellReferenceHelper.getRow(cellString); // Get the sheet index String sheetName = s.substring(0, sep); // Remove single quotes, if they exist if (sheetName.charAt(0) == '\'' && sheetName.charAt(sheetName.length() - 1) == '\'') { sheetName = sheetName.substring(1, sheetName.length() - 1); } sheet = es.getExternalSheetIndex(sheetName); if (sheet < 0) { throw new FormulaException(FormulaException.SHEET_REF_NOT_FOUND, sheetName); } // Get the last cell index columnLast = CellReferenceHelper.getColumn(endcell); rowLast = CellReferenceHelper.getRow(endcell); columnFirstRelative = true; rowFirstRelative = true; columnLastRelative = true; rowLastRelative = true; } /** * Accessor for the first column * * @return the first column */ int getFirstColumn() { return columnFirst; } /** * Accessor for the first row * * @return the first row */ int getFirstRow() { return rowFirst; } /** * Accessor for the last column * * @return the last column */ int getLastColumn() { return columnLast; } /** * Accessor for the last row * * @return the last row */ int getLastRow() { return rowLast; } /** * Reads the ptg data from the array starting at the specified position * * @param data the RPN array * @param pos the current position in the array, excluding the ptg identifier * @return the number of bytes read */ public int read(byte[] data, int pos) { sheet = IntegerHelper.getInt(data[pos], data[pos + 1]); rowFirst = IntegerHelper.getInt(data[pos + 2], data[pos + 3]); rowLast = IntegerHelper.getInt(data[pos + 4], data[pos + 5]); int columnMask = IntegerHelper.getInt(data[pos + 6], data[pos + 7]); columnFirst = columnMask & 0x00ff; columnFirstRelative = ((columnMask & 0x4000) != 0); rowFirstRelative = ((columnMask & 0x8000) != 0); columnMask = IntegerHelper.getInt(data[pos + 8], data[pos + 9]); columnLast = columnMask & 0x00ff; columnLastRelative = ((columnMask & 0x4000) != 0); rowLastRelative = ((columnMask & 0x8000) != 0); return 10; } /** * Gets the string version of this area * * @param buf the area to populate */ public void getString(StringBuffer buf) { CellReferenceHelper.getCellReference (sheet, columnFirst, rowFirst, workbook, buf); buf.append(':'); CellReferenceHelper.getCellReference(columnLast, rowLast, buf); } /** * Gets the token representation of this item in RPN * * @return the bytes applicable to this formula */ byte[] getBytes() { byte[] data = new byte[11]; data[0] = Token.AREA3D.getCode(); IntegerHelper.getTwoBytes(sheet, data, 1); IntegerHelper.getTwoBytes(rowFirst, data, 3); IntegerHelper.getTwoBytes(rowLast, data, 5); int grcol = columnFirst; // Set the row/column relative bits if applicable if (rowFirstRelative) { grcol |= 0x8000; } if (columnFirstRelative) { grcol |= 0x4000; } IntegerHelper.getTwoBytes(grcol, data, 7); grcol = columnLast; // Set the row/column relative bits if applicable if (rowLastRelative) { grcol |= 0x8000; } if (columnLastRelative) { grcol |= 0x4000; } IntegerHelper.getTwoBytes(grcol, data, 9); return data; } /** * Adjusts all the relative cell references in this formula by the * amount specified. Used when copying formulas * * @param colAdjust the amount to add on to each relative cell reference * @param rowAdjust the amount to add on to each relative row reference */ public void adjustRelativeCellReferences(int colAdjust, int rowAdjust) { if (columnFirstRelative) { columnFirst += colAdjust; } if (columnLastRelative) { columnLast += colAdjust; } if (rowFirstRelative) { rowFirst += rowAdjust; } if (rowLastRelative) { rowLast += rowAdjust; } } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the column was inserted * @param col the column number which was inserted * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ public void columnInserted(int sheetIndex, int col, boolean currentSheet) { if (sheetIndex != sheet) { return; } if (columnFirst >= col) { columnFirst++; } if (columnLast >= col) { columnLast++; } } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the column was removed * @param col the column number which was removed * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void columnRemoved(int sheetIndex, int col, boolean currentSheet) { if (sheetIndex != sheet) { return; } if (col < columnFirst) { columnFirst--; } if (col <= columnLast) { columnLast--; } } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the row was inserted * @param row the row number which was inserted * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void rowInserted(int sheetIndex, int row, boolean currentSheet) { if (sheetIndex != sheet) { return; } if (rowLast == 0xffff) { // area applies to the whole column, so nothing to do return; } if (row <= rowFirst) { rowFirst++; } if (row <= rowLast) { rowLast++; } } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the row was removed * @param row the row number which was removed * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void rowRemoved(int sheetIndex, int row, boolean currentSheet) { if (sheetIndex != sheet) { return; } if (rowLast == 0xffff) { // area applies to the whole column, so nothing to do return; } if (row < rowFirst) { rowFirst--; } if (row <= rowLast) { rowLast--; } } /** * Used by subclasses columns/row range to set the range information * * @param sht the sheet containing the area * @param colFirst the first column * @param colLast the last column * @param rwFirst the first row * @param rwLast the last row * @param colFirstRel flag indicating whether the first column is relative * @param colLastRel flag indicating whether the last column is relative * @param rowFirstRel flag indicating whether the first row is relative * @param rowLastRel flag indicating whether the last row is relative */ protected void setRangeData(int sht, int colFirst, int colLast, int rwFirst, int rwLast, boolean colFirstRel, boolean colLastRel, boolean rowFirstRel, boolean rowLastRel) { sheet = sht; columnFirst = colFirst; columnLast = colLast; rowFirst = rwFirst; rowLast = rwLast; columnFirstRelative = colFirstRel; columnLastRelative = colLastRel; rowFirstRelative = rowFirstRel; rowLastRelative = rowLastRel; } /** * If this formula was on an imported sheet, check that * cell references to another sheet are warned appropriately */ void handleImportedCellReferences() { setInvalid(); } } jexcelapi/src/jxl/biff/formula/SubExpression.java0000750000175000017500000000523311207000612022317 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2007 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; import java.util.Stack; import jxl.biff.IntegerHelper; /** * Base class for those tokens which encapsulate a subexpression */ abstract class SubExpression extends Operand implements ParsedThing { /** * The number of bytes in the subexpression */ private int length; /** * The sub expression */ private ParseItem[] subExpression; /** * Constructor */ protected SubExpression() { } /** * Reads the ptg data from the array starting at the specified position * * @param data the RPN array * @param pos the current position in the array, excluding the ptg identifier * @return the number of bytes read */ public int read(byte[] data, int pos) { length = IntegerHelper.getInt(data[pos], data[pos+1]); return 2; } /** * Gets the operands for this operator from the stack */ public void getOperands(Stack s) { } /** * Gets the token representation of this item in RPN. The Attribute * token is a special case, which overrides anything useful we could do * in the base class * * @return the bytes applicable to this formula */ byte[] getBytes() { return null; } /** * Gets the precedence for this operator. Operator precedents run from * 1 to 5, one being the highest, 5 being the lowest * * @return the operator precedence */ int getPrecedence() { return 5; } /** * Accessor for the length * * @return the length of the subexpression */ public int getLength() { return length; } protected final void setLength(int l) { length = l; } public void setSubExpression(ParseItem[] pi) { subExpression = pi; } protected ParseItem[] getSubExpression() { return subExpression; } } jexcelapi/src/jxl/biff/formula/Area.java0000750000175000017500000002403611207000612020360 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; import jxl.common.Assert; import jxl.common.Logger; import jxl.biff.CellReferenceHelper; import jxl.biff.IntegerHelper; /** * A nested class to hold range information */ class Area extends Operand implements ParsedThing { /** * The logger */ private static Logger logger = Logger.getLogger(Area.class); /** * The first column */ private int columnFirst; /** * The first row */ private int rowFirst; /** * The last column */ private int columnLast; /** * The last row */ private int rowLast; /** * Indicates whether the first column is a relative or absolute reference */ private boolean columnFirstRelative; /** * Indicates whether the first row is a relative or absolute reference */ private boolean rowFirstRelative; /** * Indicates whether the last column is a relative or absolute reference */ private boolean columnLastRelative; /** * Indicates whether the last row is a relative or absolute reference */ private boolean rowLastRelative; /** * Constructor */ Area() { } /** * Constructor invoked when parsing a string formula * * @param s the string to parse */ Area(String s) { int seppos = s.indexOf(":"); Assert.verify(seppos != -1); String startcell = s.substring(0, seppos); String endcell = s.substring(seppos + 1); columnFirst = CellReferenceHelper.getColumn(startcell); rowFirst = CellReferenceHelper.getRow(startcell); columnLast = CellReferenceHelper.getColumn(endcell); rowLast = CellReferenceHelper.getRow(endcell); columnFirstRelative = CellReferenceHelper.isColumnRelative(startcell); rowFirstRelative = CellReferenceHelper.isRowRelative(startcell); columnLastRelative = CellReferenceHelper.isColumnRelative(endcell); rowLastRelative = CellReferenceHelper.isRowRelative(endcell); } /** * Accessor for the first column * * @return the first column */ int getFirstColumn() { return columnFirst; } /** * Accessor for the first row * * @return the first row */ int getFirstRow() { return rowFirst; } /** * Accessor for the last column * * @return the last column */ int getLastColumn() { return columnLast; } /** * Accessor for the last row * * @return the last row */ int getLastRow() { return rowLast; } /** * Reads the ptg data from the array starting at the specified position * * @param data the RPN array * @param pos the current position in the array, excluding the ptg identifier * @return the number of bytes read */ public int read(byte[] data, int pos) { rowFirst = IntegerHelper.getInt(data[pos], data[pos + 1]); rowLast = IntegerHelper.getInt(data[pos + 2], data[pos + 3]); int columnMask = IntegerHelper.getInt(data[pos + 4], data[pos + 5]); columnFirst = columnMask & 0x00ff; columnFirstRelative = ((columnMask & 0x4000) != 0); rowFirstRelative = ((columnMask & 0x8000) != 0); columnMask = IntegerHelper.getInt(data[pos + 6], data[pos + 7]); columnLast = columnMask & 0x00ff; columnLastRelative = ((columnMask & 0x4000) != 0); rowLastRelative = ((columnMask & 0x8000) != 0); return 8; } /** * Gets the string representation of this item * * @param buf the string buffer */ public void getString(StringBuffer buf) { CellReferenceHelper.getCellReference(columnFirst, rowFirst, buf); buf.append(':'); CellReferenceHelper.getCellReference(columnLast, rowLast, buf); } /** * Gets the token representation of this item in RPN * * @return the bytes applicable to this formula */ byte[] getBytes() { byte[] data = new byte[9]; data[0] = !useAlternateCode() ? Token.AREA.getCode() : Token.AREA.getCode2(); IntegerHelper.getTwoBytes(rowFirst, data, 1); IntegerHelper.getTwoBytes(rowLast, data, 3); int grcol = columnFirst; // Set the row/column relative bits if applicable if (rowFirstRelative) { grcol |= 0x8000; } if (columnFirstRelative) { grcol |= 0x4000; } IntegerHelper.getTwoBytes(grcol, data, 5); grcol = columnLast; // Set the row/column relative bits if applicable if (rowLastRelative) { grcol |= 0x8000; } if (columnLastRelative) { grcol |= 0x4000; } IntegerHelper.getTwoBytes(grcol, data, 7); return data; } /** * Adjusts all the relative cell references in this formula by the * amount specified. Used when copying formulas * * @param colAdjust the amount to add on to each relative cell reference * @param rowAdjust the amount to add on to each relative row reference */ public void adjustRelativeCellReferences(int colAdjust, int rowAdjust) { if (columnFirstRelative) { columnFirst += colAdjust; } if (columnLastRelative) { columnLast += colAdjust; } if (rowFirstRelative) { rowFirst += rowAdjust; } if (rowLastRelative) { rowLast += rowAdjust; } } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the column was inserted * @param col the column number which was inserted * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void columnInserted(int sheetIndex, int col, boolean currentSheet) { if (!currentSheet) { return; } if (col <= columnFirst) { columnFirst++; } if (col <= columnLast) { columnLast++; } } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the column was removed * @param col the column number which was removed * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void columnRemoved(int sheetIndex, int col, boolean currentSheet) { if (!currentSheet) { return; } if (col < columnFirst) { columnFirst--; } if (col <= columnLast) { columnLast--; } } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the row was inserted * @param row the row number which was inserted * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void rowInserted(int sheetIndex, int row, boolean currentSheet) { if (!currentSheet) { return; } if (rowLast == 0xffff) { // area applies to the whole column, so nothing to do return; } if (row <= rowFirst) { rowFirst++; } if (row <= rowLast) { rowLast++; } } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the row was removed * @param row the row number which was removed * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void rowRemoved(int sheetIndex, int row, boolean currentSheet) { if (!currentSheet) { return; } if (rowLast == 0xffff) { // area applies to the whole column, so nothing to do return; } if (row < rowFirst) { rowFirst--; } if (row <= rowLast) { rowLast--; } } /** * Used by subclasses columns/row range to set the range information * * @param colFirst the first column * @param colLast the last column * @param rwFirst the first row * @param rwLast the last row * @param colFirstRel flag indicating whether the first column is relative * @param colLastRel flag indicating whether the last column is relative * @param rowFirstRel flag indicating whether the first row is relative * @param rowLastRel flag indicating whether the last row is relative */ protected void setRangeData(int colFirst, int colLast, int rwFirst, int rwLast, boolean colFirstRel, boolean colLastRel, boolean rowFirstRel, boolean rowLastRel) { columnFirst = colFirst; columnLast = colLast; rowFirst = rwFirst; rowLast = rwLast; columnFirstRelative = colFirstRel; columnLastRelative = colLastRel; rowFirstRelative = rowFirstRel; rowLastRelative = rowLastRel; } /** * If this formula was on an imported sheet, check that * cell references to another sheet are warned appropriately * Does nothing here */ void handleImportedCellReferences() { } } jexcelapi/src/jxl/biff/formula/Concatenate.java0000750000175000017500000000320711207000612021731 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; /** * A cell reference in a formula */ class Concatenate extends BinaryOperator implements ParsedThing { /** * Constructor */ public Concatenate() { } /** * Gets the string representation of this symbol * * @return the concatenation symbol */ public String getSymbol() { return "&"; } /** * Abstract method which gets the token for this operator * * @return the string symbol for this token */ Token getToken() { return Token.CONCAT; } /** * Gets the precedence for this operator. Operator precedents run from * 1 to 5, one being the highest, 5 being the lowest * * @return the operator precedence */ int getPrecedence() { return 3; } } jexcelapi/src/jxl/biff/formula/CellReferenceError.java0000750000175000017500000000441311207000612023215 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2005 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; import jxl.common.Logger; /** * An cell reference error which occurs in a formula */ class CellReferenceError extends Operand implements ParsedThing { /** * The logger */ private static Logger logger = Logger.getLogger(CellReferenceError.class); /** * Constructor */ public CellReferenceError() { } /** * Reads the ptg data from the array starting at the specified position * * @param data the RPN array * @param pos the current position in the array, excluding the ptg identifier * @return the number of bytes read */ public int read(byte[] data, int pos) { // the data is unused - just return the four bytes return 4; } /** * Gets the cell reference as a string for this item * * @param buf the string buffer to populate */ public void getString(StringBuffer buf) { buf.append(FormulaErrorCode.REF.getDescription()); } /** * Gets the token representation of this item in RPN * * @return the bytes applicable to this formula */ byte[] getBytes() { byte[] data = new byte[5]; data[0] = Token.REFERR.getCode(); // bytes 1-5 are unused return data; } /** * If this formula was on an imported sheet, check that * cell references to another sheet are warned appropriately * Does nothing */ void handleImportedCellReferences() { } } jexcelapi/src/jxl/biff/formula/NotEqual.java0000750000175000017500000000303611207000612021235 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; /** * A cell reference in a formula */ class NotEqual extends BinaryOperator implements ParsedThing { /** * Constructor */ public NotEqual() { } public String getSymbol() { return "<>"; } /** * Abstract method which gets the token for this operator * * @return the string symbol for this token */ Token getToken() { return Token.NOT_EQUAL; } /** * Gets the precedence for this operator. Operator precedents run from * 1 to 5, one being the highest, 5 being the lowest * * @return the operator precedence */ int getPrecedence() { return 5; } } jexcelapi/src/jxl/biff/formula/ArgumentSeparator.java0000750000175000017500000000221111207000612023142 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; /** * A dummy token used when parsing strings in order to indicate the * separation of parameters */ class ArgumentSeparator extends StringParseItem { /** * Constructor */ public ArgumentSeparator() { } } jexcelapi/src/jxl/biff/formula/UnaryMinus.java0000750000175000017500000000342011207000612021614 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; /** * A cell reference in a formula */ class UnaryMinus extends UnaryOperator implements ParsedThing { /** * Constructor */ public UnaryMinus() { } public String getSymbol() { return "-"; } /** * Abstract method which gets the token for this operator * * @return the string symbol for this token */ Token getToken() { return Token.UNARY_MINUS; } /** * Gets the precedence for this operator. Operator precedents run from * 1 to 5, one being the highest, 5 being the lowest * * @return the operator precedence */ int getPrecedence() { return 2; } /** * If this formula was on an imported sheet, check that * cell references to another sheet are warned appropriately * Does nothing, as operators don't have cell references */ void handleImportedCellReferences() { } } jexcelapi/src/jxl/biff/formula/ColumnRange.java0000750000175000017500000000472111207000612021721 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2005 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; import jxl.common.Assert; import jxl.common.Logger; import jxl.biff.CellReferenceHelper; /** * A class to hold range information across two entire columns */ class ColumnRange extends Area { /** * The logger */ private static Logger logger = Logger.getLogger(ColumnRange.class); /** * Constructor */ ColumnRange() { super(); } /** * Constructor invoked when parsing a string formula * * @param s the string to parse */ ColumnRange(String s) { int seppos = s.indexOf(":"); Assert.verify(seppos != -1); String startcell = s.substring(0, seppos); String endcell = s.substring(seppos + 1); int columnFirst = CellReferenceHelper.getColumn(startcell); int rowFirst = 0; int columnLast = CellReferenceHelper.getColumn(endcell); int rowLast = 0xffff; boolean columnFirstRelative = CellReferenceHelper.isColumnRelative(startcell); boolean rowFirstRelative = false; boolean columnLastRelative = CellReferenceHelper.isColumnRelative(endcell); boolean rowLastRelative = false; setRangeData(columnFirst, columnLast, rowFirst, rowLast, columnFirstRelative, columnLastRelative, rowFirstRelative, rowLastRelative); } /** * Gets the string representation of this item * * @param buf the string buffer */ public void getString(StringBuffer buf) { CellReferenceHelper.getColumnReference(getFirstColumn(), buf); buf.append(':'); CellReferenceHelper.getColumnReference(getLastColumn(), buf); } } jexcelapi/src/jxl/biff/formula/MemFunc.java0000750000175000017500000000264011207000612021037 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; import java.util.Stack; import jxl.biff.IntegerHelper; /** * Indicates that the function doesn't evaluate to a constant reference */ class MemFunc extends SubExpression { /** * Constructor */ public MemFunc() { } public void getString(StringBuffer sb) { } /** * If this formula was on an imported sheet, check that * cell references to another sheet are warned appropriately * Does nothing */ void handleImportedCellReferences() { } } jexcelapi/src/jxl/biff/formula/CellReference3d.java0000750000175000017500000001752511207327750022461 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; import jxl.common.Logger; import jxl.Cell; import jxl.biff.CellReferenceHelper; import jxl.biff.IntegerHelper; /** * A 3d cell reference in a formula */ class CellReference3d extends Operand implements ParsedThing { /** * The logger */ private static Logger logger = Logger.getLogger(CellReference3d.class); /** * Indicates whether the column reference is relative or absolute */ private boolean columnRelative; /** * Indicates whether the row reference is relative or absolute */ private boolean rowRelative; /** * The column reference */ private int column; /** * The row reference */ private int row; /** * The cell containing the formula. Stored in order to determine * relative cell values */ private Cell relativeTo; /** * The sheet which the reference is present on */ private int sheet; /** * A handle to the container of the external sheets ie. the workbook */ private ExternalSheet workbook; /** * Constructor * * @param rt the cell containing the formula * @param w the list of external sheets */ public CellReference3d(Cell rt, ExternalSheet w) { relativeTo = rt; workbook = w; } /** * Constructs this object from a string * * @param s the string * @param w the external sheet * @exception FormulaException */ public CellReference3d(String s, ExternalSheet w) throws FormulaException { workbook = w; columnRelative = true; rowRelative = true; // Get the cell details int sep = s.indexOf('!'); String cellString = s.substring(sep + 1); column = CellReferenceHelper.getColumn(cellString); row = CellReferenceHelper.getRow(cellString); // Get the sheet index String sheetName = s.substring(0, sep); // Remove single quotes, if they exist if (sheetName.charAt(0) == '\'' && sheetName.charAt(sheetName.length() - 1) == '\'') { sheetName = sheetName.substring(1, sheetName.length() - 1); } sheet = w.getExternalSheetIndex(sheetName); if (sheet < 0) { throw new FormulaException(FormulaException.SHEET_REF_NOT_FOUND, sheetName); } } /** * Reads the ptg data from the array starting at the specified position * * @param data the RPN array * @param pos the current position in the array, excluding the ptg identifier * @return the number of bytes read */ public int read(byte[] data, int pos) { sheet = IntegerHelper.getInt(data[pos], data[pos + 1]); row = IntegerHelper.getInt(data[pos + 2], data[pos + 3]); int columnMask = IntegerHelper.getInt(data[pos + 4], data[pos + 5]); column = columnMask & 0x00ff; columnRelative = ((columnMask & 0x4000) != 0); rowRelative = ((columnMask & 0x8000) != 0); return 6; } /** * Accessor for the column * * @return the column number */ public int getColumn() { return column; } /** * Accessor for the row * * @return the row number */ public int getRow() { return row; } /** * Gets the string version of this cell reference * * @param buf the buffer to append to */ public void getString(StringBuffer buf) { CellReferenceHelper.getCellReference(sheet, column, !columnRelative, row, !rowRelative, workbook, buf); } /** * Gets the token representation of this item in RPN * * @return the bytes applicable to this formula */ byte[] getBytes() { byte[] data = new byte[7]; data[0] = Token.REF3D.getCode(); IntegerHelper.getTwoBytes(sheet, data, 1); IntegerHelper.getTwoBytes(row, data, 3); int grcol = column; // Set the row/column relative bits if applicable if (rowRelative) { grcol |= 0x8000; } if (columnRelative) { grcol |= 0x4000; } IntegerHelper.getTwoBytes(grcol, data, 5); return data; } /** * Adjusts all the relative cell references in this formula by the * amount specified. Used when copying formulas * * @param colAdjust the amount to add on to each relative cell reference * @param rowAdjust the amount to add on to each relative row reference */ public void adjustRelativeCellReferences(int colAdjust, int rowAdjust) { if (columnRelative) { column += colAdjust; } if (rowRelative) { row += rowAdjust; } } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the column was inserted * @param col the column number which was inserted * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ public void columnInserted(int sheetIndex, int col, boolean currentSheet) { if (sheetIndex != sheet) { return; } if (column >= col) { column++; } } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the column was removed * @param col the column number which was removed * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void columnRemoved(int sheetIndex, int col, boolean currentSheet) { if (sheetIndex != sheet) { return; } if (column >= col) { column--; } } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the row was inserted * @param r the row number which was inserted * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void rowInserted(int sheetIndex, int r, boolean currentSheet) { if (sheetIndex != sheet) { return; } if (row >= r) { row++; } } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the row was removed * @param r the row number which was removed * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void rowRemoved(int sheetIndex, int r, boolean currentSheet) { if (sheetIndex != sheet) { return; } if (row >= r) { row--; } } /** * If this formula was on an imported sheet, check that * cell references to another sheet are warned appropriately * Flags the formula as invalid */ void handleImportedCellReferences() { setInvalid(); } } jexcelapi/src/jxl/biff/formula/Plus.java0000750000175000017500000000342211207000612020427 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; /** * Ambiguously defined plus operator, used as a place holder when parsing * string formulas. At this stage it could be either * a unary or binary operator - the string parser will deduce which and * create the appropriate type */ class Plus extends StringOperator { /** * Constructor */ public Plus() { super(); } /** * Abstract method which gets the binary version of this operator */ Operator getBinaryOperator() { return new Add(); } /** * Abstract method which gets the unary version of this operator */ Operator getUnaryOperator() { return new UnaryPlus(); } /** * If this formula was on an imported sheet, check that * cell references to another sheet are warned appropriately * Does nothing, as operators don't have cell references */ void handleImportedCellReferences() { } } jexcelapi/src/jxl/biff/formula/Parenthesis.java0000750000175000017500000001324111207000612021771 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; import java.util.Stack; /** * A cell reference in a formula */ class Parenthesis extends Operator implements ParsedThing { /** * Constructor */ public Parenthesis() { } /** * Reads the ptg data from the array starting at the specified position * * @param data the RPN array * @param pos the current position in the array, excluding the ptg identifier * @return the number of bytes read */ public int read(byte[] data, int pos) { return 0; } /** * Gets the operands for this operator from the stack */ public void getOperands(Stack s) { ParseItem pi = (ParseItem) s.pop(); add(pi); } public void getString(StringBuffer buf) { ParseItem[] operands = getOperands(); buf.append('('); operands[0].getString(buf); buf.append(')'); } /** * Adjusts all the relative cell references in this formula by the * amount specified. Used when copying formulas * * @param colAdjust the amount to add on to each relative cell reference * @param rowAdjust the amount to add on to each relative row reference */ public void adjustRelativeCellReferences(int colAdjust, int rowAdjust) { ParseItem[] operands = getOperands(); operands[0].adjustRelativeCellReferences(colAdjust, rowAdjust); } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the column was inserted * @param col the column number which was inserted * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void columnInserted(int sheetIndex, int col, boolean currentSheet) { ParseItem[] operands = getOperands(); operands[0].columnInserted(sheetIndex, col, currentSheet); } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the column was removed * @param col the column number which was removed * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void columnRemoved(int sheetIndex, int col, boolean currentSheet) { ParseItem[] operands = getOperands(); operands[0].columnRemoved(sheetIndex, col, currentSheet); } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the row was inserted * @param row the row number which was inserted * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void rowInserted(int sheetIndex, int row, boolean currentSheet) { ParseItem[] operands = getOperands(); operands[0].rowInserted(sheetIndex, row, currentSheet); } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the row was removed * @param row the row number which was removed * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void rowRemoved(int sheetIndex, int row, boolean currentSheet) { ParseItem[] operands = getOperands(); operands[0].rowRemoved(sheetIndex, row, currentSheet); } /** * If this formula was on an imported sheet, check that * cell references to another sheet are warned appropriately * Does nothing, as operators don't have cell references */ void handleImportedCellReferences() { ParseItem[] operands = getOperands(); operands[0].handleImportedCellReferences(); } /** * Abstract method which gets the token for this operator * * @return the string symbol for this token */ Token getToken() { return Token.PARENTHESIS; } /** * Gets the token representation of this item in RPN * * @return the bytes applicable to this formula */ byte[] getBytes() { // Get the data for the operands ParseItem[] operands = getOperands(); byte[] data = operands[0].getBytes(); // Add on the operator byte byte[] newdata = new byte[data.length + 1]; System.arraycopy(data, 0, newdata, 0, data.length); newdata[data.length] = getToken().getCode(); return newdata; } /** * Gets the precedence for this operator. Operator precedents run from * 1 to 5, one being the highest, 5 being the lowest * * @return the operator precedence */ int getPrecedence() { return 4; } } jexcelapi/src/jxl/biff/formula/Divide.java0000750000175000017500000000316011207000612020707 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; /** * A cell reference in a formula */ class Divide extends BinaryOperator implements ParsedThing { /** * Constructor */ public Divide() { } /** * Gets the string representation of this symbol * * @return the symbol */ public String getSymbol() { return "/"; } /** * Abstract method which gets the token for this operator * * @return the string symbol for this token */ Token getToken() { return Token.DIVIDE; } /** * Gets the precedence for this operator. Operator precedents run from * 1 to 5, one being the highest, 5 being the lowest * * @return the operator precedence */ int getPrecedence() { return 3; } } jexcelapi/src/jxl/biff/formula/FormulaErrorCode.java0000750000175000017500000000713111207000612022717 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2005 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; /** * Enumeration for formula error codes */ public class FormulaErrorCode { /** * The error code */ private int errorCode; /** * The description */ private String description; /** * The list of error codes */ private static FormulaErrorCode[] codes = new FormulaErrorCode[0]; /** * Constructor * * @param code the code * @param desc the description */ FormulaErrorCode(int code, String desc) { errorCode = code; description = desc; FormulaErrorCode[] newcodes = new FormulaErrorCode[codes.length + 1]; System.arraycopy(codes, 0, newcodes, 0, codes.length); newcodes[codes.length] = this; codes = newcodes; } /** * Accessor for the code * * @return the code */ public int getCode() { return errorCode; } /** * Accessor for the description * * @return the description */ public String getDescription() { return description; } /** * Gets the error type given just the code * * @param code the code to lookup * @return the error type */ public static FormulaErrorCode getErrorCode(int code) { boolean found = false; FormulaErrorCode ec = UNKNOWN; for (int i = 0; i < codes.length && !found; i++) { if (codes[i].errorCode == code) { found = true; ec = codes[i]; } } return ec; } /** * Gets the error type given the string value * * @param code the code to lookup * @return the error type */ public static FormulaErrorCode getErrorCode(String code) { boolean found = false; FormulaErrorCode ec = UNKNOWN; if (code == null || code.length() == 0) { return ec; } for (int i = 0; i < codes.length && !found; i++) { if (codes[i].description.equals(code)) { found = true; ec = codes[i]; } } return ec; } public static final FormulaErrorCode UNKNOWN = new FormulaErrorCode(0xff, "?"); public static final FormulaErrorCode NULL = new FormulaErrorCode(0x0, "#NULL!"); public static final FormulaErrorCode DIV0 = new FormulaErrorCode(0x7, "#DIV/0!"); public static final FormulaErrorCode VALUE = new FormulaErrorCode(0xf, "#VALUE!"); public static final FormulaErrorCode REF = new FormulaErrorCode(0x17, "#REF!"); public static final FormulaErrorCode NAME = new FormulaErrorCode(0x1d, "#NAME?"); public static final FormulaErrorCode NUM = new FormulaErrorCode(0x24, "#NUM!"); public static final FormulaErrorCode NA = new FormulaErrorCode(0x2a, "#N/A!"); } jexcelapi/src/jxl/biff/formula/IntegerValue.java0000750000175000017500000000560311207000612022101 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; import jxl.common.Logger; import jxl.biff.IntegerHelper; /** * A cell reference in a formula */ class IntegerValue extends NumberValue implements ParsedThing { /** * The logger */ private static Logger logger = Logger.getLogger(IntegerValue.class); /** * The value of this integer */ private double value; /** * Flag which indicates whether or not this integer is out range */ private boolean outOfRange; /** * Constructor */ public IntegerValue() { outOfRange = false; } /** * Constructor for an integer value being read from a string */ public IntegerValue(String s) { try { value = Integer.parseInt(s); } catch (NumberFormatException e) { logger.warn(e, e); value = 0; } short v = (short) value; outOfRange = (value != v); } /** * Reads the ptg data from the array starting at the specified position * * @param data the RPN array * @param pos the current position in the array, excluding the ptg identifier * @return the number of bytes read */ public int read(byte[] data, int pos) { value = IntegerHelper.getInt(data[pos], data[pos+1]); return 2; } /** * Gets the token representation of this item in RPN * * @return the bytes applicable to this formula */ byte[] getBytes() { byte[] data = new byte[3]; data[0] = Token.INTEGER.getCode(); IntegerHelper.getTwoBytes((int) value, data, 1); return data; } /** * Accessor for the value * * @return the value */ public double getValue() { return value; } /** * Accessor for the out of range flag * * @return TRUE if the value is out of range for an excel integer */ boolean isOutOfRange() { return outOfRange; } /** * If this formula was on an imported sheet, check that * cell references to another sheet are warned appropriately * Does nothing */ void handleImportedCellReferences() { } } jexcelapi/src/jxl/biff/formula/Operator.java0000750000175000017500000000454111207000612021302 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; import java.util.Stack; /** * An operator is a node in a parse tree. Its children can be other * operators or operands * Arithmetic operators and functions are all considered operators */ abstract class Operator extends ParseItem { /** * The items which this operator manipulates. There will be at most two */ private ParseItem[] operands; /** * Constructor */ public Operator() { operands = new ParseItem[0]; } /** * Tells the operands to use the alternate code */ protected void setOperandAlternateCode() { for (int i = 0 ; i < operands.length ; i++) { operands[i].setAlternateCode(); } } /** * Adds operands to this item */ protected void add(ParseItem n) { n.setParent(this); // Grow the array ParseItem[] newOperands = new ParseItem[operands.length + 1]; System.arraycopy(operands, 0, newOperands, 0, operands.length); newOperands[operands.length] = n; operands = newOperands; } /** * Gets the operands for this operator from the stack */ public abstract void getOperands(Stack s); /** * Gets the operands ie. the children of the node */ protected ParseItem[] getOperands() { return operands; } /** * Gets the precedence for this operator. Operator precedents run from * 1 to 5, one being the highest, 5 being the lowest * * @return the operator precedence */ abstract int getPrecedence(); } jexcelapi/src/jxl/biff/formula/NameRange.java0000750000175000017500000000672211227112623021357 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; import jxl.common.Assert; import jxl.common.Logger; import jxl.biff.IntegerHelper; import jxl.biff.NameRangeException; import jxl.biff.WorkbookMethods; /** * A name operand */ class NameRange extends Operand implements ParsedThing { /** * The logger */ private static Logger logger = Logger.getLogger(NameRange.class); /** * A handle to the name table */ private WorkbookMethods nameTable; /** * The string name */ private String name; /** * The index into the name table */ private int index; /** * Constructor */ public NameRange(WorkbookMethods nt) { nameTable = nt; Assert.verify(nameTable != null); } /** * Constructor when parsing a string via the api * * @param nm the name string * @param nt the name table */ public NameRange(String nm, WorkbookMethods nt) throws FormulaException { name = nm; nameTable = nt; index = nameTable.getNameIndex(name); if (index < 0 ) { throw new FormulaException(FormulaException.CELL_NAME_NOT_FOUND, name); } index += 1; // indexes are 1-based } /** * Reads the ptg data from the array starting at the specified position * * @param data the RPN array * @param pos the current position in the array, excluding the ptg identifier * @return the number of bytes read */ public int read(byte[] data, int pos) throws FormulaException { try { index = IntegerHelper.getInt(data[pos], data[pos+1]); name = nameTable.getName(index - 1); // ilbl is 1-based return 4; } catch (NameRangeException e) { throw new FormulaException(FormulaException.CELL_NAME_NOT_FOUND,""); } } /** * Gets the token representation of this item in RPN * * @return the bytes applicable to this formula */ byte[] getBytes() { byte[] data = new byte[5]; data[0] = Token.NAMED_RANGE.getValueCode(); if (getParseContext() == ParseContext.DATA_VALIDATION) { data[0] = Token.NAMED_RANGE.getReferenceCode(); } IntegerHelper.getTwoBytes(index, data, 1); return data; } /** * Abstract method implementation to get the string equivalent of this * token * * @param buf the string to append to */ public void getString(StringBuffer buf) { buf.append(name); } /** * If this formula was on an imported sheet, check that * cell references to another sheet are warned appropriately * Flags the formula as invalid */ void handleImportedCellReferences() { setInvalid(); } } jexcelapi/src/jxl/biff/formula/MemArea.java0000750000175000017500000000407711207000612021022 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2007 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; import jxl.biff.IntegerHelper; /** * Indicates that the function doesn't evaluate to a constant reference */ class MemArea extends SubExpression { /** * Constructor */ public MemArea() { } public void getString(StringBuffer buf) { ParseItem[] subExpression = getSubExpression(); if (subExpression.length == 1) { subExpression[0].getString(buf); } else if (subExpression.length == 2) { subExpression[1].getString(buf); buf.append(':'); subExpression[0].getString(buf); } } /** * Reads the ptg data from the array starting at the specified position * * @param data the RPN array * @param pos the current position in the array, excluding the ptg identifier * @return the number of bytes read */ public int read(byte[] data, int pos) { // For mem areas, the first four bytes are not used setLength(IntegerHelper.getInt(data[pos+4], data[pos+5])); return 6; } /** * If this formula was on an imported sheet, check that * cell references to another sheet are warned appropriately * Does nothing */ void handleImportedCellReferences() { } } jexcelapi/src/jxl/biff/formula/GreaterThan.java0000750000175000017500000000304511207000612021711 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; /** * A cell reference in a formula */ class GreaterThan extends BinaryOperator implements ParsedThing { /** * Constructor */ public GreaterThan() { } public String getSymbol() { return ">"; } /** * Abstract method which gets the token for this operator * * @return the string symbol for this token */ Token getToken() { return Token.GREATER_THAN; } /** * Gets the precedence for this operator. Operator precedents run from * 1 to 5, one being the highest, 5 being the lowest * * @return the operator precedence */ int getPrecedence() { return 5; } } jexcelapi/src/jxl/biff/formula/Minus.java0000750000175000017500000000361611207000612020604 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; import jxl.common.Logger; /** * Ambiguously defined minus operator, used as a place holder when parsing * string formulas. At this stage it could be either * a unary or binary operator - the string parser will deduce which and * create the appropriate type */ class Minus extends StringOperator { // The logger private static Logger logger = Logger.getLogger(StringOperator.class); /** * Constructor */ public Minus() { super(); } /** * Abstract method which gets the binary version of this operator */ Operator getBinaryOperator() { return new Subtract(); } /** * Abstract method which gets the unary version of this operator */ Operator getUnaryOperator() { return new UnaryMinus(); } /** * If this formula was on an imported sheet, check that * cell references to another sheet are warned appropriately * Does nothing, as operators don't have cell references */ void handleImportedCellReferences() { } } jexcelapi/src/jxl/biff/formula/StringValue.java0000750000175000017500000000614011207000612021747 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; import jxl.common.Logger; import jxl.WorkbookSettings; import jxl.biff.IntegerHelper; import jxl.biff.StringHelper; /** * A string constant operand in a formula */ class StringValue extends Operand implements ParsedThing { /** * The logger */ private final static Logger logger = Logger.getLogger(StringValue.class); /** * The string value */ private String value; /** * The workbook settings */ private WorkbookSettings settings; /** * Constructor */ public StringValue(WorkbookSettings ws) { settings = ws; } /** * Constructor used when parsing a string formula * * @param s the string token, including quote marks */ public StringValue(String s) { // remove the quotes value = s; } /** * Reads the ptg data from the array starting at the specified position * * @param data the RPN array * @param pos the current position in the array, excluding the ptg identifier * @return the number of bytes read */ public int read(byte[] data, int pos) { int length = data[pos] & 0xff; int consumed = 2; if ((data[pos+1] & 0x01) == 0) { value = StringHelper.getString(data, length, pos+2, settings); consumed += length; } else { value = StringHelper.getUnicodeString(data, length, pos+2); consumed += length * 2; } return consumed; } /** * Gets the token representation of this item in RPN * * @return the bytes applicable to this formula */ byte[] getBytes() { byte[] data = new byte[value.length() * 2 + 3]; data[0] = Token.STRING.getCode(); data[1] = (byte) (value.length()); data[2] = 0x01; StringHelper.getUnicodeBytes(value, data, 3); return data; } /** * Abstract method implementation to get the string equivalent of this * token * * @param buf the string to append to */ public void getString(StringBuffer buf) { buf.append("\""); buf.append(value); buf.append("\""); } /** * If this formula was on an imported sheet, check that * cell references to another sheet are warned appropriately * Does nothing */ void handleImportedCellReferences() { } } jexcelapi/src/jxl/biff/formula/SharedFormulaArea.java0000750000175000017500000001011411207000612023025 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; import jxl.Cell; import jxl.biff.CellReferenceHelper; import jxl.biff.IntegerHelper; /** * A cell reference in a formula */ class SharedFormulaArea extends Operand implements ParsedThing { private int columnFirst; private int rowFirst; private int columnLast; private int rowLast; private boolean columnFirstRelative; private boolean rowFirstRelative; private boolean columnLastRelative; private boolean rowLastRelative; /** * The cell containing the formula. Stored in order to determine * relative cell values */ private Cell relativeTo; /** * Constructor * * @param the cell the formula is relative to */ public SharedFormulaArea(Cell rt) { relativeTo = rt; } int getFirstColumn() { return columnFirst; } int getFirstRow() { return rowFirst; } int getLastColumn() { return columnLast; } int getLastRow() { return rowLast; } /** * Reads the ptg data from the array starting at the specified position * * @param data the RPN array * @param pos the current position in the array, excluding the ptg identifier * @return the number of bytes read */ public int read(byte[] data, int pos) { // Preserve signage on column and row values, because they will // probably be relative rowFirst = IntegerHelper.getShort(data[pos], data[pos+1]); rowLast = IntegerHelper.getShort(data[pos+2], data[pos+3]); int columnMask = IntegerHelper.getInt(data[pos+4], data[pos+5]); columnFirst = columnMask & 0x00ff; columnFirstRelative = ((columnMask & 0x4000) != 0); rowFirstRelative = ((columnMask & 0x8000) != 0); if (columnFirstRelative) { columnFirst = relativeTo.getColumn() + columnFirst; } if (rowFirstRelative) { rowFirst = relativeTo.getRow() + rowFirst; } columnMask = IntegerHelper.getInt(data[pos+6], data[pos+7]); columnLast = columnMask & 0x00ff; columnLastRelative = ((columnMask & 0x4000) != 0); rowLastRelative = ((columnMask & 0x8000) != 0); if (columnLastRelative) { columnLast = relativeTo.getColumn() + columnLast; } if (rowLastRelative) { rowLast = relativeTo.getRow() + rowLast; } return 8; } public void getString(StringBuffer buf) { CellReferenceHelper.getCellReference(columnFirst, rowFirst, buf); buf.append(':'); CellReferenceHelper.getCellReference(columnLast, rowLast, buf); } /** * Gets the token representation of this item in RPN * * @return the bytes applicable to this formula */ byte[] getBytes() { byte[] data = new byte[9]; data[0] = Token.AREA.getCode(); // Use absolute references for columns, so don't bother about // the col relative/row relative bits IntegerHelper.getTwoBytes(rowFirst, data, 1); IntegerHelper.getTwoBytes(rowLast, data, 3); IntegerHelper.getTwoBytes(columnFirst, data, 5); IntegerHelper.getTwoBytes(columnLast, data, 7); return data; } /** * If this formula was on an imported sheet, check that * cell references to another sheet are warned appropriately * Does nothing */ void handleImportedCellReferences() { } } jexcelapi/src/jxl/biff/formula/ParseItem.java0000750000175000017500000001433711207000612021404 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; import jxl.common.Logger; /** * Abstract base class for an item in a formula parse tree */ abstract class ParseItem { // The logger private static Logger logger = Logger.getLogger(ParseItem.class); /** * The parent of this parse item */ private ParseItem parent; /** * Volatile flag */ private boolean volatileFunction; /** * Indicates that the alternative token code should be used * @deprecated - use the ParseContext now */ private boolean alternateCode; /** * Indicates that an alternative token code should be used */ private ParseContext parseContext; /** * Indicates whether this tree represents a valid formula or not. If not * the parser replaces it with a valid one */ private boolean valid; /** * Constructor */ public ParseItem() { volatileFunction = false; alternateCode = false; valid = true; parseContext = parseContext.DEFAULT; } /** * Called by this class to initialize the parent */ protected void setParent(ParseItem p) { parent = p; } /** * Sets the volatile flag and ripples all the way up the parse tree */ protected void setVolatile() { volatileFunction = true; if (parent != null && !parent.isVolatile()) { parent.setVolatile(); } } /** * Sets the invalid flag and ripples all the way up the parse tree */ protected final void setInvalid() { valid = false; if (parent != null) { parent.setInvalid(); } } /** * Accessor for the volatile function * * @return TRUE if the formula is volatile, FALSE otherwise */ final boolean isVolatile() { return volatileFunction; } /** * Accessor for the volatile function * * @return TRUE if the formula is volatile, FALSE otherwise */ final boolean isValid() { return valid; } /** * Gets the string representation of this item * @param ws the workbook settings */ abstract void getString(StringBuffer buf); /** * Gets the token representation of this item in RPN * * @return the bytes applicable to this formula */ abstract byte[] getBytes(); /** * Adjusts all the relative cell references in this formula by the * amount specified. Used when copying formulas * * @param colAdjust the amount to add on to each relative cell reference * @param rowAdjust the amount to add on to each relative row reference */ abstract void adjustRelativeCellReferences(int colAdjust, int rowAdjust); /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the column was inserted * @param col the column number which was inserted * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ abstract void columnInserted(int sheetIndex, int col, boolean currentSheet); /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the column was removed * @param col the column number which was removed * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ abstract void columnRemoved(int sheetIndex, int col, boolean currentSheet); /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the row was inserted * @param row the row number which was inserted * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ abstract void rowInserted(int sheetIndex, int row, boolean currentSheet); /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the row was removed * @param row the row number which was removed * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ abstract void rowRemoved(int sheetIndex, int row, boolean currentSheet); /** * If this formula was on an imported sheet, check that * cell references to another sheet are warned appropriately */ abstract void handleImportedCellReferences(); /** * Tells the operands to use the alternate code * * @deprecated - use setParseContext now */ protected void setAlternateCode() { alternateCode = true; } /** * Accessor for the alternate code flag * * @return TRUE to use the alternate code, FALSE otherwise * @deprecated - use setParseContext now */ protected final boolean useAlternateCode() { return alternateCode; } /** * Tells the operands to use the alternate code * * @pc the parse context */ protected void setParseContext(ParseContext pc) { parseContext = pc; } /** * Accessor for the alternate code flag * * @return the parse context */ protected final ParseContext getParseContext() { return parseContext; } } jexcelapi/src/jxl/biff/formula/RangeSeparator.java0000750000175000017500000000441011207000612022417 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; import jxl.biff.IntegerHelper; /** * A "holding" token for a range separator. This token gets instantiated * when the lexical analyzer can't distinguish a range cleanly, eg in the * case where where one of the identifiers of the range is a formula */ class RangeSeparator extends BinaryOperator implements ParsedThing { /** * Constructor */ public RangeSeparator() { } public String getSymbol() { return ":"; } /** * Abstract method which gets the token for this operator * * @return the string symbol for this token */ Token getToken() { return Token.RANGE; } /** * Gets the precedence for this operator. Operator precedents run from * 1 to 5, one being the highest, 5 being the lowest * * @return the operator precedence */ int getPrecedence() { return 1; } /** * Overrides the getBytes() method in the base class and prepends the * memFunc token * * @return the bytes */ byte[] getBytes() { setVolatile(); setOperandAlternateCode(); byte[] funcBytes = super.getBytes(); byte[] bytes = new byte[funcBytes.length+3]; System.arraycopy(funcBytes, 0, bytes, 3, funcBytes.length); // Indicate the mem func bytes[0] = Token.MEM_FUNC.getCode(); IntegerHelper.getTwoBytes(funcBytes.length, bytes, 1); return bytes; } } jexcelapi/src/jxl/biff/formula/Function.java0000750000175000017500000006410611207000612021277 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; import jxl.common.Logger; import jxl.WorkbookSettings; /** * An enumeration detailing the Excel function codes */ final class Function { /** * The logger */ private static Logger logger = Logger.getLogger(Function.class); /** * The code which applies to this function */ private final int code; /** * The property name of this function */ private final String name; /** * The number of args this function expects */ private final int numArgs; /** * All available functions. This attribute is package protected in order * to enable the FunctionNames to initialize */ private static Function[] functions = new Function[0]; /** * Constructor * Sets the token value and adds this token to the array of all token * * @param v the biff code for the token * @param s the string * @param a the number of arguments */ private Function(int v, String s, int a) { code = v; name = s; numArgs = a; // Grow the array Function[] newarray = new Function[functions.length + 1]; System.arraycopy(functions, 0, newarray, 0, functions.length); newarray[functions.length] = this; functions = newarray; } /** * Standard hash code method * * @return the hash code */ public int hashCode() { return code; } /** * Gets the function code - used when generating token data * * @return the code */ int getCode() { return code; } /** * Gets the property name. Used by the FunctionNames object when initializing * the locale specific names * * @return the property name for this function */ String getPropertyName() { return name; } /** * Gets the function name * @param ws the workbook settings * @return the function name */ String getName(WorkbookSettings ws) { FunctionNames fn = ws.getFunctionNames(); return fn.getName(this); } /** * Gets the number of arguments for this function * * @return the number of arguments */ int getNumArgs() { return numArgs; } /** * Gets the type object from its integer value * * @param v the function value * @return the function */ public static Function getFunction(int v) { Function f = null; for (int i = 0; i < functions.length; i++) { if (functions[i].code == v) { f = functions[i]; break; } } return f != null ? f : UNKNOWN; } /** * Gets the type object from its string value. Used when parsing strings * * @param v the function name * @param ws the workbook settings * @return the function */ public static Function getFunction(String v, WorkbookSettings ws) { FunctionNames fn = ws.getFunctionNames(); Function f = fn.getFunction(v); return f != null ? f : UNKNOWN; } /** * Accessor for all the functions, used by the internationalization * work around * * @return all the functions */ static Function[] getFunctions() { return functions; } // The functions public static final Function COUNT = new Function(0x0, "count", 0xff); public static final Function ATTRIBUTE = new Function(0x1, "", 0xff); public static final Function ISNA = new Function(0x2, "isna", 1); public static final Function ISERROR = new Function(0x3, "iserror", 1); public static final Function SUM = new Function(0x4, "sum", 0xff); public static final Function AVERAGE = new Function(0x5, "average", 0xff); public static final Function MIN = new Function(0x6, "min", 0xff); public static final Function MAX = new Function(0x7, "max", 0xff); public static final Function ROW = new Function(0x8, "row", 0xff); public static final Function COLUMN = new Function(0x9, "column", 0xff); public static final Function NA = new Function(0xa, "na", 0); public static final Function NPV = new Function(0xb, "npv", 0xff); public static final Function STDEV = new Function(0xc, "stdev", 0xff); public static final Function DOLLAR = new Function(0xd, "dollar", 2); public static final Function FIXED = new Function(0xe, "fixed", 0xff); public static final Function SIN = new Function(0xf, "sin", 1); public static final Function COS = new Function(0x10, "cos", 1); public static final Function TAN = new Function(0x11, "tan", 1); public static final Function ATAN = new Function(0x12, "atan", 1); public static final Function PI = new Function(0x13, "pi", 0); public static final Function SQRT = new Function(0x14, "sqrt", 1); public static final Function EXP = new Function(0x15, "exp", 1); public static final Function LN = new Function(0x16, "ln", 1); public static final Function LOG10 = new Function(0x17, "log10", 1); public static final Function ABS = new Function(0x18, "abs", 1); public static final Function INT = new Function(0x19, "int", 1); public static final Function SIGN = new Function(0x1a, "sign", 1); public static final Function ROUND = new Function(0x1b, "round", 2); public static final Function LOOKUP = new Function(0x1c, "lookup", 2); public static final Function INDEX = new Function(0x1d, "index", 3); public static final Function REPT = new Function(0x1e, "rept", 2); public static final Function MID = new Function(0x1f, "mid", 3); public static final Function LEN = new Function(0x20, "len", 1); public static final Function VALUE = new Function(0x21, "value", 1); public static final Function TRUE = new Function(0x22, "true", 0); public static final Function FALSE = new Function(0x23, "false", 0); public static final Function AND = new Function(0x24, "and", 0xff); public static final Function OR = new Function(0x25, "or", 0xff); public static final Function NOT = new Function(0x26, "not", 1); public static final Function MOD = new Function(0x27, "mod", 2); public static final Function DCOUNT = new Function(0x28, "dcount", 3); public static final Function DSUM = new Function(0x29, "dsum", 3); public static final Function DAVERAGE = new Function(0x2a, "daverage", 3); public static final Function DMIN = new Function(0x2b, "dmin", 3); public static final Function DMAX = new Function(0x2c, "dmax", 3); public static final Function DSTDEV = new Function(0x2d, "dstdev", 3); public static final Function VAR = new Function(0x2e, "var", 0xff); public static final Function DVAR = new Function(0x2f, "dvar", 3); public static final Function TEXT = new Function(0x30, "text", 2); public static final Function LINEST = new Function(0x31, "linest", 0xff); public static final Function TREND = new Function(0x32, "trend", 0xff); public static final Function LOGEST = new Function(0x33, "logest", 0xff); public static final Function GROWTH = new Function(0x34, "growth", 0xff); //public static final Function GOTO = new Function(0x35, "GOTO",); //public static final Function HALT = new Function(0x36, "HALT",); public static final Function PV = new Function(0x38, "pv", 0xff); public static final Function FV = new Function(0x39, "fv", 0xff); public static final Function NPER = new Function(0x3a, "nper", 0xff); public static final Function PMT = new Function(0x3b, "pmt", 0xff); public static final Function RATE = new Function(0x3c, "rate", 0xff); //public static final Function MIRR = new Function(0x3d, "MIRR",); //public static final Function IRR = new Function(0x3e, "IRR",); public static final Function RAND = new Function(0x3f, "rand", 0); public static final Function MATCH = new Function(0x40, "match", 3); public static final Function DATE = new Function(0x41, "date", 3); public static final Function TIME = new Function(0x42, "time", 3); public static final Function DAY = new Function(0x43, "day", 1); public static final Function MONTH = new Function(0x44, "month", 1); public static final Function YEAR = new Function(0x45, "year", 1); public static final Function WEEKDAY = new Function(0x46, "weekday", 2); public static final Function HOUR = new Function(0x47, "hour", 1); public static final Function MINUTE = new Function(0x48, "minute", 1); public static final Function SECOND = new Function(0x49, "second", 1); public static final Function NOW = new Function(0x4a, "now", 0); public static final Function AREAS = new Function(0x4b, "areas", 0xff); public static final Function ROWS = new Function(0x4c, "rows", 1); public static final Function COLUMNS = new Function(0x4d, "columns", 0xff); public static final Function OFFSET = new Function(0x4e, "offset", 0xff); //public static final Function ABSREF = new Function(0x4f, "ABSREF",); //public static final Function RELREF = new Function(0x50, "RELREF",); //public static final Function ARGUMENT = new Function(0x51,"ARGUMENT",); public static final Function SEARCH = new Function(0x52, "search", 0xff); public static final Function TRANSPOSE = new Function(0x53, "transpose", 0xff); public static final Function ERROR = new Function(0x54, "error", 1); //public static final Function STEP = new Function(0x55, "STEP",); public static final Function TYPE = new Function(0x56, "type", 1); //public static final Function ECHO = new Function(0x57, "ECHO",); //public static final Function SETNAME = new Function(0x58, "SETNAME",); //public static final Function CALLER = new Function(0x59, "CALLER",); //public static final Function DEREF = new Function(0x5a, "DEREF",); //public static final Function WINDOWS = new Function(0x5b, "WINDOWS",); //public static final Function SERIES = new Function(0x5c, "SERIES",); //public static final Function DOCUMENTS = new Function(0x5d,"DOCUMENTS",); //public static final Function ACTIVECELL = new Function(0x5e,"ACTIVECELL",); //public static final Function SELECTION = new Function(0x5f,"SELECTION",); //public static final Function RESULT = new Function(0x60, "RESULT",); public static final Function ATAN2 = new Function(0x61, "atan2", 1); public static final Function ASIN = new Function(0x62, "asin", 1); public static final Function ACOS = new Function(0x63, "acos", 1); public static final Function CHOOSE = new Function(0x64, "choose", 0xff); public static final Function HLOOKUP = new Function(0x65, "hlookup", 0xff); public static final Function VLOOKUP = new Function(0x66, "vlookup", 0xff); //public static final Function LINKS = new Function(0x67, "LINKS",); //public static final Function INPUT = new Function(0x68, "INPUT",); public static final Function ISREF = new Function(0x69, "isref", 1); //public static final Function GETFORMULA = new Function(0x6a,"GETFORMULA",); //public static final Function GETNAME = new Function(0x6b, "GETNAME",); //public static final Function SETVALUE = new Function(0x6c,"SETVALUE",); public static final Function LOG = new Function(0x6d, "log", 0xff); //public static final Function EXEC = new Function(0x6e, "EXEC",); public static final Function CHAR = new Function(0x6f, "char", 1); public static final Function LOWER = new Function(0x70, "lower", 1); public static final Function UPPER = new Function(0x71, "upper", 1); public static final Function PROPER = new Function(0x72, "proper", 1); public static final Function LEFT = new Function(0x73, "left", 0xff); public static final Function RIGHT = new Function(0x74, "right", 0xff); public static final Function EXACT = new Function(0x75, "exact", 2); public static final Function TRIM = new Function(0x76, "trim", 1); public static final Function REPLACE = new Function(0x77, "replace", 4); public static final Function SUBSTITUTE = new Function(0x78, "substitute", 0xff); public static final Function CODE = new Function(0x79, "code", 1); //public static final Function NAMES = new Function(0x7a, "NAMES",); //public static final Function DIRECTORY = new Function(0x7b,"DIRECTORY",); public static final Function FIND = new Function(0x7c, "find", 0xff); public static final Function CELL = new Function(0x7d, "cell", 2); public static final Function ISERR = new Function(0x7e, "iserr", 1); public static final Function ISTEXT = new Function(0x7f, "istext", 1); public static final Function ISNUMBER = new Function(0x80, "isnumber", 1); public static final Function ISBLANK = new Function(0x81, "isblank", 1); public static final Function T = new Function(0x82, "t", 1); public static final Function N = new Function(0x83, "n", 1); //public static final Function FOPEN = new Function(0x84, "FOPEN",); //public static final Function FCLOSE = new Function(0x85, "FCLOSE",); //public static final Function FSIZE = new Function(0x86, "FSIZE",); //public static final Function FREADLN = new Function(0x87, "FREADLN",); //public static final Function FREAD = new Function(0x88, "FREAD",); //public static final Function FWRITELN = new Function(0x89,"FWRITELN",); //public static final Function FWRITE = new Function(0x8a, "FWRITE",); //public static final Function FPOS = new Function(0x8b, "FPOS",); public static final Function DATEVALUE = new Function(0x8c, "datevalue", 1); public static final Function TIMEVALUE = new Function(0x8d, "timevalue", 1); public static final Function SLN = new Function(0x8e, "sln", 3); public static final Function SYD = new Function(0x8f, "syd", 3); public static final Function DDB = new Function(0x90, "ddb", 0xff); //public static final Function GETDEF = new Function(0x91, "GETDEF",); //public static final Function REFTEXT = new Function(0x92, "REFTEXT",); //public static final Function TEXTREF = new Function(0x93, "TEXTREF",); public static final Function INDIRECT = new Function(0x94, "indirect", 0xff); //public static final Function REGISTER = new Function(0x95,"REGISTER",); //public static final Function CALL = new Function(0x96, "CALL",); //public static final Function ADDBAR = new Function(0x97, "ADDBAR",); //public static final Function ADDMENU = new Function(0x98, "ADDMENU",); //public static final Function ADDCOMMAND = // new Function(0x99,"ADDCOMMAND",); //public static final Function ENABLECOMMAND = // new Function(0x9a,"ENABLECOMMAND",); //public static final Function CHECKCOMMAND = // new Function(0x9b,"CHECKCOMMAND",); //public static final Function RENAMECOMMAND = // new Function(0x9c,"RENAMECOMMAND",); //public static final Function SHOWBAR = new Function(0x9d, "SHOWBAR",); //public static final Function DELETEMENU = // new Function(0x9e,"DELETEMENU",); //public static final Function DELETECOMMAND = // new Function(0x9f,"DELETECOMMAND",); //public static final Function GETCHARTITEM = // new Function(0xa0,"GETCHARTITEM",); //public static final Function DIALOGBOX = new Function(0xa1,"DIALOGBOX",); public static final Function CLEAN = new Function(0xa2, "clean", 1); public static final Function MDETERM = new Function(0xa3, "mdeterm", 0xff); public static final Function MINVERSE = new Function(0xa4, "minverse", 0xff); public static final Function MMULT = new Function(0xa5, "mmult", 0xff); //public static final Function FILES = new Function(0xa6, "FILES", public static final Function IPMT = new Function(0xa7, "ipmt", 0xff); public static final Function PPMT = new Function(0xa8, "ppmt", 0xff); public static final Function COUNTA = new Function(0xa9, "counta", 0xff); public static final Function PRODUCT = new Function(0xb7, "product", 0xff); public static final Function FACT = new Function(0xb8, "fact", 1); //public static final Function GETCELL = new Function(0xb9, "GETCELL",); //public static final Function GETWORKSPACE = // new Function(0xba,"GETWORKSPACE",); //public static final Function GETWINDOW = new Function(0xbb,"GETWINDOW",); //public static final Function GETDOCUMENT = // new Function(0xbc,"GETDOCUMENT",); public static final Function DPRODUCT = new Function(0xbd, "dproduct", 3); public static final Function ISNONTEXT = new Function(0xbe, "isnontext", 1); //public static final Function GETNOTE = new Function(0xbf, "GETNOTE",); //public static final Function NOTE = new Function(0xc0, "NOTE",); public static final Function STDEVP = new Function(0xc1, "stdevp", 0xff); public static final Function VARP = new Function(0xc2, "varp", 0xff); public static final Function DSTDEVP = new Function(0xc3, "dstdevp", 0xff); public static final Function DVARP = new Function(0xc4, "dvarp", 0xff); public static final Function TRUNC = new Function(0xc5, "trunc", 0xff); public static final Function ISLOGICAL = new Function(0xc6, "islogical", 1); public static final Function DCOUNTA = new Function(0xc7, "dcounta", 0xff); public static final Function FINDB = new Function(0xcd, "findb", 0xff); public static final Function SEARCHB = new Function(0xce, "searchb", 3); public static final Function REPLACEB = new Function(0xcf, "replaceb", 4); public static final Function LEFTB = new Function(0xd0, "leftb", 0xff); public static final Function RIGHTB = new Function(0xd1, "rightb", 0xff); public static final Function MIDB = new Function(0xd2, "midb", 3); public static final Function LENB = new Function(0xd3, "lenb", 1); public static final Function ROUNDUP = new Function(0xd4, "roundup", 2); public static final Function ROUNDDOWN = new Function(0xd5, "rounddown", 2); public static final Function RANK = new Function(0xd8, "rank", 0xff); public static final Function ADDRESS = new Function(0xdb, "address", 0xff); public static final Function AYS360 = new Function(0xdc, "days360", 0xff); public static final Function ODAY = new Function(0xdd, "today", 0); public static final Function VDB = new Function(0xde, "vdb", 0xff); public static final Function MEDIAN = new Function(0xe3, "median", 0xff); public static final Function SUMPRODUCT = new Function(0xe4, "sumproduct", 0xff); public static final Function SINH = new Function(0xe5, "sinh", 1); public static final Function COSH = new Function(0xe6, "cosh", 1); public static final Function TANH = new Function(0xe7, "tanh", 1); public static final Function ASINH = new Function(0xe8, "asinh", 1); public static final Function ACOSH = new Function(0xe9, "acosh", 1); public static final Function ATANH = new Function(0xea, "atanh", 1); public static final Function INFO = new Function(0xf4, "info", 1); public static final Function AVEDEV = new Function(0x10d, "avedev", 0XFF); public static final Function BETADIST = new Function(0x10e, "betadist", 0XFF); public static final Function GAMMALN = new Function(0x10f, "gammaln", 1); public static final Function BETAINV = new Function(0x110, "betainv", 0XFF); public static final Function BINOMDIST = new Function(0x111, "binomdist", 4); public static final Function CHIDIST = new Function(0x112, "chidist", 2); public static final Function CHIINV = new Function(0x113, "chiinv", 2); public static final Function COMBIN = new Function(0x114, "combin", 2); public static final Function CONFIDENCE = new Function(0x115, "confidence", 3); public static final Function CRITBINOM = new Function(0x116, "critbinom", 3); public static final Function EVEN = new Function(0x117, "even", 1); public static final Function EXPONDIST = new Function(0x118, "expondist", 3); public static final Function FDIST = new Function(0x119, "fdist", 3); public static final Function FINV = new Function(0x11a, "finv", 3); public static final Function FISHER = new Function(0x11b, "fisher", 1); public static final Function FISHERINV = new Function(0x11c, "fisherinv", 1); public static final Function FLOOR = new Function(0x11d, "floor", 2); public static final Function GAMMADIST = new Function(0x11e, "gammadist", 4); public static final Function GAMMAINV = new Function(0x11f, "gammainv", 3); public static final Function CEILING = new Function(0x120, "ceiling", 2); public static final Function HYPGEOMDIST = new Function(0x121, "hypgeomdist", 4); public static final Function LOGNORMDIST = new Function(0x122, "lognormdist", 3); public static final Function LOGINV = new Function(0x123, "loginv", 3); public static final Function NEGBINOMDIST = new Function(0x124, "negbinomdist", 3); public static final Function NORMDIST = new Function(0x125, "normdist", 4); public static final Function NORMSDIST = new Function(0x126, "normsdist", 1); public static final Function NORMINV = new Function(0x127, "norminv", 3); public static final Function NORMSINV = new Function(0x128, "normsinv", 1); public static final Function STANDARDIZE = new Function(0x129, "standardize", 3); public static final Function ODD = new Function(0x12a, "odd", 1); public static final Function PERMUT = new Function(0x12b, "permut", 2); public static final Function POISSON = new Function(0x12c, "poisson", 3); public static final Function TDIST = new Function(0x12d, "tdist", 3); public static final Function WEIBULL = new Function(0x12e, "weibull", 4); public static final Function SUMXMY2 = new Function(303, "sumxmy2", 0xff); public static final Function SUMX2MY2 = new Function(304, "sumx2my2", 0xff); public static final Function SUMX2PY2 = new Function(305, "sumx2py2", 0xff); public static final Function CHITEST = new Function(0x132, "chitest", 0xff); public static final Function CORREL = new Function(0x133, "correl", 0xff); public static final Function COVAR = new Function(0x134, "covar", 0xff); public static final Function FORECAST = new Function(0x135, "forecast", 0xff); public static final Function FTEST = new Function(0x136, "ftest", 0xff); public static final Function INTERCEPT = new Function(0x137, "intercept", 0xff); public static final Function PEARSON = new Function(0x138, "pearson", 0xff); public static final Function RSQ = new Function(0x139, "rsq", 0xff); public static final Function STEYX = new Function(0x13a, "steyx", 0xff); public static final Function SLOPE = new Function(0x13b, "slope", 2); public static final Function TTEST = new Function(0x13c, "ttest", 0xff); public static final Function PROB = new Function(0x13d, "prob", 0xff); public static final Function DEVSQ = new Function(0x13e, "devsq", 0xff); public static final Function GEOMEAN = new Function(0x13f, "geomean", 0xff); public static final Function HARMEAN = new Function(0x140, "harmean", 0xff); public static final Function SUMSQ = new Function(0x141, "sumsq", 0xff); public static final Function KURT = new Function(0x142, "kurt", 0xff); public static final Function SKEW = new Function(0x143, "skew", 0xff); public static final Function ZTEST = new Function(0x144, "ztest", 0xff); public static final Function LARGE = new Function(0x145, "large", 0xff); public static final Function SMALL = new Function(0x146, "small", 0xff); public static final Function QUARTILE = new Function(0x147, "quartile", 0xff); public static final Function PERCENTILE = new Function(0x148, "percentile", 0xff); public static final Function PERCENTRANK = new Function(0x149, "percentrank", 0xff); public static final Function MODE = new Function(0x14a, "mode", 0xff); public static final Function TRIMMEAN = new Function(0x14b, "trimmean", 0xff); public static final Function TINV = new Function(0x14c, "tinv", 2); public static final Function CONCATENATE = new Function(0x150, "concatenate", 0xff); public static final Function POWER = new Function(0x151, "power", 2); public static final Function RADIANS = new Function(0x156, "radians", 1); public static final Function DEGREES = new Function(0x157, "degrees", 1); public static final Function SUBTOTAL = new Function(0x158, "subtotal", 0xff); public static final Function SUMIF = new Function(0x159, "sumif", 0xff); public static final Function COUNTIF = new Function(0x15a, "countif", 2); public static final Function COUNTBLANK = new Function(0x15b, "countblank", 1); public static final Function HYPERLINK = new Function(0x167, "hyperlink", 2); public static final Function AVERAGEA = new Function(0x169, "averagea", 0xff); public static final Function MAXA = new Function(0x16a, "maxa", 0xff); public static final Function MINA = new Function(0x16b, "mina", 0xff); public static final Function STDEVPA = new Function(0x16c, "stdevpa", 0xff); public static final Function VARPA = new Function(0x16d, "varpa", 0xff); public static final Function STDEVA = new Function(0x16e, "stdeva", 0xff); public static final Function VARA = new Function(0x16f, "vara", 0xff); // If token. This is not an excel assigned number, but one made up // in order that the if command may be recognized public static final Function IF = new Function(0xfffe, "if", 0xff); // Unknown token public static final Function UNKNOWN = new Function(0xffff, "", 0); } jexcelapi/src/jxl/biff/formula/Multiply.java0000750000175000017500000000303311207000612021321 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; /** * A cell reference in a formula */ class Multiply extends BinaryOperator implements ParsedThing { /** * Constructor */ public Multiply() { } public String getSymbol() { return "*"; } /** * Abstract method which gets the token for this operator * * @return the string symbol for this token */ Token getToken() { return Token.MULTIPLY; } /** * Gets the precedence for this operator. Operator precedents run from * 1 to 5, one being the highest, 5 being the lowest * * @return the operator precedence */ int getPrecedence() { return 3; } } jexcelapi/src/jxl/biff/formula/BinaryOperator.java0000750000175000017500000001522611207000612022451 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; import jxl.common.Logger; import java.util.Stack; /** * A cell reference in a formula */ abstract class BinaryOperator extends Operator implements ParsedThing { // The logger private static final Logger logger = Logger.getLogger(BinaryOperator.class); /** * Constructor */ public BinaryOperator() { } /** * Reads the ptg data from the array starting at the specified position * * @param data the RPN array * @param pos the current position in the array, excluding the ptg identifier * @return the number of bytes read */ public int read(byte[] data, int pos) { return 0; } /** * Gets the operands for this operator from the stack * * @param s the token stack */ public void getOperands(Stack s) { ParseItem o1 = (ParseItem) s.pop(); ParseItem o2 = (ParseItem) s.pop(); add(o1); add(o2); } /** * Gets the string version of this binary operator * * @param buf a the string buffer */ public void getString(StringBuffer buf) { ParseItem[] operands = getOperands(); operands[1].getString(buf); buf.append(getSymbol()); operands[0].getString(buf); } /** * Adjusts all the relative cell references in this formula by the * amount specified. Used when copying formulas * * @param colAdjust the amount to add on to each relative cell reference * @param rowAdjust the amount to add on to each relative row reference */ public void adjustRelativeCellReferences(int colAdjust, int rowAdjust) { ParseItem[] operands = getOperands(); operands[1].adjustRelativeCellReferences(colAdjust, rowAdjust); operands[0].adjustRelativeCellReferences(colAdjust, rowAdjust); } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the column was inserted * @param col the column number which was inserted * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void columnInserted(int sheetIndex, int col, boolean currentSheet) { ParseItem[] operands = getOperands(); operands[1].columnInserted(sheetIndex, col, currentSheet); operands[0].columnInserted(sheetIndex, col, currentSheet); } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the column was removed * @param col the column number which was removed * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void columnRemoved(int sheetIndex, int col, boolean currentSheet) { ParseItem[] operands = getOperands(); operands[1].columnRemoved(sheetIndex, col, currentSheet); operands[0].columnRemoved(sheetIndex, col, currentSheet); } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the row was inserted * @param row the row number which was inserted * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void rowInserted(int sheetIndex, int row, boolean currentSheet) { ParseItem[] operands = getOperands(); operands[1].rowInserted(sheetIndex, row, currentSheet); operands[0].rowInserted(sheetIndex, row, currentSheet); } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the row was removed * @param row the row number which was removed * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void rowRemoved(int sheetIndex, int row, boolean currentSheet) { ParseItem[] operands = getOperands(); operands[1].rowRemoved(sheetIndex, row, currentSheet); operands[0].rowRemoved(sheetIndex, row, currentSheet); } /** * Gets the token representation of this item in RPN * * @return the bytes applicable to this formula */ byte[] getBytes() { // Get the data for the operands ParseItem[] operands = getOperands(); byte[] data = new byte[0]; // Get the operands in reverse order to get the RPN for (int i = operands.length - 1; i >= 0; i--) { byte[] opdata = operands[i].getBytes(); // Grow the array byte[] newdata = new byte[data.length + opdata.length]; System.arraycopy(data, 0, newdata, 0, data.length); System.arraycopy(opdata, 0, newdata, data.length, opdata.length); data = newdata; } // Add on the operator byte byte[] newdata = new byte[data.length + 1]; System.arraycopy(data, 0, newdata, 0, data.length); newdata[data.length] = getToken().getCode(); return newdata; } /** * Abstract method which gets the binary operator string symbol * * @return the string symbol for this token */ abstract String getSymbol(); /** * Abstract method which gets the token for this operator * * @return the string symbol for this token */ abstract Token getToken(); /** * If this formula was on an imported sheet, check that * cell references to another sheet are warned appropriately * Does nothing, as operators don't have cell references */ void handleImportedCellReferences() { ParseItem[] operands = getOperands(); operands[0].handleImportedCellReferences(); operands[1].handleImportedCellReferences(); } } jexcelapi/src/jxl/biff/formula/Name.java0000750000175000017500000000404011207000612020361 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; import jxl.biff.IntegerHelper; /** * A name operand */ class Name extends Operand implements ParsedThing { /** * Constructor */ public Name() { } /** * Reads the ptg data from the array starting at the specified position * * @param data the RPN array * @param pos the current position in the array, excluding the ptg identifier * @return the number of bytes read */ public int read(byte[] data, int pos) { return 6; } /** * Gets the token representation of this item in RPN * * @return the bytes applicable to this formula */ byte[] getBytes() { byte[] data = new byte[6]; return data; } /** * Abstract method implementation to get the string equivalent of this * token * * @param buf the string to append to */ public void getString(StringBuffer buf) { buf.append("[Name record not implemented]"); } /** * If this formula was on an imported sheet, check that * cell references to another sheet are warned appropriately * Sets this formula to invalid */ void handleImportedCellReferences() { setInvalid(); } } jexcelapi/src/jxl/biff/formula/ColumnRange3d.java0000750000175000017500000000701211207000612022144 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2005 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; import jxl.common.Assert; import jxl.common.Logger; import jxl.biff.CellReferenceHelper; /** * A nested class to hold range information */ class ColumnRange3d extends Area3d { /** * The logger */ private static Logger logger = Logger.getLogger(ColumnRange3d.class); /** * A handle to the workbook */ private ExternalSheet workbook; /** * The sheet number */ private int sheet; /** * Constructor * * @param es the external sheet */ ColumnRange3d(ExternalSheet es) { super(es); workbook = es; } /** * Constructor invoked when parsing a string formula * * @param s the string to parse * @param es the external sheet * @exception FormulaException */ ColumnRange3d(String s, ExternalSheet es) throws FormulaException { super(es); workbook = es; int seppos = s.lastIndexOf(":"); Assert.verify(seppos != -1); String startcell = s.substring(0, seppos); String endcell = s.substring(seppos + 1); // Get the the start cell details int sep = s.indexOf('!'); String cellString = s.substring(sep + 1, seppos); int columnFirst = CellReferenceHelper.getColumn(cellString); int rowFirst = 0; // Get the sheet index String sheetName = s.substring(0, sep); int sheetNamePos = sheetName.lastIndexOf(']'); // Remove single quotes, if they exist if (sheetName.charAt(0) == '\'' && sheetName.charAt(sheetName.length() - 1) == '\'') { sheetName = sheetName.substring(1, sheetName.length() - 1); } sheet = es.getExternalSheetIndex(sheetName); if (sheet < 0) { throw new FormulaException(FormulaException.SHEET_REF_NOT_FOUND, sheetName); } // Get the last cell index int columnLast = CellReferenceHelper.getColumn(endcell); int rowLast = 0xffff; boolean columnFirstRelative = true; boolean rowFirstRelative = true; boolean columnLastRelative = true; boolean rowLastRelative = true; setRangeData(sheet, columnFirst, columnLast, rowFirst, rowLast, columnFirstRelative, rowFirstRelative, columnLastRelative, rowLastRelative); } /** * Gets the string representation of this column range * * @param buf the string buffer to append to */ public void getString(StringBuffer buf) { buf.append('\''); buf.append(workbook.getExternalSheetName(sheet)); buf.append('\''); buf.append('!'); CellReferenceHelper.getColumnReference(getFirstColumn(), buf); buf.append(':'); CellReferenceHelper.getColumnReference(getLastColumn(), buf); } } jexcelapi/src/jxl/biff/formula/GreaterEqual.java0000750000175000017500000000305111207000612022063 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; /** * A cell reference in a formula */ class GreaterEqual extends BinaryOperator implements ParsedThing { /** * Constructor */ public GreaterEqual() { } public String getSymbol() { return ">="; } /** * Abstract method which gets the token for this operator * * @return the string symbol for this token */ Token getToken() { return Token.GREATER_EQUAL; } /** * Gets the precedence for this operator. Operator precedents run from * 1 to 5, one being the highest, 5 being the lowest * * @return the operator precedence */ int getPrecedence() { return 5; } } jexcelapi/src/jxl/biff/formula/CloseParentheses.java0000750000175000017500000000211111207000612022745 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; /** * The close of parentheses token */ class CloseParentheses extends StringParseItem { /** * Constructor */ public CloseParentheses() { } } jexcelapi/src/jxl/biff/formula/Operand.java0000750000175000017500000000637211207000612021103 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; /** * An operand in the parse tree. Operands represent leaf nodes in the * tree, and may not have children * Operands include numerical values, cell references and ranges */ abstract class Operand extends ParseItem { /** * Constructor */ public Operand() { } /** * Default behaviour is to do nothing * * @param colAdjust the amount to add on to each relative cell reference * @param rowAdjust the amount to add on to each relative row reference */ public void adjustRelativeCellReferences(int colAdjust, int rowAdjust) { } /** * Default behaviour is to do nothing * * @param sheetIndex the sheet on which the column was inserted * @param col the column number which was inserted * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void columnInserted(int sheetIndex, int col, boolean currentSheet) { } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the column was removed * @param col the column number which was removed * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void columnRemoved(int sheetIndex, int col, boolean currentSheet) { } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the row was inserted * @param row the row number which was inserted * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void rowInserted(int sheetIndex, int row, boolean currentSheet) { } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the row was removed * @param row the row number which was removed * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void rowRemoved(int sheetIndex, int row, boolean currentSheet) { } } jexcelapi/src/jxl/biff/formula/Percent.java0000750000175000017500000000377311207000612021115 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; /** * A cell reference in a formula */ class Percent extends UnaryOperator implements ParsedThing { /** * Constructor */ public Percent() { } public String getSymbol() { return "%"; } public void getString(StringBuffer buf) { ParseItem[] operands = getOperands(); operands[0].getString(buf); buf.append(getSymbol()); } /** * If this formula was on an imported sheet, check that * cell references to another sheet are warned appropriately * Does nothing, as operators don't have cell references */ void handleImportedCellReferences() { ParseItem[] operands = getOperands(); operands[0].handleImportedCellReferences(); } /** * Abstract method which gets the token for this operator * * @return the string symbol for this token */ Token getToken() { return Token.PERCENT; } /** * Gets the precedence for this operator. Operator precedents run from * 1 to 5, one being the highest, 5 being the lowest * * @return the operator precedence */ int getPrecedence() { return 5; } } jexcelapi/src/jxl/biff/formula/Add.java0000750000175000017500000000313411207000612020174 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; /** * A cell reference in a formula */ class Add extends BinaryOperator implements ParsedThing { /** * Constructor */ public Add() { } /** * Gets the symbol for string displays * * @return the symbol */ public String getSymbol() { return "+"; } /** * Abstract method which gets the token for this operator * * @return the string symbol for this token */ Token getToken() { return Token.ADD; } /** * Gets the precedence for this operator. Operator precedents run from * 1 to 5, one being the highest, 5 being the lowest * * @return the operator precedence */ int getPrecedence() { return 4; } } jexcelapi/src/jxl/biff/formula/StringFunction.java0000750000175000017500000000354111207000612022462 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; import jxl.common.Logger; import jxl.WorkbookSettings; /** * Class used to hold a function when reading it in from a string. At this * stage it is unknown whether it is a BuiltInFunction or a VariableArgFunction */ class StringFunction extends StringParseItem { /** * The logger */ private static Logger logger = Logger.getLogger(StringFunction.class); /** * The function */ private Function function; /** * The function string */ private String functionString; /** * Constructor * * @param s the lexically parsed stirng */ StringFunction(String s) { functionString = s.substring(0, s.length() - 1); } /** * Accessor for the function * * @param ws the workbook settings * @return the function */ Function getFunction(WorkbookSettings ws) { if (function == null) { function = Function.getFunction(functionString, ws); } return function; } } jexcelapi/src/jxl/biff/formula/BooleanValue.java0000750000175000017500000000464511207000612022070 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; /** * A boolean operand in a formula */ class BooleanValue extends Operand implements ParsedThing { /** * The boolean value */ private boolean value; /** * Constructor */ public BooleanValue() { } /** * Constructor used when parsing a string formula * * @param s the string token, including quote marks */ public BooleanValue(String s) { // remove the quotes value = Boolean.valueOf(s).booleanValue(); } /** * Reads the ptg data from the array starting at the specified position * * @param data the RPN array * @param pos the current position in the array, excluding the ptg identifier * @return the number of bytes read */ public int read(byte[] data, int pos) { value = data[pos] == 1 ? true : false; return 1; } /** * Gets the token representation of this item in RPN * * @return the bytes applicable to this formula */ byte[] getBytes() { byte[] data = new byte[2]; data[0] = Token.BOOL.getCode(); data[1] = (byte) (value == true ? 1 : 0); return data; } /** * Abstract method implementation to get the string equivalent of this * token * * @param buf the string to append to */ public void getString(StringBuffer buf) { buf.append((new Boolean(value)).toString()); } /** * If this formula was on an imported sheet, check that * cell references to another sheet are warned appropriately * Does nothing */ void handleImportedCellReferences() { } } jexcelapi/src/jxl/biff/formula/VariableArgFunction.java0000750000175000017500000002250011207000612023367 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; import java.util.Stack; import jxl.common.Logger; import jxl.WorkbookSettings; import jxl.biff.IntegerHelper; /** * A built in function in a formula. These functions take a variable * number of arguments, such as a range (eg. SUM etc) */ class VariableArgFunction extends Operator implements ParsedThing { /** * The logger */ private static Logger logger = Logger.getLogger(VariableArgFunction.class); /** * The function */ private Function function; /** * The number of arguments */ private int arguments; /** * Flag which indicates whether this was initialized from the client * api or from an excel sheet */ private boolean readFromSheet; /** * The workbooks settings */ private WorkbookSettings settings; /** * Constructor */ public VariableArgFunction(WorkbookSettings ws) { readFromSheet = true; settings = ws; } /** * Constructor used when parsing a function from a string * * @param f the function * @param a the number of arguments */ public VariableArgFunction(Function f, int a, WorkbookSettings ws) { function = f; arguments = a; readFromSheet = false; settings = ws; } /** * Reads the ptg data from the array starting at the specified position * * @param data the RPN array * @param pos the current position in the array, excluding the ptg identifier * @return the number of bytes read * @exception FormulaException */ public int read(byte[] data, int pos) throws FormulaException { arguments = data[pos]; int index = IntegerHelper.getInt(data[pos+1], data[pos+2]); function = Function.getFunction(index); if (function == Function.UNKNOWN) { throw new FormulaException(FormulaException.UNRECOGNIZED_FUNCTION, index); } return 3; } /** * Gets the operands for this operator from the stack */ public void getOperands(Stack s) { // parameters are in the correct order, god damn them ParseItem[] items = new ParseItem[arguments]; for (int i = arguments - 1; i >= 0 ; i--) { ParseItem pi = (ParseItem) s.pop(); items[i] = pi; } for (int i = 0 ; i < arguments; i++) { add(items[i]); } } public void getString(StringBuffer buf) { buf.append(function.getName(settings)); buf.append('('); if (arguments > 0) { ParseItem[] operands = getOperands(); if (readFromSheet) { // arguments are in the same order they were specified operands[0].getString(buf); for (int i = 1; i < arguments; i++) { buf.append(','); operands[i].getString(buf); } } else { // arguments are stored in the reverse order to which they // were specified, so iterate through them backwards operands[arguments - 1].getString(buf); for (int i = arguments - 2; i >= 0 ; i--) { buf.append(','); operands[i].getString(buf); } } } buf.append(')'); } /** * Adjusts all the relative cell references in this formula by the * amount specified. Used when copying formulas * * @param colAdjust the amount to add on to each relative cell reference * @param rowAdjust the amount to add on to each relative row reference */ public void adjustRelativeCellReferences(int colAdjust, int rowAdjust) { ParseItem[] operands = getOperands(); for (int i = 0 ; i < operands.length ; i++) { operands[i].adjustRelativeCellReferences(colAdjust, rowAdjust); } } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the column was inserted * @param col the column number which was inserted * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void columnInserted(int sheetIndex, int col, boolean currentSheet) { ParseItem[] operands = getOperands(); for (int i = 0 ; i < operands.length ; i++) { operands[i].columnInserted(sheetIndex, col, currentSheet); } } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the column was removed * @param col the column number which was removed * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void columnRemoved(int sheetIndex, int col, boolean currentSheet) { ParseItem[] operands = getOperands(); for (int i = 0 ; i < operands.length ; i++) { operands[i].columnRemoved(sheetIndex, col, currentSheet); } } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the row was inserted * @param row the row number which was inserted * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void rowInserted(int sheetIndex, int row, boolean currentSheet) { ParseItem[] operands = getOperands(); for (int i = 0 ; i < operands.length ; i++) { operands[i].rowInserted(sheetIndex, row, currentSheet); } } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the row was removed * @param row the row number which was removed * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void rowRemoved(int sheetIndex, int row, boolean currentSheet) { ParseItem[] operands = getOperands(); for (int i = 0 ; i < operands.length ; i++) { operands[i].rowRemoved(sheetIndex, row, currentSheet); } } /** * If this formula was on an imported sheet, check that * cell references to another sheet are warned appropriately * Does nothing, as operators don't have cell references */ void handleImportedCellReferences() { ParseItem[] operands = getOperands(); for (int i = 0 ; i < operands.length ; i++) { operands[i].handleImportedCellReferences(); } } /** * Gets the underlying function */ Function getFunction() { return function; } /** * Gets the token representation of this item in RPN * * @return the bytes applicable to this formula */ byte[] getBytes() { handleSpecialCases(); // Get the data for the operands - in the correct order ParseItem[] operands = getOperands(); byte[] data = new byte[0]; for (int i = 0 ; i < operands.length ; i++) { byte[] opdata = operands[i].getBytes(); // Grow the array byte[] newdata = new byte[data.length + opdata.length]; System.arraycopy(data, 0, newdata, 0, data.length); System.arraycopy(opdata, 0, newdata, data.length, opdata.length); data = newdata; } // Add on the operator byte byte[] newdata = new byte[data.length + 4]; System.arraycopy(data, 0, newdata, 0, data.length); newdata[data.length] = !useAlternateCode() ? Token.FUNCTIONVARARG.getCode() : Token.FUNCTIONVARARG.getCode2() ; newdata[data.length+1] = (byte) arguments; IntegerHelper.getTwoBytes(function.getCode(), newdata, data.length+2); return newdata; } /** * Gets the precedence for this operator. Operator precedents run from * 1 to 5, one being the highest, 5 being the lowest * * @return the operator precedence */ int getPrecedence() { return 3; } /** * Handles functions which form a special case */ private void handleSpecialCases() { // Handle the array functions. Tell all the Area records to // use their alternative token code if (function == Function.SUMPRODUCT) { // Get the data for the operands - in reverse order ParseItem[] operands = getOperands(); for (int i = operands.length - 1 ; i >= 0 ; i--) { if (operands[i] instanceof Area) { operands[i].setAlternateCode(); } } } } } jexcelapi/src/jxl/biff/formula/StringParseItem.java0000750000175000017500000000747211207000612022575 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2003 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; /** * A dummy implementation used for typing information when tokens * are read when parsing strings. These are then stored by the parser before * being re-stored as the appropriate RPN syntactic equivalent */ class StringParseItem extends ParseItem { /** * Constructor */ protected StringParseItem() { } /** * Gets the string representation of this item. Does nothing here * * @param buf */ void getString(StringBuffer buf) { } /** * Gets the token representation of this item in RPN. Does nothing here * * @return the bytes applicable to this formula */ byte[] getBytes() { return new byte[0]; } /** * Default behaviour is to do nothing * * @param colAdjust the amount to add on to each relative cell reference * @param rowAdjust the amount to add on to each relative row reference */ public void adjustRelativeCellReferences(int colAdjust, int rowAdjust) { } /** * Default behaviour is to do nothing * * @param sheetIndex the sheet on which the column was inserted * @param col the column number which was inserted * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void columnInserted(int sheetIndex, int col, boolean currentSheet) { } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the column was removed * @param col the column number which was removed * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void columnRemoved(int sheetIndex, int col, boolean currentSheet) { } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the row was inserted * @param row the row number which was inserted * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void rowInserted(int sheetIndex, int row, boolean currentSheet) { } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the row was removed * @param row the row number which was removed * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void rowRemoved(int sheetIndex, int row, boolean currentSheet) { } /** * If this formula was on an imported sheet, check that * cell references to another sheet are warned appropriately * Does nothing */ void handleImportedCellReferences() { } } jexcelapi/src/jxl/biff/formula/Token.java0000750000175000017500000001527311207000612020573 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; import java.util.HashMap; /** * An enumeration detailing the Excel parsed tokens * A particular token may be associated with more than one token code */ class Token { /** * The array of values which apply to this token */ public final int[] value; /** * All available tokens, keyed on value */ private static HashMap tokens = new HashMap(20); /** * Constructor * Sets the token value and adds this token to the array of all token * * @param v the biff code for the token */ private Token(int v) { value = new int[] {v}; tokens.put(new Integer(v), this); } /** * Constructor * Sets the token value and adds this token to the array of all token * * @param v the biff code for the token */ private Token(int v1, int v2) { value = new int[] {v1, v2}; tokens.put(new Integer(v1), this); tokens.put(new Integer(v2), this); } /** * Constructor * Sets the token value and adds this token to the array of all token * * @param v the biff code for the token */ private Token(int v1, int v2, int v3) { value = new int[] {v1, v2, v3}; tokens.put(new Integer(v1), this); tokens.put(new Integer(v2), this); tokens.put(new Integer(v3), this); } /** * Constructor * Sets the token value and adds this token to the array of all token * * @param v the biff code for the token */ private Token(int v1, int v2, int v3, int v4) { value = new int[] {v1, v2, v3, v4}; tokens.put(new Integer(v1), this); tokens.put(new Integer(v2), this); tokens.put(new Integer(v3), this); tokens.put(new Integer(v4), this); } /** * Constructor * Sets the token value and adds this token to the array of all token * * @param v the biff code for the token */ private Token(int v1, int v2, int v3, int v4, int v5) { value = new int[] {v1, v2, v3, v4, v5}; tokens.put(new Integer(v1), this); tokens.put(new Integer(v2), this); tokens.put(new Integer(v3), this); tokens.put(new Integer(v4), this); tokens.put(new Integer(v5), this); } /** * Gets the token code for the specified token * * @return the token code. This is the first item in the array */ public byte getCode() { return (byte) value[0]; } /** * Gets the reference token code for the specified token. This is always * the first on the list * * @return the token code. This is the first item in the array */ public byte getReferenceCode() { return (byte) value[0]; } /** * Gets the an alternative token code for the specified token * Used for certain types of volatile function * * @return the token code */ public byte getCode2() { return (byte) (value.length > 0 ? value[1] : value[0]); } /** * Gets the value token code for the specified token. This is always * the second item on the list * * @return the token code */ public byte getValueCode() { return (byte) (value.length > 0 ? value[1] : value[0]); } /** * Gets the type object from its integer value */ public static Token getToken(int v) { Token t = (Token) tokens.get(new Integer(v)); return t != null ? t : UNKNOWN; } // Operands public static final Token REF = new Token(0x44, 0x24, 0x64); public static final Token REF3D = new Token(0x5a, 0x3a, 0x7a); public static final Token MISSING_ARG = new Token(0x16); public static final Token STRING = new Token(0x17); public static final Token ERR = new Token(0x1c); public static final Token BOOL = new Token(0x1d); public static final Token INTEGER = new Token(0x1e); public static final Token DOUBLE = new Token(0x1f); public static final Token REFERR = new Token(0x2a, 0x4a, 0x6a); public static final Token REFV = new Token(0x2c, 0x4c, 0x6c); public static final Token AREAV = new Token(0x2d, 0x4d, 0x6d); public static final Token MEM_AREA = new Token(0x26, 0x46, 0x66); public static final Token AREA = new Token(0x25, 0x65, 0x45); public static final Token NAMED_RANGE = new Token(0x23, 0x43, 0x63); //need 0x23 for data validation references public static final Token NAME = new Token(0x39, 0x59); public static final Token AREA3D = new Token(0x3b, 0x5b); // Unary Operators public static final Token UNARY_PLUS = new Token(0x12); public static final Token UNARY_MINUS = new Token(0x13); public static final Token PERCENT = new Token(0x14); public static final Token PARENTHESIS = new Token(0x15); // Binary Operators public static final Token ADD = new Token(0x3); public static final Token SUBTRACT = new Token(0x4); public static final Token MULTIPLY = new Token(0x5); public static final Token DIVIDE = new Token(0x6); public static final Token POWER = new Token(0x7); public static final Token CONCAT = new Token(0x8); public static final Token LESS_THAN = new Token(0x9); public static final Token LESS_EQUAL = new Token(0xa); public static final Token EQUAL = new Token(0xb); public static final Token GREATER_EQUAL = new Token(0xc); public static final Token GREATER_THAN = new Token(0xd); public static final Token NOT_EQUAL = new Token(0xe); public static final Token UNION = new Token(0x10); public static final Token RANGE = new Token(0x11); // Functions public static final Token FUNCTION = new Token(0x41, 0x21, 0x61); public static final Token FUNCTIONVARARG = new Token(0x42, 0x22, 0x62); // Control public static final Token ATTRIBUTE = new Token(0x19); public static final Token MEM_FUNC = new Token(0x29, 0x49, 0x69); // Unknown token public static final Token UNKNOWN = new Token(0xffff); } jexcelapi/src/jxl/biff/formula/SharedFormulaCellReference.java0000750000175000017500000000715511207000612024666 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; import jxl.common.Logger; import jxl.Cell; import jxl.biff.CellReferenceHelper; import jxl.biff.IntegerHelper; /** * A cell reference in a formula */ class SharedFormulaCellReference extends Operand implements ParsedThing { // The logger private static Logger logger = Logger.getLogger(SharedFormulaCellReference.class); /** * Indicates whether the column reference is relative or absolute */ private boolean columnRelative; /** * Indicates whether the row reference is relative or absolute */ private boolean rowRelative; /** * The column reference */ private int column; /** * The row reference */ private int row; /** * The cell containing the formula. Stored in order to determine * relative cell values */ private Cell relativeTo; /** * Constructor * * @param the cell the formula is relative to */ public SharedFormulaCellReference(Cell rt) { relativeTo = rt; } /** * Reads the ptg data from the array starting at the specified position * * @param data the RPN array * @param pos the current position in the array, excluding the ptg identifier * @return the number of bytes read */ public int read(byte[] data, int pos) { // Preserve signage on column and row values, because they will // probably be relative row = IntegerHelper.getShort(data[pos], data[pos+1]); int columnMask = IntegerHelper.getInt(data[pos+2], data[pos+3]); column = (byte) (columnMask & 0xff); columnRelative = ((columnMask & 0x4000) != 0); rowRelative = ((columnMask & 0x8000) != 0); if (columnRelative && relativeTo != null) { column = relativeTo.getColumn() + column; } if (rowRelative && relativeTo != null) { row = relativeTo.getRow() + row; } return 4; } public int getColumn() { return column; } public int getRow() { return row; } public void getString(StringBuffer buf) { CellReferenceHelper.getCellReference(column, row, buf); } /** * Gets the token representation of this item in RPN * * @return the bytes applicable to this formula */ byte[] getBytes() { byte[] data = new byte[5]; data[0] = Token.REF.getCode(); IntegerHelper.getTwoBytes(row, data, 1); int columnMask = column; if (columnRelative) { columnMask |= 0x4000; } if (rowRelative) { columnMask |= 0x8000; } IntegerHelper.getTwoBytes(columnMask, data, 3); return data; } /** * If this formula was on an imported sheet, check that * cell references to another sheet are warned appropriately * Does nothing */ void handleImportedCellReferences() { } } jexcelapi/src/jxl/biff/formula/MissingArg.java0000750000175000017500000000407611207000612021555 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; /** * Represents a missing argument in an argument list */ class MissingArg extends Operand implements ParsedThing { /** * Constructor */ public MissingArg() { } /** * Reads the ptg data from the array starting at the specified position. * A missing argument contains no associated data * * @param data the RPN array * @param pos the current position in the array, excluding the ptg identifier * @return the number of bytes read */ public int read(byte[] data, int pos) { return 0; } /** * Gets the token representation of this item in RPN * * @return the bytes applicable to this formula */ byte[] getBytes() { byte[] data = new byte[1]; data[0] = Token.MISSING_ARG.getCode(); return data; } /** * Abstract method implementation to get the string equivalent of this * token * * @param buf the string to append to */ public void getString(StringBuffer buf) { } /** * If this formula was on an imported sheet, check that * cell references to another sheet are warned appropriately * Does nothing */ void handleImportedCellReferences() { } } jexcelapi/src/jxl/biff/formula/NumberValue.java0000750000175000017500000000231411207000612021730 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; /** * A constant numerical value in a formula */ abstract class NumberValue extends Operand implements ParsedThing { protected NumberValue() { } public abstract double getValue(); public void getString(StringBuffer buf) { buf.append(Double.toString(getValue())); } } jexcelapi/src/jxl/biff/formula/UnaryOperator.java0000750000175000017500000001317111207000612022320 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; import java.util.Stack; /** * A cell reference in a formula */ abstract class UnaryOperator extends Operator implements ParsedThing { /** * Constructor */ public UnaryOperator() { } /** * Reads the ptg data from the array starting at the specified position * * @param data the RPN array * @param pos the current position in the array, excluding the ptg identifier * @return the number of bytes read */ public int read(byte[] data, int pos) { return 0; } /** * Gets the operands for this operator from the stack */ public void getOperands(Stack s) { ParseItem o1 = (ParseItem) s.pop(); add(o1); } /** * Gets the string * * @param buf */ public void getString(StringBuffer buf) { ParseItem[] operands = getOperands(); buf.append(getSymbol()); operands[0].getString(buf); } /** * Adjusts all the relative cell references in this formula by the * amount specified. Used when copying formulas * * @param colAdjust the amount to add on to each relative cell reference * @param rowAdjust the amount to add on to each relative row reference */ public void adjustRelativeCellReferences(int colAdjust, int rowAdjust) { ParseItem[] operands = getOperands(); operands[0].adjustRelativeCellReferences(colAdjust, rowAdjust); } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the column was inserted * @param col the column number which was inserted * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void columnInserted(int sheetIndex, int col, boolean currentSheet) { ParseItem[] operands = getOperands(); operands[0].columnInserted(sheetIndex, col, currentSheet); } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the column was removed * @param col the column number which was removed * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void columnRemoved(int sheetIndex, int col, boolean currentSheet) { ParseItem[] operands = getOperands(); operands[0].columnRemoved(sheetIndex, col, currentSheet); } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the row was inserted * @param row the row number which was inserted * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void rowInserted(int sheetIndex, int row, boolean currentSheet) { ParseItem[] operands = getOperands(); operands[0].rowInserted(sheetIndex, row, currentSheet); } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the row was removed * @param row the row number which was removed * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void rowRemoved(int sheetIndex, int row, boolean currentSheet) { ParseItem[] operands = getOperands(); operands[0].rowRemoved(sheetIndex, row, currentSheet); } /** * Gets the token representation of this item in RPN * * @return the bytes applicable to this formula */ byte[] getBytes() { // Get the data for the operands ParseItem[] operands = getOperands(); byte[] data = operands[0].getBytes(); // Add on the operator byte byte[] newdata = new byte[data.length + 1]; System.arraycopy(data, 0, newdata, 0, data.length); newdata[data.length] = getToken().getCode(); return newdata; } /** * Abstract method which gets the binary operator string symbol * * @return the string symbol for this token */ abstract String getSymbol(); /** * Abstract method which gets the token for this operator * * @return the string symbol for this token */ abstract Token getToken(); /** * If this formula was on an imported sheet, check that * cell references to another sheet are warned appropriately * Does nothing, as operators don't have cell references */ void handleImportedCellReferences() { ParseItem[] operands = getOperands(); operands[0].handleImportedCellReferences(); } } jexcelapi/src/jxl/biff/formula/Attribute.java0000750000175000017500000003361611207000612021457 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; import java.util.Stack; import jxl.common.Logger; import jxl.WorkbookSettings; import jxl.biff.IntegerHelper; /** * A special attribute control token - typically either a SUM function * or an IF function */ class Attribute extends Operator implements ParsedThing { /** * The logger */ private static Logger logger = Logger.getLogger(Attribute.class); /** * The options used by the attribute */ private int options; /** * The word contained in this attribute */ private int word; /** * The workbook settings */ private WorkbookSettings settings; private static final int SUM_MASK = 0x10; private static final int IF_MASK = 0x02; private static final int CHOOSE_MASK = 0x04; private static final int GOTO_MASK = 0x08; /** * If this attribute is an IF functions, sets the associated if conditions */ private VariableArgFunction ifConditions; /** * Constructor * * @param ws the workbook settings */ public Attribute(WorkbookSettings ws) { settings = ws; } /** * Constructor for use when this is called when parsing a string * * @param sf the built in function * @param ws the workbook settings */ public Attribute(StringFunction sf, WorkbookSettings ws) { settings = ws; if (sf.getFunction(settings) == Function.SUM) { options |= SUM_MASK; } else if (sf.getFunction(settings) == Function.IF) { options |= IF_MASK; } } /** * Sets the if conditions for this attribute, if it represents an IF function * * @param vaf a VariableArgFunction value */ void setIfConditions(VariableArgFunction vaf) { ifConditions = vaf; // Sometimes there is not Attribute token, so we need to create // an attribute out of thin air. In that case, make sure the if mask options |= IF_MASK; } /** * Reads the ptg data from the array starting at the specified position * * @param data the RPN array * @param pos the current position in the array, excluding the ptg identifier * @return the number of bytes read */ public int read(byte[] data, int pos) { options = data[pos]; word = IntegerHelper.getInt(data[pos + 1], data[pos + 2]); if (!isChoose()) { return 3; } // word contains the number of jumps by index. // and there is an additional final jump to the choose function itself. return 3 + (word + 1) * 2; } /** * Queries whether this attribute is a function * * @return TRUE if this is a function, FALSE otherwise */ public boolean isFunction() { return (options & (SUM_MASK | IF_MASK)) != 0; } /** * Queries whether this attribute is a sum * * @return TRUE if this is SUM, FALSE otherwise */ public boolean isSum() { return (options & SUM_MASK) != 0; } /** * Queries whether this attribute is an IF * * @return TRUE if this is an IF, FALSE otherwise */ public boolean isIf() { return (options & IF_MASK) != 0; } /** * Queries whether this attribute is a goto * * @return TRUE if this is a goto, FALSE otherwise */ public boolean isGoto() { return (options & GOTO_MASK) != 0; } /** * Queries whether this attribute is a CHOOSE * * @return TRUE if this is a CHOOSE, FALSE otherwise */ public boolean isChoose() { return (options & CHOOSE_MASK) != 0; } /** * Gets the operands for this operator from the stack * * @param s the token stack */ public void getOperands(Stack s) { if ((options & SUM_MASK) != 0) { ParseItem o1 = (ParseItem) s.pop(); add(o1); } else if ((options & IF_MASK) != 0) { ParseItem o1 = (ParseItem) s.pop(); add(o1); } } /** * Gets the string version of the attribute * * @param buf the buffer to populate */ public void getString(StringBuffer buf) { if ((options & SUM_MASK) != 0) { ParseItem[] operands = getOperands(); buf.append(Function.SUM.getName(settings)); buf.append('('); operands[0].getString(buf); buf.append(')'); } else if ((options & IF_MASK) != 0) { buf.append(Function.IF.getName(settings)); buf.append('('); ParseItem[] operands = ifConditions.getOperands(); // Operands are in the correct order for IFs for (int i = 0; i < operands.length - 1; i++) { operands[i].getString(buf); buf.append(','); } operands[operands.length - 1].getString(buf); buf.append(')'); } } /** * Gets the token representation of this item in RPN. The Attribute * token is a special case, which overrides anything useful we could do * in the base class * * @return the bytes applicable to this formula */ byte[] getBytes() { byte[] data = new byte[0]; if (isSum()) { // Get the data for the operands ParseItem[] operands = getOperands(); // Get the operands in reverse order to get the RPN for (int i = operands.length - 1; i >= 0; i--) { byte[] opdata = operands[i].getBytes(); // Grow the array byte[] newdata = new byte[data.length + opdata.length]; System.arraycopy(data, 0, newdata, 0, data.length); System.arraycopy(opdata, 0, newdata, data.length, opdata.length); data = newdata; } // Add on the operator byte byte[] newdata = new byte[data.length + 4]; System.arraycopy(data, 0, newdata, 0, data.length); newdata[data.length] = Token.ATTRIBUTE.getCode(); newdata[data.length + 1] = SUM_MASK; data = newdata; } else if (isIf()) { return getIf(); } return data; } /** * Gets the associated if conditions with this attribute * * @return the associated if conditions */ private byte[] getIf() { ParseItem[] operands = ifConditions.getOperands(); // The position of the offset to the false portion of the expression int falseOffsetPos = 0; int gotoEndPos = 0; int numArgs = operands.length; // First, write out the conditions byte[] data = operands[0].getBytes(); // Grow the array by three and write out the optimized if attribute int pos = data.length; byte[] newdata = new byte[data.length + 4]; System.arraycopy(data, 0, newdata, 0, data.length); data = newdata; data[pos] = Token.ATTRIBUTE.getCode(); data[pos + 1] = 0x2; falseOffsetPos = pos + 2; // Get the true portion of the expression and add it to the array byte[] truedata = operands[1].getBytes(); newdata = new byte[data.length + truedata.length]; System.arraycopy(data, 0, newdata, 0, data.length); System.arraycopy(truedata, 0, newdata, data.length, truedata.length); data = newdata; // Grow the array by three and write out the goto end attribute pos = data.length; newdata = new byte[data.length + 4]; System.arraycopy(data, 0, newdata, 0, data.length); data = newdata; data[pos] = Token.ATTRIBUTE.getCode(); data[pos + 1] = 0x8; gotoEndPos = pos + 2; // If the false condition exists, then add that to the array if (numArgs > 2) { // Set the offset to the false expression to be the current position IntegerHelper.getTwoBytes(data.length - falseOffsetPos - 2, data, falseOffsetPos); // Copy in the false expression byte[] falsedata = operands[numArgs - 1].getBytes(); newdata = new byte[data.length + falsedata.length]; System.arraycopy(data, 0, newdata, 0, data.length); System.arraycopy(falsedata, 0, newdata, data.length, falsedata.length); data = newdata; // Write the goto to skip over the varargs token pos = data.length; newdata = new byte[data.length + 4]; System.arraycopy(data, 0, newdata, 0, data.length); data = newdata; data[pos] = Token.ATTRIBUTE.getCode(); data[pos + 1] = 0x8; data[pos + 2] = 0x3; } // Grow the array and write out the varargs function pos = data.length; newdata = new byte[data.length + 4]; System.arraycopy(data, 0, newdata, 0, data.length); data = newdata; data[pos] = Token.FUNCTIONVARARG.getCode(); data[pos + 1] = (byte) numArgs; data[pos + 2] = 1; data[pos + 3] = 0; // indicates the end of the expression // Position the final offsets int endPos = data.length - 1; if (numArgs < 3) { // Set the offset to the false expression to be the current position IntegerHelper.getTwoBytes(endPos - falseOffsetPos - 5, data, falseOffsetPos); } // Set the offset after the true expression IntegerHelper.getTwoBytes(endPos - gotoEndPos - 2, data, gotoEndPos); return data; } /** * Gets the precedence for this operator. Operator precedents run from * 1 to 5, one being the highest, 5 being the lowest * * @return the operator precedence */ int getPrecedence() { return 3; } /** * Default behaviour is to do nothing * * @param colAdjust the amount to add on to each relative cell reference * @param rowAdjust the amount to add on to each relative row reference */ public void adjustRelativeCellReferences(int colAdjust, int rowAdjust) { ParseItem[] operands = null; if (isIf()) { operands = ifConditions.getOperands(); } else { operands = getOperands(); } for (int i = 0; i < operands.length; i++) { operands[i].adjustRelativeCellReferences(colAdjust, rowAdjust); } } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the column was inserted * @param col the column number which was inserted * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void columnInserted(int sheetIndex, int col, boolean currentSheet) { ParseItem[] operands = null; if (isIf()) { operands = ifConditions.getOperands(); } else { operands = getOperands(); } for (int i = 0; i < operands.length; i++) { operands[i].columnInserted(sheetIndex, col, currentSheet); } } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the column was removed * @param col the column number which was removed * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void columnRemoved(int sheetIndex, int col, boolean currentSheet) { ParseItem[] operands = null; if (isIf()) { operands = ifConditions.getOperands(); } else { operands = getOperands(); } for (int i = 0; i < operands.length; i++) { operands[i].columnRemoved(sheetIndex, col, currentSheet); } } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the row was inserted * @param row the row number which was inserted1 * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void rowInserted(int sheetIndex, int row, boolean currentSheet) { ParseItem[] operands = null; if (isIf()) { operands = ifConditions.getOperands(); } else { operands = getOperands(); } for (int i = 0; i < operands.length; i++) { operands[i].rowInserted(sheetIndex, row, currentSheet); } } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the row was removed * @param row the row number which was removed * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ void rowRemoved(int sheetIndex, int row, boolean currentSheet) { ParseItem[] operands = null; if (isIf()) { operands = ifConditions.getOperands(); } else { operands = getOperands(); } for (int i = 0; i < operands.length; i++) { operands[i].rowRemoved(sheetIndex, row, currentSheet); } } /** * If this formula was on an imported sheet, check that * cell references to another sheet are warned appropriately * Does nothing, as operators don't have cell references */ void handleImportedCellReferences() { ParseItem[] operands = null; if (isIf()) { operands = ifConditions.getOperands(); } else { operands = getOperands(); } for (int i = 0; i < operands.length; i++) { operands[i].handleImportedCellReferences(); } } } jexcelapi/src/jxl/biff/formula/LessEqual.java0000750000175000017500000000305411207000612021403 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; /** * A cell reference in a formula */ class LessEqual extends BinaryOperator implements ParsedThing { /** * Constructor */ public LessEqual() { } public String getSymbol() { return "<="; } /** * Abstract method which gets the token for this operator * * @return the string symbol for this token */ Token getToken() { return Token.LESS_EQUAL; } /** * Gets the precedence for this operator. Operator precedents run from * 1 to 5, one being the highest, 5 being the lowest * * @return the operator precedence */ int getPrecedence() { return 5; } } jexcelapi/src/jxl/biff/formula/TokenFormulaParser.java0000750000175000017500000003506311227113326023306 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; import java.util.Stack; import jxl.common.Assert; import jxl.common.Logger; import jxl.Cell; import jxl.WorkbookSettings; import jxl.biff.WorkbookMethods; /** * Parses the excel ptgs into a parse tree */ class TokenFormulaParser implements Parser { /** * The logger */ private static Logger logger = Logger.getLogger(TokenFormulaParser.class); /** * The Excel ptgs */ private byte[] tokenData; /** * The cell containing the formula. This is used in order to determine * relative cell values */ private Cell relativeTo; /** * The current position within the array */ private int pos; /** * The parse tree */ private ParseItem root; /** * The hash table of items that have been parsed */ private Stack tokenStack; /** * A reference to the workbook which holds the external sheet * information */ private ExternalSheet workbook; /** * A reference to the name table */ private WorkbookMethods nameTable; /** * The workbook settings */ private WorkbookSettings settings; /** * The parse context */ private ParseContext parseContext; /** * Constructor */ public TokenFormulaParser(byte[] data, Cell c, ExternalSheet es, WorkbookMethods nt, WorkbookSettings ws, ParseContext pc) { tokenData = data; pos = 0; relativeTo = c; workbook = es; nameTable = nt; tokenStack = new Stack(); settings = ws; parseContext = pc; Assert.verify(nameTable != null); } /** * Parses the sublist of tokens. In most cases this will equate to * the full list * * @exception FormulaException */ public void parse() throws FormulaException { parseSubExpression(tokenData.length); // Finally, there should be one thing left on the stack. Get that // and add it to the root node root = (ParseItem) tokenStack.pop(); Assert.verify(tokenStack.empty()); } /** * Parses the sublist of tokens. In most cases this will equate to * the full list * * @param len the length of the subexpression to parse * @exception FormulaException */ private void parseSubExpression(int len) throws FormulaException { int tokenVal = 0; Token t = null; // Indicates that we are parsing the incredibly complicated and // hacky if construct that MS saw fit to include, the gits Stack ifStack = new Stack(); // The end position of the sub-expression int endpos = pos + len; while (pos < endpos) { tokenVal = tokenData[pos]; pos++; t = Token.getToken(tokenVal); if (t == Token.UNKNOWN) { throw new FormulaException (FormulaException.UNRECOGNIZED_TOKEN, tokenVal); } Assert.verify(t != Token.UNKNOWN); // Operands if (t == Token.REF) { CellReference cr = new CellReference(relativeTo); pos += cr.read(tokenData, pos); tokenStack.push(cr); } else if (t == Token.REFERR) { CellReferenceError cr = new CellReferenceError(); pos += cr.read(tokenData, pos); tokenStack.push(cr); } else if (t == Token.ERR) { ErrorConstant ec = new ErrorConstant(); pos += ec.read(tokenData, pos); tokenStack.push(ec); } else if (t == Token.REFV) { SharedFormulaCellReference cr = new SharedFormulaCellReference(relativeTo); pos += cr.read(tokenData, pos); tokenStack.push(cr); } else if (t == Token.REF3D) { CellReference3d cr = new CellReference3d(relativeTo, workbook); pos += cr.read(tokenData, pos); tokenStack.push(cr); } else if (t == Token.AREA) { Area a = new Area(); pos += a.read(tokenData, pos); tokenStack.push(a); } else if (t == Token.AREAV) { SharedFormulaArea a = new SharedFormulaArea(relativeTo); pos += a.read(tokenData, pos); tokenStack.push(a); } else if (t == Token.AREA3D) { Area3d a = new Area3d(workbook); pos += a.read(tokenData, pos); tokenStack.push(a); } else if (t == Token.NAME) { Name n = new Name(); pos += n.read(tokenData, pos); n.setParseContext(parseContext); tokenStack.push(n); } else if (t == Token.NAMED_RANGE) { NameRange nr = new NameRange(nameTable); pos += nr.read(tokenData, pos); nr.setParseContext(parseContext); tokenStack.push(nr); } else if (t == Token.INTEGER) { IntegerValue i = new IntegerValue(); pos += i.read(tokenData, pos); tokenStack.push(i); } else if (t == Token.DOUBLE) { DoubleValue d = new DoubleValue(); pos += d.read(tokenData, pos); tokenStack.push(d); } else if (t == Token.BOOL) { BooleanValue bv = new BooleanValue(); pos += bv.read(tokenData, pos); tokenStack.push(bv); } else if (t == Token.STRING) { StringValue sv = new StringValue(settings); pos += sv.read(tokenData, pos); tokenStack.push(sv); } else if (t == Token.MISSING_ARG) { MissingArg ma = new MissingArg(); pos += ma.read(tokenData, pos); tokenStack.push(ma); } // Unary Operators else if (t == Token.UNARY_PLUS) { UnaryPlus up = new UnaryPlus(); pos += up.read(tokenData, pos); addOperator(up); } else if (t == Token.UNARY_MINUS) { UnaryMinus um = new UnaryMinus(); pos += um.read(tokenData, pos); addOperator(um); } else if (t == Token.PERCENT) { Percent p = new Percent(); pos += p.read(tokenData, pos); addOperator(p); } // Binary Operators else if (t == Token.SUBTRACT) { Subtract s = new Subtract(); pos += s.read(tokenData, pos); addOperator(s); } else if (t == Token.ADD) { Add s = new Add(); pos += s.read(tokenData, pos); addOperator(s); } else if (t == Token.MULTIPLY) { Multiply s = new Multiply(); pos += s.read(tokenData, pos); addOperator(s); } else if (t == Token.DIVIDE) { Divide s = new Divide(); pos += s.read(tokenData, pos); addOperator(s); } else if (t == Token.CONCAT) { Concatenate c = new Concatenate(); pos += c.read(tokenData, pos); addOperator(c); } else if (t == Token.POWER) { Power p = new Power(); pos += p.read(tokenData, pos); addOperator(p); } else if (t == Token.LESS_THAN) { LessThan lt = new LessThan(); pos += lt.read(tokenData, pos); addOperator(lt); } else if (t == Token.LESS_EQUAL) { LessEqual lte = new LessEqual(); pos += lte.read(tokenData, pos); addOperator(lte); } else if (t == Token.GREATER_THAN) { GreaterThan gt = new GreaterThan(); pos += gt.read(tokenData, pos); addOperator(gt); } else if (t == Token.GREATER_EQUAL) { GreaterEqual gte = new GreaterEqual(); pos += gte.read(tokenData, pos); addOperator(gte); } else if (t == Token.NOT_EQUAL) { NotEqual ne = new NotEqual(); pos += ne.read(tokenData, pos); addOperator(ne); } else if (t == Token.EQUAL) { Equal e = new Equal(); pos += e.read(tokenData, pos); addOperator(e); } else if (t == Token.PARENTHESIS) { Parenthesis p = new Parenthesis(); pos += p.read(tokenData, pos); addOperator(p); } // Functions else if (t == Token.ATTRIBUTE) { Attribute a = new Attribute(settings); pos += a.read(tokenData, pos); if (a.isSum()) { addOperator(a); } else if (a.isIf()) { // Add it to a special stack for ifs ifStack.push(a); } } else if (t == Token.FUNCTION) { BuiltInFunction bif = new BuiltInFunction(settings); pos += bif.read(tokenData, pos); addOperator(bif); } else if (t == Token.FUNCTIONVARARG) { VariableArgFunction vaf = new VariableArgFunction(settings); pos += vaf.read(tokenData, pos); if (vaf.getFunction() != Function.ATTRIBUTE) { addOperator(vaf); } else { // This is part of an IF function. Get the operands, but then // add it to the top of the if stack vaf.getOperands(tokenStack); Attribute ifattr = null; if (ifStack.empty()) { ifattr = new Attribute(settings); } else { ifattr = (Attribute) ifStack.pop(); } ifattr.setIfConditions(vaf); tokenStack.push(ifattr); } } // Other things else if (t == Token.MEM_FUNC) { MemFunc memFunc = new MemFunc(); handleMemoryFunction(memFunc); } else if (t == Token.MEM_AREA) { MemArea memArea = new MemArea(); handleMemoryFunction(memArea); } } } /** * Handles a memory function */ private void handleMemoryFunction(SubExpression subxp) throws FormulaException { pos += subxp.read(tokenData, pos); // Create new tokenStack for the sub expression Stack oldStack = tokenStack; tokenStack = new Stack(); parseSubExpression(subxp.getLength()); ParseItem[] subexpr = new ParseItem[tokenStack.size()]; int i = 0; while (!tokenStack.isEmpty()) { subexpr[i] = (ParseItem) tokenStack.pop(); i++; } subxp.setSubExpression(subexpr); tokenStack = oldStack; tokenStack.push(subxp); } /** * Adds the specified operator to the parse tree, taking operands off * the stack as appropriate */ private void addOperator(Operator o) { // Get the operands off the stack o.getOperands(tokenStack); // Add this operator onto the stack tokenStack.push(o); } /** * Gets the formula as a string */ public String getFormula() { StringBuffer sb = new StringBuffer(); root.getString(sb); return sb.toString(); } /** * Adjusts all the relative cell references in this formula by the * amount specified. Used when copying formulas * * @param colAdjust the amount to add on to each relative cell reference * @param rowAdjust the amount to add on to each relative row reference */ public void adjustRelativeCellReferences(int colAdjust, int rowAdjust) { root.adjustRelativeCellReferences(colAdjust, rowAdjust); } /** * Gets the bytes for the formula. This takes into account any * token mapping necessary because of shared formulas * * @return the bytes in RPN */ public byte[] getBytes() { return root.getBytes(); } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the column was inserted * @param col the column number which was inserted * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ public void columnInserted(int sheetIndex, int col, boolean currentSheet) { root.columnInserted(sheetIndex, col, currentSheet); } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the column was removed * @param col the column number which was removed * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ public void columnRemoved(int sheetIndex, int col, boolean currentSheet) { root.columnRemoved(sheetIndex, col, currentSheet); } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the column was inserted * @param row the column number which was inserted * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ public void rowInserted(int sheetIndex, int row, boolean currentSheet) { root.rowInserted(sheetIndex, row, currentSheet); } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the column was removed * @param row the column number which was removed * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ public void rowRemoved(int sheetIndex, int row, boolean currentSheet) { root.rowRemoved(sheetIndex, row, currentSheet); } /** * If this formula was on an imported sheet, check that * cell references to another sheet are warned appropriately * * @return TRUE if the formula is valid import, FALSE otherwise */ public boolean handleImportedCellReferences() { root.handleImportedCellReferences(); return root.isValid(); } } jexcelapi/src/jxl/biff/formula/ParsedThing.java0000750000175000017500000000244011207000612021713 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; /** * An interface for an excel ptg */ interface ParsedThing { /** * Reads the ptg data from the array starting at the specified position * * @param data the RPN array * @param pos the current position in the array, excluding the ptg identifier * @return the number of bytes read */ public int read(byte[] data, int pos) throws FormulaException; } jexcelapi/src/jxl/biff/formula/FormulaParser.java0000750000175000017500000001757211227113041022304 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the7 Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; import jxl.common.Assert; import jxl.common.Logger; import jxl.Cell; import jxl.WorkbookSettings; import jxl.biff.WorkbookMethods; /** * Parses the formula passed in (either as parsed strings or as a string) * into a tree of operators and operands */ public class FormulaParser { /** * The logger */ private static final Logger logger = Logger.getLogger(FormulaParser.class); /** * The formula parser. The object implementing this interface will either * parse tokens or strings */ private Parser parser; /** * Constructor which creates the parse tree out of tokens * * @param tokens the list of parsed tokens * @param rt the cell containing the formula * @param es a handle to the external sheet * @param nt a handle to the name table * @param ws the workbook settings * @param pc the parse context * @exception FormulaException */ public FormulaParser(byte[] tokens, Cell rt, ExternalSheet es, WorkbookMethods nt, WorkbookSettings ws) throws FormulaException { // A null workbook bof means that it is a writable workbook and therefore // must be biff8 if (es.getWorkbookBof() != null && !es.getWorkbookBof().isBiff8()) { throw new FormulaException(FormulaException.BIFF8_SUPPORTED); } Assert.verify(nt != null); parser = new TokenFormulaParser(tokens, rt, es, nt, ws, ParseContext.DEFAULT); } /** * Constructor which creates the parse tree out of tokens * * @param tokens the list of parsed tokens * @param rt the cell containing the formula * @param es a handle to the external sheet * @param nt a handle to the name table * @param ws the workbook settings * @param pc the parse context * @exception FormulaException */ public FormulaParser(byte[] tokens, Cell rt, ExternalSheet es, WorkbookMethods nt, WorkbookSettings ws, ParseContext pc) throws FormulaException { // A null workbook bof means that it is a writable workbook and therefore // must be biff8 if (es.getWorkbookBof() != null && !es.getWorkbookBof().isBiff8()) { throw new FormulaException(FormulaException.BIFF8_SUPPORTED); } Assert.verify(nt != null); parser = new TokenFormulaParser(tokens, rt, es, nt, ws, pc); } /** * Constructor which creates the parse tree out of the string * * @param form the formula string * @param es the external sheet handle * @param nt the name table * @param ws the workbook settings */ public FormulaParser(String form, ExternalSheet es, WorkbookMethods nt, WorkbookSettings ws) { parser = new StringFormulaParser(form, es, nt, ws, ParseContext.DEFAULT); } /** * Constructor which creates the parse tree out of the string * * @param form the formula string * @param es the external sheet handle * @param nt the name table * @param ws the workbook settings * @param pc the context of the parse */ public FormulaParser(String form, ExternalSheet es, WorkbookMethods nt, WorkbookSettings ws, ParseContext pc) { parser = new StringFormulaParser(form, es, nt, ws, pc); } /** * Adjusts all the relative cell references in this formula by the * amount specified. Used when copying formulas * * @param colAdjust the amount to add on to each relative cell reference * @param rowAdjust the amount to add on to each relative row reference */ public void adjustRelativeCellReferences(int colAdjust, int rowAdjust) { parser.adjustRelativeCellReferences(colAdjust, rowAdjust); } /** * Parses the formula into a parse tree * * @exception FormulaException */ public void parse() throws FormulaException { parser.parse(); } /** * Gets the formula as a string * * @return the formula as a string * @exception FormulaException */ public String getFormula() throws FormulaException { return parser.getFormula(); } /** * Gets the bytes for the formula. This takes into account any * token mapping necessary because of shared formulas * * @return the bytes in RPN */ public byte[] getBytes() { return parser.getBytes(); } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the column was inserted * @param col the column number which was inserted * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ public void columnInserted(int sheetIndex, int col, boolean currentSheet) { parser.columnInserted(sheetIndex, col, currentSheet); } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the column was inserted * @param col the column number which was removed * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ public void columnRemoved(int sheetIndex, int col, boolean currentSheet) { parser.columnRemoved(sheetIndex, col, currentSheet); } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the column was inserted * @param row the row number which was inserted * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ public void rowInserted(int sheetIndex, int row, boolean currentSheet) { parser.rowInserted(sheetIndex, row, currentSheet); } /** * Called when a column is inserted on the specified sheet. Tells * the formula parser to update all of its cell references beyond this * column * * @param sheetIndex the sheet on which the column was inserted * @param row the row number which was removed * @param currentSheet TRUE if this formula is on the sheet in which the * column was inserted, FALSE otherwise */ public void rowRemoved(int sheetIndex, int row, boolean currentSheet) { parser.rowRemoved(sheetIndex, row, currentSheet); } /** * If this formula was on an imported sheet, check that * cell references to another sheet are warned appropriately * * @return TRUE if the formula is valid import, FALSE otherwise */ public boolean handleImportedCellReferences() { return parser.handleImportedCellReferences(); } } jexcelapi/src/jxl/biff/formula/LessThan.java0000750000175000017500000000303411207000612021224 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; /** * A cell reference in a formula */ class LessThan extends BinaryOperator implements ParsedThing { /** * Constructor */ public LessThan() { } public String getSymbol() { return "<"; } /** * Abstract method which gets the token for this operator * * @return the string symbol for this token */ Token getToken() { return Token.LESS_THAN; } /** * Gets the precedence for this operator. Operator precedents run from * 1 to 5, one being the highest, 5 being the lowest * * @return the operator precedence */ int getPrecedence() { return 5; } } jexcelapi/src/jxl/biff/formula/ErrorConstant.java0000750000175000017500000000457011207000612022314 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2006 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff.formula; import jxl.biff.IntegerHelper; /** * An error constant */ class ErrorConstant extends Operand implements ParsedThing { /** * The error */ private FormulaErrorCode error; /** * Constructor */ public ErrorConstant() { } /** * Constructor * * @param s the error constant */ public ErrorConstant(String s) { error = FormulaErrorCode.getErrorCode(s); } /** * Reads the ptg data from the array starting at the specified position * * @param data the RPN array * @param pos the current position in the array, excluding the ptg identifier * @return the number of bytes read */ public int read(byte[] data, int pos) { int code = data[pos]; error = FormulaErrorCode.getErrorCode(code); return 1; } /** * Gets the token representation of this item in RPN * * @return the bytes applicable to this formula */ byte[] getBytes() { byte[] data = new byte[2]; data[0] = Token.ERR.getCode(); data[1] = (byte) error.getCode(); return data; } /** * Abstract method implementation to get the string equivalent of this * token * * @param buf the string to append to */ public void getString(StringBuffer buf) { buf.append(error.getDescription()); } /** * If this formula was on an imported sheet, check that * cell references to another sheet are warned appropriately * Does nothing */ void handleImportedCellReferences() { } } jexcelapi/src/jxl/biff/ConditionalFormatRecord.java0000750000175000017500000000300511207000612022607 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2007 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; import jxl.common.Logger; import jxl.read.biff.Record; /** * The conditional format conditions */ public class ConditionalFormatRecord extends WritableRecordData { // the logger private static Logger logger = Logger.getLogger(ConditionalFormatRecord.class); /** * The data */ private byte[] data; /** * Constructor */ public ConditionalFormatRecord(Record t) { super(t); data = getRecord().getData(); } /** * Retrieves the data for output to binary file * * @return the data to be written */ public byte[] getData() { return data; } } jexcelapi/src/jxl/biff/FontRecord.java0000750000175000017500000002737411207000612020120 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; import jxl.common.Assert; import jxl.common.Logger; import jxl.WorkbookSettings; import jxl.format.Colour; import jxl.format.Font; import jxl.format.ScriptStyle; import jxl.format.UnderlineStyle; import jxl.read.biff.Record; /** * A record containing the necessary data for the font information */ public class FontRecord extends WritableRecordData implements Font { /** * The logger */ private static Logger logger = Logger.getLogger(FontRecord.class); /** * The point height of this font */ private int pointHeight; /** * The index into the colour palette */ private int colourIndex; /** * The bold weight for this font (normal or bold) */ private int boldWeight; /** * The style of the script (italic or normal) */ private int scriptStyle; /** * The underline style for this font (none, single, double etc) */ private int underlineStyle; /** * The font family */ private byte fontFamily; /** * The character set */ private byte characterSet; /** * Indicates whether or not this font is italic */ private boolean italic; /** * Indicates whether or not this font is struck out */ private boolean struckout; /** * The name of this font */ private String name; /** * Flag to indicate whether the derived data (such as the font index) has * been initialized or not */ private boolean initialized; /** * The index of this font in the font list */ private int fontIndex; /** * Dummy indicators for overloading the constructor */ private static class Biff7 {}; public static final Biff7 biff7 = new Biff7(); /** * The conversion factor between microsoft internal units and point size */ private static final int EXCEL_UNITS_PER_POINT = 20; /** * Constructor, used when creating a new font for writing out. * * @param bold the bold indicator * @param ps the point size * @param us the underline style * @param fn the name * @param it italicised indicator * @param ss the script style * @param ci the colour index */ protected FontRecord(String fn, int ps, int bold, boolean it, int us, int ci, int ss) { super(Type.FONT); boldWeight = bold; underlineStyle = us; name = fn; pointHeight = ps; italic = it; scriptStyle = ss; colourIndex = ci; initialized = false; struckout = false; } /** * Constructs this object from the raw data. Used when reading in a * format record * * @param t the raw data * @param ws the workbook settings */ public FontRecord(Record t, WorkbookSettings ws) { super(t); byte[] data = getRecord().getData(); pointHeight = IntegerHelper.getInt(data[0], data[1]) / EXCEL_UNITS_PER_POINT; colourIndex = IntegerHelper.getInt(data[4], data[5]); boldWeight = IntegerHelper.getInt(data[6], data[7]); scriptStyle = IntegerHelper.getInt(data[8], data[9]); underlineStyle = data[10]; fontFamily = data[11]; characterSet = data[12]; initialized = false; if ((data[2] & 0x02) != 0) { italic = true; } if ((data[2] & 0x08) != 0) { struckout = true; } int numChars = data[14]; if (data[15] == 0) { name = StringHelper.getString(data, numChars, 16, ws); } else if (data[15] == 1) { name = StringHelper.getUnicodeString(data, numChars, 16); } else { // Some font names don't have the unicode indicator name = StringHelper.getString(data, numChars, 15, ws); } } /** * Constructs this object from the raw data. Used when reading in a * format record * * @param t the raw data * @param ws the workbook settings * @param dummy dummy overload */ public FontRecord(Record t, WorkbookSettings ws, Biff7 dummy) { super(t); byte[] data = getRecord().getData(); pointHeight = IntegerHelper.getInt(data[0], data[1]) / EXCEL_UNITS_PER_POINT; colourIndex = IntegerHelper.getInt(data[4], data[5]); boldWeight = IntegerHelper.getInt(data[6], data[7]); scriptStyle = IntegerHelper.getInt(data[8], data[9]); underlineStyle = data[10]; fontFamily = data[11]; initialized = false; if ((data[2] & 0x02) != 0) { italic = true; } if ((data[2] & 0x08) != 0) { struckout = true; } int numChars = data[14]; name = StringHelper.getString(data, numChars, 15, ws); } /** * Publicly available copy constructor * * @param f the font to copy */ protected FontRecord(Font f) { super(Type.FONT); Assert.verify(f != null); pointHeight = f.getPointSize(); colourIndex = f.getColour().getValue(); boldWeight = f.getBoldWeight(); scriptStyle = f.getScriptStyle().getValue(); underlineStyle = f.getUnderlineStyle().getValue(); italic = f.isItalic(); name = f.getName(); struckout = f.isStruckout(); initialized = false; } /** * Gets the byte data for writing out * * @return the raw data */ public byte[] getData() { byte[] data = new byte[16 + name.length() * 2]; // Excel expects font heights in 1/20ths of a point IntegerHelper.getTwoBytes(pointHeight * EXCEL_UNITS_PER_POINT, data, 0); // Set the font attributes to be zero for now if (italic) { data[2] |= 0x2; } if (struckout) { data[2] |= 0x08; } // Set the index to the colour palette IntegerHelper.getTwoBytes(colourIndex, data, 4); // Bold style IntegerHelper.getTwoBytes(boldWeight, data, 6); // Script style IntegerHelper.getTwoBytes(scriptStyle, data, 8); // Underline style data[10] = (byte) underlineStyle; // Set the font family to be 0 data[11] = fontFamily; // Set the character set to be zero data[12] = characterSet; // Set the reserved bit to be zero data[13] = 0; // Set the length of the font name data[14] = (byte) name.length(); data[15] = (byte) 1; // Copy in the string StringHelper.getUnicodeBytes(name, data, 16); return data; } /** * Accessor to see whether this object is initialized or not. * * @return TRUE if this font record has been initialized, FALSE otherwise */ public final boolean isInitialized() { return initialized; } /** * Sets the font index of this record. Called from the FormattingRecords * object * * @param pos the position of this font in the workbooks font list */ public final void initialize(int pos) { fontIndex = pos; initialized = true; } /** * Resets the initialize flag. This is called by the constructor of * WritableWorkbookImpl to reset the statically declared fonts */ public final void uninitialize() { initialized = false; } /** * Accessor for the font index * * @return the font index */ public final int getFontIndex() { return fontIndex; } /** * Sets the point size for this font, if the font hasn't been initialized * * @param ps the point size */ protected void setFontPointSize(int ps) { Assert.verify(!initialized); pointHeight = ps; } /** * Gets the point size for this font, if the font hasn't been initialized * * @return the point size */ public int getPointSize() { return pointHeight; } /** * Sets the bold style for this font, if the font hasn't been initialized * * @param bs the bold style */ protected void setFontBoldStyle(int bs) { Assert.verify(!initialized); boldWeight = bs; } /** * Gets the bold weight for this font * * @return the bold weight for this font */ public int getBoldWeight() { return boldWeight; } /** * Sets the italic indicator for this font, if the font hasn't been * initialized * * @param i the italic flag */ protected void setFontItalic(boolean i) { Assert.verify(!initialized); italic = i; } /** * Returns the italic flag * * @return TRUE if this font is italic, FALSE otherwise */ public boolean isItalic() { return italic; } /** * Sets the underline style for this font, if the font hasn't been * initialized * * @param us the underline style */ protected void setFontUnderlineStyle(int us) { Assert.verify(!initialized); underlineStyle = us; } /** * Gets the underline style for this font * * @return the underline style */ public UnderlineStyle getUnderlineStyle() { return UnderlineStyle.getStyle(underlineStyle); } /** * Sets the colour for this font, if the font hasn't been * initialized * * @param c the colour */ protected void setFontColour(int c) { Assert.verify(!initialized); colourIndex = c; } /** * Gets the colour for this font * * @return the colour */ public Colour getColour() { return Colour.getInternalColour(colourIndex); } /** * Sets the script style (eg. superscript, subscript) for this font, * if the font hasn't been initialized * * @param ss the colour */ protected void setFontScriptStyle(int ss) { Assert.verify(!initialized); scriptStyle = ss; } /** * Gets the script style * * @return the script style */ public ScriptStyle getScriptStyle() { return ScriptStyle.getStyle(scriptStyle); } /** * Gets the name of this font * * @return the name of this font */ public String getName() { return name; } /** * Standard hash code method * @return the hash code for this object */ public int hashCode() { return name.hashCode(); } /** * Standard equals method * @param o the object to compare * @return TRUE if the objects are equal, FALSE otherwise */ public boolean equals(Object o) { if (o == this) { return true; } if (!(o instanceof FontRecord)) { return false; } FontRecord font = (FontRecord) o; if (pointHeight == font.pointHeight && colourIndex == font.colourIndex && boldWeight == font.boldWeight && scriptStyle == font.scriptStyle && underlineStyle == font.underlineStyle && italic == font.italic && struckout == font.struckout && fontFamily == font.fontFamily && characterSet == font.characterSet && name.equals(font.name)) { return true; } return false; } /** * Accessor for the strike out flag * * @return TRUE if this font is struck out, FALSE otherwise */ public boolean isStruckout() { return struckout; } /** * Sets the struck out flag * * @param os TRUE if the font is struck out, false otherwise */ protected void setFontStruckout(boolean os) { struckout = os; } } jexcelapi/src/jxl/biff/CellFinder.java0000750000175000017500000001507611207000612020056 0ustar drazzibdrazzib/********************************************************************** * * Copyright (C) 2008 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; import java.util.regex.Pattern; import java.util.regex.Matcher; import jxl.Sheet; import jxl.Cell; import jxl.CellType; import jxl.LabelCell; /** * Refactorisation to provide more sophisticated find cell by contents * functionality */ public class CellFinder { private Sheet sheet; public CellFinder(Sheet s) { sheet = s; } /** * Gets the cell whose contents match the string passed in. * If no match is found, then null is returned. The search is performed * on a row by row basis, so the lower the row number, the more * efficiently the algorithm will perform * * @param contents the string to match * @param firstCol the first column within the range * @param firstRow the first row of the range * @param lastCol the last column within the range * @param lastRow the last row within the range * @param reverse indicates whether to perform a reverse search or not * @return the Cell whose contents match the parameter, null if not found */ public Cell findCell(String contents, int firstCol, int firstRow, int lastCol, int lastRow, boolean reverse) { Cell cell = null; boolean found = false; int numCols = lastCol - firstCol; int numRows = lastRow - firstRow; int row1 = reverse ? lastRow : firstRow; int row2 = reverse ? firstRow : lastRow; int col1 = reverse ? lastCol : firstCol; int col2 = reverse ? firstCol : lastCol; int inc = reverse ? -1 : 1; for (int i = 0; i <= numCols && found == false; i++) { for (int j = 0; j <= numRows && found == false; j++) { int curCol = col1 + i * inc; int curRow = row1 + j * inc; if (curCol < sheet.getColumns() && curRow < sheet.getRows()) { Cell c = sheet.getCell(curCol, curRow); if (c.getType() != CellType.EMPTY) { if (c.getContents().equals(contents)) { cell = c; found = true; } } } } } return cell; } /** * Finds a cell within a given range of cells * * @param contents the string to match * @return the Cell whose contents match the parameter, null if not found */ public Cell findCell(String contents) { Cell cell = null; boolean found = false; for (int i = 0 ; i < sheet.getRows() && found == false; i++) { Cell[] row = sheet.getRow(i); for (int j = 0 ; j < row.length && found == false; j++) { if (row[j].getContents().equals(contents)) { cell = row[j]; found = true; } } } return cell; } /** * Gets the cell whose contents match the regular expressionstring passed in. * If no match is found, then null is returned. The search is performed * on a row by row basis, so the lower the row number, the more * efficiently the algorithm will perform * * @param pattern the regular expression string to match * @param firstCol the first column within the range * @param firstRow the first row of the range * @param lastCol the last column within the range * @param lastRow the last row within the range * @param reverse indicates whether to perform a reverse search or not * @return the Cell whose contents match the parameter, null if not found */ public Cell findCell(Pattern pattern, int firstCol, int firstRow, int lastCol, int lastRow, boolean reverse) { Cell cell = null; boolean found = false; int numCols = lastCol - firstCol; int numRows = lastRow - firstRow; int row1 = reverse ? lastRow : firstRow; int row2 = reverse ? firstRow : lastRow; int col1 = reverse ? lastCol : firstCol; int col2 = reverse ? firstCol : lastCol; int inc = reverse ? -1 : 1; for (int i = 0; i <= numCols && found == false; i++) { for (int j = 0; j <= numRows && found == false; j++) { int curCol = col1 + i * inc; int curRow = row1 + j * inc; if (curCol < sheet.getColumns() && curRow < sheet.getRows()) { Cell c = sheet.getCell(curCol, curRow); if (c.getType() != CellType.EMPTY) { Matcher m = pattern.matcher(c.getContents()); if (m.matches()) { cell = c; found = true; } } } } } return cell; } /** * Gets the cell whose contents match the string passed in. * If no match is found, then null is returned. The search is performed * on a row by row basis, so the lower the row number, the more * efficiently the algorithm will perform. This method differs * from the findCell methods in that only cells with labels are * queried - all numerical cells are ignored. This should therefore * improve performance. * * @param contents the string to match * @return the Cell whose contents match the paramter, null if not found */ public LabelCell findLabelCell(String contents) { LabelCell cell = null; boolean found = false; for (int i = 0; i < sheet.getRows() && !found; i++) { Cell[] row = sheet.getRow(i); for (int j = 0; j < row.length && !found; j++) { if ((row[j].getType() == CellType.LABEL || row[j].getType() == CellType.STRING_FORMULA) && row[j].getContents().equals(contents)) { cell = (LabelCell) row[j]; found = true; } } } return cell; } } jexcelapi/src/jxl/biff/Type.java0000750000175000017500000002533411207000612016766 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; /** * An enumeration class which contains the biff types */ public final class Type { /** * The biff value for this type */ public final int value; /** * An array of all types */ private static Type[] types = new Type[0]; /** * Constructor * Sets the biff value and adds this type to the array of all types * * @param v the biff code for the type */ private Type(int v) { value = v; // Add to the list of available types Type[] newTypes = new Type[types.length + 1]; System.arraycopy(types, 0, newTypes, 0, types.length); newTypes[types.length] = this; types = newTypes; } private static class ArbitraryType {}; private static ArbitraryType arbitrary = new ArbitraryType(); /** * Constructor used for the creation of arbitrary types */ private Type(int v, ArbitraryType arb) { value = v; } /** * Standard hash code method * @return the hash code */ public int hashCode() { return value; } /** * Standard equals method * @param o the object to compare * @return TRUE if the objects are equal, FALSE otherwise */ public boolean equals(Object o) { if (o == this) { return true; } if (!(o instanceof Type)) { return false; } Type t = (Type) o; return value == t.value; } /** * Gets the type object from its integer value * @param v the internal code * @return the type */ public static Type getType(int v) { for (int i = 0; i < types.length; i++) { if (types[i].value == v) { return types[i]; } } return UNKNOWN; } /** * Used to create an arbitrary record type. This method is only * used during bespoke debugging process. The creation of an * arbitrary type does not add it to the static list of known types */ public static Type createType(int v) { return new Type(v, arbitrary); } /** */ public static final Type BOF = new Type(0x809); /** */ public static final Type EOF = new Type(0x0a); /** */ public static final Type BOUNDSHEET = new Type(0x85); /** */ public static final Type SUPBOOK = new Type(0x1ae); /** */ public static final Type EXTERNSHEET = new Type(0x17); /** */ public static final Type DIMENSION = new Type(0x200); /** */ public static final Type BLANK = new Type(0x201); /** */ public static final Type MULBLANK = new Type(0xbe); /** */ public static final Type ROW = new Type(0x208); /** */ public static final Type NOTE = new Type(0x1c); /** */ public static final Type TXO = new Type(0x1b6); /** */ public static final Type RK = new Type(0x7e); /** */ public static final Type RK2 = new Type(0x27e); /** */ public static final Type MULRK = new Type(0xbd); /** */ public static final Type INDEX = new Type(0x20b); /** */ public static final Type DBCELL = new Type(0xd7); /** */ public static final Type SST = new Type(0xfc); /** */ public static final Type COLINFO = new Type(0x7d); /** */ public static final Type EXTSST = new Type(0xff); /** */ public static final Type CONTINUE = new Type(0x3c); /** */ public static final Type LABEL = new Type(0x204); /** */ public static final Type RSTRING = new Type(0xd6); /** */ public static final Type LABELSST = new Type(0xfd); /** */ public static final Type NUMBER = new Type(0x203); /** */ public static final Type NAME = new Type(0x18); /** */ public static final Type TABID = new Type(0x13d); /** */ public static final Type ARRAY = new Type(0x221); /** */ public static final Type STRING = new Type(0x207); /** */ public static final Type FORMULA = new Type(0x406); /** */ public static final Type FORMULA2 = new Type(0x6); /** */ public static final Type SHAREDFORMULA = new Type(0x4bc); /** */ public static final Type FORMAT = new Type(0x41e); /** */ public static final Type XF = new Type(0xe0); /** */ public static final Type BOOLERR = new Type(0x205); /** */ public static final Type INTERFACEHDR = new Type(0xe1); /** */ public static final Type SAVERECALC = new Type(0x5f); /** */ public static final Type INTERFACEEND = new Type(0xe2); /** */ public static final Type XCT = new Type(0x59); /** */ public static final Type CRN = new Type(0x5a); /** */ public static final Type DEFCOLWIDTH = new Type(0x55); /** */ public static final Type DEFAULTROWHEIGHT = new Type(0x225); /** */ public static final Type WRITEACCESS = new Type(0x5c); /** */ public static final Type WSBOOL = new Type(0x81); /** */ public static final Type CODEPAGE = new Type(0x42); /** */ public static final Type DSF = new Type(0x161); /** */ public static final Type FNGROUPCOUNT = new Type(0x9c); /** */ public static final Type FILTERMODE = new Type(0x9b); /** */ public static final Type AUTOFILTERINFO = new Type(0x9d); /** */ public static final Type AUTOFILTER = new Type(0x9e); /** */ public static final Type COUNTRY = new Type(0x8c); /** */ public static final Type PROTECT = new Type(0x12); /** */ public static final Type SCENPROTECT = new Type(0xdd); /** */ public static final Type OBJPROTECT = new Type(0x63); /** */ public static final Type PRINTHEADERS = new Type(0x2a); /** */ public static final Type HEADER = new Type(0x14); /** */ public static final Type FOOTER = new Type(0x15); /** */ public static final Type HCENTER = new Type(0x83); /** */ public static final Type VCENTER = new Type(0x84); /** */ public static final Type FILEPASS = new Type(0x2f); /** */ public static final Type SETUP = new Type(0xa1); /** */ public static final Type PRINTGRIDLINES = new Type(0x2b); /** */ public static final Type GRIDSET = new Type(0x82); /** */ public static final Type GUTS = new Type(0x80); /** */ public static final Type WINDOWPROTECT = new Type(0x19); /** */ public static final Type PROT4REV = new Type(0x1af); /** */ public static final Type PROT4REVPASS = new Type(0x1bc); /** */ public static final Type PASSWORD = new Type(0x13); /** */ public static final Type REFRESHALL = new Type(0x1b7); /** */ public static final Type WINDOW1 = new Type(0x3d); /** */ public static final Type WINDOW2 = new Type(0x23e); /** */ public static final Type BACKUP = new Type(0x40); /** */ public static final Type HIDEOBJ = new Type(0x8d); /** */ public static final Type NINETEENFOUR = new Type(0x22); /** */ public static final Type PRECISION = new Type(0xe); /** */ public static final Type BOOKBOOL = new Type(0xda); /** */ public static final Type FONT = new Type(0x31); /** */ public static final Type MMS = new Type(0xc1); /** */ public static final Type CALCMODE = new Type(0x0d); /** */ public static final Type CALCCOUNT = new Type(0x0c); /** */ public static final Type REFMODE = new Type(0x0f); /** */ public static final Type TEMPLATE = new Type(0x60); /** */ public static final Type OBJPROJ = new Type(0xd3); /** */ public static final Type DELTA = new Type(0x10); /** */ public static final Type MERGEDCELLS = new Type(0xe5); /** */ public static final Type ITERATION = new Type(0x11); /** */ public static final Type STYLE = new Type(0x293); /** */ public static final Type USESELFS = new Type(0x160); /** */ public static final Type VERTICALPAGEBREAKS = new Type(0x1a); /** */ public static final Type HORIZONTALPAGEBREAKS = new Type(0x1b); /** */ public static final Type SELECTION = new Type(0x1d); /** */ public static final Type HLINK = new Type(0x1b8); /** */ public static final Type OBJ = new Type(0x5d); /** */ public static final Type MSODRAWING = new Type(0xec); /** */ public static final Type MSODRAWINGGROUP = new Type(0xeb); /** */ public static final Type LEFTMARGIN = new Type(0x26); /** */ public static final Type RIGHTMARGIN = new Type(0x27); /** */ public static final Type TOPMARGIN = new Type(0x28); /** */ public static final Type BOTTOMMARGIN = new Type(0x29); /** */ public static final Type EXTERNNAME = new Type(0x23); /** */ public static final Type PALETTE = new Type(0x92); /** */ public static final Type PLS = new Type(0x4d); /** */ public static final Type SCL = new Type(0xa0); /** */ public static final Type PANE = new Type(0x41); /** */ public static final Type WEIRD1 = new Type(0xef); /** */ public static final Type SORT = new Type(0x90); /** */ public static final Type CONDFMT = new Type(0x1b0); /** */ public static final Type CF = new Type(0x1b1); /** */ public static final Type DV = new Type(0x1be); /** */ public static final Type DVAL = new Type(0x1b2); /** */ public static final Type BUTTONPROPERTYSET = new Type(0x1ba); /** * */ public static final Type EXCEL9FILE = new Type(0x1c0); // Chart types /** */ public static final Type FONTX = new Type(0x1026); /** */ public static final Type IFMT = new Type(0x104e); /** */ public static final Type FBI = new Type(0x1060); /** */ public static final Type ALRUNS = new Type(0x1050); /** */ public static final Type SERIES = new Type(0x1003); /** */ public static final Type SERIESLIST = new Type(0x1016); /** */ public static final Type SBASEREF = new Type(0x1048); /** */ public static final Type UNKNOWN = new Type(0xffff); // Pivot stuff /** */ // public static final Type R = new Type(0xffff); // Unknown types public static final Type U1C0 = new Type(0x1c0); public static final Type U1C1 = new Type(0x1c1); } jexcelapi/src/jxl/biff/WritableRecordData.java0000750000175000017500000001077711207000612021554 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; import jxl.common.Logger; import jxl.read.biff.Record; /** * Extension of the standard RecordData which is used to support those * records which, once read, may also be written */ public abstract class WritableRecordData extends RecordData implements ByteData { /** * The logger */ private static Logger logger = Logger.getLogger(WritableRecordData.class); /** * The maximum length allowed by Excel for any record length */ protected static final int maxRecordLength = 8228; /** * Constructor used by the writable records * * @param t the biff type of this record */ protected WritableRecordData(Type t) { super(t); } /** * Constructor used when reading a record * * @param t the raw data read from the biff file */ protected WritableRecordData(Record t) { super(t); } /** * Used when writing out records. This portion of the method handles the * biff code and the length of the record and appends on the data retrieved * from the subclasses * * @return the full record data to be written out to the compound file */ public final byte[] getBytes() { byte[] data = getData(); int dataLength = data.length; // Don't the call the automatic continuation code for now // Assert.verify(dataLength <= maxRecordLength - 4); // If the bytes length is greater than the max record length // then split out the data set into continue records if (data.length > maxRecordLength - 4) { dataLength = maxRecordLength - 4; data = handleContinueRecords(data); } byte[] bytes = new byte[data.length + 4]; System.arraycopy(data, 0, bytes, 4, data.length); IntegerHelper.getTwoBytes(getCode(), bytes, 0); IntegerHelper.getTwoBytes(dataLength, bytes, 2); return bytes; } /** * The number of bytes for this record exceeds the maximum record * length, so a continue is required * @param data the raw data * @return the continued data */ private byte[] handleContinueRecords(byte[] data) { // Deduce the number of continue records int continuedData = data.length - (maxRecordLength - 4); int numContinueRecords = continuedData / (maxRecordLength - 4) + 1; // Create the new byte array, allowing for the continue records // code and length byte[] newdata = new byte[data.length + numContinueRecords * 4]; // Copy the bona fide record data into the beginning of the super // record System.arraycopy(data, 0, newdata, 0, maxRecordLength - 4); int oldarraypos = maxRecordLength - 4; int newarraypos = maxRecordLength - 4; // Now handle all the continue records for (int i = 0; i < numContinueRecords; i++) { // The number of bytes to add into the new array int length = Math.min(data.length - oldarraypos, maxRecordLength - 4); // Add in the continue record code IntegerHelper.getTwoBytes(Type.CONTINUE.value, newdata, newarraypos); IntegerHelper.getTwoBytes(length, newdata, newarraypos + 2); // Copy in as much of the new data as possible System.arraycopy(data, oldarraypos, newdata, newarraypos + 4, length); // Update the position counters oldarraypos += length; newarraypos += length + 4; } return newdata; } /** * Abstract method called by the getBytes method. Subclasses implement * this method to incorporate their specific binary data - excluding the * biff code and record length, which is handled by this class * * @return subclass specific biff data */ protected abstract byte[] getData(); } jexcelapi/src/jxl/biff/AutoFilter.java0000750000175000017500000000354411207000612020122 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2007 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; import java.io.IOException; import jxl.write.biff.File; /** * Information for autofiltering */ public class AutoFilter { private FilterModeRecord filterMode; private AutoFilterInfoRecord autoFilterInfo; private AutoFilterRecord autoFilter; /** * Constructor */ public AutoFilter(FilterModeRecord fmr, AutoFilterInfoRecord afir) { filterMode = fmr; autoFilterInfo = afir; } public void add(AutoFilterRecord af) { autoFilter = af; // make this into a list sometime } /** * Writes out the data validation * * @exception IOException * @param outputFile the output file */ public void write(File outputFile) throws IOException { if (filterMode != null) { outputFile.write(filterMode); } if (autoFilterInfo != null) { outputFile.write(autoFilterInfo); } if (autoFilter != null) { outputFile.write(autoFilter); } } } jexcelapi/src/jxl/biff/FormattingRecords.java0000750000175000017500000003512311207000612021476 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; import java.io.IOException; import java.text.DateFormat; import java.text.NumberFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import jxl.common.Assert; import jxl.common.Logger; import jxl.format.Colour; import jxl.format.RGB; import jxl.write.biff.File; /** * The list of XF records and formatting records for the workbook */ public class FormattingRecords { /** * The logger */ private static Logger logger = Logger.getLogger(FormattingRecords.class); /** * A hash map of FormatRecords, for random access retrieval when reading * in a spreadsheet */ private HashMap formats; /** * A list of formats, used when writing out a spreadsheet */ private ArrayList formatsList; /** * The list of extended format records */ private ArrayList xfRecords; /** * The next available index number for custom format records */ private int nextCustomIndexNumber; /** * A handle to the available fonts */ private Fonts fonts; /** * The colour palette */ private PaletteRecord palette; /** * The start index number for custom format records */ private static final int customFormatStartIndex = 0xa4; /** * The maximum number of format records. This is some weird internal * Excel constraint */ private static final int maxFormatRecordsIndex = 0x1b9; /** * The minimum number of XF records for a sheet. The rationalization * processes commences immediately after this number */ private static final int minXFRecords = 21; /** * Constructor * * @param f the container for the fonts */ public FormattingRecords(Fonts f) { xfRecords = new ArrayList(10); formats = new HashMap(10); formatsList = new ArrayList(10); fonts = f; nextCustomIndexNumber = customFormatStartIndex; } /** * Adds an extended formatting record to the list. If the XF record passed * in has not been initialized, its index is determined based on the * xfRecords list, and * this position is passed to the XF records initialize method * * @param xf the xf record to add * @exception NumFormatRecordsException */ public final void addStyle(XFRecord xf) throws NumFormatRecordsException { if (!xf.isInitialized()) { int pos = xfRecords.size(); xf.initialize(pos, this, fonts); xfRecords.add(xf); } else { // The XF record has probably been read in. If the index is greater // Than the size of the list, then it is not a preset format, // so add it if (xf.getXFIndex() >= xfRecords.size()) { xfRecords.add(xf); } } } /** * Adds a cell format to the hash map, keyed on its index. If the format * record is not initialized, then its index number is determined and its * initialize method called. If the font is not a built in format, then it * is added to the list of formats for writing out * * @param fr the format record */ public final void addFormat(DisplayFormat fr) throws NumFormatRecordsException { // Handle the case the where the index number in the read Excel // file exhibits some major weirdness if (fr.isInitialized() && fr.getFormatIndex() >= maxFormatRecordsIndex) { logger.warn("Format index exceeds Excel maximum - assigning custom " + "number"); fr.initialize(nextCustomIndexNumber); nextCustomIndexNumber++; } // Initialize the format record with a custom index number if (!fr.isInitialized()) { fr.initialize(nextCustomIndexNumber); nextCustomIndexNumber++; } if (nextCustomIndexNumber > maxFormatRecordsIndex) { nextCustomIndexNumber = maxFormatRecordsIndex; throw new NumFormatRecordsException(); } if (fr.getFormatIndex() >= nextCustomIndexNumber) { nextCustomIndexNumber = fr.getFormatIndex() + 1; } if (!fr.isBuiltIn()) { formatsList.add(fr); formats.put(new Integer(fr.getFormatIndex()), fr); } } /** * Sees if the extended formatting record at the specified position * represents a date. First checks against the built in formats, and * then checks against the hash map of FormatRecords * * @param pos the xf format index * @return TRUE if this format index is formatted as a Date */ public final boolean isDate(int pos) { XFRecord xfr = (XFRecord) xfRecords.get(pos); if (xfr.isDate()) { return true; } FormatRecord fr = (FormatRecord) formats.get(new Integer(xfr.getFormatRecord())); return fr == null ? false : fr.isDate(); } /** * Gets the DateFormat used to format the cell. * * @param pos the xf format index * @return the DateFormat object used to format the date in the original * excel cell */ public final DateFormat getDateFormat(int pos) { XFRecord xfr = (XFRecord) xfRecords.get(pos); if (xfr.isDate()) { return xfr.getDateFormat(); } FormatRecord fr = (FormatRecord) formats.get(new Integer(xfr.getFormatRecord())); if (fr == null) { return null; } return fr.isDate() ? fr.getDateFormat() : null; } /** * Gets the NumberFormat used to format the cell. * * @param pos the xf format index * @return the DateFormat object used to format the date in the original * excel cell */ public final NumberFormat getNumberFormat(int pos) { XFRecord xfr = (XFRecord) xfRecords.get(pos); if (xfr.isNumber()) { return xfr.getNumberFormat(); } FormatRecord fr = (FormatRecord) formats.get(new Integer(xfr.getFormatRecord())); if (fr == null) { return null; } return fr.isNumber() ? fr.getNumberFormat() : null; } /** * Gets the format record * * @param index the formatting record index to retrieve * @return the format record at the specified index */ FormatRecord getFormatRecord(int index) { return (FormatRecord) formats.get(new Integer(index)); } /** * Writes out all the format records and the XF records * * @param outputFile the file to write to * @exception IOException */ public void write(File outputFile) throws IOException { // Write out all the formats Iterator i = formatsList.iterator(); FormatRecord fr = null; while (i.hasNext()) { fr = (FormatRecord) i.next(); outputFile.write(fr); } // Write out the styles i = xfRecords.iterator(); XFRecord xfr = null; while (i.hasNext()) { xfr = (XFRecord) i.next(); outputFile.write(xfr); } // Write out the style records BuiltInStyle style = new BuiltInStyle(0x10, 3); outputFile.write(style); style = new BuiltInStyle(0x11, 6); outputFile.write(style); style = new BuiltInStyle(0x12, 4); outputFile.write(style); style = new BuiltInStyle(0x13, 7); outputFile.write(style); style = new BuiltInStyle(0x0, 0); outputFile.write(style); style = new BuiltInStyle(0x14, 5); outputFile.write(style); } /** * Accessor for the fonts used by this workbook * * @return the fonts container */ protected final Fonts getFonts() { return fonts; } /** * Gets the XFRecord for the specified index. Used when copying individual * cells * * @param index the XF record to retrieve * @return the XF record at the specified index */ public final XFRecord getXFRecord(int index) { return (XFRecord) xfRecords.get(index); } /** * Gets the number of formatting records on the list. This is used by the * writable subclass because there is an upper limit on the amount of * format records that are allowed to be present in an excel sheet * * @return the number of format records present */ protected final int getNumberOfFormatRecords() { return formatsList.size(); } /** * Rationalizes all the fonts, removing duplicate entries * * @return the list of new font index number */ public IndexMapping rationalizeFonts() { return fonts.rationalize(); } /** * Rationalizes the cell formats. Duplicate * formats are removed and the format indexed of the cells * adjusted accordingly * * @param fontMapping the font mapping index numbers * @param formatMapping the format mapping index numbers * @return the list of new font index number */ public IndexMapping rationalize(IndexMapping fontMapping, IndexMapping formatMapping) { // Update the index codes for the XF records using the format // mapping and the font mapping // at the same time XFRecord xfr = null; for (Iterator it = xfRecords.iterator(); it.hasNext();) { xfr = (XFRecord) it.next(); if (xfr.getFormatRecord() >= customFormatStartIndex) { xfr.setFormatIndex(formatMapping.getNewIndex(xfr.getFormatRecord())); } xfr.setFontIndex(fontMapping.getNewIndex(xfr.getFontIndex())); } ArrayList newrecords = new ArrayList(minXFRecords); IndexMapping mapping = new IndexMapping(xfRecords.size()); int numremoved = 0; int numXFRecords = Math.min(minXFRecords, xfRecords.size()); // Copy across the fundamental styles for (int i = 0; i < numXFRecords; i++) { newrecords.add(xfRecords.get(i)); mapping.setMapping(i, i); } if (numXFRecords < minXFRecords) { logger.warn("There are less than the expected minimum number of " + "XF records"); return mapping; } // Iterate through the old list for (int i = minXFRecords; i < xfRecords.size(); i++) { XFRecord xf = (XFRecord) xfRecords.get(i); // Compare against formats already on the list boolean duplicate = false; for (Iterator it = newrecords.iterator(); it.hasNext() && !duplicate;) { XFRecord xf2 = (XFRecord) it.next(); if (xf2.equals(xf)) { duplicate = true; mapping.setMapping(i, mapping.getNewIndex(xf2.getXFIndex())); numremoved++; } } // If this format is not a duplicate then add it to the new list if (!duplicate) { newrecords.add(xf); mapping.setMapping(i, i - numremoved); } } // It is sufficient to merely change the xf index field on all XFRecords // In this case, CellValues which refer to defunct format records // will nevertheless be written out with the correct index number for (Iterator i = xfRecords.iterator(); i.hasNext();) { XFRecord xf = (XFRecord) i.next(); xf.rationalize(mapping); } // Set the new list xfRecords = newrecords; return mapping; } /** * Rationalizes the display formats. Duplicate * formats are removed and the format indices of the cells * adjusted accordingly. It is invoked immediately prior to writing * writing out the sheet * @return the index mapping between the old display formats and the * rationalized ones */ public IndexMapping rationalizeDisplayFormats() { ArrayList newformats = new ArrayList(); int numremoved = 0; IndexMapping mapping = new IndexMapping(nextCustomIndexNumber); // Iterate through the old list Iterator i = formatsList.iterator(); DisplayFormat df = null; DisplayFormat df2 = null; boolean duplicate = false; while (i.hasNext()) { df = (DisplayFormat) i.next(); Assert.verify(!df.isBuiltIn()); // Compare against formats already on the list Iterator i2 = newformats.iterator(); duplicate = false; while (i2.hasNext() && !duplicate) { df2 = (DisplayFormat) i2.next(); if (df2.equals(df)) { duplicate = true; mapping.setMapping(df.getFormatIndex(), mapping.getNewIndex(df2.getFormatIndex())); numremoved++; } } // If this format is not a duplicate then add it to the new list if (!duplicate) { newformats.add(df); int indexnum = df.getFormatIndex() - numremoved; if (indexnum > maxFormatRecordsIndex) { logger.warn("Too many number formats - using default format."); indexnum = 0; // the default number format index } mapping.setMapping(df.getFormatIndex(), df.getFormatIndex() - numremoved); } } // Set the new list formatsList = newformats; // Update the index codes for the remaining formats i = formatsList.iterator(); while (i.hasNext()) { df = (DisplayFormat) i.next(); df.initialize(mapping.getNewIndex(df.getFormatIndex())); } return mapping; } /** * Accessor for the colour palette * * @return the palette */ public PaletteRecord getPalette() { return palette; } /** * Called from the WorkbookParser to set the colour palette * * @param pr the palette */ public void setPalette(PaletteRecord pr) { palette = pr; } /** * Sets the RGB value for the specified colour for this workbook * * @param c the colour whose RGB value is to be overwritten * @param r the red portion to set (0-255) * @param g the green portion to set (0-255) * @param b the blue portion to set (0-255) */ public void setColourRGB(Colour c, int r, int g, int b) { if (palette == null) { palette = new PaletteRecord(); } palette.setColourRGB(c, r, g, b); } /** * Accessor for the RGB value for the specified colour * * @return the RGB for the specified colour */ public RGB getColourRGB(Colour c) { if (palette == null) { return c.getDefaultRGB(); } return palette.getColourRGB(c); } } jexcelapi/src/jxl/biff/BaseCellFeatures.java0000750000175000017500000003353611263327254021241 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2004 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; import java.util.Collection; import jxl.common.Assert; import jxl.common.Logger; import jxl.CellReferenceHelper; import jxl.Range; import jxl.biff.drawing.ComboBox; import jxl.biff.drawing.Comment; import jxl.write.biff.CellValue; /** * Container for any additional cell features */ public class BaseCellFeatures { /** * The logger */ public static Logger logger = Logger.getLogger(BaseCellFeatures.class); /** * The comment */ private String comment; /** * The comment width in cells */ private double commentWidth; /** * The comment height in cells */ private double commentHeight; /** * A handle to the drawing object */ private Comment commentDrawing; /** * A handle to the combo box object */ private ComboBox comboBox; /** * The data validation settings */ private DataValiditySettingsRecord validationSettings; /** * The DV Parser used to contain the validation details */ private DVParser dvParser; /** * Indicates whether a drop down is required */ private boolean dropDown; /** * Indicates whether this cell features has data validation */ private boolean dataValidation; /** * The cell to which this is attached, and which may need to be notified */ private CellValue writableCell; // Constants private final static double defaultCommentWidth = 3; private final static double defaultCommentHeight = 4; // Validation conditions protected static class ValidationCondition { private DVParser.Condition condition; private static ValidationCondition[] types = new ValidationCondition[0]; ValidationCondition(DVParser.Condition c) { condition = c; ValidationCondition[] oldtypes = types; types = new ValidationCondition[oldtypes.length+1]; System.arraycopy(oldtypes, 0, types, 0, oldtypes.length); types[oldtypes.length] = this; } public DVParser.Condition getCondition() { return condition; } } public static final ValidationCondition BETWEEN = new ValidationCondition(DVParser.BETWEEN); public static final ValidationCondition NOT_BETWEEN = new ValidationCondition(DVParser.NOT_BETWEEN); public static final ValidationCondition EQUAL = new ValidationCondition(DVParser.EQUAL); public static final ValidationCondition NOT_EQUAL = new ValidationCondition(DVParser.NOT_EQUAL); public static final ValidationCondition GREATER_THAN = new ValidationCondition(DVParser.GREATER_THAN); public static final ValidationCondition LESS_THAN = new ValidationCondition(DVParser.LESS_THAN); public static final ValidationCondition GREATER_EQUAL = new ValidationCondition(DVParser.GREATER_EQUAL); public static final ValidationCondition LESS_EQUAL = new ValidationCondition(DVParser.LESS_EQUAL); /** * Constructor */ protected BaseCellFeatures() { } /** * Copy constructor * * @param the cell to copy */ public BaseCellFeatures(BaseCellFeatures cf) { // The comment stuff comment = cf.comment; commentWidth = cf.commentWidth; commentHeight = cf.commentHeight; // The data validation stuff. dropDown = cf.dropDown; dataValidation = cf.dataValidation; validationSettings = cf.validationSettings; // ? if (cf.dvParser != null) { dvParser = new DVParser(cf.dvParser); } } /** * Accessor for the cell comment */ protected String getComment() { return comment; } /** * Accessor for the comment width */ public double getCommentWidth() { return commentWidth; } /** * Accessor for the comment height */ public double getCommentHeight() { return commentHeight; } /** * Called by the cell when the features are added * * @param wc the writable cell */ public final void setWritableCell(CellValue wc) { writableCell = wc; } /** * Internal method to set the cell comment. Used when reading */ public void setReadComment(String s, double w, double h) { comment = s; commentWidth = w; commentHeight = h; } /** * Internal method to set the data validation. Used when reading */ public void setValidationSettings(DataValiditySettingsRecord dvsr) { Assert.verify(dvsr != null); validationSettings = dvsr; dataValidation = true; } /** * Sets the cell comment * * @param s the comment */ public void setComment(String s) { setComment(s, defaultCommentWidth, defaultCommentHeight); } /** * Sets the cell comment * * @param s the comment * @param height the height of the comment box in cells * @param width the width of the comment box in cells */ public void setComment(String s, double width, double height) { comment = s; commentWidth = width; commentHeight = height; if (commentDrawing != null) { commentDrawing.setCommentText(s); commentDrawing.setWidth(width); commentDrawing.setWidth(height); // commentDrawing is set up when trying to modify a copied cell } } /** * Removes the cell comment, if present */ public void removeComment() { // Set the comment string to be empty comment = null; // Remove the drawing from the drawing group if (commentDrawing != null) { // do not call DrawingGroup.remove() because comments are not present // on the Workbook DrawingGroup record writableCell.removeComment(commentDrawing); commentDrawing = null; } } /** * Public function which removes any data validation, if present */ public void removeDataValidation() { if (!dataValidation) { return; } // If the data validation is shared, then generate a warning DVParser dvp = getDVParser(); if (dvp.extendedCellsValidation()) { logger.warn("Cannot remove data validation from " + CellReferenceHelper.getCellReference(writableCell) + " as it is part of the shared reference " + CellReferenceHelper.getCellReference(dvp.getFirstColumn(), dvp.getFirstRow()) + "-" + CellReferenceHelper.getCellReference(dvp.getLastColumn(), dvp.getLastRow())); return; } // Remove the validation from the WritableSheet object if present writableCell.removeDataValidation(); clearValidationSettings(); } /** * Internal function which removes any data validation, including * shared ones, if present. This is called from WritableSheetImpl * in response to a call to removeDataValidation */ public void removeSharedDataValidation() { if (!dataValidation) { return; } // Remove the validation from the WritableSheet object if present writableCell.removeDataValidation(); clearValidationSettings(); } /** * Sets the comment drawing object */ public final void setCommentDrawing(Comment c) { commentDrawing = c; } /** * Accessor for the comment drawing */ public final Comment getCommentDrawing() { return commentDrawing; } /** * Gets the data validation list as a formula. Used only when reading * * @return the validation formula as a list */ public String getDataValidationList() { if (validationSettings == null) { return null; } return validationSettings.getValidationFormula(); } /** * The list of items to validate for this cell. For each object in the * collection, the toString() method will be called and the data entered * will be validated against that string * * @param c the list of valid values */ public void setDataValidationList(Collection c) { if (dataValidation && getDVParser().extendedCellsValidation()) { logger.warn("Cannot set data validation on " + CellReferenceHelper.getCellReference(writableCell) + " as it is part of a shared data validation"); return; } clearValidationSettings(); dvParser = new DVParser(c); dropDown = true; dataValidation = true; } /** * The list of items to validate for this cell in the form of a cell range. * * @param c the list of valid values */ public void setDataValidationRange(int col1, int r1, int col2, int r2) { if (dataValidation && getDVParser().extendedCellsValidation()) { logger.warn("Cannot set data validation on " + CellReferenceHelper.getCellReference(writableCell) + " as it is part of a shared data validation"); return; } clearValidationSettings(); dvParser = new DVParser(col1, r1, col2, r2); dropDown = true; dataValidation = true; } /** * Sets the data validation based upon a named range */ public void setDataValidationRange(String namedRange) { if (dataValidation && getDVParser().extendedCellsValidation()) { logger.warn("Cannot set data validation on " + CellReferenceHelper.getCellReference(writableCell) + " as it is part of a shared data validation"); return; } clearValidationSettings(); dvParser = new DVParser(namedRange); dropDown = true; dataValidation = true; } /** * Sets the data validation based upon a numerical condition */ public void setNumberValidation(double val, ValidationCondition c) { if (dataValidation && getDVParser().extendedCellsValidation()) { logger.warn("Cannot set data validation on " + CellReferenceHelper.getCellReference(writableCell) + " as it is part of a shared data validation"); return; } clearValidationSettings(); dvParser = new DVParser(val, Double.NaN, c.getCondition()); dropDown = false; dataValidation = true; } public void setNumberValidation(double val1, double val2, ValidationCondition c) { if (dataValidation && getDVParser().extendedCellsValidation()) { logger.warn("Cannot set data validation on " + CellReferenceHelper.getCellReference(writableCell) + " as it is part of a shared data validation"); return; } clearValidationSettings(); dvParser = new DVParser(val1, val2, c.getCondition()); dropDown = false; dataValidation = true; } /** * Accessor for the data validation * * @return TRUE if this has a data validation associated with it, FALSE otherwise */ public boolean hasDataValidation() { return dataValidation; } /** * Clears out any existing validation settings */ private void clearValidationSettings() { validationSettings = null; dvParser = null; dropDown = false; comboBox = null; dataValidation = false; } /** * Accessor for whether a drop down is required * * @return TRUE if this requires a drop down, FALSE otherwise */ public boolean hasDropDown() { return dropDown; } /** * Sets the combo box drawing object for list validations * * @param cb the combo box */ public void setComboBox(ComboBox cb) { comboBox = cb; } /** * Gets the dv parser */ public DVParser getDVParser() { // straightforward - this was created as a writable cell if (dvParser != null) { return dvParser; } // this was copied from a readable cell, and then copied again if (validationSettings != null) { dvParser = new DVParser(validationSettings.getDVParser()); return dvParser; } return null; // keep the compiler happy } /** * Use the same data validation logic as the specified cell features * * @param cf the data validation to reuse */ public void shareDataValidation(BaseCellFeatures source) { if (dataValidation) { logger.warn("Attempting to share a data validation on cell " + CellReferenceHelper.getCellReference(writableCell) + " which already has a data validation"); return; } clearValidationSettings(); dvParser = source.getDVParser(); validationSettings = null; dataValidation = true; dropDown = source.dropDown; comboBox = source.comboBox; } /** * Gets the range of cells to which the data validation applies. If the * validation applies to just this cell, this will be reflected in the * returned range * * @return the range to which the same validation extends, or NULL if this * cell doesn't have a validation */ public Range getSharedDataValidationRange() { if (!dataValidation) { return null; } DVParser dvp = getDVParser(); return new SheetRangeImpl(writableCell.getSheet(), dvp.getFirstColumn(), dvp.getFirstRow(), dvp.getLastColumn(), dvp.getLastRow()); } } jexcelapi/src/jxl/biff/Fonts.java0000750000175000017500000001064711207000612017137 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import jxl.common.Assert; import jxl.write.biff.File; /** * A container for the list of fonts used in this workbook */ public class Fonts { /** * The list of fonts */ private ArrayList fonts; /** * The default number of fonts */ private static final int numDefaultFonts = 4; /** * Constructor */ public Fonts() { fonts = new ArrayList(); } /** * Adds a font record to this workbook. If the FontRecord passed in has not * been initialized, then its font index is determined based upon the size * of the fonts list. The FontRecord's initialized method is called, and * it is added to the list of fonts. * * @param f the font to add */ public void addFont(FontRecord f) { if (!f.isInitialized()) { int pos = fonts.size(); // Remember that the pos with index 4 is skipped if (pos >= 4) { pos++; } f.initialize(pos); fonts.add(f); } } /** * Used by FormattingRecord for retrieving the fonts for the * hardcoded styles * * @param index the index of the font to return * @return the font with the specified font index */ public FontRecord getFont(int index) { // remember to allow for the fact that font index 4 is not used if (index > 4) { index--; } return (FontRecord) fonts.get(index); } /** * Writes out the list of fonts * * @param outputFile the compound file to write the data to * @exception IOException */ public void write(File outputFile) throws IOException { Iterator i = fonts.iterator(); FontRecord font = null; while (i.hasNext()) { font = (FontRecord) i.next(); outputFile.write(font); } } /** * Rationalizes all the fonts, removing any duplicates * * @return the mappings between new indexes and old ones */ IndexMapping rationalize() { IndexMapping mapping = new IndexMapping(fonts.size() + 1); // allow for skipping record 4 ArrayList newfonts = new ArrayList(); FontRecord fr = null; int numremoved = 0; // Preserve the default fonts for (int i = 0; i < numDefaultFonts; i++) { fr = (FontRecord) fonts.get(i); newfonts.add(fr); mapping.setMapping(fr.getFontIndex(), fr.getFontIndex()); } // Now do the rest Iterator it = null; FontRecord fr2 = null; boolean duplicate = false; for (int i = numDefaultFonts; i < fonts.size(); i++) { fr = (FontRecord) fonts.get(i); // Compare to all the fonts currently on the list duplicate = false; it = newfonts.iterator(); while (it.hasNext() && !duplicate) { fr2 = (FontRecord) it.next(); if (fr.equals(fr2)) { duplicate = true; mapping.setMapping(fr.getFontIndex(), mapping.getNewIndex(fr2.getFontIndex())); numremoved++; } } if (!duplicate) { // Add to the new list newfonts.add(fr); int newindex = fr.getFontIndex() - numremoved; Assert.verify(newindex > 4); mapping.setMapping(fr.getFontIndex(), newindex); } } // Iterate through the remaining fonts, updating all the font indices it = newfonts.iterator(); while (it.hasNext()) { fr = (FontRecord) it.next(); fr.initialize(mapping.getNewIndex(fr.getFontIndex())); } fonts = newfonts; return mapping; } } jexcelapi/src/jxl/biff/BaseCompoundFile.java0000750000175000017500000002011111207000612021210 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; import jxl.common.Assert; import jxl.common.Logger; /** * Contains the common data for a compound file */ public abstract class BaseCompoundFile { /** * The logger */ private static Logger logger = Logger.getLogger(BaseCompoundFile.class); /** * The identifier at the beginning of every OLE file */ protected static final byte[] IDENTIFIER = new byte[] {(byte) 0xd0, (byte) 0xcf, (byte) 0x11, (byte) 0xe0, (byte) 0xa1, (byte) 0xb1, (byte) 0x1a, (byte) 0xe1}; /** */ protected static final int NUM_BIG_BLOCK_DEPOT_BLOCKS_POS = 0x2c; /** */ protected static final int SMALL_BLOCK_DEPOT_BLOCK_POS = 0x3c; /** */ protected static final int NUM_SMALL_BLOCK_DEPOT_BLOCKS_POS = 0x40; /** */ protected static final int ROOT_START_BLOCK_POS = 0x30; /** */ protected static final int BIG_BLOCK_SIZE = 0x200; /** */ protected static final int SMALL_BLOCK_SIZE = 0x40; /** */ protected static final int EXTENSION_BLOCK_POS = 0x44; /** */ protected static final int NUM_EXTENSION_BLOCK_POS = 0x48; /** */ protected static final int PROPERTY_STORAGE_BLOCK_SIZE = 0x80; /** */ protected static final int BIG_BLOCK_DEPOT_BLOCKS_POS = 0x4c; /** */ protected static final int SMALL_BLOCK_THRESHOLD = 0x1000; // property storage offsets /** */ private static final int SIZE_OF_NAME_POS = 0x40; /** */ private static final int TYPE_POS = 0x42; /** */ private static final int COLOUR_POS = 0x43; /** */ private static final int PREVIOUS_POS = 0x44; /** */ private static final int NEXT_POS = 0x48; /** */ private static final int CHILD_POS = 0x4c; /** */ private static final int START_BLOCK_POS = 0x74; /** */ private static final int SIZE_POS = 0x78; /** * The standard property sets */ public final static String ROOT_ENTRY_NAME = "Root Entry"; public final static String WORKBOOK_NAME = "Workbook"; public final static String SUMMARY_INFORMATION_NAME = "\u0005SummaryInformation"; public final static String DOCUMENT_SUMMARY_INFORMATION_NAME = "\u0005DocumentSummaryInformation"; public final static String COMP_OBJ_NAME = "\u0001CompObj"; public final static String[] STANDARD_PROPERTY_SETS = new String[] {ROOT_ENTRY_NAME, WORKBOOK_NAME, SUMMARY_INFORMATION_NAME, DOCUMENT_SUMMARY_INFORMATION_NAME}; /** * Property storage types */ public final static int NONE_PS_TYPE = 0; public final static int DIRECTORY_PS_TYPE = 1; public final static int FILE_PS_TYPE = 2; public final static int ROOT_ENTRY_PS_TYPE = 5; /** * Inner class to represent the property storage sets. Access is public * to allow access from the PropertySetsReader demo utility */ public class PropertyStorage { /** * The name of this property set */ public String name; /** * The type of the property set */ public int type; /** * The colour of the property set */ public int colour; /** * The block number in the stream which this property sets starts at */ public int startBlock; /** * The size, in bytes, of this property set */ public int size; /** * The previous property set */ public int previous; /** * The next property set */ public int next; /** * The child for this property set */ public int child; /** * The data that created this set */ public byte[] data; /** * Constructs a property set * * @param d the bytes */ public PropertyStorage(byte[] d) { data = d; int nameSize = IntegerHelper.getInt(data[SIZE_OF_NAME_POS], data[SIZE_OF_NAME_POS + 1]); if (nameSize > SIZE_OF_NAME_POS) { logger.warn("property set name exceeds max length - truncating"); nameSize = SIZE_OF_NAME_POS; } type = data[TYPE_POS]; colour = data[COLOUR_POS]; startBlock = IntegerHelper.getInt (data[START_BLOCK_POS], data[START_BLOCK_POS + 1], data[START_BLOCK_POS + 2], data[START_BLOCK_POS + 3]); size = IntegerHelper.getInt (data[SIZE_POS], data[SIZE_POS + 1], data[SIZE_POS + 2], data[SIZE_POS + 3]); previous = IntegerHelper.getInt (data[PREVIOUS_POS], data[PREVIOUS_POS+1], data[PREVIOUS_POS+2], data[PREVIOUS_POS+3]); next = IntegerHelper.getInt (data[NEXT_POS], data[NEXT_POS+1], data[NEXT_POS+2], data[NEXT_POS+3]); child = IntegerHelper.getInt (data[CHILD_POS], data[CHILD_POS+1], data[CHILD_POS+2], data[CHILD_POS+3]); int chars = 0; if (nameSize > 2) { chars = (nameSize - 1) / 2; } StringBuffer n = new StringBuffer(""); for (int i = 0; i < chars ; i++) { n.append( (char) data[i * 2]); } name = n.toString(); } /** * Constructs an empty property set. Used when writing the file * * @param name the property storage name */ public PropertyStorage(String name) { data = new byte[PROPERTY_STORAGE_BLOCK_SIZE]; Assert.verify(name.length() < 32); IntegerHelper.getTwoBytes((name.length() + 1) * 2, data, SIZE_OF_NAME_POS); // add one to the name length to allow for the null character at // the end for (int i = 0; i < name.length(); i++) { data[i * 2] = (byte) name.charAt(i); } } /** * Sets the type * * @param t the type */ public void setType(int t) { type = t; data[TYPE_POS] = (byte) t; } /** * Sets the number of the start block * * @param sb the number of the start block */ public void setStartBlock(int sb) { startBlock = sb; IntegerHelper.getFourBytes(sb, data, START_BLOCK_POS); } /** * Sets the size of the file * * @param s the size */ public void setSize(int s) { size = s; IntegerHelper.getFourBytes(s, data, SIZE_POS); } /** * Sets the previous block * * @param prev the previous block */ public void setPrevious(int prev) { previous = prev; IntegerHelper.getFourBytes(prev, data, PREVIOUS_POS); } /** * Sets the next block * * @param nxt the next block */ public void setNext(int nxt) { next = nxt; IntegerHelper.getFourBytes(next, data, NEXT_POS); } /** * Sets the child * * @param dir the child */ public void setChild(int dir) { child = dir; IntegerHelper.getFourBytes(child, data, CHILD_POS); } /** * Sets the colour * * @param col colour */ public void setColour(int col) { colour = col == 0 ? 0 : 1; data[COLOUR_POS] = (byte) colour; } } /** * Constructor */ protected BaseCompoundFile() { } } jexcelapi/src/jxl/biff/DValParser.java0000750000175000017500000000706411234607053020064 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2004 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; import jxl.common.Logger; import jxl.biff.IntegerHelper; /** * Class which parses the binary data associated with Data Validity (DVal) * setting */ public class DValParser { /** * The logger */ private static Logger logger = Logger.getLogger(DValParser.class); // The option masks private static int PROMPT_BOX_VISIBLE_MASK = 0x1; private static int PROMPT_BOX_AT_CELL_MASK = 0x2; private static int VALIDITY_DATA_CACHED_MASK = 0x4; /** * Prompt box visible */ private boolean promptBoxVisible; /** * Empty cells allowed */ private boolean promptBoxAtCell; /** * Cell validity data cached in following DV records */ private boolean validityDataCached; /** * The number of following DV records */ private int numDVRecords; /** * The object id of the associated down arrow */ private int objectId; /** * Constructor */ public DValParser(byte[] data) { int options = IntegerHelper.getInt(data[0], data[1]); promptBoxVisible = (options & PROMPT_BOX_VISIBLE_MASK) != 0; promptBoxAtCell = (options & PROMPT_BOX_AT_CELL_MASK) != 0; validityDataCached = (options & VALIDITY_DATA_CACHED_MASK) != 0; objectId = IntegerHelper.getInt(data[10], data[11], data[12], data[13]); numDVRecords = IntegerHelper.getInt(data[14], data[15], data[16], data[17]); } /** * Constructor */ public DValParser(int objid, int num) { objectId = objid; numDVRecords = num; validityDataCached = true; } /** * Gets the data */ public byte[] getData() { byte[] data = new byte[18]; int options = 0; if (promptBoxVisible) { options |= PROMPT_BOX_VISIBLE_MASK; } if (promptBoxAtCell) { options |= PROMPT_BOX_AT_CELL_MASK; } if (validityDataCached) { options |= VALIDITY_DATA_CACHED_MASK; } IntegerHelper.getTwoBytes(options, data, 0); IntegerHelper.getFourBytes(objectId, data, 10); IntegerHelper.getFourBytes(numDVRecords, data, 14); return data; } /** * Called when a remove row or column results in one of DV records being * removed */ public void dvRemoved() { numDVRecords--; } /** * Accessor for the number of DV records * * @return the number of DV records for this list */ public int getNumberOfDVRecords() { return numDVRecords; } /** * Accessor for the object id * * @return the object id */ public int getObjectId() { return objectId; } /** * Called when adding a DV record on a copied DVal */ public void dvAdded() { numDVRecords++; } } jexcelapi/src/jxl/biff/BuiltInStyle.java0000750000175000017500000000361611207000612020433 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; /** * Represents a built in, rather than a user defined, style. * This class is used by the FormattingRecords class when writing out the hard* * coded styles */ class BuiltInStyle extends WritableRecordData { /** * The XF index of this style */ private int xfIndex; /** * The reference number of this style */ private int styleNumber; /** * Constructor * * @param xfind the xf index of this style * @param sn the style number of this style */ public BuiltInStyle(int xfind, int sn) { super(Type.STYLE); xfIndex = xfind; styleNumber = sn; } /** * Abstract method implementation to get the raw byte data ready to write out * * @return The byte data */ public byte[] getData() { byte[] data = new byte[4]; IntegerHelper.getTwoBytes(xfIndex, data, 0); // Set the built in bit data[1] |= 0x80; data[2] = (byte) styleNumber; // Set the outline level data[3] = (byte) 0xff; return data; } } jexcelapi/src/jxl/biff/FilterModeRecord.java0000750000175000017500000000276711207000612021243 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2007 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; import jxl.common.Logger; import jxl.read.biff.Record; /** * Range information for conditional formatting */ public class FilterModeRecord extends WritableRecordData { // The logger private static Logger logger = Logger.getLogger(FilterModeRecord.class); /** * The data */ private byte[] data; /** * Constructor */ public FilterModeRecord(Record t) { super(t); data = getRecord().getData(); } /** * Retrieves the data for output to binary file * * @return the data to be written */ public byte[] getData() { return data; } } jexcelapi/src/jxl/biff/DoubleHelper.java0000750000175000017500000000612111207000612020410 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2001 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; /** * Class to help handle doubles */ public class DoubleHelper { /** * Private constructor to prevent instantiation */ private DoubleHelper() { } /** * Gets the IEEE value from the byte array passed in * * @param pos the position in the data block which contains the double value * @param data the data block containing the raw bytes * @return the double value converted from the raw data */ public static double getIEEEDouble(byte[] data, int pos) { int num1 = IntegerHelper.getInt(data[pos], data[pos + 1], data[pos + 2], data[pos + 3]); int num2 = IntegerHelper.getInt(data[pos + 4], data[pos + 5], data[pos + 6], data[pos + 7]); // Long.parseLong doesn't like the sign bit, so have to extract this // information and put it in at the end. (Acknowledgment: thanks // to Ruben for pointing this out) boolean negative = ((num2 & 0x80000000) != 0); // Thanks to Lyle for the following improved IEEE double processing long val = ((num2 & 0x7fffffff) * 0x100000000L) + (num1 < 0 ? 0x100000000L + num1 : num1); double value = Double.longBitsToDouble(val); if (negative) { value = -value; } return value; } /** * Puts the IEEE representation of the double provided into the array * at the designated position * * @param target the data block into which the binary representation is to * be placed * @param pos the position in target in which to place the bytes * @param d the double value to convert to raw bytes */ public static void getIEEEBytes(double d, byte[] target, int pos) { long val = Double.doubleToLongBits(d); target[pos] = (byte) (val & 0xff); target[pos + 1] = (byte) ((val & 0xff00) >> 8); target[pos + 2] = (byte) ((val & 0xff0000) >> 16); target[pos + 3] = (byte) ((val & 0xff000000) >> 24); target[pos + 4] = (byte) ((val & 0xff00000000L) >> 32); target[pos + 5] = (byte) ((val & 0xff0000000000L) >> 40); target[pos + 6] = (byte) ((val & 0xff000000000000L) >> 48); target[pos + 7] = (byte) ((val & 0xff00000000000000L) >> 56) ; } } jexcelapi/src/jxl/biff/AutoFilterRecord.java0000750000175000017500000000276711207000612021267 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2007 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; import jxl.common.Logger; import jxl.read.biff.Record; /** * Range information for conditional formatting */ public class AutoFilterRecord extends WritableRecordData { // The logger private static Logger logger = Logger.getLogger(AutoFilterRecord.class); /** * The data */ private byte[] data; /** * Constructor */ public AutoFilterRecord(Record t) { super(t); data = getRecord().getData(); } /** * Retrieves the data for output to binary file * * @return the data to be written */ public byte[] getData() { return data; } } jexcelapi/src/jxl/biff/DataValidityListRecord.java0000750000175000017500000000671411234606752022441 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2004 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; import jxl.common.Logger; import jxl.read.biff.Record; /** * Record containing the list of data validation settings for a given sheet */ public class DataValidityListRecord extends WritableRecordData { private static Logger logger = Logger.getLogger (DataValidityListRecord.class); /** * The number of settings records associated with this list */ private int numSettings; /** * The object id of the associated down arrow */ private int objectId; /** * The dval parser */ private DValParser dvalParser; /** * The data */ private byte[] data; /** * Constructor */ public DataValidityListRecord(Record t) { super(t); data = getRecord().getData(); objectId = IntegerHelper.getInt(data[10], data[11], data[12], data[13]); numSettings = IntegerHelper.getInt(data[14], data[15], data[16], data[17]); } /** * Constructor called when generating a data validity list from the API */ public DataValidityListRecord(DValParser dval) { super(Type.DVAL); dvalParser = dval; } /** * Copy constructor * * @param dvlr the record copied from a read only sheet */ DataValidityListRecord(DataValidityListRecord dvlr) { super(Type.DVAL); data = dvlr.getData(); } /** * Accessor for the number of settings records associated with this list */ int getNumberOfSettings() { return numSettings; } /** * Retrieves the data for output to binary file * * @return the data to be written */ public byte[] getData() { if (dvalParser == null) { return data; } return dvalParser.getData(); } /** * Called when a remove row or column results in one of DV records being * removed */ void dvRemoved() { if (dvalParser == null) { dvalParser = new DValParser(data); } dvalParser.dvRemoved(); } /** * Called when a writable DV record is added to a copied validity list */ void dvAdded() { if (dvalParser == null) { dvalParser = new DValParser(data); } dvalParser.dvAdded(); } /** * Accessor for the number of DV records * * @return the number of DV records for this list */ public boolean hasDVRecords() { if (dvalParser == null) { return true; } return dvalParser.getNumberOfDVRecords() > 0; } /** * Accessor for the object id * * @return the object id */ public int getObjectId() { if (dvalParser == null) { return objectId; } return dvalParser.getObjectId(); } } jexcelapi/src/jxl/biff/NameRangeException.java0000750000175000017500000000233311207000612021553 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2009 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; import jxl.JXLException; /** * A properly typed exception in case consumers of the API specifically * wish to handle the case when the workbook is password protected */ public class NameRangeException extends JXLException { /** * Constructor */ public NameRangeException() { super(""); } } jexcelapi/src/jxl/biff/EmptyCell.java0000750000175000017500000001053111207000612017734 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; import jxl.CellFeatures; import jxl.CellType; import jxl.format.Alignment; import jxl.format.CellFormat; import jxl.format.Border; import jxl.format.BorderLineStyle; import jxl.format.VerticalAlignment; import jxl.write.WritableCell; import jxl.write.WritableCellFeatures; /** * An empty cell. Represents an empty, as opposed to a blank cell * in the workbook */ public class EmptyCell implements WritableCell { /** * The row of this empty cell */ private int row; /** * The column number of this empty cell */ private int col; /** * Constructs an empty cell at the specified position * * @param c the zero based column * @param r the zero based row */ public EmptyCell(int c, int r) { row = r; col = c; } /** * Returns the row number of this cell * * @return the row number of this cell */ public int getRow() { return row; } /** * Returns the column number of this cell * * @return the column number of this cell */ public int getColumn() { return col; } /** * Returns the content type of this cell * * @return the content type for this cell */ public CellType getType() { return CellType.EMPTY; } /** * Quick and dirty function to return the contents of this cell as a string. * * @return an empty string */ public String getContents() { return ""; } /** * Accessor for the format which is applied to this cell * * @return the format applied to this cell */ public CellFormat getCellFormat() { return null; } /** * Dummy override * @param flag the hidden flag */ public void setHidden(boolean flag) { } /** * Dummy override * @param flag dummy */ public void setLocked(boolean flag) { } /** * Dummy override * @param align dummy */ public void setAlignment(Alignment align) { } /** * Dummy override * @param valign dummy */ public void setVerticalAlignment(VerticalAlignment valign) { } /** * Dummy override * @param line dummy * @param border dummy */ public void setBorder(Border border, BorderLineStyle line) { } /** * Dummy override * @param cf dummy */ public void setCellFormat(CellFormat cf) { } /** * Dummy override * @param cf dummy * @deprecated */ public void setCellFormat(jxl.CellFormat cf) { } /** * Indicates whether or not this cell is hidden, by virtue of either * the entire row or column being collapsed * * @return TRUE if this cell is hidden, FALSE otherwise */ public boolean isHidden() { return false; } /** * Implementation of the deep copy function * * @param c the column which the new cell will occupy * @param r the row which the new cell will occupy * @return a copy of this cell, which can then be added to the sheet */ public WritableCell copyTo(int c, int r) { return new EmptyCell(c, r); } /** * Accessor for the cell features * * @return the cell features or NULL if this cell doesn't have any */ public CellFeatures getCellFeatures() { return null; } /** * Accessor for the cell features * * @return the cell features or NULL if this cell doesn't have any */ public WritableCellFeatures getWritableCellFeatures() { return null; } /** * Accessor for the cell features */ public void setCellFeatures(WritableCellFeatures wcf) { } } jexcelapi/src/jxl/biff/EncodedURLHelper.java0000750000175000017500000000735111207000612021130 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2005 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; import jxl.common.Logger; import jxl.WorkbookSettings; /** * Helper to get the Microsoft encoded URL from the given string */ public class EncodedURLHelper { /** * The logger */ private static Logger logger = Logger.getLogger(EncodedURLHelper.class); // The control codes private static byte msDosDriveLetter = 0x01; private static byte sameDrive = 0x02; private static byte endOfSubdirectory = 0x03; private static byte parentDirectory = 0x04; private static byte unencodedUrl = 0x05; public static byte[] getEncodedURL(String s, WorkbookSettings ws) { if (s.startsWith("http:")) { return getURL(s, ws); } else { return getFile(s, ws); } } private static byte[] getFile(String s, WorkbookSettings ws) { ByteArray byteArray = new ByteArray(); int pos = 0; if (s.charAt(1) == ':') { // we have a drive letter byteArray.add(msDosDriveLetter); byteArray.add((byte) s.charAt(0)); pos = 2; } else if (s.charAt(pos) == '\\' || s.charAt(pos) == '/') { byteArray.add(sameDrive); } while (s.charAt(pos) == '\\' || s.charAt(pos) == '/') { pos++; } while (pos < s.length()) { int nextSepIndex1 = s.indexOf('/', pos); int nextSepIndex2 = s.indexOf('\\', pos); int nextSepIndex = 0; String nextFileNameComponent = null; if (nextSepIndex1 != -1 && nextSepIndex2 != -1) { // choose the smallest (ie. nearest) separator nextSepIndex = Math.min(nextSepIndex1, nextSepIndex2); } else if (nextSepIndex1 == -1 || nextSepIndex2 == -1) { // chose the maximum separator nextSepIndex = Math.max(nextSepIndex1, nextSepIndex2); } if (nextSepIndex == -1) { // no more separators nextFileNameComponent = s.substring(pos); pos = s.length(); } else { nextFileNameComponent = s.substring(pos, nextSepIndex); pos = nextSepIndex + 1; } if (nextFileNameComponent.equals(".")) { // current directory - do nothing } else if (nextFileNameComponent.equals("..")) { // parent directory byteArray.add(parentDirectory); } else { // add the filename component byteArray.add(StringHelper.getBytes(nextFileNameComponent, ws)); } if (pos < s.length()) { byteArray.add(endOfSubdirectory); } } return byteArray.getBytes(); } private static byte[] getURL(String s, WorkbookSettings ws) { ByteArray byteArray = new ByteArray(); byteArray.add(unencodedUrl); byteArray.add((byte) s.length()); byteArray.add(StringHelper.getBytes(s, ws)); return byteArray.getBytes(); } } jexcelapi/src/jxl/biff/XFRecord.java0000750000175000017500000012142111207000612017513 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; import java.text.DateFormat; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.text.NumberFormat; import java.text.SimpleDateFormat; import jxl.common.Assert; import jxl.common.Logger; import jxl.WorkbookSettings; import jxl.format.Alignment; import jxl.format.Border; import jxl.format.BorderLineStyle; import jxl.format.CellFormat; import jxl.format.Colour; import jxl.format.Font; import jxl.format.Format; import jxl.format.Orientation; import jxl.format.Pattern; import jxl.format.VerticalAlignment; import jxl.read.biff.Record; /** * Holds an extended formatting record */ public class XFRecord extends WritableRecordData implements CellFormat { /** * The logger */ private static Logger logger = Logger.getLogger(XFRecord.class); /** * The index to the format record */ public int formatIndex; /** * The index of the parent format */ private int parentFormat; /** * The format type */ private XFType xfFormatType; /** * Indicates whether this is a date formatting record */ private boolean date; /** * Indicates whether this is a number formatting record */ private boolean number; /** * The date format for this record. Deduced when the record is * read in from a spreadsheet */ private DateFormat dateFormat; /** * The number format for this record. Deduced when the record is read in * from a spreadsheet */ private NumberFormat numberFormat; /** * The used attribute. Needs to be preserved in order to get accurate * rationalization */ private byte usedAttributes; /** * The index to the font record used by this XF record */ private int fontIndex; /** * Flag to indicate whether this XF record represents a locked cell */ private boolean locked; /** * Flag to indicate whether this XF record is hidden */ private boolean hidden; /** * The alignment for this cell (left, right, centre) */ private Alignment align; /** * The vertical alignment for the cell (top, bottom, centre) */ private VerticalAlignment valign; /** * The orientation of the cell */ private Orientation orientation; /** * Flag to indicates whether the data (normally text) in the cell will be * wrapped around to fit in the cell width */ private boolean wrap; /** * Indentation of the cell text */ private int indentation; /** * Flag to indicate that this format is shrink to fit */ private boolean shrinkToFit; /** * The border indicator for the left of this cell */ private BorderLineStyle leftBorder; /** * The border indicator for the right of the cell */ private BorderLineStyle rightBorder; /** * The border indicator for the top of the cell */ private BorderLineStyle topBorder; /** * The border indicator for the bottom of the cell */ private BorderLineStyle bottomBorder; /** * The border colour for the left of the cell */ private Colour leftBorderColour; /** * The border colour for the right of the cell */ private Colour rightBorderColour; /** * The border colour for the top of the cell */ private Colour topBorderColour; /** * The border colour for the bottom of the cell */ private Colour bottomBorderColour; /** * The background colour */ private Colour backgroundColour; /** * The background pattern */ private Pattern pattern; /** * The options mask which is used to store the processed cell options (such * as alignment, borders etc) */ private int options; /** * The index of this XF record within the workbook */ private int xfIndex; /** * The font object for this XF record */ private FontRecord font; /** * The format object for this XF record. This is used when creating * a writable record */ private DisplayFormat format; /** * Flag to indicate whether this XF record has been initialized */ private boolean initialized; /** * Indicates whether this cell was constructed by an API or read * from an existing Excel file */ private boolean read; /** * The excel format for this record. This is used to display the actual * excel format string back to the user (eg. when generating certain * types of XML document) as opposed to the java equivalent */ private Format excelFormat; /** * Flag to indicate whether the format information has been initialized. * This is false if the xf record has been read in, but true if it * has been written */ private boolean formatInfoInitialized; /** * Flag to indicate whether this cell was copied. If it was copied, then * it can be set to uninitialized, allowing us to change certain format * information */ private boolean copied; /** * A handle to the formatting records. The purpose of this is * to read the formatting information back, for the purposes of * output eg. to some form of XML */ private FormattingRecords formattingRecords; /** * Constants for the used attributes */ private static final int USE_FONT = 0x4; private static final int USE_FORMAT = 0x8; private static final int USE_ALIGNMENT = 0x10; private static final int USE_BORDER = 0x20; private static final int USE_BACKGROUND = 0x40; private static final int USE_PROTECTION = 0x80; private static final int USE_DEFAULT_VALUE=0xf8; /** * The list of built in date format values */ private static final int[] dateFormats = new int[] {0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x2d, 0x2e, 0x2f}; /** * The list of java date format equivalents */ private static final DateFormat[] javaDateFormats = new DateFormat[] {SimpleDateFormat.getDateInstance(DateFormat.SHORT), SimpleDateFormat.getDateInstance(DateFormat.MEDIUM), new SimpleDateFormat("d-MMM"), new SimpleDateFormat("MMM-yy"), new SimpleDateFormat("h:mm a"), new SimpleDateFormat("h:mm:ss a"), new SimpleDateFormat("H:mm"), new SimpleDateFormat("H:mm:ss"), new SimpleDateFormat("M/d/yy H:mm"), new SimpleDateFormat("mm:ss"), new SimpleDateFormat("H:mm:ss"), new SimpleDateFormat("mm:ss.S")}; /** * The list of built in number format values */ private static int[] numberFormats = new int[] {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x30}; /** * The list of java number format equivalents */ private static NumberFormat[] javaNumberFormats = new NumberFormat[] {new DecimalFormat("0"), new DecimalFormat("0.00"), new DecimalFormat("#,##0"), new DecimalFormat("#,##0.00"), new DecimalFormat("$#,##0;($#,##0)"), new DecimalFormat("$#,##0;($#,##0)"), new DecimalFormat("$#,##0.00;($#,##0.00)"), new DecimalFormat("$#,##0.00;($#,##0.00)"), new DecimalFormat("0%"), new DecimalFormat("0.00%"), new DecimalFormat("0.00E00"), new DecimalFormat("#,##0;(#,##0)"), new DecimalFormat("#,##0;(#,##0)"), new DecimalFormat("#,##0.00;(#,##0.00)"), new DecimalFormat("#,##0.00;(#,##0.00)"), new DecimalFormat("#,##0;(#,##0)"), new DecimalFormat("$#,##0;($#,##0)"), new DecimalFormat("#,##0.00;(#,##0.00)"), new DecimalFormat("$#,##0.00;($#,##0.00)"), new DecimalFormat("##0.0E0")}; // Type to distinguish between biff7 and biff8 private static class BiffType {}; public static final BiffType biff8 = new BiffType(); public static final BiffType biff7 = new BiffType(); /** * The biff type */ private BiffType biffType; // Type to distinguish between cell and style records private static class XFType { } protected static final XFType cell = new XFType(); protected static final XFType style = new XFType(); /** * Constructs this object from the raw data * * @param t the raw data * @param bt the biff type */ public XFRecord(Record t, WorkbookSettings ws, BiffType bt) { super(t); biffType = bt; byte[] data = getRecord().getData(); fontIndex = IntegerHelper.getInt(data[0], data[1]); formatIndex = IntegerHelper.getInt(data[2], data[3]); date = false; number = false; // Compare against the date formats for (int i = 0; i < dateFormats.length && date == false; i++) { if (formatIndex == dateFormats[i]) { date = true; dateFormat = javaDateFormats[i]; } } // Compare against the number formats for (int i = 0; i < numberFormats.length && number == false; i++) { if (formatIndex == numberFormats[i]) { number = true; DecimalFormat df = (DecimalFormat) javaNumberFormats[i].clone(); DecimalFormatSymbols symbols = new DecimalFormatSymbols(ws.getLocale()); df.setDecimalFormatSymbols(symbols); numberFormat = df; //numberFormat = javaNumberFormats[i]; } } // Initialize the parent format and the type int cellAttributes = IntegerHelper.getInt(data[4], data[5]); parentFormat = (cellAttributes & 0xfff0) >> 4; int formatType = cellAttributes & 0x4; xfFormatType = formatType == 0 ? cell : style; locked = ((cellAttributes & 0x1) != 0); hidden = ((cellAttributes & 0x2) != 0); if (xfFormatType == cell && (parentFormat & 0xfff) == 0xfff) { // Something is screwy with the parent format - set to zero parentFormat = 0; logger.warn("Invalid parent format found - ignoring"); } initialized = false; read = true; formatInfoInitialized = false; copied = false; } /** * A constructor used when creating a writable record * * @param fnt the font * @param form the format */ public XFRecord(FontRecord fnt, DisplayFormat form) { super(Type.XF); initialized = false; locked = true; hidden = false; align = Alignment.GENERAL; valign = VerticalAlignment.BOTTOM; orientation = Orientation.HORIZONTAL; wrap = false; leftBorder = BorderLineStyle.NONE; rightBorder = BorderLineStyle.NONE; topBorder = BorderLineStyle.NONE; bottomBorder = BorderLineStyle.NONE; leftBorderColour = Colour.AUTOMATIC; rightBorderColour = Colour.AUTOMATIC; topBorderColour = Colour.AUTOMATIC; bottomBorderColour = Colour.AUTOMATIC; pattern = Pattern.NONE; backgroundColour = Colour.DEFAULT_BACKGROUND; indentation = 0; shrinkToFit = false; usedAttributes = (byte) (USE_FONT | USE_FORMAT | USE_BACKGROUND | USE_ALIGNMENT | USE_BORDER); // This will be set by the initialize method and the subclass respectively parentFormat = 0; xfFormatType = null; font = fnt; format = form; biffType = biff8; read = false; copied = false; formatInfoInitialized = true; Assert.verify(font != null); Assert.verify(format != null); } /** * Copy constructor. Used for copying writable formats, typically * when duplicating formats to handle merged cells * * @param fmt XFRecord */ protected XFRecord(XFRecord fmt) { super(Type.XF); initialized = false; locked = fmt.locked; hidden = fmt.hidden; align = fmt.align; valign = fmt.valign; orientation = fmt.orientation; wrap = fmt.wrap; leftBorder = fmt.leftBorder; rightBorder = fmt.rightBorder; topBorder = fmt.topBorder; bottomBorder = fmt.bottomBorder; leftBorderColour = fmt.leftBorderColour; rightBorderColour = fmt.rightBorderColour; topBorderColour = fmt.topBorderColour; bottomBorderColour = fmt.bottomBorderColour; pattern = fmt.pattern; xfFormatType = fmt.xfFormatType; indentation = fmt.indentation; shrinkToFit = fmt.shrinkToFit; parentFormat = fmt.parentFormat; backgroundColour = fmt.backgroundColour; // Shallow copy is sufficient for these purposes font = fmt.font; format = fmt.format; fontIndex = fmt.fontIndex; formatIndex = fmt.formatIndex; formatInfoInitialized = fmt.formatInfoInitialized; biffType = biff8; read = false; copied = true; } /** * A public copy constructor which can be used for copy formats between * different sheets. Unlike the the other copy constructor, this * version does a deep copy * * @param cellFormat the format to copy */ protected XFRecord(CellFormat cellFormat) { super(Type.XF); Assert.verify(cellFormat != null); Assert.verify(cellFormat instanceof XFRecord); XFRecord fmt = (XFRecord) cellFormat; if (!fmt.formatInfoInitialized) { fmt.initializeFormatInformation(); } locked = fmt.locked; hidden = fmt.hidden; align = fmt.align; valign = fmt.valign; orientation = fmt.orientation; wrap = fmt.wrap; leftBorder = fmt.leftBorder; rightBorder = fmt.rightBorder; topBorder = fmt.topBorder; bottomBorder = fmt.bottomBorder; leftBorderColour = fmt.leftBorderColour; rightBorderColour = fmt.rightBorderColour; topBorderColour = fmt.topBorderColour; bottomBorderColour = fmt.bottomBorderColour; pattern = fmt.pattern; xfFormatType = fmt.xfFormatType; parentFormat = fmt.parentFormat; indentation = fmt.indentation; shrinkToFit = fmt.shrinkToFit; backgroundColour = fmt.backgroundColour; // Deep copy of the font font = new FontRecord(fmt.getFont()); // Copy the format if (fmt.getFormat() == null) { // format is writable if (fmt.format.isBuiltIn()) { format = fmt.format; } else { // Format is not built in, so do a deep copy format = new FormatRecord((FormatRecord) fmt.format); } } else if (fmt.getFormat() instanceof BuiltInFormat) { // read excel format is built in excelFormat = (BuiltInFormat) fmt.excelFormat; format = (BuiltInFormat) fmt.excelFormat; } else { // read excel format is user defined Assert.verify(fmt.formatInfoInitialized); // in this case FormattingRecords should initialize the excelFormat // field with an instance of FormatRecord Assert.verify(fmt.excelFormat instanceof FormatRecord); // Format is not built in, so do a deep copy FormatRecord fr = new FormatRecord((FormatRecord) fmt.excelFormat); // Set both format fields to be the same object, since // FormatRecord implements all the necessary interfaces excelFormat = fr; format = fr; } biffType = biff8; // The format info should be all OK by virtue of the deep copy formatInfoInitialized = true; // This format was not read in read = false; // Treat this as a new cell record, so set the copied flag to false copied = false; // The font or format indexes need to be set, so set initialized to false initialized = false; } /** * Gets the java date format for this format record * * @return returns the date format */ public DateFormat getDateFormat() { return dateFormat; } /** * Gets the java number format for this format record * * @return returns the number format */ public NumberFormat getNumberFormat() { return numberFormat; } /** * Gets the lookup number of the format record * * @return returns the lookup number of the format record */ public int getFormatRecord() { return formatIndex; } /** * Sees if this format is a date format * * @return TRUE if this refers to a built in date format */ public boolean isDate() { return date; } /** * Sees if this format is a number format * * @return TRUE if this refers to a built in date format */ public boolean isNumber() { return number; } /** * Converts the various fields into binary data. If this object has * been read from an Excel file rather than being requested by a user (ie. * if the read flag is TRUE) then * no processing takes place and the raw data is simply returned. * * @return the raw data for writing */ public byte[] getData() { // Format rationalization process means that we always want to // regenerate the format info - even if the spreadsheet was // read in if (!formatInfoInitialized) { initializeFormatInformation(); } byte[] data = new byte[20]; IntegerHelper.getTwoBytes(fontIndex, data, 0); IntegerHelper.getTwoBytes(formatIndex, data, 2); // Do the cell attributes int cellAttributes = 0; if (getLocked()) { cellAttributes |= 0x01; } if (getHidden()) { cellAttributes |= 0x02; } if (xfFormatType == style) { cellAttributes |= 0x04; parentFormat = 0xffff; } cellAttributes |= (parentFormat << 4); IntegerHelper.getTwoBytes(cellAttributes, data, 4); int alignMask = align.getValue(); if (wrap) { alignMask |= 0x08; } alignMask |= (valign.getValue() << 4); alignMask |= (orientation.getValue() << 8); IntegerHelper.getTwoBytes(alignMask, data, 6); data[9] = (byte) 0x10; // Set the borders int borderMask = leftBorder.getValue(); borderMask |= (rightBorder.getValue() << 4); borderMask |= (topBorder.getValue() << 8); borderMask |= (bottomBorder.getValue() << 12); IntegerHelper.getTwoBytes(borderMask, data, 10); // Set the border palette information if border mask is non zero // Hard code the colours to be black if (borderMask != 0) { byte lc = (byte)leftBorderColour.getValue(); byte rc = (byte)rightBorderColour.getValue(); byte tc = (byte)topBorderColour.getValue(); byte bc = (byte)bottomBorderColour.getValue(); int sideColourMask = (lc & 0x7f) | ((rc & 0x7f) << 7); int topColourMask = (tc & 0x7f) | ((bc & 0x7f) << 7); IntegerHelper.getTwoBytes(sideColourMask, data, 12); IntegerHelper.getTwoBytes(topColourMask, data, 14); } // Set the background pattern int patternVal = pattern.getValue() << 10; IntegerHelper.getTwoBytes(patternVal, data, 16); // Set the colour palette int colourPaletteMask = backgroundColour.getValue(); colourPaletteMask |= (0x40 << 7); IntegerHelper.getTwoBytes(colourPaletteMask, data, 18); // Set the cell options options |= indentation & 0x0f; if (shrinkToFit) { options |= 0x10; } else { options &= 0xef; } data[8] = (byte) options; if (biffType == biff8) { data[9] = (byte) usedAttributes; } return data; } /** * Accessor for the locked flag * * @return TRUE if this XF record locks cells, FALSE otherwise */ protected final boolean getLocked() { return locked; } /** * Accessor for the hidden flag * * @return TRUE if this XF record hides the cell, FALSE otherwise */ protected final boolean getHidden() { return hidden; } /** * Sets whether or not this XF record locks the cell * * @param l the locked flag */ protected final void setXFLocked(boolean l) { locked = l; usedAttributes |= USE_PROTECTION; } /** * Sets the cell options * * @param opt the cell options */ protected final void setXFCellOptions(int opt) { options |= opt; } /** * Sets the horizontal alignment for the data in this cell. * This method should only be called from its writable subclass * CellXFRecord * * @param a the alignment */ protected void setXFAlignment(Alignment a) { Assert.verify(!initialized); align = a; usedAttributes |= USE_ALIGNMENT; } /** * Sets the indentation * * @param i the indentation */ protected void setXFIndentation(int i) { Assert.verify(!initialized); indentation = i; usedAttributes |= USE_ALIGNMENT; } /** * Sets the shrink to fit flag * * @param s the shrink to fit flag */ protected void setXFShrinkToFit(boolean s) { Assert.verify(!initialized); shrinkToFit = s; usedAttributes |= USE_ALIGNMENT; } /** * Gets the horizontal cell alignment * * @return the alignment */ public Alignment getAlignment() { if (!formatInfoInitialized) { initializeFormatInformation(); } return align; } /** * Gets the indentation * * @return the indentation */ public int getIndentation() { if (!formatInfoInitialized) { initializeFormatInformation(); } return indentation; } /** * Gets the shrink to fit flag * * @return TRUE if this format is shrink to fit, FALSE otherise */ public boolean isShrinkToFit() { if (!formatInfoInitialized) { initializeFormatInformation(); } return shrinkToFit; } /** * Accessor for whether a particular cell is locked * * @return TRUE if this cell is locked, FALSE otherwise */ public boolean isLocked() { if (!formatInfoInitialized) { initializeFormatInformation(); } return locked; } /** * Gets the vertical cell alignment * * @return the alignment */ public VerticalAlignment getVerticalAlignment() { if (!formatInfoInitialized) { initializeFormatInformation(); } return valign; } /** * Gets the orientation * * @return the orientation */ public Orientation getOrientation() { if (!formatInfoInitialized) { initializeFormatInformation(); } return orientation; } /** * Sets the horizontal alignment for the data in this cell. * This method should only be called from its writable subclass * CellXFRecord * * @param c the background colour * @param p the background pattern */ protected void setXFBackground(Colour c, Pattern p) { Assert.verify(!initialized); backgroundColour = c; pattern = p; usedAttributes |= USE_BACKGROUND; } /** * Gets the background colour used by this cell * * @return the foreground colour */ public Colour getBackgroundColour() { if (!formatInfoInitialized) { initializeFormatInformation(); } return backgroundColour; } /** * Gets the pattern used by this cell format * * @return the background pattern */ public Pattern getPattern() { if (!formatInfoInitialized) { initializeFormatInformation(); } return pattern; } /** * Sets the vertical alignment for the data in this cell * This method should only be called from its writable subclass * CellXFRecord * * @param va the vertical alignment */ protected void setXFVerticalAlignment(VerticalAlignment va) { Assert.verify(!initialized); valign = va; usedAttributes |= USE_ALIGNMENT; } /** * Sets the vertical alignment for the data in this cell * This method should only be called from its writable subclass * CellXFRecord * * @param o the orientation */ protected void setXFOrientation(Orientation o) { Assert.verify(!initialized); orientation = o; usedAttributes |= USE_ALIGNMENT; } /** * Sets whether the data in this cell is wrapped * This method should only be called from its writable subclass * CellXFRecord * * @param w the wrap flag */ protected void setXFWrap(boolean w) { Assert.verify(!initialized); wrap = w; usedAttributes |= USE_ALIGNMENT; } /** * Gets whether or not the contents of this cell are wrapped * * @return TRUE if this cell's contents are wrapped, FALSE otherwise */ public boolean getWrap() { if (!formatInfoInitialized) { initializeFormatInformation(); } return wrap; } /** * Sets the border for this cell * This method should only be called from its writable subclass * CellXFRecord * * @param b the border * @param ls the border line style */ protected void setXFBorder(Border b, BorderLineStyle ls, Colour c) { Assert.verify(!initialized); if (c == Colour.BLACK || c == Colour.UNKNOWN) { c = Colour.PALETTE_BLACK; } if (b == Border.LEFT) { leftBorder = ls; leftBorderColour = c; } else if (b == Border.RIGHT) { rightBorder = ls; rightBorderColour = c; } else if (b == Border.TOP) { topBorder = ls; topBorderColour = c; } else if (b == Border.BOTTOM) { bottomBorder = ls; bottomBorderColour = c; } usedAttributes |= USE_BORDER; return; } /** * Gets the line style for the given cell border * If a border type of ALL or NONE is specified, then a line style of * NONE is returned * * @param border the cell border we are interested in * @return the line style of the specified border */ public BorderLineStyle getBorder(Border border) { return getBorderLine(border); } /** * Gets the line style for the given cell border * If a border type of ALL or NONE is specified, then a line style of * NONE is returned * * @param border the cell border we are interested in * @return the line style of the specified border */ public BorderLineStyle getBorderLine(Border border) { // Don't bother with the short cut records if (border == Border.NONE || border == Border.ALL) { return BorderLineStyle.NONE; } if (!formatInfoInitialized) { initializeFormatInformation(); } if (border == Border.LEFT) { return leftBorder; } else if (border == Border.RIGHT) { return rightBorder; } else if (border == Border.TOP) { return topBorder; } else if (border == Border.BOTTOM) { return bottomBorder; } return BorderLineStyle.NONE; } /** * Gets the line style for the given cell border * If a border type of ALL or NONE is specified, then a line style of * NONE is returned * * @param border the cell border we are interested in * @return the line style of the specified border */ public Colour getBorderColour(Border border) { // Don't bother with the short cut records if (border == Border.NONE || border == Border.ALL) { return Colour.PALETTE_BLACK; } if (!formatInfoInitialized) { initializeFormatInformation(); } if (border == Border.LEFT) { return leftBorderColour; } else if (border == Border.RIGHT) { return rightBorderColour; } else if (border == Border.TOP) { return topBorderColour; } else if (border == Border.BOTTOM) { return bottomBorderColour; } return Colour.BLACK; } /** * Determines if this cell format has any borders at all. Used to * set the new borders when merging a group of cells * * @return TRUE if this cell has any borders, FALSE otherwise */ public final boolean hasBorders() { if (!formatInfoInitialized) { initializeFormatInformation(); } if (leftBorder == BorderLineStyle.NONE && rightBorder == BorderLineStyle.NONE && topBorder == BorderLineStyle.NONE && bottomBorder == BorderLineStyle.NONE) { return false; } return true; } /** * If this cell has not been read in from an existing Excel sheet, * then initializes this record with the XF index passed in. Calls * initialized on the font and format record * * @param pos the xf index to initialize this record with * @param fr the containing formatting records * @param fonts the container for the fonts * @exception NumFormatRecordsException */ public final void initialize(int pos, FormattingRecords fr, Fonts fonts) throws NumFormatRecordsException { xfIndex = pos; formattingRecords = fr; // If this file has been read in or copied, // the font and format indexes will // already be initialized, so just set the initialized flag and // return if (read || copied) { initialized = true; return; } if (!font.isInitialized()) { fonts.addFont(font); } if (!format.isInitialized()) { fr.addFormat(format); } fontIndex = font.getFontIndex(); formatIndex = format.getFormatIndex(); initialized = true; } /** * Resets the initialize flag. This is called by the constructor of * WritableWorkbookImpl to reset the statically declared fonts */ public final void uninitialize() { // As the default formats are cloned internally, the initialized // flag should never be anything other than false if (initialized == true) { logger.warn("A default format has been initialized"); } initialized = false; } /** * Sets the XF index. Called when rationalizing the XF records * immediately prior to writing * * @param xfi the new xf index */ final void setXFIndex(int xfi) { xfIndex = xfi; } /** * Accessor for the XF index * * @return the XF index for this cell */ public final int getXFIndex() { return xfIndex; } /** * Accessor to see if this format is initialized * * @return TRUE if this format is initialized, FALSE otherwise */ public final boolean isInitialized() { return initialized; } /** * Accessor to see if this format was read in. Used when checking merged * cells * * @return TRUE if this XF record was read in, FALSE if it was generated by * the user API */ public final boolean isRead() { return read; } /** * Gets the format used by this format * * @return the format */ public Format getFormat() { if (!formatInfoInitialized) { initializeFormatInformation(); } return excelFormat; } /** * Gets the font used by this format * * @return the font */ public Font getFont() { if (!formatInfoInitialized) { initializeFormatInformation(); } return font; } /** * Initializes the internal format information from the data read in */ private void initializeFormatInformation() { // Initialize the cell format string if (formatIndex < BuiltInFormat.builtIns.length && BuiltInFormat.builtIns[formatIndex] != null) { excelFormat = BuiltInFormat.builtIns[formatIndex]; } else { excelFormat = formattingRecords.getFormatRecord(formatIndex); } // Initialize the font font = formattingRecords.getFonts().getFont(fontIndex); // Initialize the cell format data from the binary record byte[] data = getRecord().getData(); // Get the parent record int cellAttributes = IntegerHelper.getInt(data[4], data[5]); parentFormat = (cellAttributes & 0xfff0) >> 4; int formatType = cellAttributes & 0x4; xfFormatType = formatType == 0 ? cell : style; locked = ((cellAttributes & 0x1) != 0); hidden = ((cellAttributes & 0x2) != 0); if (xfFormatType == cell && (parentFormat & 0xfff) == 0xfff) { // Something is screwy with the parent format - set to zero parentFormat = 0; logger.warn("Invalid parent format found - ignoring"); } int alignMask = IntegerHelper.getInt(data[6], data[7]); // Get the wrap if ((alignMask & 0x08) != 0) { wrap = true; } // Get the horizontal alignment align = Alignment.getAlignment(alignMask & 0x7); // Get the vertical alignment valign = VerticalAlignment.getAlignment((alignMask >> 4) & 0x7); // Get the orientation orientation = Orientation.getOrientation((alignMask >> 8) & 0xff); int attr = IntegerHelper.getInt(data[8], data[9]); // Get the indentation indentation = attr & 0x0F; // Get the shrink to fit flag shrinkToFit = (attr & 0x10) != 0; // Get the used attribute if (biffType == biff8) { usedAttributes = data[9]; } // Get the borders int borderMask = IntegerHelper.getInt(data[10], data[11]); leftBorder = BorderLineStyle.getStyle(borderMask & 0x7); rightBorder = BorderLineStyle.getStyle((borderMask >> 4) & 0x7); topBorder = BorderLineStyle.getStyle((borderMask >> 8) & 0x7); bottomBorder = BorderLineStyle.getStyle((borderMask >> 12) & 0x7); int borderColourMask = IntegerHelper.getInt(data[12], data[13]); leftBorderColour = Colour.getInternalColour(borderColourMask & 0x7f); rightBorderColour = Colour.getInternalColour ((borderColourMask & 0x3f80) >> 7); borderColourMask = IntegerHelper.getInt(data[14], data[15]); topBorderColour = Colour.getInternalColour(borderColourMask & 0x7f); bottomBorderColour = Colour.getInternalColour ((borderColourMask & 0x3f80) >> 7); if (biffType == biff8) { // Get the background pattern. This is the six most significant bits int patternVal = IntegerHelper.getInt(data[16], data[17]); patternVal = patternVal & 0xfc00; patternVal = patternVal >> 10; pattern = Pattern.getPattern(patternVal); // Get the background colour int colourPaletteMask = IntegerHelper.getInt(data[18], data[19]); backgroundColour = Colour.getInternalColour(colourPaletteMask & 0x3f); if (backgroundColour == Colour.UNKNOWN || backgroundColour == Colour.DEFAULT_BACKGROUND1) { backgroundColour = Colour.DEFAULT_BACKGROUND; } } else { pattern = Pattern.NONE; backgroundColour = Colour.DEFAULT_BACKGROUND; } // Set the lazy initialization flag formatInfoInitialized = true; } /** * Standard hash code implementation * @return the hash code */ public int hashCode() { // Must have its formats info initialized in order to compute the hash code if (!formatInfoInitialized) { initializeFormatInformation(); } int hashValue = 17; int oddPrimeNumber = 37; // The boolean fields hashValue = oddPrimeNumber*hashValue + (hidden ? 1:0); hashValue = oddPrimeNumber*hashValue + (locked ? 1:0); hashValue = oddPrimeNumber*hashValue + (wrap ? 1:0); hashValue = oddPrimeNumber*hashValue + (shrinkToFit ? 1:0); // The enumerations if (xfFormatType == cell) { hashValue = oddPrimeNumber*hashValue + 1; } else if (xfFormatType == style) { hashValue = oddPrimeNumber*hashValue + 2; } hashValue = oddPrimeNumber*hashValue + (align.getValue() + 1); hashValue = oddPrimeNumber*hashValue + (valign.getValue() + 1); hashValue = oddPrimeNumber*hashValue + (orientation.getValue()); hashValue ^= leftBorder.getDescription().hashCode(); hashValue ^= rightBorder.getDescription().hashCode(); hashValue ^= topBorder.getDescription().hashCode(); hashValue ^= bottomBorder.getDescription().hashCode(); hashValue = oddPrimeNumber*hashValue + (leftBorderColour.getValue()); hashValue = oddPrimeNumber*hashValue + (rightBorderColour.getValue()); hashValue = oddPrimeNumber*hashValue + (topBorderColour.getValue()); hashValue = oddPrimeNumber*hashValue + (bottomBorderColour.getValue()); hashValue = oddPrimeNumber*hashValue + (backgroundColour.getValue()); hashValue = oddPrimeNumber*hashValue + (pattern.getValue() + 1); // The integer fields hashValue = oddPrimeNumber*hashValue + usedAttributes; hashValue = oddPrimeNumber*hashValue + parentFormat; hashValue = oddPrimeNumber*hashValue + fontIndex; hashValue = oddPrimeNumber*hashValue + formatIndex; hashValue = oddPrimeNumber*hashValue + indentation; return hashValue; } /** * Equals method. This is called when comparing writable formats * in order to prevent duplicate formats being added to the workbook * * @param o object to compare * @return TRUE if the objects are equal, FALSE otherwise */ public boolean equals(Object o) { if (o == this) { return true; } if (!(o instanceof XFRecord)) { return false; } XFRecord xfr = (XFRecord) o; // Both records must be writable and have their format info initialized if (!formatInfoInitialized) { initializeFormatInformation(); } if (!xfr.formatInfoInitialized) { xfr.initializeFormatInformation(); } if (xfFormatType != xfr.xfFormatType || parentFormat != xfr.parentFormat || locked != xfr.locked || hidden != xfr.hidden || usedAttributes != xfr.usedAttributes) { return false; } if (align != xfr.align || valign != xfr.valign || orientation != xfr.orientation || wrap != xfr.wrap || shrinkToFit != xfr.shrinkToFit || indentation != xfr.indentation) { return false; } if (leftBorder != xfr.leftBorder || rightBorder != xfr.rightBorder || topBorder != xfr.topBorder || bottomBorder != xfr.bottomBorder) { return false; } if (leftBorderColour != xfr.leftBorderColour || rightBorderColour != xfr.rightBorderColour || topBorderColour != xfr.topBorderColour || bottomBorderColour != xfr.bottomBorderColour) { return false; } if (backgroundColour != xfr.backgroundColour || pattern != xfr.pattern) { return false; } if (initialized && xfr.initialized) { // Both formats are initialized, so it is sufficient to just do // shallow equals on font, format objects, // since we are testing for the presence of clones anwyay // Use indices rather than objects because of the rationalization // process (which does not set the object on an XFRecord) if (fontIndex != xfr.fontIndex || formatIndex != xfr.formatIndex) { return false; } } else { // Perform a deep compare of fonts and formats if (!font.equals(xfr.font) || !format.equals(xfr.format)) { return false; } } return true; } /** * Sets the format index. This is called during the rationalization process * when some of the duplicate number formats have been removed * @param newindex the new format index */ void setFormatIndex(int newindex) { formatIndex = newindex; } /** * Accessor for the font index. Called by the FormattingRecords objects * during the rationalization process * @return the font index */ public int getFontIndex() { return fontIndex; } /** * Sets the font index. This is called during the rationalization process * when some of the duplicate fonts have been removed * @param newindex the new index */ void setFontIndex(int newindex) { fontIndex = newindex; } /** * Sets the format type and parent format from the writable subclass * @param t the xf type * @param pf the parent format */ protected void setXFDetails(XFType t, int pf) { xfFormatType = t; parentFormat = pf; } /** * Changes the appropriate indexes during the rationalization process * @param xfMapping the xf index re-mappings */ void rationalize(IndexMapping xfMapping) { xfIndex = xfMapping.getNewIndex(xfIndex); if (xfFormatType == cell) { parentFormat = xfMapping.getNewIndex(parentFormat); } } /** * Sets the font object with a workbook specific clone. Called from * the CellValue object when the font has been identified as a statically * shared font * Also called to superimpose a HyperlinkFont on an existing label cell */ public void setFont(FontRecord f) { // This style cannot be initialized, otherwise it would mean it would // have been initialized with shared font // However, sometimes (when setting a row or column format) an initialized // XFRecord may have its font overridden by the column/row font = f; } } jexcelapi/src/jxl/biff/IntegerHelper.java0000750000175000017500000000727211207000612020603 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; /** * Converts excel byte representations into integers */ public final class IntegerHelper { /** * Private constructor disables the instantiation of this object */ private IntegerHelper() { } /** * Gets an int from two bytes * * @param b2 the second byte * @param b1 the first byte * @return The integer value */ public static int getInt(byte b1, byte b2) { int i1 = b1 & 0xff; int i2 = b2 & 0xff; int val = i2 << 8 | i1; return val; } /** * Gets an short from two bytes * * @param b2 the second byte * @param b1 the first byte * @return The short value */ public static short getShort(byte b1, byte b2) { short i1 = (short) (b1 & 0xff); short i2 = (short) (b2 & 0xff); short val = (short) (i2 << 8 | i1); return val; } /** * Gets an int from four bytes, doing all the necessary swapping * * @param b1 a byte * @param b2 a byte * @param b3 a byte * @param b4 a byte * @return the integer value represented by the four bytes */ public static int getInt(byte b1, byte b2, byte b3, byte b4) { int i1 = getInt(b1, b2); int i2 = getInt(b3, b4); int val = i2 << 16 | i1; return val; } /** * Gets a two byte array from an integer * * @param i the integer * @return the two bytes */ public static byte[] getTwoBytes(int i) { byte[] bytes = new byte[2]; bytes[0] = (byte) (i & 0xff); bytes[1] = (byte) ((i & 0xff00) >> 8); return bytes; } /** * Gets a four byte array from an integer * * @param i the integer * @return a four byte array */ public static byte[] getFourBytes(int i) { byte[] bytes = new byte[4]; int i1 = i & 0xffff; int i2 = (i & 0xffff0000) >> 16; getTwoBytes(i1, bytes, 0); getTwoBytes(i2, bytes, 2); return bytes; } /** * Converts an integer into two bytes, and places it in the array at the * specified position * * @param target the array to place the byte data into * @param pos the position at which to place the data * @param i the integer value to convert */ public static void getTwoBytes(int i, byte[] target, int pos) { target[pos] = (byte) (i & 0xff); target[pos + 1] = (byte) ((i & 0xff00) >> 8); } /** * Converts an integer into four bytes, and places it in the array at the * specified position * * @param target the array which is to contain the converted data * @param pos the position in the array in which to place the data * @param i the integer to convert */ public static void getFourBytes(int i, byte[] target, int pos) { byte[] bytes = getFourBytes(i); target[pos] = bytes[0]; target[pos + 1] = bytes[1]; target[pos + 2] = bytes[2]; target[pos + 3] = bytes[3]; } } jexcelapi/src/jxl/biff/ConditionalFormat.java0000750000175000017500000000607411207000612021461 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2007 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl.biff; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import jxl.WorkbookSettings; import jxl.biff.formula.ExternalSheet; import jxl.write.biff.File; /** * Class containing the CONDFMT and CF records for conditionally formatting * a cell */ public class ConditionalFormat { /** * The range of the format */ private ConditionalFormatRangeRecord range; /** * The format conditions */ private ArrayList conditions; /** * Constructor */ public ConditionalFormat(ConditionalFormatRangeRecord cfrr) { range = cfrr; conditions = new ArrayList(); } /** * Adds a condition * * @param cond the condition */ public void addCondition(ConditionalFormatRecord cond) { conditions.add(cond); } /** * Inserts a blank column into this spreadsheet. If the column is out of * range of the columns in the sheet, then no action is taken * * @param col the column to insert */ public void insertColumn(int col) { range.insertColumn(col); } /** * Removes a column from this spreadsheet. If the column is out of range * of the columns in the sheet, then no action is taken * * @param col the column to remove */ public void removeColumn(int col) { range.removeColumn(col); } /** * Removes a row from this spreadsheet. If the row is out of * range of the columns in the sheet, then no action is taken * * @param row the row to remove */ public void removeRow(int row) { range.removeRow(row); } /** * Inserts a blank row into this spreadsheet. If the row is out of range * of the rows in the sheet, then no action is taken * * @param row the row to insert */ public void insertRow(int row) { range.insertRow(row); } /** * Writes out the data validation * * @exception IOException * @param outputFile the output file */ public void write(File outputFile) throws IOException { outputFile.write(range); for (Iterator i = conditions.iterator(); i.hasNext();) { ConditionalFormatRecord cfr = (ConditionalFormatRecord) i.next(); outputFile.write(cfr); } } } jexcelapi/src/jxl/Cell.java0000750000175000017500000000535311207000610016013 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl; import jxl.format.CellFormat; /** * Represents an individual Cell within a Sheet. May be queried for its * type and its content */ public interface Cell { /** * Returns the row number of this cell * * @return the row number of this cell */ public int getRow(); /** * Returns the column number of this cell * * @return the column number of this cell */ public int getColumn(); /** * Returns the content type of this cell * * @return the content type for this cell */ public CellType getType(); /** * Indicates whether or not this cell is hidden, by virtue of either * the entire row or column being collapsed * * @return TRUE if this cell is hidden, FALSE otherwise */ public boolean isHidden(); /** * Quick and dirty function to return the contents of this cell as a string. * For more complex manipulation of the contents, it is necessary to cast * this interface to correct subinterface * * @return the contents of this cell as a string */ public String getContents(); /** * Gets the cell format which applies to this cell * Note that for cell with a cell type of EMPTY, which has no formatting * information, this method will return null. Some empty cells (eg. on * template spreadsheets) may have a cell type of EMPTY, but will * actually contain formatting information * * @return the cell format applied to this cell, or NULL if this is an * empty cell */ public CellFormat getCellFormat(); /** * Gets any special cell features, such as comments (notes) or cell * validation present for this cell * * @return the cell features, or NULL if this cell has no special features */ public CellFeatures getCellFeatures(); } jexcelapi/src/jxl/NumberCell.java0000750000175000017500000000264011207000610017160 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl; import java.text.NumberFormat; /** * A cell which contains a numerical value */ public interface NumberCell extends Cell { /** * Gets the double contents for this cell. * * @return the cell contents */ public double getValue(); /** * Gets the NumberFormat used to format this cell. This is the java * equivalent of the Excel format * * @return the NumberFormat used to format the cell */ public NumberFormat getNumberFormat(); } jexcelapi/src/jxl/CellFormat.java0000750000175000017500000000216311207000610017160 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl; /** * Interface for cell formats - used for typing information * * @deprecated Repackaged as jxl.format.CellFormat */ public interface CellFormat extends jxl.format.CellFormat { } jexcelapi/src/jxl/SheetSettings.java0000750000175000017500000007442311207000610017731 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl; import jxl.common.Assert; import jxl.format.PageOrientation; import jxl.format.PaperSize; import jxl.biff.SheetRangeImpl; import jxl.Range; import jxl.format.PageOrder; /** * This is a bean which client applications may use to get/set various * properties which are associated with a particular worksheet, such * as headers and footers, page orientation etc. */ public final class SheetSettings { /** * The page orientation */ private PageOrientation orientation; /** * The page order */ private PageOrder pageOrder; /** * The paper size for printing */ private PaperSize paperSize; /** * Indicates whether or not this sheet is protected */ private boolean sheetProtected; /** * Indicates whether or not this sheet is hidden */ private boolean hidden; /** * Indicates whether or not this sheet is selected */ private boolean selected; /** * The header */ private HeaderFooter header; /** * The margin allocated for any page headers, in inches */ private double headerMargin; /** * The footer */ private HeaderFooter footer; /** * The margin allocated for any page footers, in inches */ private double footerMargin; /** * The scale factor used when printing */ private int scaleFactor; /** * The zoom factor used when viewing. Note the difference between * this and the scaleFactor which is used when printing */ private int zoomFactor; /** * The page number at which to commence printing */ private int pageStart; /** * The number of pages into which this excel sheet is squeezed widthwise */ private int fitWidth; /** * The number of pages into which this excel sheet is squeezed heightwise */ private int fitHeight; /** * The horizontal print resolution */ private int horizontalPrintResolution; /** * The vertical print resolution */ private int verticalPrintResolution; /** * The margin from the left hand side of the paper in inches */ private double leftMargin; /** * The margin from the right hand side of the paper in inches */ private double rightMargin; /** * The margin from the top of the paper in inches */ private double topMargin; /** * The margin from the bottom of the paper in inches */ private double bottomMargin; /** * Indicates whether to fit the print to the pages or scale the output * This field is manipulated indirectly by virtue of the setFitWidth/Height * methods */ private boolean fitToPages; /** * Indicates whether grid lines should be displayed */ private boolean showGridLines; /** * Indicates whether grid lines should be printed */ private boolean printGridLines; /** * Indicates whether sheet headings should be printed */ private boolean printHeaders; /** * Indicates the view mode */ private boolean pageBreakPreviewMode; /** * Indicates whether the sheet should display zero values */ private boolean displayZeroValues; /** * The password for protected sheets */ private String password; /** * The password hashcode - used when copying sheets */ private int passwordHash; /** * The default column width, in characters */ private int defaultColumnWidth; /** * The default row height, in 1/20th of a point */ private int defaultRowHeight; /** * The horizontal freeze pane */ private int horizontalFreeze; /** * The vertical freeze position */ private int verticalFreeze; /** * Vertical centre flag */ private boolean verticalCentre; /** * Horizontal centre flag */ private boolean horizontalCentre; /** * The number of copies to print */ private int copies; /** * Automatic formula calculation */ private boolean automaticFormulaCalculation; /** * Recalculate the formulas before save */ private boolean recalculateFormulasBeforeSave; /** * The magnification factor for use during page break preview mode (in * percent) */ private int pageBreakPreviewMagnification; /** * The magnification factor for use during normal mode (in percent) */ private int normalMagnification; /** * The print area */ private Range printArea; /** * The print row titles */ private Range printTitlesRow; /** * The print column titles */ private Range printTitlesCol; /** * A handle to the sheet - used internally for ranges */ private Sheet sheet; // *** // The defaults // ** private static final PageOrientation DEFAULT_ORIENTATION = PageOrientation.PORTRAIT; private static final PageOrder DEFAULT_ORDER = PageOrder.RIGHT_THEN_DOWN; private static final PaperSize DEFAULT_PAPER_SIZE = PaperSize.A4; private static final double DEFAULT_HEADER_MARGIN = 0.5; private static final double DEFAULT_FOOTER_MARGIN = 0.5; private static final int DEFAULT_PRINT_RESOLUTION = 0x12c; private static final double DEFAULT_WIDTH_MARGIN = 0.75; private static final double DEFAULT_HEIGHT_MARGIN = 1; private static final int DEFAULT_DEFAULT_COLUMN_WIDTH = 8; private static final int DEFAULT_ZOOM_FACTOR = 100; private static final int DEFAULT_NORMAL_MAGNIFICATION = 100; private static final int DEFAULT_PAGE_BREAK_PREVIEW_MAGNIFICATION = 60; // The publicly accessible values /** * The default value for the default row height */ public static final int DEFAULT_DEFAULT_ROW_HEIGHT = 0xff; /** * Default constructor */ public SheetSettings(Sheet s) { sheet = s; // for internal use, when accessing ranges orientation = DEFAULT_ORIENTATION; pageOrder = DEFAULT_ORDER; paperSize = DEFAULT_PAPER_SIZE; sheetProtected = false; hidden = false; selected = false; headerMargin = DEFAULT_HEADER_MARGIN; footerMargin = DEFAULT_FOOTER_MARGIN; horizontalPrintResolution = DEFAULT_PRINT_RESOLUTION; verticalPrintResolution = DEFAULT_PRINT_RESOLUTION; leftMargin = DEFAULT_WIDTH_MARGIN; rightMargin = DEFAULT_WIDTH_MARGIN; topMargin = DEFAULT_HEIGHT_MARGIN; bottomMargin = DEFAULT_HEIGHT_MARGIN; fitToPages = false; showGridLines = true; printGridLines = false; printHeaders = false; pageBreakPreviewMode = false; displayZeroValues = true; defaultColumnWidth = DEFAULT_DEFAULT_COLUMN_WIDTH; defaultRowHeight = DEFAULT_DEFAULT_ROW_HEIGHT; zoomFactor = DEFAULT_ZOOM_FACTOR; pageBreakPreviewMagnification = DEFAULT_PAGE_BREAK_PREVIEW_MAGNIFICATION; normalMagnification = DEFAULT_NORMAL_MAGNIFICATION; horizontalFreeze = 0; verticalFreeze = 0; copies = 1; header = new HeaderFooter(); footer = new HeaderFooter(); automaticFormulaCalculation = true; recalculateFormulasBeforeSave = true; } /** * Copy constructor. Called when copying sheets * @param copy the settings to copy */ public SheetSettings(SheetSettings copy, Sheet s) { Assert.verify(copy != null); sheet = s; // for internal use when accessing ranges orientation = copy.orientation; pageOrder = copy.pageOrder; paperSize = copy.paperSize; sheetProtected = copy.sheetProtected; hidden = copy.hidden; selected = false; // don't copy the selected flag headerMargin = copy.headerMargin; footerMargin = copy.footerMargin; scaleFactor = copy.scaleFactor; pageStart = copy.pageStart; fitWidth = copy.fitWidth; fitHeight = copy.fitHeight; horizontalPrintResolution = copy.horizontalPrintResolution; verticalPrintResolution = copy.verticalPrintResolution; leftMargin = copy.leftMargin; rightMargin = copy.rightMargin; topMargin = copy.topMargin; bottomMargin = copy.bottomMargin; fitToPages = copy.fitToPages; password = copy.password; passwordHash = copy.passwordHash; defaultColumnWidth = copy.defaultColumnWidth; defaultRowHeight = copy.defaultRowHeight; zoomFactor = copy.zoomFactor; pageBreakPreviewMagnification = copy.pageBreakPreviewMagnification; normalMagnification = copy.normalMagnification; showGridLines = copy.showGridLines; displayZeroValues = copy.displayZeroValues; pageBreakPreviewMode = copy.pageBreakPreviewMode; horizontalFreeze = copy.horizontalFreeze; verticalFreeze = copy.verticalFreeze; horizontalCentre = copy.horizontalCentre; verticalCentre = copy.verticalCentre; copies = copy.copies; header = new HeaderFooter(copy.header); footer = new HeaderFooter(copy.footer); automaticFormulaCalculation = copy.automaticFormulaCalculation; recalculateFormulasBeforeSave = copy.recalculateFormulasBeforeSave; if (copy.printArea != null) { printArea = new SheetRangeImpl (sheet, copy.getPrintArea().getTopLeft().getColumn(), copy.getPrintArea().getTopLeft().getRow(), copy.getPrintArea().getBottomRight().getColumn(), copy.getPrintArea().getBottomRight().getRow()); } if (copy.printTitlesRow != null) { printTitlesRow = new SheetRangeImpl (sheet, copy.getPrintTitlesRow().getTopLeft().getColumn(), copy.getPrintTitlesRow().getTopLeft().getRow(), copy.getPrintTitlesRow().getBottomRight().getColumn(), copy.getPrintTitlesRow().getBottomRight().getRow()); } if (copy.printTitlesCol != null) { printTitlesCol = new SheetRangeImpl (sheet, copy.getPrintTitlesCol().getTopLeft().getColumn(), copy.getPrintTitlesCol().getTopLeft().getRow(), copy.getPrintTitlesCol().getBottomRight().getColumn(), copy.getPrintTitlesCol().getBottomRight().getRow()); } } /** * Sets the paper orientation for printing this sheet * * @param po the orientation */ public void setOrientation(PageOrientation po) { orientation = po; } /** * Accessor for the orientation * * @return the orientation */ public PageOrientation getOrientation() { return orientation; } /** * Accessor for the order * * @return */ public PageOrder getPageOrder() { return pageOrder; } /** * Sets the page order for printing this sheet * * @param order */ public void setPageOrder(PageOrder order) { this.pageOrder = order; } /** * Sets the paper size to be used when printing this sheet * * @param ps the paper size */ public void setPaperSize(PaperSize ps) { paperSize = ps; } /** * Accessor for the paper size * * @return the paper size */ public PaperSize getPaperSize() { return paperSize; } /** * Queries whether this sheet is protected (ie. read only) * * @return TRUE if this sheet is read only, FALSE otherwise */ public boolean isProtected() { return sheetProtected; } /** * Sets the protected (ie. read only) status of this sheet * * @param p the protected status */ public void setProtected(boolean p) { sheetProtected = p; } /** * Sets the margin for any page headers * * @param d the margin in inches */ public void setHeaderMargin(double d) { headerMargin = d; } /** * Accessor for the header margin * * @return the header margin */ public double getHeaderMargin() { return headerMargin; } /** * Sets the margin for any page footer * * @param d the footer margin in inches */ public void setFooterMargin(double d) { footerMargin = d; } /** * Accessor for the footer margin * * @return the footer margin */ public double getFooterMargin() { return footerMargin; } /** * Sets the hidden status of this worksheet * * @param h the hidden flag */ public void setHidden(boolean h) { hidden = h; } /** * Accessor for the hidden nature of this sheet * * @return TRUE if this sheet is hidden, FALSE otherwise */ public boolean isHidden() { return hidden; } /** * Sets this sheet to be when it is opened in excel * * @deprecated use overloaded version which takes a boolean */ public void setSelected() { setSelected(true); } /** * Sets this sheet to be when it is opened in excel * * @param s sets whether this sheet is selected or not */ public void setSelected(boolean s) { selected = s; } /** * Accessor for the selected nature of the sheet * * @return TRUE if this sheet is selected, FALSE otherwise */ public boolean isSelected() { return selected; } /** * Sets the scale factor for this sheet to be used when printing. The * parameter is a percentage, therefore setting a scale factor of 100 will * print at normal size, 50 half size, 200 double size etc * * @param sf the scale factor as a percentage */ public void setScaleFactor(int sf) { scaleFactor = sf; fitToPages = false; } /** * Accessor for the scale factor * * @return the scale factor */ public int getScaleFactor() { return scaleFactor; } /** * Sets the page number at which to commence printing * * @param ps the page start number */ public void setPageStart(int ps) { pageStart = ps; } /** * Accessor for the page start * * @return the page start */ public int getPageStart() { return pageStart; } /** * Sets the number of pages widthwise which this sheet should be * printed into * * @param fw the number of pages */ public void setFitWidth(int fw) { fitWidth = fw; fitToPages = true; } /** * Accessor for the fit width * * @return the number of pages this sheet will be printed into widthwise */ public int getFitWidth() { return fitWidth; } /** * Sets the number of pages vertically that this sheet will be printed into * * @param fh the number of pages this sheet will be printed into heightwise */ public void setFitHeight(int fh) { fitHeight = fh; fitToPages = true; } /** * Accessor for the fit height * * @return the number of pages this sheet will be printed into heightwise */ public int getFitHeight() { return fitHeight; } /** * Sets the horizontal print resolution * * @param hpw the print resolution */ public void setHorizontalPrintResolution(int hpw) { horizontalPrintResolution = hpw; } /** * Accessor for the horizontal print resolution * * @return the horizontal print resolution */ public int getHorizontalPrintResolution() { return horizontalPrintResolution; } /** * Sets the vertical print reslution * * @param vpw the vertical print resolution */ public void setVerticalPrintResolution(int vpw) { verticalPrintResolution = vpw; } /** * Accessor for the vertical print resolution * * @return the vertical print resolution */ public int getVerticalPrintResolution() { return verticalPrintResolution; } /** * Sets the right margin * * @param m the right margin in inches */ public void setRightMargin(double m) { rightMargin = m; } /** * Accessor for the right margin * * @return the right margin in inches */ public double getRightMargin() { return rightMargin; } /** * Sets the left margin * * @param m the left margin in inches */ public void setLeftMargin(double m) { leftMargin = m; } /** * Accessor for the left margin * * @return the left margin in inches */ public double getLeftMargin() { return leftMargin; } /** * Sets the top margin * * @param m the top margin in inches */ public void setTopMargin(double m) { topMargin = m; } /** * Accessor for the top margin * * @return the top margin in inches */ public double getTopMargin() { return topMargin; } /** * Sets the bottom margin * * @param m the bottom margin in inches */ public void setBottomMargin(double m) { bottomMargin = m; } /** * Accessor for the bottom margin * * @return the bottom margin in inches */ public double getBottomMargin() { return bottomMargin; } /** * Gets the default margin width * * @return the default margin width */ public double getDefaultWidthMargin() { return DEFAULT_WIDTH_MARGIN; } /** * Gets the default margin height * * @return the default margin height */ public double getDefaultHeightMargin() { return DEFAULT_HEIGHT_MARGIN; } /** * Accessor for the fit width print flag * @return TRUE if the print is to fit to pages, false otherwise */ public boolean getFitToPages() { return fitToPages; } /** * Accessor for the fit to pages flag * @param b TRUE to fit to pages, FALSE to use a scale factor */ public void setFitToPages(boolean b) { fitToPages = b; } /** * Accessor for the password * * @return the password to unlock this sheet, or NULL if not protected */ public String getPassword() { return password; } /** * Sets the password for this sheet * * @param s the password */ public void setPassword(String s) { password = s; } /** * Accessor for the password hash - used only when copying sheets * * @return passwordHash */ public int getPasswordHash() { return passwordHash; } /** * Accessor for the password hash - used only when copying sheets * * @param ph the password hash */ public void setPasswordHash(int ph) { passwordHash = ph; } /** * Accessor for the default column width * * @return the default column width, in characters */ public int getDefaultColumnWidth() { return defaultColumnWidth; } /** * Sets the default column width * * @param w the new default column width */ public void setDefaultColumnWidth(int w) { defaultColumnWidth = w; } /** * Accessor for the default row height * * @return the default row height, in 1/20ths of a point */ public int getDefaultRowHeight() { return defaultRowHeight; } /** * Sets the default row height * * @param h the default row height, in 1/20ths of a point */ public void setDefaultRowHeight(int h) { defaultRowHeight = h; } /** * Accessor for the zoom factor. Do not confuse zoom factor (which relates * to the on screen view) with scale factor (which refers to the scale factor * when printing) * * @return the zoom factor as a percentage */ public int getZoomFactor() { return zoomFactor; } /** * Sets the zoom factor. Do not confuse zoom factor (which relates * to the on screen view) with scale factor (which refers to the scale factor * when printing) * * @param zf the zoom factor as a percentage */ public void setZoomFactor(int zf) { zoomFactor = zf; } /** * Accessor for the page break preview mangificaton factor. * Do not confuse zoom factor or scale factor * * @return the page break preview magnification a percentage */ public int getPageBreakPreviewMagnification() { return pageBreakPreviewMagnification; } /** * Accessor for the page break preview magnificaton factor. * Do not confuse zoom factor or scale factor * * @param f the page break preview magnification as a percentage */ public void setPageBreakPreviewMagnification(int f) { pageBreakPreviewMagnification =f ; } /** * Accessor for the nomral view magnificaton factor. * Do not confuse zoom factor or scale factor * * @return the page break preview magnification a percentage */ public int getNormalMagnification() { return normalMagnification; } /** * Accessor for the normal magnificaton factor. * Do not confuse zoom factor or scale factor * * @param f the page break preview magnification as a percentage */ public void setNormalMagnification(int f) { normalMagnification = f ; } /** * Accessor for the displayZeroValues property * * @return TRUE to display zero values, FALSE not to bother */ public boolean getDisplayZeroValues() { return displayZeroValues; } /** * Sets the displayZeroValues property * * @param b TRUE to show zero values, FALSE not to bother */ public void setDisplayZeroValues(boolean b) { displayZeroValues = b; } /** * Accessor for the showGridLines property * * @return TRUE if grid lines will be shown, FALSE otherwise */ public boolean getShowGridLines() { return showGridLines; } /** * Sets the showGridLines property * * @param b TRUE to show grid lines on this sheet, FALSE otherwise */ public void setShowGridLines(boolean b) { showGridLines = b; } /** * Accessor for the pageBreakPreview mode * * @return TRUE if page break preview is enabled, FALSE otherwise */ public boolean getPageBreakPreviewMode() { return pageBreakPreviewMode; } /** * Sets the pageBreakPreviewMode property * * @param b TRUE to launch in page break preview mode, FALSE otherwise */ public void setPageBreakPreviewMode(boolean b) { pageBreakPreviewMode = b; } /** * Accessor for the printGridLines property * * @return TRUE if grid lines will be printed, FALSE otherwise */ public boolean getPrintGridLines() { return printGridLines; } /** * Sets the printGridLines property * * @param b TRUE to print grid lines on this sheet, FALSE otherwise */ public void setPrintGridLines(boolean b) { printGridLines = b; } /** * Accessor for the printHeaders property * * @return TRUE if headers will be printed, FALSE otherwise */ public boolean getPrintHeaders() { return printHeaders; } /** * Sets the printHeaders property * * @param b TRUE to print headers on this sheet, FALSE otherwise */ public void setPrintHeaders(boolean b) { printHeaders = b; } /** * Gets the row at which the pane is frozen horizontally * * @return the row at which the pane is horizontally frozen, or 0 if there * is no freeze */ public int getHorizontalFreeze() { return horizontalFreeze; } /** * Sets the row at which the pane is frozen horizontally * * @param row the row number to freeze at */ public void setHorizontalFreeze(int row) { horizontalFreeze = Math.max(row, 0); } /** * Gets the column at which the pane is frozen vertically * * @return the column at which the pane is vertically frozen, or 0 if there * is no freeze */ public int getVerticalFreeze() { return verticalFreeze; } /** * Sets the row at which the pane is frozen vertically * * @param col the column number to freeze at */ public void setVerticalFreeze(int col) { verticalFreeze = Math.max(col, 0); } /** * Sets the number of copies * * @param c the number of copies */ public void setCopies(int c) { copies = c; } /** * Accessor for the number of copies to print * * @return the number of copies */ public int getCopies() { return copies; } /** * Accessor for the header * * @return the header */ public HeaderFooter getHeader() { return header; } /** * Sets the header * * @param h the header */ public void setHeader(HeaderFooter h) { header = h; } /** * Sets the footer * * @param f the footer */ public void setFooter(HeaderFooter f) { footer = f; } /** * Accessor for the footer * * @return the footer */ public HeaderFooter getFooter() { return footer; } /** * Accessor for the horizontal centre * * @return Returns the horizontalCentre. */ public boolean isHorizontalCentre() { return horizontalCentre; } /** * Sets the horizontal centre * * @param horizCentre The horizontalCentre to set. */ public void setHorizontalCentre(boolean horizCentre) { this.horizontalCentre = horizCentre; } /** * Accessor for the vertical centre * * @return Returns the verticalCentre. */ public boolean isVerticalCentre() { return verticalCentre; } /** * Sets the vertical centre * * @param vertCentre The verticalCentre to set. */ public void setVerticalCentre(boolean vertCentre) { this.verticalCentre = vertCentre; } /** * Sets the automatic formula calculation flag * * @param auto - TRUE to automatically calculate the formulas, * FALSE otherwise */ public void setAutomaticFormulaCalculation(boolean auto) { automaticFormulaCalculation = auto; } /** * Retrieves the automatic formula calculation flag * * @return TRUE if formulas are calculated automatically, FALSE if they * are calculated manually */ public boolean getAutomaticFormulaCalculation() { return automaticFormulaCalculation; } /** * Sets the recalculate formulas when the sheet is saved flag * * @param recalc - TRUE to automatically calculate the formulas when the, * spreadsheet is saved, FALSE otherwise */ public void setRecalculateFormulasBeforeSave(boolean recalc) { recalculateFormulasBeforeSave = recalc; } /** * Retrieves the recalculate formulas before save flag * * @return TRUE if formulas are calculated before the sheet is saved, * FALSE otherwise */ public boolean getRecalculateFormulasBeforeSave() { return recalculateFormulasBeforeSave; } /** * Sets the print area for this sheet * * @param firstCol the first column of the print area * @param firstRow the first row of the print area * @param lastCol the last column of the print area * @param lastRow the last row of the print area */ public void setPrintArea(int firstCol, int firstRow, int lastCol, int lastRow) { printArea = new SheetRangeImpl(sheet, firstCol, firstRow, lastCol, lastRow); } /** * Accessor for the print area * * @return the print area, or NULL if one is not defined for this sheet */ public Range getPrintArea() { return printArea; } /** * Sets both of the print titles for this sheet * * @param firstRow the first row of the print row titles * @param lastRow the last row of the print row titles * @param firstCol the first column of the print column titles * @param lastCol the last column of the print column titles */ public void setPrintTitles(int firstRow, int lastRow, int firstCol, int lastCol) { setPrintTitlesRow(firstRow, lastRow); setPrintTitlesCol(firstCol, lastCol); } /** * Sets the print row titles for this sheet * * @param firstRow the first row of the print titles * @param lastRow the last row of the print titles */ public void setPrintTitlesRow(int firstRow, int lastRow) { printTitlesRow = new SheetRangeImpl(sheet, 0, firstRow, 255, lastRow); } /** * Sets the print column titles for this sheet * * @param firstRow the first row of the print titles * @param lastRow the last row of the print titles */ public void setPrintTitlesCol(int firstCol, int lastCol) { printTitlesCol = new SheetRangeImpl(sheet, firstCol, 0, lastCol, 65535); } /** * Accessor for the print row titles * * @return the print row titles, or NULL if one is not defined for this sheet */ public Range getPrintTitlesRow() { return printTitlesRow; } /** * Accessor for the print column titles * * @return the print column titles, or NULL if one is not defined for this * sheet */ public Range getPrintTitlesCol() { return printTitlesCol; } } jexcelapi/src/jxl/WorkbookSettings.java0000750000175000017500000005741411207000610020457 0ustar drazzibdrazzib/********************************************************************* * * Copyright (C) 2002 Andrew Khan * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ***************************************************************************/ package jxl; import java.io.File; import java.util.HashMap; import java.util.Locale; import jxl.common.Logger; import jxl.biff.CountryCode; import jxl.biff.formula.FunctionNames; /** * This is a bean which client applications may use to set various advanced * workbook properties. Use of this bean is not mandatory, and its absence * will merely result in workbooks being read/written using the default * settings */ public final class WorkbookSettings { /** * The logger */ private static Logger logger = Logger.getLogger(WorkbookSettings.class); /** * The amount of memory allocated to store the workbook data when * reading a worksheet. For processeses reading many small workbooks inside * a WAS it might be necessary to reduce the default size */ private int initialFileSize; /** * The amount of memory allocated to the array containing the workbook * data when its current amount is exhausted. */ private int arrayGrowSize; /** * Flag to indicate whether the drawing feature is enabled or not * Drawings deactivated using -Djxl.nodrawings=true on the JVM command line * Activated by default or by using -Djxl.nodrawings=false on the JVM command * line */ private boolean drawingsDisabled; /** * Flag to indicate whether the name feature is enabled or not * Names deactivated using -Djxl.nonames=true on the JVM command line * Activated by default or by using -Djxl.nonames=false on the JVM command * line */ private boolean namesDisabled; /** * Flag to indicate whether formula cell references should be adjusted * following row/column insertion/deletion */ private boolean formulaReferenceAdjustDisabled; /** * Flag to indicate whether the system hint garbage collection * is enabled or not. * As a rule of thumb, it is desirable to enable garbage collection * when reading large spreadsheets from a batch process or from the * command line, but better to deactivate the feature when reading * large spreadsheets within a WAS, as the calls to System.gc() not * only garbage collect the junk in JExcelApi, but also in the * webservers JVM and can cause significant slowdown * GC deactivated using -Djxl.nogc=true on the JVM command line * Activated by default or by using -Djxl.nogc=false on the JVM command line */ private boolean gcDisabled; /** * Flag to indicate whether the rationalization of cell formats is * disabled or not. * Rationalization is enabled by default, but may be disabled for * performance reasons. It can be deactivated using -Djxl.norat=true on * the JVM command line */ private boolean rationalizationDisabled; /** * Flag to indicate whether or not the merged cell checking has been * disabled */ private boolean mergedCellCheckingDisabled; /** * Flag to indicate whether the copying of additional property sets * are disabled */ private boolean propertySetsDisabled; /** * Flag to indicate that cell validation criteria are ignored */ private boolean cellValidationDisabled; /** * Flag to indicate whether or not to ignore blank cells when processing * sheets. Cells which are identified as blank can still have associated * cell formats which the processing program may still need to read */ private boolean ignoreBlankCells; /** * Flag to indicate whether auto filtering should be read/copied */ private boolean autoFilterDisabled; /** * Flag to indicate whether a temporary file should be used when * writing out the workbook */ private boolean useTemporaryFileDuringWrite; /** * The directory for used for the temporary file during write. If this * is NULL, the default system directory is used */ private File temporaryFileDuringWriteDirectory; /** * The locale. Normally this is the same as the system locale, but there * may be cases (eg. where you are uploading many spreadsheets from foreign * sources) where you may want to specify the locale on an individual * worksheet basis * The locale may also be specified on the command line using the lang and * country System properties eg. -Djxl.lang=en -Djxl.country=UK for UK * English */ private Locale locale; /** * The locale specific function names for this workbook */ private FunctionNames functionNames; /** * The character encoding used for reading non-unicode strings. This can * be different from the default platform encoding if processing spreadsheets * from abroad. This may also be set using the system property jxl.encoding */ private String encoding; /** * The character set used by the readable spreadsheeet */ private int characterSet; /** * The display language used by Excel (ISO 3166 mnemonic) */ private String excelDisplayLanguage; /** * The regional settings used by Excel (ISO 3166 mnemonic) */ private String excelRegionalSettings; /** * A hash map of function names keyed on locale */ private HashMap localeFunctionNames; /** * Flag to indicate whether all external data and pivot stuff should * refreshed */ private boolean refreshAll; /** * Flag to indicate whether the file is a template or not (Usually with .xlt * file name extension) */ private boolean template; /** * Flag to indicate whether the file has been written by excel 2000. * * The EXCEL9FILE record indicates the file was written by Excel 2000. It has * no record data field and is C0010000h. Any application other than Excel * 2000 that edits the file should not write out this record. * * However, it seemas that excel 2003 + 2007 still set this flag.... */ private boolean excel9file= false; /** * The WINDOWPROTECT record stores an option from the Protect Workbook * dialog box. * * =1 if the workbook windows are protected */ private boolean windowProtected; /** * Write access user name. * When not set (null) then we set it to Java Excel API + Version number */ private String writeAccess; /** * The HIDEOBJ record stores options selected in the Options dialog,View tab. */ private int hideobj; /** * The HIDEOBJ record stores options selected in the Options dialog,View tab. */ public final static int HIDEOBJ_HIDE_ALL= 2; /** * The HIDEOBJ record stores options selected in the Options dialog,View tab. */ public final static int HIDEOBJ_SHOW_PLACEHOLDERS= 1; /** * The HIDEOBJ record stores options selected in the Options dialog,View tab. */ public final static int HIDEOBJ_SHOW_ALL= 0; // ** // The default values // ** private static final int DEFAULT_INITIAL_FILE_SIZE = 5 * 1024 * 1024; // 5 megabytes private static final int DEFAULT_ARRAY_GROW_SIZE = 1024 * 1024; // 1 megabyte /** * Default constructor */ public WorkbookSettings() { initialFileSize = DEFAULT_INITIAL_FILE_SIZE; arrayGrowSize = DEFAULT_ARRAY_GROW_SIZE; localeFunctionNames = new HashMap(); excelDisplayLanguage = CountryCode.USA.getCode(); excelRegionalSettings = CountryCode.UK.getCode(); refreshAll = false; template = false; excel9file = false; windowProtected = false; hideobj = HIDEOBJ_SHOW_ALL; // Initialize other properties from the system properties try { boolean suppressWarnings = Boolean.getBoolean("jxl.nowarnings"); setSuppressWarnings(suppressWarnings); drawingsDisabled = Boolean.getBoolean("jxl.nodrawings"); namesDisabled = Boolean.getBoolean("jxl.nonames"); gcDisabled = Boolean.getBoolean("jxl.nogc"); rationalizationDisabled = Boolean.getBoolean("jxl.norat"); mergedCellCheckingDisabled = Boolean.getBoolean("jxl.nomergedcellchecks"); formulaReferenceAdjustDisabled = Boolean.getBoolean("jxl.noformulaadjust"); propertySetsDisabled = Boolean.getBoolean("jxl.nopropertysets"); ignoreBlankCells = Boolean.getBoolean("jxl.ignoreblanks"); cellValidationDisabled = Boolean.getBoolean("jxl.nocellvalidation"); autoFilterDisabled = !Boolean.getBoolean("jxl.autofilter"); // autofilter currently disabled by default useTemporaryFileDuringWrite = Boolean.getBoolean("jxl.usetemporaryfileduringwrite"); String tempdir = System.getProperty("jxl.temporaryfileduringwritedirectory"); if (tempdir != null) { temporaryFileDuringWriteDirectory = new File(tempdir); } encoding = System.getProperty("file.encoding"); } catch (SecurityException e) { logger.warn("Error accessing system properties.", e); } // Initialize the locale to the system locale try { if (System.getProperty("jxl.lang") == null || System.getProperty("jxl.country") == null) { locale = Locale.getDefault(); } else { locale = new Locale(System.getProperty("jxl.lang"), System.getProperty("jxl.country")); } if (System.getProperty("jxl.encoding") != null) { encoding = System.getProperty("jxl.encoding"); } } catch (SecurityException e) { logger.warn("Error accessing system properties.", e); locale = Locale.getDefault(); } } /** * Sets the amount of memory by which to increase the amount of * memory allocated to storing the workbook data. * For processeses reading many small workbooks * inside a WAS it might be necessary to reduce the default size * Default value is 1 megabyte * * @param sz the file size in bytes */ public void setArrayGrowSize(int sz) { arrayGrowSize = sz; } /** * Accessor for the array grow size property * * @return the array grow size */ public int getArrayGrowSize() { return arrayGrowSize; } /** * Sets the initial amount of memory allocated to store the workbook data * when reading a worksheet. For processeses reading many small workbooks * inside a WAS it might be necessary to reduce the default size * Default value is 5 megabytes * * @param sz the file size in bytes */ public void setInitialFileSize(int sz) { initialFileSize = sz; } /** * Accessor for the initial file size property * * @return the initial file size */ public int getInitialFileSize() { return initialFileSize; } /** * Gets the drawings disabled flag * * @return TRUE if drawings are disabled, FALSE otherwise */ public boolean getDrawingsDisabled() { return drawingsDisabled; } /** * Accessor for the disabling of garbage collection * * @return FALSE if JExcelApi hints for garbage collection, TRUE otherwise */ public boolean getGCDisabled() { return gcDisabled; } /** * Accessor for the disabling of interpretation of named ranges * * @return FALSE if named cells are interpreted, TRUE otherwise */ public boolean getNamesDisabled() { return namesDisabled; } /** * Disables the handling of names * * @param b TRUE to disable the names feature, FALSE otherwise */ public void setNamesDisabled(boolean b) { namesDisabled = b; } /** * Disables the handling of drawings * * @param b TRUE to disable the names feature, FALSE otherwise */ public void setDrawingsDisabled(boolean b) { drawingsDisabled = b; } /** * Sets whether or not to rationalize the cell formats before * writing out the sheet. The default value is true * * @param r the rationalization flag */ public void setRationalization(boolean r) { rationalizationDisabled = !r; } /** * Accessor to retrieve the rationalization flag * * @return TRUE if rationalization is off, FALSE if rationalization is on */ public boolean getRationalizationDisabled() { return rationalizationDisabled; } /** * Accessor to retrieve the merged cell checking flag * * @return TRUE if merged cell checking is off, FALSE if it is on */ public boolean getMergedCellCheckingDisabled() { return mergedCellCheckingDisabled; } /** * Accessor to set the merged cell checking * * @param b - TRUE to enable merged cell checking, FALSE otherwise */ public void setMergedCellChecking(boolean b) { mergedCellCheckingDisabled = !b; } /** * Sets whether or not to enable any property sets (such as macros) * to be copied along with the workbook * Leaving this feature enabled will result in the JXL process using * more memory * * @param r the property sets flag */ public void setPropertySets(boolean r) { propertySetsDisabled = !r; } /** * Accessor to retrieve the property sets disabled flag * * @return TRUE if property sets are disabled, FALSE otherwise */ public boolean getPropertySetsDisabled() { return propertySetsDisabled; } /** * Accessor to set the suppress warnings flag. Due to the change * in logging in version 2.4, this will now set the warning * behaviour across the JVM (depending on the type of logger used) * * @param w the flag */ public void setSuppressWarnings(boolean w) { logger.setSuppressWarnings(w); } /** * Accessor for the formula adjust disabled * * @return TRUE if formulas are adjusted following row/column inserts/deletes * FALSE otherwise */ public boolean getFormulaAdjust() { return !formulaReferenceAdjustDisabled; } /** * Setter for the formula adjust disabled property * * @param b TRUE to adjust formulas, FALSE otherwise */ public void setFormulaAdjust(boolean b) { formulaReferenceAdjustDisabled = !b; } /** * Sets the locale used by JExcelApi to generate the spreadsheet. * Setting this value has no effect on the language or region of * the generated excel file * * @param l the locale */ public void setLocale(Locale l) { locale = l; } /** * Returns the locale used by JExcelAPI to read the spreadsheet * * @return the locale */ public Locale getLocale() { return locale; } /** * Accessor for the character encoding * * @return the character encoding for this workbook */ public String getEncoding() { return encoding; } /** * Sets the encoding for this workbook * * @param enc the encoding */ public void setEncoding(String enc) { encoding = enc; } /** * Gets the function names. This is used by the formula parsing package * in order to get the locale specific function names for this particular * workbook * * @return the list of function names */ public FunctionNames getFunctionNames() { if (functionNames == null) { functionNames = (FunctionNames) localeFunctionNames.get(locale); // have not previously accessed function names for this locale, // so create a brand new one and add it to the list if (functionNames == null) { functionNames = new FunctionNames(locale); localeFunctionNames.put(locale, functionNames); } } return functionNames; } /** * Accessor for the character set. This value is only used for reading * and has no effect when writing out the spreadsheet * * @return the character set used by this spreadsheet */ public int getCharacterSet() { return characterSet; } /** * Sets the character set. This is only used when the spreadsheet is * read, and has no effect when the spreadsheet is written * * @param cs the character set encoding value */ public void setCharacterSet(int cs) { characterSet = cs; } /** * Sets the garbage collection disabled * * @param disabled TRUE to disable garbage collection, FALSE to enable it */ public void setGCDisabled(boolean disabled) { gcDisabled = disabled; } /** * Sets the ignore blanks flag * * @param ignoreBlanks TRUE to ignore blanks, FALSE to take them into account */ public void setIgnoreBlanks(boolean ignoreBlanks) { ignoreBlankCells = ignoreBlanks; } /** * Accessor for the ignore blanks flag * * @return TRUE if blank cells are being ignored, FALSE otherwise */ public boolean getIgnoreBlanks() { return ignoreBlankCells; } /** * Sets the ignore cell validation flag * * @param cv TRUE to disable cell validation, FALSE to enable it */ public void setCellValidationDisabled(boolean cv) { cellValidationDisabled = cv; } /** * Accessor for the ignore cell validation * * @return TRUE if cell validation is disabled */ public boolean getCellValidationDisabled() { return cellValidationDisabled; } /** * Returns the two character ISO 3166 mnemonic used by excel for user * language displayto display * @return the display language */ public String getExcelDisplayLanguage() { return excelDisplayLanguage; } /** * Returns the two character ISO 3166 mnemonic used by excel for * its regional settings * @return the regional settings */ public String getExcelRegionalSettings() { return excelRegionalSettings; } /** * Sets the language in which the generated file will display * * @param code the two character ISO 3166 country code */ public void setExcelDisplayLanguage(String code) { excelDisplayLanguage = code; } /** * Sets the regional settings for the generated excel file * * @param code the two character ISO 3166 country code */ public void setExcelRegionalSettings(String code) { excelRegionalSettings = code; } /** * Accessor for the autofilter disabled feature * * @return TRUE if autofilter is disabled, FALSE otherwise */ public boolean getAutoFilterDisabled() { return autoFilterDisabled; } /** * Sets the autofilter disabled * * @param disabled */ public void setAutoFilterDisabled(boolean disabled) { autoFilterDisabled = disabled; } /** * Accessor for the temporary file during write. If this is set, then * when the workbook is written a temporary file will be used to store * the interim binary data, otherwise it will take place in memory. Setting * this flag involves an assessment of the trade-offs between memory usage * and performance * * @return TRUE if a temporary is file is used during writing, * FALSE otherwise */ public boolean getUseTemporaryFileDuringWrite() { return useTemporaryFileDuringWrite; } /** * Sets whether a temporary file is used during the generation of * the workbook. If not set, the workbook will take place entirely in * memory. Setting * this flag involves an assessment of the trade-offs between memory usage * and performance * * @return TRUE if a temporary is file is used during writing, * FALSE otherwise */ public void setUseTemporaryFileDuringWrite(boolean temp) { useTemporaryFileDuringWrite = temp; } /** * Used in conjunction with the UseTemporaryFileDuringWrite setting to * set the target directory for the temporary files. If this is not set, * the system default temporary directory is used. * This has no effect unless the useTemporaryFileDuringWrite setting * is TRUE * * @param dir the directory to which temporary files should be written */ public void setTemporaryFileDuringWriteDirectory(File dir) { temporaryFileDuringWriteDirectory = dir; } /** * Used in conjunction with the UseTemporaryFileDuringWrite setting to * set the target directory for the temporary files. This value can * be NULL, in which case the normal system default temporary directory * is used instead * * @return the temporary directory used during write, or NULL if it is * not set */ public File getTemporaryFileDuringWriteDirectory() { return temporaryFileDuringWriteDirectory; } /** * When true then Refresh All should be done on all external data ranges and * PivotTables when loading the workbook (the default is =0) * * @param refreshAll the refreshAll to set */ public void setRefreshAll(boolean refreshAll) { this.refreshAll = refreshAll; } /** * When true then Refresh All should be done on all external data ranges and * PivotTables when loading the workbook (the default is =0) * * @return the refreshAll value */ public boolean getRefreshAll() { return refreshAll; } /** * Workbook Is a Template * @return the template */ public boolean getTemplate() { return template; } /** * Workbook Is a Template * @param template the template to set */ public void setTemplate(boolean template) { this.template = template; } /** * Has this file been written by excel 2000? * * @return the excel9file */ public boolean getExcel9File() { return excel9file; } /** * @param excel9file the excel9file to set */ public void setExcel9File(boolean excel9file) { this.excel9file = excel9file; } /** * @return the windowprotected */ public boolean getWindowProtected() { return windowProtected; } /** * @param windowprotected the windowprotected to set */ public void setWindowProtected(boolean windowprotected) { this.windowProtected = windowProtected; } /** * The HIDEOBJ record stores options selected in the Options dialog,View tab * * Possible values are: * HIDEOBJ_HIDE_ALL, HIDEOBJ_SHOW_ALL and HIDEOBJ_SHOW_PLACEHOLDERS * @return the hideobj */ public int getHideobj() { return hideobj; } /** * The HIDEOBJ record stores options selected in the Options dialog,View tab * * Possible values are: * HIDEOBJ_HIDE_ALL, HIDEOBJ_SHOW_ALL and HIDEOBJ_SHOW_PLACEHOLDERS * @param hideobj the hideobj to set */ public void setHideobj(int hideobj) { this.hideobj = hideobj; } /** * @return the writeAccess */ public String getWriteAccess() { return writeAccess; } /** * @param writeAccess the writeAccess to set */ public void setWriteAccess(String writeAccess) { this.writeAccess = writeAccess; } } jexcelapi/jxlrwtest.xls0000750000175000017500000026700011251257140015515 0ustar drazzibdrazzibࡱ>   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~Root Entry Fs;P1%6WorkbookV#_VBA_PROJECT_CUR"pQ#%P1%Ctls P (ɀ\pJPMorgan Chase & Co. Ba= ThisWorkbook=Z<%8X@"1Arial1Arial1Arial1Arial1Arial1Arial1Arial1Arial1Arial1 Arial1 Arial1$Arial1Arial1Arial1Arial1Arial1Arial1Arial1QTahoma1QTahoma1QTahoma1QTahoma1Tahoma""#,##0;\-""#,##0""#,##0;[Red]\-""#,##0""#,##0.00;\-""#,##0.00#""#,##0.00;[Red]\-""#,##0.005*0_-""* #,##0_-;\-""* #,##0_-;_-""* "-"_-;_-@_-,)'_-* #,##0_-;\-* #,##0_-;_-* "-"_-;_-@_-=,8_-""* #,##0.00_-;\-""* #,##0.00_-;_-""* "-"??_-;_-@_-4+/_-* #,##0.00_-;\-* #,##0.00_-;_-* "-"??_-;_-@_- 0.00000 0.00000E+00 0.0000dd\ mm\ yyyy\ hh:mm:ssdd\ mmm\ yyyy\ hh:mm:ss                + ) , *                ( ( (      (  @7  (X    Z    Q  Q  # (P (pUU@ @   (xU@  (p@ (pP  (p@  `@@  `@  `P @  `@7  `P@ 7  `0  `P 0  `P 0  `PP 0 (p  (pP    8@@  0@  0P @  0P@  0P  0PP  `original modified,Dates: form_button_macroLabels:nametest:P! Numbers;   ; value1:value2:T Ǧ0 OURpvF WIpFpvF WIJFIFHHC  !"$"$C|" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?S#5sӅ?Paasr+t~e e]҅G>`GFM3Z.hX0OPqVv@=}8pb#F;g9ri [ihۓU4=yEЭr8UaZBEAм*^Pɞ:}(2 ݼՃ Lߍ.0ҧ܎(۠NEbzMZpm= (㞴=2j& SBW#C=+8t\*M^*4NӸܯMy@6c:Qqv_սԃƎ`HPv@9JPQ44ʐ2qV)EbuM*9p[nآ)=jhO[>ݍ=&(Tp:3õI;xv59䚕JЎ;f*'>>͟.rsKSi)Enf~ ,OZ܃*=t+ؗ\xs c<<=b18ivd~UhG'@ 8d'݃zSvإX^W< "Vr% mle9ڬD RsfL4l8U.nM;8zw┨ 3EƊ=zo`xaG1KSg^>'[1O "DF1Ry'֮0p"*%ԥM31`u}fm\wf3 g<4sָ$ v"`MAǨTL{i'+HB0 S({@Dzc }jFHqzdO+*)9ԏ Ն,iK ($Ћb邪? f9- M)=ܬSc!Qh)ǭUztEn!Ld`\M !Q*S$u=G_;c NCcV1rx9Ei"i6~l'8c*) 䝥.hW#Q<@rIyWݳ&*}R*=<9B>Rg)blF,hlҎaB=~QqnϯLQ+Jsq4|uf1c4qO9J9jNz怙v*ycyc,F֔ނ=rڐWZ?:O+p}J^_ڍ* ~P$Rf4;ဩN:ȸR6Y{XP«^Fq嵳mWl瞄UekcShB A:@e*elI*L0p+U=kT3n|QQX:6D@iv#('< Woن [*.Rg3gJiLm֌Kp+SƀIVW:()눛tPo ےg֙Rj?9ueyiB׋1D52|ք+neӄF'#6őbq/~]xۜ4QCV&s'9; roOuk:m~e8Kp֨BBXolM~,7:U6,K0;/5Jkiے[$g-QOcUs+QJ:'ky-f`~XWdPN g)oB9vFIxMh@\sִ~z*t)`qTOfa*RJ6Ͻ! [;S횿hȢуN~=2sZ"Ls9'"&fuSKTgxf鎵,p)\qW r]Zdd~uOҩ[u tTr7o}VcIhCCMͩ;r*7iqh4B?+YQ^IhŀSvˏLQHI4tڧi%Yru$F|B>©[{V\ǁT~`ƻ) hpUF)'5oHcE54O ccG׊ +ZpiDo>c攪:8єgy'O/#'E7_iH\HX TfLn#{C *2zrޡxl I|W;h8ᷩ ,&"rer!r=F{pjHsx/lm#!I`dIPgV5qsK- G wvڑ/q]/^DI8e98<=9 U)%VotPkMk Pq*t3=[??:M1qK}XvϠs K(f6X{ | ,6OsZnK$%0 B?:yI~+Xŧڝ }iIS5`´v9%#O,j5M$bxjHaUH?+fu,hǠi !X %ȡTpZm(1eo(I@9=9Ӄ\ΩȆ6}Nq_ n9y 5￸4qkjdC!J=yZjV0]-ʸt, e rqާQ w;gXy۴hl|Yz&繮I{;0hAjHڪ+;Kk0٧s ՏqwjŞIom^浴Mcc'2⤚oF(!s᱅`#FF Nx=En<d̬r@z)֜'sXڵ֯wSKmo#Wpõ QԳ3`;bZvKZܽdGĥx,Ű?2Q-ۢC 8pҕDH<^ MC[^ gMNѴĨQ1S2\ZT ocs3%rf\ nkya5-d$KB䪘jd y'oq)v%H!ٷ*8c4^AȫuܼKzf2O˸<ե`ZZ7 ׏SVQ䪟*x\ҽf|g%ПR@ jd;~a[Y#EV[hʜʳ6xs8l`tc>>͕ta8m9P ]pojq$r$RY#6:DP4A UaiDG?RVCR6yCr,LƘT=c#i"=֮Ds.i\Zo>&zݘ9 {,*\{ N@ҢN|>qFe<{8q°3m.lȹ[3ӏ& "棑F ^qƠBDYp < 0ݎI"͈G c =~)i|1ԧ 02pFs :ҹҹ݊*"]iaB QY!<^l] 'K6݀I :V{D͔&͒G5[д`8:S{x\LJ# r05I!3}9.c>̫ /#'*2o!3E<,5؊(KH3$V%k{+i/n8,W3*QmEZF̷Y9D7r{qFNMAJg=Үxl\sުGY#3YY̘n*g:C'dZv!2zMߕs4Ue~kC1Wᙔ̃ w"c|\j4r@rrxmG\81 ^f$` '_Uz*6vwȱyh\`2s_uu7W?msu n,$oT6Ԟbɭ#.(C H9vxU!k$Ck9L Hw:}Zmumb6Is=Y8+(K}p&_?[˦ZIfڬyh0rTRXIXG:c1$fےI==hO4<i$)?-GRm-m&PJHu8P9hSO{6o`{^o͕km,Wء=j'Vx-X #xy$ R\pL ~_xCl~r0_'IG^S`c9끜W?q}+Kd˨j04o,~QsPh =Yv?L=fjV7WAgY >lp#x8;GMVMB8nDQrJod9l) @yҩ).[zQbWlV/u" u% hh^ݦx| ~Z(#,n9#MMѬc$Gi 8gr3@tioi5CrWl*pͻ$usch[Is\\*NO^iZs"#=ԃN8$خRT(sFsKyga<3WY%>瞜zL۸ G H\3$刕נj08KZk")K2-;T1F8KME-7J{UQt˂!Vibu> =,1$pOL2(7`[s_XOTCll ru7R5W[2;!CRΠc[)MZu pKx/=9u'}cXmUE g;9S8#W'ns>jDUsb)ŝ Kc?}M6EȨ:d9Ym5Iq~HX0ZMV!Ѩzc=sOQ\R`7is$ҢnÖaqX^kzm!;d%]IWjc<)lym fi[7GXjyfLukr&.CK!'~}ULzcׇѤ1Yb.صR:[ڭIL9FӜWm4$`l{ֶDT 1zėS+K * k\7?e[X u0H N~NmCCKϠdk 鲠D+cMLYeX k_03&#>tr{dޛJoX(UI\s<Z(gy;:qWhhE8]5_^aumPk~*]!I$HKi\99#^j47Npiy 3/|횊?xHg:w#wqufЊthئ3y;'Mc8y Mv<!:٪k/q&*ƅdYZ-7b?3Hf=p3Xtڷ*YA0?*z7If[ @8ZM =VBGGB~; -5G,\ZIwwbby뚿_kRgXWK G*9KwK"=*7JxqJA1k[I ۚEEA^vӦi5_h)#\['&[#'Գ1K'D#QK>"Vk$`;=ݕ.{{eݩ k%M=m߸fRPQ*Eq=*#SYGx{ƹVўYkbۺO<}TM?Ji`uqeb# z j7 VUf-]\w?R&T=Iz6tZZbqQ|'$gxץ$r,ugbwGZNj6]ȑvo}{归^G#lqc?::Z3H\Gŷn&+@ ta to=hxz=N"xp?{r8;z-mHKh!Y03J}y'\YW/'CҮ[3xh.>.߈ 2Dk6Io-I.0׉x=L\İl.=ϝ-ݔ8n3Y yHǖ۸Յ8D% r$MEu{^gaxRHtP]VM8 fH/?N5v}OȬZ y2J^!$\i(hnXӑKld93H%LezD/HNw,,ӱe9͒2OlTVREr6v\יd`POJPckw rq"r[i٣K6B$#j23ぎ9~&>youAUc_h#'s5bq#Dzt=#ӵ-w_қN6\E 'zWdzz%̔rLVlTnm~WFm;J}*K5;-yqB6:UCdw0T 2kr,;OS>v9[ݖ"(6E~B_ m-NgDoUvrwTߕ޳ޤ=kWT].igpJOuWeE} h,t2$Q''9JerN.f6Բ tDK3vkWu;Ƭ }$ƥcYU8e Qr+]R6}MU#w!_(ǵA NL\.pbp$ΒɄL5MMд;;>#A!vJ#:wVK-py`1)~?b AϘsp1y y%[wE9¨-a2wl9ʵ]|Duml0I?UN`A;}7cp1|# m~]7ҷXjkoJ_()#$4:4.cxI<\ ?£YDH 8UO Akb}oafe(GcT`rʶ?tP@fu}V}&ώD,EfRjY8O=$ezۿx3?WJϊ4?23mʹ/^<'sSŘ~(Z^z>cu ^\){C`wq?5κ VGp;P?J(LO d) zs\_ekd.X\(K&`ThF.w:oxSN/c #Fw3JW 1rs\]k0W ~X2 ]'5Gζ%5Gu qozszEvbe}#*}/4UEݤ?=^$3 cec,?4jlr5^$Z^nDf\Ã4d=iօ b ;Yr{W5Bvv-<"8'F*jX9 $lt1axP+}AJMݜ[B&&G^R3psOh"dFm˰"G?x`&\napU Hhޥ(?@Ijʝ}ٞv5f \}8!db2GJ4rS4SǞSn3S[ZuLg#ܜYF_mtO22ǂ:` kf?h._jAb=NG>\iw.li>c%ҫ9W0fFK~=gkUY[:IPeI ;bcGrb_Vn Epُ%J)Uobfk'K¹`{pܞSK-qJɲ%Pgdlw9< OrqT(fBFM[Gh"$bII !8r=Fj啕eҤ´Syٲq0,AlO~A?^]!Mk2Y2=IZesnH{لaY 5?d\{t5Gu{PvIʃڜpa$#?LSȍbi'׭mU7ա#EvlP_nqN{ (2[^m"!0i#9[X8LQ9ۚRMu8#JX3OIwE9P1[@}2"+mzO]5m6i<}j1+G 'v<6R\Y^\ +/m]DvXW BϠ$뤅MRH2g γxbZ=YciuD5#cGckR^_j(] N_xE%C?ME/~sW?ݔ[W1}Rs{k߇ZJyVA7ndw\ojݱtmtim %P 7P ]f?ryLwX?yOZtM%e@2rk le'tt1V8&Vs{qZ.`+JʱZ&X֭ܫJ9,@?כV=L=>Hjp=WS}Éz}qT-i;lWiXQ 죦cJ:nFuDaqEHPd##/q3d`n%X\0-#v,[,sPs);iqiv$hxcpߊ1бlg'qHdxЉShr?,TNW܍_YS8@?GdIПԊ\́-).%l!*Ne`?r9aϙ)%k9VWL#v;܄#ë.:*j)x^FxzՂXnN8 bGR3,gbԂњDN }z1j fnF>aczt=f+sV£}eխAL !/$#r_B;tl;n$_&e\M7GN[0s&§&P3DI'c^jaah$e%Ydc!#`c"P.[=+S"kl`iRrX9s*v_ A%Lpr{k>XSiC˖v1q3T)U٦Z-c?Lcڬ\j"\nf4{e\䡔T)41hw 1&j~4fFYKc?FD':*kKl ,mk6[u $PZKU CjI {m~#@1ҵZʴ49!PqWxS6:~//Qn''8Ÿnyk)0J@0o+1'3=oNOެ `gNy:W x{pcEH2wϿo5dCH 淆FsxWK\rD= )ꅱƓyj$xLJls1X0RPVNPy[qYճZ{lnå|4<6b,0RJOZlv!aN@1ҷtm[YT nx'\2t2 _ue#),++OdX#W@̔(,L;dU=+V(&X_;?%hlCۦex{ zJK t8eyjɻo0Bp0=7P<$1Zto,?ʵ?vNASN,G T%ZcT # y⡒sF=k7ѺimJ|R6>?j]N~X< E>ß ur{~_ҷSJgv m>p}c9 (e֭JطɼAٲ rwu 1/kƵK `rXH]E^yV8&xRj2XmGu_ȱ+:FR3ִB]aC% #i/9ֺF<[MI-ąsAں-&;Œ N[hz{IK{C>Sqq#:uDv*=Eau+(}˕ez:UEi뭀ڸ=]u36nF V?=G&$ h?NW'&bXR-So`gں+ KKH1u6?C 3򪐩VD -tK8,#In#\E4F4U ;?dksvN"0BLGk̷2]Z)!V)GBqY>'9lTB|}I-k 7e9sk֬ $;r;¹M[ĶF`):#bkM^xXd}ˌ{W}* SКNxxw @ 4ϜwuؕTrM9]c*5Lb$CJ_-1I>l9^it$ߵ +{D[DsVjGY׮FX=nVˉ,u1C'ۧ55Sov6?)[I @{ӏ344[wB =jeܸ}ƠIcH`dd@7zfn o9 6qV^ F:t/l#\3,yq]Y'(pϽgAV̲UAXb#x l;cܜg9ȝEmu͙䘳37 MlbA1#?ҫiS+?W`-)gV,*ON8&cm/'FT]MEųU1 o~VI ~Z7M܋y,3`~j8 k R ʺdA:Tn$qc֕on-TI&0~O5҇Hgt?*թ} ZəZVayCw7~^ܰ!f?.᱘TzUᰙbɸvV-^2]НQyRS562$ -mM7W0̳rT'銭x[(HI9Cߥp7ZBh2dVsR;)u\%k'+\̲Aݑ[}+ p8G 꼀}k˫par$g ϰQsKiކRi쮤Fp=+6syHy@i 8*[I_ihەk>H)yzVgWy ]yFUXQ@\$ϰ4v7 GQZ_LiV(e2x Y.}w1Ȗ4]u*ZE}u'!: sT쐛sԯn v^@,ruR4B4c>G[M3(p˅pj  (n@}j$!s bUkӌT&̺YCAۧJ5 \pAqE>6W7Nc\Sԭ֦P1Hz!s![0ܯOnOCG]g00 <~u)E s$ 9#9ڻ%}2N皁(0Bzw*R)K"%!qZ) xrΘߟLc+:eGF)Q=)|(仜n?:9T*ž/c=j՗n8Vۆ$#7HP z_;R$;&$d޲0"#P:bs)1o1m;A`3hj xo#?_βZ& *=F˫[z[!]hʔ$Ȝ[djC#4'cUM={8[ڴyo/?/vi]?Y6Cc@Q4 (n' sX[;--8,K.=A=r$5DLؤt q]VqG*ΤDm 1c=q>,կ&$bX|5F.ZIԕ*&,C{eqg-*nH(8?CU- ̻s$÷ԑZ֚iq23p x!wG1u:ܙ0r>hO׭WShebW?Iکw!0sC~u l1IT3pH {cQ&ކ=3Xn'K:($c=>ljZf EGR8NeX/CJIB/d$`LdPaHjf@Q>UcHK= 2eXFF$U+m#8kj;Mcq!Ix8ҩKwr>՛6Bw1Fbsp*H.8hZr,3 tls+ƫ8BOSՓvf0$s]O4 h7r:o]m8Rյc "A 5-BYBӼ1b pq1Z%0~~v]B*,ӱo1='<`7RGCA_򤐌c֖[ x-m<~}%y2Nfs]<2&ǫ:e8Oܹye9#96ӹ0(E<6~E!BU d6}Tv5jߣܣydaode&bL!F ?^X0.&5O埥G5)<q lg5T+$fO>ݳG5:V*]Y;oܐ:7Wc9~Yb(0j,CiN: cؚ.Ue1<cϮ:V=.H`GbxM+&gFIC;dLk䉥* "ǖ3Xe fcP?6K|L'v3> !fpHQ.Rf,A~DyxD 2x9*xfr8 mյ[l1}+;UYtdz*ȕ0a:vjgݺEVlrsI4+yKHc2 v&hˍ"sjH £: c=ϭ$v ="c+ #y]ː>yQò|*ɨ\(>٤]tv :3Tp?_j颏q03 |E0sԆ7/;?j *dd}{ǘʼoQ\.~TMLRG@NJ `Q{S{#?ِ"0V 7{֢[H jcmxn<ت1 dؤSPޅl'Kl_VL CY1&!3ӎivKs%CH@Պ\px=qTs%IvOɓZ[ZL:Ǐ1SA0Зq@z{U08Fm\aM;RAUw~bd>=XnL>x^Amm;I' U$̐%^JoX *Hd K{Qٸ&hb@ l~*y;[]8Z%.)i˵c?)jn q׏W.Ll#<VN1ح9RK.=ךV<{vȡT#g zK$ tpR[Au 2~p 5o|ϴ`e!RlMLF222N1OHUg*Ķ33u'Y-WʄLB0G _5QVF\M8k[GTOUI,}4f#: N'yU+%LaVԶoΦ0LE19empZ=Ǡgf?$U)cTH>p3>[Z[$?3tf-o#"{SCtmY03^5-:s>@?5 %<~cToJXv7O)PT3B=@?bˀp9U( +GxwKݽ8啁XJv 3Q?$Sz{(ݙ͝\0ڲ:cA#,P|s\t G5BmZ8ex 1Qgj/-#KHd#r*ege# g ?+m [%*F*GuHkWiap0xUU8ӭf)qGk3cZ232m8>=E-,yh 0nt95zI(CֱGs,Z,ukHa/0;20'2\b8=*wnj!@=O?f\]VV6.T18M7N0`Oei/x橧cry7 gr vWciƤwː9>Uܭ$2UǝF?j$L=棕`sRh̟f^I;_^G^Zݫ4;gq*OBWNsη'`wq,qV*JˀG׿4sGW-h928fEʏ`sZVmm,ѽۅFI3ڦ3HUɆY )UsO'[/r6;gL<bN&r;p}=km/%`3%GAټ&61[FWnڱJO`-iVe\ŀ?Z,AV#o&:Ǧ{6, c#=1LI| !G#MvuF+ܪK#m #=Ac>ʳ1;Wf\ռip3Z1Pꪠ `U>sU(K!d `QtzD򴐓A9p+Bl~nx,G@<{B=&)$9S'ЩJm˟q"Oz)%/#H Cz sRj:̚PW$J8*vs RY7b'xcU$ڌ:ZZ#/"F;Θ*zs?A{5QqdbK#U.˨k8YOTcU$q@٢U(wy2m_㌌- SK"q>Q{jۊFGg&buC{*Th"Ca?_Ʋ-!%Wv=;ɥ;f_韔jTWjpGN֡Mg`R K4P5 O^Y9"Fھ'GM[pRI%+3OLљX01 :`Vť kI9`9(nvhY4uR|`rUsE09VlahʰrTj7)#U9Y;&DX؜b._$< lm*Oخ r@Rx;y?*X̂Wf`p{U-oL#wB黖+:,v0>V3̑yM:C {DnǠ2N>G¬vQ}*Ap7"Ȭ]0CpjGYM3zdU2TBgRHX~zSÄh>y+*FV%gې7`{7+NSqHBY#G@rjl HFdH:N1&~JS sH ?ʝ΅+!QUG=>idWaՔyr,qc?(,Hq߭DR@r0έ ?.=7w7ܲ)A$g&wq?dluI-@7#w" ҨѮKqPG{$K#-wVRFrit~ZiрMWŦ` glX#wMu==).Wϖn!cГ2OAԪV`%ԍqseiqGl|Fsjy&Kk%]jg 6=20ĞG9-=32J劏@AkU)اKMO2eg8b2Hs}8Td\Y 16UWw8+5[K]21uz$h?w\=9F944Fw{,-Ī㌒x={}^V<[id$ $k'8Ya4n^(IX!Up2Ğq/yyTq?JSkd\& 2A#JpA= ѷF%12iQ < Ϸ yW%F :a5/WO5")-axpŁ  %^k|%^4]?wec|a2jꚼsʂ_ܪ"\旲L46mpgd#ah{0ť²]({cӊSIX\,ИbA\5"ޤ̋\J&lK3q [֗58.Kn5n$U *Ty25]VQ0[wʐR$n:9Gk@ij6zrq[VVEDǦ, 8Q` TNSHԍmL/K;]JbXl7r?Ҵׅ&D,Ⱦj[ӊ4 r1?ry$V[}96v/߽dt&ScO$gxkcúe\[֗s,3X p2x96r[38ւkImo9S;=Z&;K-&HR=yYSk+oT* ;VnjRyM A0淥o9^J5+vqIbg('ͩ rR3FdvzpIT/nH$t9n{Y#J5QG@GTߙ61 =ֺz0goD $gu ⳟ249*.g0rקG4jp(b٘C/c!̾dX SF6ѝό)<2qkܤ{d?; 02˕T@ &f}J)Yd`A~[@^pGP"r]n@Zr~$TkrlAiZI0wO`*T0&]mFFHF۸({`*F6UNJ++8P1S r\ (wldy#Y p}826,wcT/RfUP;pǸV|~d(G&N?*J /֢y &28U߭4Z{w]fbܝG\ ڨ_j'u,1WcolDi"_ WsT-/#9GJ%M4.kQ-ôaG77;Ov[s1hncv $;gsVݵ\0ے= #r 'KIs=Cj_m$W O= '''G (> 2?Z҇Is&#L?Fx3F;;-ۉ#Y[>YIʌ$8Q t'=;uŧGkP #Lya#6j&2Mz!b 6[Vr6rk.b\(W#~9m=(6gVe_Q}j=/EPI==jm#pr}:m$"i!c;{j@Q5K8:?gQ2(:oY.9Q|q [xf,[*F3tFu,ކI"b5#$}8{0_y4:ǒ{d}+y7'x^x1[«gnVI+;Jhɒ@NY>n8ۓ^29=}I8[!e`7 /Y| wd7ַOCf ,#d0Ãr85F9y`pp8 !`#=)>@Y&Xa򪹓zI?2A!Ďd[̸@0ݓߎ)ApnV<z0 ը-ݔ  $KFU܅dc=:jfU ETҝohn"+M1Rٻ'ޣʎI FK=y\/D9CA?e=Ϸ{*0&wzzRmqؙñ@ }IXJ =#p09>ZfNzsLu]s Kw4汷hʒIǐS/a Us}5#"QBu梷I 1N=RZ:,vPIkhtԤ>@Qvgҳd@O$ϷKixɴ| vGNşBB().ûϿt)݇76|<8,<9{tF] Tߺ隚O$s JdQ=kKY\{"!+L"iQ!]8kMWv8'"ۆyry#=rI0CH4Ck;N;Dc3ONh/%lQr˷QHg Z$ N; iI6c2F LԿz՛Ii #*`TRw %qQ7̙eάJgHw;)RqAYLgɭ"%OR1ʬD7|e{1Fs1ʬD7|eJFIFddDucky<Adobed       !1AQ"2aqBR#3bSC$4rTc%5!1AQa"q2B3Rr# ?$Nī G>UqA3S4p[߅@*xZ!z $mKbxPun0[(B "'Kzy0NAe|J6+d}&œ A"I 6Pn|1"e|܈ }F^CĎ`|(,zp>T@IWnTP#ĉQV7x$M 99hroKhb"d ($H5[߇JF#*ї)Hm&'Yb &I[p#PbI_L<.QBBlY-bª$w#i6"Clex1aOh{mI8q1Yh聆+'8[T؅4ƚD YvL $UҁI/g7`G=p.6RƑGMEے~NH̥O(׍4S-| (*IсVr Hm L%|-`M& CETvUԜ!a 3F~ŐkA<2qk!8ܞU.F&N ._My|)f6ږ 17~CbzDu]G@8+f ԑr~B$oHX! 6ǏUB7l{\Uήm6\_j,`")[aM14rA-Jr4s3[ali{U<Fh"FP &.x)Ias yN'YQJ6@IΤyh Iϝ0&[Ɛ+$ F)8F?a7AE#F9$^' $hv\ `*8$VL 8rju"hi0b%3|¥Xpq0U[y~;`rtb.1,u|6ސcO!@" :KO>tN0;)p igTK@" *C7Br ARgmc"ko b=- vG}1m"GE./1x[b2Ƃ?T!by}rL\E 5"Ȣ v- jeEOo i4|Gmƭ2`iXUqsm+ EQn)64.`|6f5ZT(K6>*%߁T>&,Wѱ] WZdv234HĒ2 m^\8 ͷz͹iNPC'Kx IҔ=;d h)5;[1醐:R=.^Qj{+h^}.ƔʹMoP @[.xW4A'=4_C,ƃ)ACd4nCEa@UF(<ſqm)ȠFUHWQo$6۷&Kn^ch?`06.Txqn XQ5LkU9n"(`ص y` =>>&DT F^1ip5ŵ7ƶƖ=_qvh%2*.upZ_o&z.6d)|(B[r'x|j-S }EAvwԲhr3#oE$9‘{ʷPw@|"v}/@{س1q1+ہ*wob^h䪱y{|B2cS8IM<C>ٳfXd&u$YkX׻yIʪV3~E;Ł2%ao-*ŭq]%YDQ&(q9&Ck W{dO/|ŒU uyqxoy[UNLFe2*|E"ww{r6h;BǍxA]gLhy!T{2䈛p4S'_4yghoϔ"=i 1cјoMՊߍy|=/Z74;w^ݱ+][*Kl*MɵɮqVW[G^$X0sLCbOqw]ӧJə i< Åykf> }"bܲ&oMkX(b sͱl20W)c\ޤm̋{.,8+.Ko_w #\ ,L]L#D(O+hjfbǕ%1fk;Џ’`Ebeʊc(!WAMSIUIVʻL:V*Lw$8{Vve4scBؐN%{q_S`u8P9^?2SmG0|>uwkj2^ChEˏ,܄ 70bW2U{7`lx;C˙3\b` m-ҕ T'|cO><4{i.ɶpwעɏ#ʬ"Ŷ8 4@Dobv<'͑FT1JD&b}WIu?3k1g+$ر=,*"ޣy+u+c&FBu<>5&B@bq6K|V4J9/% 6IynIVݯk#cV<`>4Vz$~Ҕ(g:O|h܃i}OA'Mo$..}HUƾRoҖju&} {TwY|aiݬ;qe[*{S,f6*[.E-ƼCLѕi5Ƭomj% ʝ"4]SGacʊhQrrʭI+K{/=ȖN m$머>%3A휕\x6A8Ÿ7$W|Jeܧ9U@+XP؂?3}4;knɍ06uz:^^I^ٗ'{otdM3NM4oN0Kmp)l_ӈ0o5y)[΃@{蹅W{!ծXݿ.;F߻]AWarZn"P I'_nÏk|ĸm9'\Sc7/r>Q_Lسavӏ]ѣ/a'x$Lĝ/016 [9WZy[^_Ľ(I(0$UG2Q`S+xqErUhô8}rI fݸw~+_MJZUP$72*քE]sqM6XYtmd`UȚ&U+hNS^8G/=fKx=גbM6 .#_H_pO/zIϺ,8dCןz"I >~OV"l_"gՏZv֎ZWSVi@jxWҾFqD~8kwaٌRxǥ|M #|'DZ{Ǚ23KN`vKnPvv騯Ex2nݻDFeNB bI]?u{ /ՒA ?1o~7yzeodI+(L$k~l;N(_:uOQ:6G(1F]@/nx77 `Br`hf4tlDP<$ہpZA$UP۔( B"ˋ eg`uS+ EĎvb f8@qbT\H*|Lmm.Gdʹ0HF >xkֽÕkw:E&1 F uzZ-Q";,3fމIJ, ։($ Nr5-"׻~NŌ,v$]BIP6o}xV|OR4CZ0 *Bn ֖K;ۏn[3NR.u>-Jj/yєt _P9SnPX.c#z{wjHּn'̛) p$iee8w_Aʫ]IYKD&e*xa%F+ h IӐ/RB/UϚx.6ʯG%~(VXrugfsō)$۝)6Gp |+Yߦώ8s1ჼbe BTcɇ:kn=(ѡWp%ʑ{Lv)%b5e1;a_Vj$h/;6N'c#uyLRUk:IXԪh{N^oȐBJE- ^ubK#R̊#bXC#i?Q96<.O?Dž"״aYrfDb-qhw-f&[oSo5MThnDITÐMuNR&DLB'B&- C5+Fm%ф=)I o”X9=KX./T18ؽ\\GĘ{ۭ4qKDDžVMഃλ6nnOHhRX%A}l.M)@>ǃ4K*Ȕي;,t; ;~Ӊ҇{@6`m+>7Va+].(cajɬ'](׽cdvNεdYdW. l]q~ma)my#6rFk/C`irrN[{lA$mP|ޝ} zRV ]REUknYbI*Z,4Ru 8zf',%0iu99ohK迯o:_H$1 .?^lj}{?uY.|DJ-B *wzn|],v1mUzL-NAiYTڰgI2U k>'ZeW):JS^0'hQD#UX )rNJK77 A$ nkؕAHoq&L27QTnkeG)*mlt¢FЏw.J!upAu[6 < ,OSqe*͍ 9 ,pLlB[m֕ԖfOGiZE5`ı!%xubYmc}AFsS۷Ig&y\T.ڞ. M~ōڊ+dr ;3(d*K_(/t;vܑn-ʍ{G˶"}7uԧw, OF¨[X\;ov) ^1{]b,.ESN A$=;9K[IV/e`,QAKm0~DeQLn|4fLTm6 vlHS2{6C&[|@ޝDhfG`R2 ""nMʥji7'iR55ݹ?@r-+z֔0/:!,oOC;mXi'elsΞx9cYO3}E+["_W'[zjd9>c9qen3MrMm^׬iJC#S;4ǑʨH&6HRרaKgX׏!=Ž$_TPl}fsm:c oH L]+.Tw(媪-Cx]¹6;,ۆ@ەPv$q" ,?)MCBwm:3_#O7µLwu|hh^HݖKIweiTdbmAdžJkC>:l*%G!) f,T:\5d]1LC XmĚHcEݙ +3Ih`O.ll'ݑo3U&Áߤ7)ӷcrklXZƥ0qQ3 o7oZNI-T>!T#>:ԭpRŏ{$ѷߥj9%xcfWbeSn᧍ X_idY7k9ߌUUymu$+NI6H7@Q~f7/~~4׷{ z})WQY8"129kg6|*)WC-=? RD"#|<֭] =[I xeQ jrO?C#d87 Kp8 e:8踦| P0[)`x=\M[Q5k9vlULI\{:^Ƣ-U &>mie͍s,_Ll-$]:J ln_.3q",ܟ /K!ŷa%6kƱ4G/fņ\l%A+ cKnBOy@ȸ}J/8i2``:ҽzv\ vBnH2Zs1Cwq'ϓUlGW Jz>ʗq#a6HY1XsvVM*Ǵ&||1ec6pXى lp"c 19{n'ǝrjm%jwn{|ɉ&MEǘʪ]뽜2g|y12f?MqBx/3ѰLȫ  {v[cc ђ&8n4r#*l.r8RPZʪM[Ó ]cfY'676[r-rz1Qzl( [ӕa y$g26nϭm5ۥOg%0c:ˢي ZHo3cdJc׳ һF]x%{{.?rcGDe&u:(]7ݙf`!EAM!'JH<$fO 3 p_s"C2R~+i01b|GS8=+ (K1D{w452m,VٓHcxXǍXnGt ;J/9A,]WNHEe#Sh/f{.nmH$Ppp~Ǔ*VV(َfmZT].m~O _~cPqcR%l^@\Vwo8۱9|x[jqC4}q#qﳂ :e&UL5?.# K@bOD M .R*820vNNl9| s'e 0ncƛ`YR5Pd טmK<I#yB$X iS܅T X)r4+! iԭaUd2ZmS%.:\s] j|*<SsݥM{\/rX:WR&A$\uSAkܓ~<e8Xpnu$^n2_HFZ&ʭŖ:@I\0P-4!I(y/Rxh8 W(dT^rpv*&/뛖亙tC,l]A+;rxel)UPqIqk TW!wH0ﶬEisr?bj881cmx7$nm:]6FTͅz1?~6 mwVz #o)HS$v:|4?Q6er C~g*e1-p~ԥ2|GVRaܓLC,9<Nԁ^E#!\c#!6+O6/.Cj,$Oo U@<7[*L.OVX_Ӏ;qpu?gkR3F  uH[,"o!m,y" $uQ@9W5lJ]/ZGx<4k+Nou5M:ƅY'pV.?ÝQ%~%%g,Hu7AE|xBEx}'!@/LG9 \Z>.u,f_>H _.4؆?}+B.W̧yq ;P"K}|jƾn{+b?#;vNKz} o6ƸWj.vktp巟u]D&er$",f"6[W(@=,f"6[W( UffOxڭVKkQ>w4mbؗe[R[FP(Ը0B\(+!&i. ąEƅ.T\NɹaD×w_sD&?P0 < xa oA'0cQ3' p=2 qA{h1TvVw 쏢?ƁC3DD,oB<T{gihv=hCgU/_<{Jͮ %bۅ#T"Ύ 5 SPZCPmTlj0FzavvJK4s+?ת9񴚳ƶrO^٬`z^FZXR #5.d欩l63E]^OlGJFq*W 1U 8Dmsy (Yc9o*pvU.:.s5u֣ j+Zl%7dvV}RC0W% ŕbj\]|f\ )a F9(|QH2߿n8}j}uqUz:dtd75Vvv |Rܔ/;i.Іc;v|9;8ѳbcnOLϿ@1X_ yyz1"9 oHN{ ܄%/~R#-Ԛ\B!Rtq~ϽJCustom format dd MMM yyyy hh:mm:ss- now standard M dd yy hh:mmdSet the date to be 18 February, 1998 11:23:28format dd MMM yyyy hh:mm:ss- now standard M dd yy hh:mm/Formula - Simple sum. Modify one of the values Modify to 6.8Formula - Complicated formulaGrey backgroundRed backgroundBackground colours"Blue background, yellow foregroundA labelNThis label will change - consequently this string will no longer be referenced All entriesin this columnare boldarialverticalplus 90minus 90URLrelative file linkabsolute file linkhttp://www.andykhan.com/..\jexcelapi\docs\index.html!d:\home\jexcelapi\docs\index.html,URL - modified to www.andykhan.com/jexcelapi/relative file link - modify number of up-levels!absolute file link - link removedRemove this rowRemove this hyperlinkHyperlink to another cell Numbers test Merged cellsSome more merged cells more mergedModified row heightAfter a page breakA Chart Chart data'Some chart data values will be modifiedCross sheet formulamodified!b10 / 2ROUND(COS(original!B10),2).Blue background, yellow foreground with borderRed background with borderDrag and Drop FormulasValuesForm 1Form 2Named cell formula value1+value2AVERAGE(value1,value1*4,value2) Boolean Value?Blue background, yellow foreground - modified to red backgroundImages Bodiam CastleRichborough Roman fortReplaced by Little Moreton Hall Red background with green borderRed background with blue borderDropdown data validationList using cell referencesTextbarneyCommentsA cell with a comment)Another cell comment - comment is altered A form buttonA control button#A cell with a comment to be removed Grouped rowsAEntire row below has data validation. Change the accepted valuesAEntire row below has data validation. Change the validation rangeb Xsz`%[(+R (ɀ (mMZ  dMbP?_*+%>c&LLeft&Ccenter &Rright &Cpage &P&~?'~?(M&d2?)M&d2?M\\ATLAS\PBMTDORF01N59.PRINTERS.C 4dXA4DINU"4|#0|IUPHdA4 [none] [none]Arial4P d?U780171<Automatic> EXCEL.EXE" 2XM&d2?M&d2?cU} $'} } }   h     ,                      0 0      0?@@@@@@           !  "   DAT! @ #  ~ ." ~ ."  ~ 1@   @  H  xVA@ !xVA@ !xVA@ ~ [@~ k@~ t@ ~ {@~ @#0@ % "-l>u.SDD AUu.S " # + ,@ .@ /@ 0@ :N  ;O $ -? $I> 0P**. ( 'Qb* '()+,.1236 78 9;@> %$ &% '& '' '(* '(( (( ((+ ((( )) )), )(( +0 +(* +((( ,1 ,(* ,((( .2 .)3 .(( 1<41<<<<2<<<<<3<<<<< 6<57< 7=6 7>?8< 8@AB9< ;7 >8$&,****,,* & @ABCDEFGHIJKOR STUVWXYZ[\] ^ @9 A; B*:~ C*?~ D*@~ E*@~ F*@~ G*@~ H*@~ I*@~ J* @~ K*"@ O<)ODAT!? Z @@ O= SA S1B S2C S3D~ T4?T6UUUUUU?T DT!T7UUUUUU?O DTDT~ U4@U6UUUUUU?UUU] LU7UUUUUU@TUU] LL~ V4@V6?VUV7@UU~ W4@W6UUUUUU?WUW7UUUUUU@VU~ X4@X6?XUX7@WU~ Y4@Y6?YUY7@XU~ Z4@Z6?ZUZ7@YU~ [4@[6?[U[7@ZU~ \4@\6?\U\7@[U~ ]5@]8?]U]9@\U8cI8V|LLLLLLLLikuv iJ kK uL vM < P Q~ @~ ?~ @ R S~ @~ @~ @~ @ T U V Y** Z~ ?~ @~ @~ @~ @~ @~  @~ "@ [ \ ]] \4 ( 3 p  6NMM?? L]`,e  (ɀ",e??3` ! ` ! ` ! _3d23 M NM4  3Q:B  Chart dataQ ;CKQQ3_4E4D $% M3O& Q4$% M3O&Q4FA' 3O ) 3 bo#M43*#M! M4% :& M3O-&Q X value'4% S)MZ3O&&Q y vale'4523  O43" c 3Oc % M "3OQ4444% WMp 3O9Q'44 eee vn  C 4Abodiam_castleir]&`frj  C 0ArichboroughuZ]&`f~~  <թ XPP? kx]4@թHg zwHPD162B  "<#andyk: A cell comment in a big box<! r "xx  6(֩XPP? kx]4@(֩@h (~#M =X <andyk: Another cell comment<! ^ ~~  <֩XPP?kx]4 @֩xi DDanD:a #<$andyk: This comment will be removed<!  #andyk#andyk# U780171>@<P1369787f''yK yK 2http://www.andykhan.com/((yK FJEXCEL~1\docs\INDEX~1.HTM82jexcelapi\docs\index.html))yK Fdocs\INDEX~1.HTM$docs\index.htmlf++yK yK 2http://www.andykhan.com/f,,yK yK 2http://www.andykhan.com/D..yK modified!A9:B14/  %mC  fred barney wilma bettyw f cMadeline Bassett Roderick Glossop Pongo Twistleton Barmy Fungy-Phipps Catsmeat Potter-PirbrightnY 3 0Powell Montgomery Lewis Bailey Smith Greene Sheet1ggD (ɀ (}w   dMbP?_*+%&\.?'\.?(\.?)\.?MSametime Print Capture dA4`'4 " d,M&d2?M&d2?U} I$} $} }   h h    ,        @     0?@@@@@@     !"#$%&'()*,-./0123456789:<=>?@ABCDEFGHIJKLNOQSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~@2iwu.S DD Ad͐v "  $I8*&P  ( 'Q'()+,123 '- '(* '(( (. ((+ ((( )/ )), )(( +0 +(* +((( ,1 ,(* ,((( 1<41<<<<2<<<<<3<<<<<***,, ABCDEFGHIJKLOPRST A9 B; C*:~ D*?~ E*@~ F*@~ G*@~ H*@~ I*@~ J*@~ K* @~ L*"@ O<O? DD P> RE SF TG&a@-ijklmnopqrstuvwxyz{|}~ iJij kKklmnopqrst uLu vMvwxyz{|}~2    X W P Q~ @~ ?~ @ R S~ @~ @~ @~ @ T U V Y: 44 Z~ ?~ @~ @~ @~ @~ @~  @~ "@ [ \  ] \  (  p  6NMM?>Lx]`j  (ɀ"j??3` ! ` ! ` ! 迏3d23 M NM4  3Q:C  Chart dataQ ;DLQQ3_4E4D $% M3O&Q4$% M3O&Q4FAV R3O< G 3 bo#M43*#M! M4% N; M3O3&Q x value'4% TMZ3O5&Q y value'4523  O43"  z3O % M "3OQ4444% HMp 3O@Q'44 eee vn  C 4Abodiam_castleir]&`&rj  C 0ArichboroughuZ]&`&  TA ?@CommandButton1pZ]` L'1 6$Forms.CommandButton.1Pxx  6lcbXPP? _-Z]4@lcb( /YKlk춿X <andyk: Another cell comment<&r~~  <CC@<0],@t)$9 $ <A form button<N ~~   < XPP? _i]4 @l* `z@YAꬅ+ "<#andyk: A cell comment in a big box<&"~~   <TXPP?_i]4 @Td+ .MQKð #<$andyk: This comment will be removed<&  #ZR  C R]F!\,  andykandyk U780171>@ 137f''yK yK 2http://www.andykhan.com/((yK FJEXCEL~1\docs\INDEX~1.HTM82jexcelapi\docs\index.html))yK Fdocs\INDEX~1.HTM$docs\index.htmlf++yK yK 2http://www.andykhan.com/f,,yK yK 2http://www.andykhan.com//  %yC  fred barney wilma bettyw f cMadeline Bassett Roderick Glossop Pongo Twistleton Barmy Fungy-Phipps Catsmeat Potter-PirbrightnY 3 0Powell Montgomery Lewis Bailey Smith Greene Sheet2 VBAp%%`,%Sheet1 vSheet2 ThisWorkbook +SLSS<N0{00020820-0000-0000-C000-000000000046}x h@%@@" ophٰAttribute VB_Name = "She@et1" Bast0{00020820- C$0046} |Global!SpacFalse dCreatablPre declaIdTru BExposeTemplateDeriv$BustomlizD2P Sub CommandButton1_Click() End  d0HIcx,CommandButton1, 4, 0, MSForms, CommandButtonME(SLSSsN0{00020820-0000-0000-C000-000000000046} h@% %*)pX@x@x*\R8004*#5d" 8HE143$B@H;ZHello ( Ҍ;}o@82Attribute VB_Name = "She@et2" Bast0{00020820- C$0046} |Global!SpacFalse dCreatablPre declaIdTru BExposeTemplateDeriv$Bustom izD2ControlCommandButton1, 4, 0, MSForms, P<@ Sub 1_Click() Range("E143").@Select Act[Cell./ulaR1C1CH o/End- #xME (SLSS<N0{00020819-0000-0000-C000-000000000046}8(%HxAttribute VB_Name = "ThisWorkbook" Bas0{00020P819-0C$0046} |GlobalSpacFalse dCreatablPredeclaIdTru BExposeTemplateDerivBustomizD2GxMEModule1;V__SRP_2 M__SRP_3Pg_VBA_PROJECTR (6 << <x &` $p%H@rC $*\Rffff*0P4c1f97e3" $ HXE145$B@H;ZHello from a form button ( o0(Attribute VB_Name = "Module1" Sub form_ton_macro() Range("E145").Select.ActiveCell.FrulaR1C 1H&o from a gEnd k rU~| 0  krU $`nas  *\G{000204EF-0000-0000-C000-000000000046}#4.0#9#C:\Program Files\Common Files\Microsoft Shared\VBA\VBA6\VBE6.DLL#Visual Basic For Applications*\G{00020813-0000-0000-C000-000000000046}#1.4#0#C:\Program Files\Microsoft Office\Office10\EXCEL.EXE#Microsoft Excel 10.0 Object Library*\G{00020430-0000-0000-C000-000000000046}#2.0#0#C:\WINDOWS\system32\stdole2.tlb#OLE Automation&*\G{2DF8D04C-5BFA-101B-BDE5-00AA0044DE52}#2.2#0#C:\Program Files\Common Files\Microsoft Shared\Office10\MSO.DLL#Microsoft Office 9.0 Object Library*\G{0D452EE1-E08F-101A-852E-02608C4D0BB4}#2.0#0#C:\WINDOWS\system32\FM20.DLL#Microsoft Forms 2.0 Object Library*\G{90C98242-9A7E-468C-8248-6A6B122F5184}#2.0#0#C:\data\u780171\Temp\Excel8.0\MSForms.exd#Microsoft Forms 2.0 Object Library.E .`M   rC  Sheet10K4c1f97e3 Sheet1 Sheet20O4c1f97e3 Sheet2INThisWorkbook0M4c1f97e3#ThisWorkbook0%Module10P4c1f97e3$Module1GHhH0~*wKa/#2b%\)ǠJ FYErͻ\c)*A{$|<@'Excel+VBAWin16~Win32MacVBA6# VBAProjectstdole`OfficeuMSFormsCSheet1 _EvaluateCommandButton1_ClickSheet2Range  ActiveCell FormulaR1C1S ThisWorkbook|Module1bform_button_macrocCommandButton1|Workbookk Worksheetx  # % H)0* pHd VBAProject4@j = r rC J< rstdole>stdole h%^*\Gdir-__SRP_0__SRP_1NPROJECTwmk{00020430-C 0046}#2.0#0#C:\WINDOWS\syst em32\e2.tlb#OLE Automation`EOffDicEOficEE2DF8D04C-5BFA-101B-BDE5EAAC42Egram Files\CommonMicrosoft Shared\@10\MSO.DLL# 9.0 Ob LibrarFyJMSForms>BSFr@ms3D452EE@1-E08F_A-8-02608C4D0BB4aRFM20 'B _&/;"1Cj qAq00}t#0q# 504 |A90C98242-9A7E-468C-8-6A6B122F5186data\u780171\Temp\Excel8.`4.exda9.E .`(M "Sheet1GSet1H2NHB1`B,"B+B*222 2 N I A|ThisWorkbookG *TiPWRkbbok 2o%p kbc`odule.cco u".2g ůİG!b.#/bK*srU~~~~~~~~k O$6{If S(     a qAA  )  VBAProjectSheet1Sheet2 ThisWorkbookModule1F /C:\PROGRA~1\COMMON~1\MICROS~1\VBA\VBA6\VBE6.DLLVBA Y 0F4C:\Program Files\Microsoft Office\Office10\EXCEL.EXEExcel Qy@0FC:\WINDOWS\system32\stdole2.tlbstdole aPL-[DR?C:\Program Files\Common Files\Microsoft Shared\Office10\MSO.DLLOffice a`.E .`M C:\WINDOWS\system32\FM20.DLLMSForms pBɐ~FHjk/Q )C:\data\u780171\Temp\Excel8.0\MSForms.exd aform_button_macro rU tSheet1Sheet1Sheet2Sheet2ThisWorkbookThisWorkbookModule1Module1ID="{059960D3-9F38-461E-BCFA-8ACF631C6950}" Document=Sheet1/&H00000000 Document=Sheet2/&H00000000 Document=ThisWorkbook/&H000PROJECT\SummaryInformation(DocumentSummaryInformation8(CompObjf00000 Module=Module1 Name="VBAProject" HelpContextID="0" VersionCompatible32="393222000" CMG="7C7E958697639B639B639B639B" DPB="5D5FB4A9748B758B758B" GC="3E3CD7C459443B453B45C4" [Host Extender Info] &H00000001={3832D640-CF90-11CF-8E43-00A0C911005A};VBE;&H00000000 &H00000002={00020818-0000-0000-C000-000000000046};Excel8.0;&H00000000 [Workspace] Sheet1=88, 89, 716, 548, C Sheet2=132, 132, 760, 592, C ThisWorkbook=0, 0, 0, 0, C Module1=44, 44, 836, 511, C Oh+'0HPp Chase Manhattan BankJPMorgan Chase & Co.Microsoft Excel@ʬx@^ @%՜.+,D՜.+,L PXd lt| /  original modifiedDatesLabels nametestNumbersoriginal!Print_Areavalue1value2  Worksheets Named Ranges 8@ _PID_HLINKSAPBpamodified!A9:B14OJhttp://www.andykhan.com/OJhttp://www.andykhan.com/ ldocs\index.htmlX7..\jexcelapi\docs\index.htmlOJhttp://www.andykhan.com/OJhttp://www.andykhan.com/OJhttp://www.andykhan.com/ ldocs\index.htmlX7..\jexcelapi\docs\index.htmlOJhttp://www.andykhan.com/ FMicrosoft Excel WorksheetBiff8Excel.Sheet.89q