1 2 /* ==================================================================== 3 * The Apache Software License, Version 1.1 4 * 5 * Copyright (c) 2002 The Apache Software Foundation. All rights 6 * reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in 17 * the documentation and/or other materials provided with the 18 * distribution. 19 * 20 * 3. The end-user documentation included with the redistribution, 21 * if any, must include the following acknowledgment: 22 * "This product includes software developed by the 23 * Apache Software Foundation (http://www.apache.org/)." 24 * Alternately, this acknowledgment may appear in the software itself, 25 * if and wherever such third-party acknowledgments normally appear. 26 * 27 * 4. The names "Apache" and "Apache Software Foundation" and 28 * "Apache POI" must not be used to endorse or promote products 29 * derived from this software without prior written permission. For 30 * written permission, please contact apache@apache.org. 31 * 32 * 5. Products derived from this software may not be called "Apache", 33 * "Apache POI", nor may "Apache" appear in their name, without 34 * prior written permission of the Apache Software Foundation. 35 * 36 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 37 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 38 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 39 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR 40 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 41 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 42 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 43 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 44 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 45 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 46 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 47 * SUCH DAMAGE. 48 * ==================================================================== 49 * 50 * This software consists of voluntary contributions made by many 51 * individuals on behalf of the Apache Software Foundation. For more 52 * information on the Apache Software Foundation, please see 53 * <http://www.apache.org/>. 54 */ 55 56 /* 57 * MulRKRecord.java 58 * 59 * Created on November 9, 2001, 4:53 PM 60 */ 61 package org.apache.poi.hssf.record; 62 63 import java.util.ArrayList; 64 65 import org.apache.poi.util.LittleEndian; 66 import org.apache.poi.hssf.util.RKUtil; 67 68 /** 69 * Used to store multiple RK numbers on a row. 1 MulRk = Multiple Cell values. 70 * HSSF just converts this into multiple NUMBER records. READ-ONLY SUPPORT!<P> 71 * REFERENCE: PG 330 Microsoft Excel 97 Developer's Kit (ISBN: 1-57231-498-2)<P> 72 * @author Andrew C. Oliver (acoliver at apache dot org) 73 * @version 2.0-pre 74 */ 75 76 public class MulRKRecord 77 extends Record 78 { 79 public final static short sid = 0xbd; 80 //private short field_1_row; 81 private int field_1_row; 82 private short field_2_first_col; 83 private ArrayList field_3_rks; 84 private short field_4_last_col; 85 86 /** Creates new MulRKRecord */ 87 88 public MulRKRecord() 89 { 90 } 91 92 /** 93 * Constructs a MulRK record and sets its fields appropriately. 94 * 95 * @param id id must be 0xbd or an exception will be throw upon validation 96 * @param size the size of the data area of the record 97 * @param data data of the record (should not contain sid/len) 98 */ 99 100 public MulRKRecord(short id, short size, byte [] data) 101 { 102 super(id, size, data); 103 } 104 105 /** 106 * Constructs a MulRK record and sets its fields appropriately. 107 * 108 * @param id id must be 0xbd or an exception will be throw upon validation 109 * @param size the size of the data area of the record 110 * @param data data of the record (should not contain sid/len) 111 * @param offset of data 112 */ 113 114 public MulRKRecord(short id, short size, byte [] data, int offset) 115 { 116 super(id, size, data, offset); 117 } 118 119 //public short getRow() 120 public int getRow() 121 { 122 return field_1_row; 123 } 124 125 /** 126 * starting column (first cell this holds in the row) 127 * @return first column number 128 */ 129 130 public short getFirstColumn() 131 { 132 return field_2_first_col; 133 } 134 135 /** 136 * ending column (last cell this holds in the row) 137 * @return first column number 138 */ 139 140 public short getLastColumn() 141 { 142 return field_4_last_col; 143 } 144 145 /** 146 * get the number of columns this contains (last-first +1) 147 * @return number of columns (last - first +1) 148 */ 149 150 public int getNumColumns() 151 { 152 return field_4_last_col - field_2_first_col + 1; 153 } 154 155 /** 156 * returns the xf index for column (coffset = column - field_2_first_col) 157 * @return the XF index for the column 158 */ 159 160 public short getXFAt(int coffset) 161 { 162 return (( RkRec ) field_3_rks.get(coffset)).xf; 163 } 164 165 /** 166 * returns the rk number for column (coffset = column - field_2_first_col) 167 * @return the value (decoded into a double) 168 */ 169 170 public double getRKNumberAt(int coffset) 171 { 172 return RKUtil.decodeNumber((( RkRec ) field_3_rks.get(coffset)).rk); 173 } 174 175 /** 176 * called by the constructor, should set class level fields. Should throw 177 * runtime exception for bad/icomplete data. 178 * 179 * @param data raw data 180 * @param size size of data 181 */ 182 183 protected void fillFields(byte [] data, short size, int offset) 184 { 185 //field_1_row = LittleEndian.getShort(data, 0 + offset); 186 field_1_row = LittleEndian.getUShort(data, 0 + offset); 187 field_2_first_col = LittleEndian.getShort(data, 2 + offset); 188 field_3_rks = parseRKs(data, 4, offset, size); 189 field_4_last_col = LittleEndian.getShort(data, 190 (field_3_rks.size() * 6) 191 + 4 + offset); 192 } 193 194 private ArrayList parseRKs(byte [] data, int offset, int recoffset, 195 short size) 196 { 197 ArrayList retval = new ArrayList(); 198 199 for (; offset < size - 2; ) 200 { 201 RkRec rec = new RkRec(); 202 203 rec.xf = LittleEndian.getShort(data, offset + recoffset); 204 offset += 2; 205 rec.rk = LittleEndian.getInt(data, offset + recoffset); 206 offset += 4; 207 retval.add(rec); 208 } 209 return retval; 210 } 211 212 public String toString() 213 { 214 StringBuffer buffer = new StringBuffer(); 215 216 buffer.append("[MULRK]\n"); 217 buffer.append("firstcol = ") 218 .append(Integer.toHexString(getFirstColumn())).append("\n"); 219 buffer.append(" lastcol = ") 220 .append(Integer.toHexString(getLastColumn())).append("\n"); 221 for (int k = 0; k < getNumColumns(); k++) 222 { 223 buffer.append("xf").append(k).append(" = ") 224 .append(Integer.toHexString(getXFAt(k))).append("\n"); 225 buffer.append("rk").append(k).append(" = ") 226 .append(getRKNumberAt(k)).append("\n"); 227 } 228 buffer.append("[/MULRK]\n"); 229 return buffer.toString(); 230 } 231 232 /** 233 * called by constructor, should throw runtime exception in the event of a 234 * record passed with a differing ID. 235 * 236 * @param id alleged id for this record 237 */ 238 239 protected void validateSid(short id) 240 { 241 if (id != sid) 242 { 243 throw new RecordFormatException("Not a MulRKRecord!"); 244 } 245 } 246 247 public short getSid() 248 { 249 return this.sid; 250 } 251 252 public int serialize(int offset, byte [] data) 253 { 254 throw new RecordFormatException( 255 "Sorry, you can't serialize a MulRK in this release"); 256 } 257 } 258 259 class RkRec 260 { 261 public short xf; 262 public int rk; 263 } 264