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 short field_2_first_col; 82 private ArrayList field_3_rks; 83 private short field_4_last_col; 84 85 /** Creates new MulRKRecord */ 86 87 public MulRKRecord() 88 { 89 } 90 91 /** 92 * Constructs a MulRK record and sets its fields appropriately. 93 * 94 * @param id id must be 0xbd or an exception will be throw upon validation 95 * @param size the size of the data area of the record 96 * @param data data of the record (should not contain sid/len) 97 */ 98 99 public MulRKRecord(short id, short size, byte [] data) 100 { 101 super(id, size, data); 102 } 103 104 /** 105 * Constructs a MulRK record and sets its fields appropriately. 106 * 107 * @param id id must be 0xbd or an exception will be throw upon validation 108 * @param size the size of the data area of the record 109 * @param data data of the record (should not contain sid/len) 110 * @param offset of data 111 */ 112 113 public MulRKRecord(short id, short size, byte [] data, int offset) 114 { 115 super(id, size, data, offset); 116 } 117 118 public short getRow() 119 { 120 return field_1_row; 121 } 122 123 /** 124 * starting column (first cell this holds in the row) 125 * @return first column number 126 */ 127 128 public short getFirstColumn() 129 { 130 return field_2_first_col; 131 } 132 133 /** 134 * ending column (last cell this holds in the row) 135 * @return first column number 136 */ 137 138 public short getLastColumn() 139 { 140 return field_4_last_col; 141 } 142 143 /** 144 * get the number of columns this contains (last-first +1) 145 * @return number of columns (last - first +1) 146 */ 147 148 public int getNumColumns() 149 { 150 return field_4_last_col - field_2_first_col + 1; 151 } 152 153 /** 154 * returns the xf index for column (coffset = column - field_2_first_col) 155 * @return the XF index for the column 156 */ 157 158 public short getXFAt(int coffset) 159 { 160 return (( RkRec ) field_3_rks.get(coffset)).xf; 161 } 162 163 /** 164 * returns the rk number for column (coffset = column - field_2_first_col) 165 * @return the value (decoded into a double) 166 */ 167 168 public double getRKNumberAt(int coffset) 169 { 170 return RKUtil.decodeNumber((( RkRec ) field_3_rks.get(coffset)).rk); 171 } 172 173 /** 174 * called by the constructor, should set class level fields. Should throw 175 * runtime exception for bad/icomplete data. 176 * 177 * @param data raw data 178 * @param size size of data 179 */ 180 181 protected void fillFields(byte [] data, short size, int offset) 182 { 183 field_1_row = LittleEndian.getShort(data, 0 + offset); 184 field_2_first_col = LittleEndian.getShort(data, 2 + offset); 185 field_3_rks = parseRKs(data, 4, offset, size); 186 field_4_last_col = LittleEndian.getShort(data, 187 (field_3_rks.size() * 6) 188 + 4 + offset); 189 } 190 191 private ArrayList parseRKs(byte [] data, int offset, int recoffset, 192 short size) 193 { 194 ArrayList retval = new ArrayList(); 195 196 for (; offset < size - 2; ) 197 { 198 RkRec rec = new RkRec(); 199 200 rec.xf = LittleEndian.getShort(data, offset + recoffset); 201 offset += 2; 202 rec.rk = LittleEndian.getInt(data, offset + recoffset); 203 offset += 4; 204 retval.add(rec); 205 } 206 return retval; 207 } 208 209 public String toString() 210 { 211 StringBuffer buffer = new StringBuffer(); 212 213 buffer.append("[MULRK]\n"); 214 buffer.append("firstcol = ") 215 .append(Integer.toHexString(getFirstColumn())).append("\n"); 216 buffer.append(" lastcol = ") 217 .append(Integer.toHexString(getLastColumn())).append("\n"); 218 for (int k = 0; k < getNumColumns(); k++) 219 { 220 buffer.append("xf").append(k).append(" = ") 221 .append(Integer.toHexString(getXFAt(k))).append("\n"); 222 buffer.append("rk").append(k).append(" = ") 223 .append(getRKNumberAt(k)).append("\n"); 224 } 225 buffer.append("[/MULRK]\n"); 226 return buffer.toString(); 227 } 228 229 /** 230 * called by constructor, should throw runtime exception in the event of a 231 * record passed with a differing ID. 232 * 233 * @param id alleged id for this record 234 */ 235 236 protected void validateSid(short id) 237 { 238 if (id != sid) 239 { 240 throw new RecordFormatException("Not a MulRKRecord!"); 241 } 242 } 243 244 public short getSid() 245 { 246 return this.sid; 247 } 248 249 public int serialize(int offset, byte [] data) 250 { 251 throw new RecordFormatException( 252 "Sorry, you can't serialize a MulRK in this release"); 253 } 254 } 255 256 class RkRec 257 { 258 public short xf; 259 public int rk; 260 } 261