1 /
55
56
61 package org.apache.poi.hssf.record;
62
63 import java.util.Stack;
64 import java.util.List;
65
66 import org.apache.poi.util.LittleEndian;
67 import org.apache.poi.hssf.record.formula.*;
68
69
75
76 public class FormulaRecord
77 extends Record
78 implements CellValueRecordInterface, Comparable
79 {
80
81 public static final boolean EXPERIMENTAL_FORMULA_SUPPORT_ENABLED=true;
82
83 public static final short sid =
84 0x06;
85
86 private short field_1_row;
87 private short field_2_column;
88 private short field_3_xf;
89 private double field_4_value;
90 private short field_5_options;
91 private int field_6_zero;
92 private short field_7_expression_len;
93 private Stack field_8_parsed_expr;
94
95 private byte[] all_data;
96
97
98
99
100 public FormulaRecord()
101 {
102 field_8_parsed_expr = new Stack();
103 }
104
105
113
114 public FormulaRecord(short id, short size, byte [] data)
115 {
116 super(id, size, data);
117 }
118
119
128
129 public FormulaRecord(short id, short size, byte [] data, int offset)
130 {
131 super(id, size, data, offset);
132 }
133
134 protected void fillFields(byte [] data, short size, int offset)
135 {
136 if (EXPERIMENTAL_FORMULA_SUPPORT_ENABLED) {
137 field_1_row = LittleEndian.getShort(data, 0 + offset);
138 field_2_column = LittleEndian.getShort(data, 2 + offset);
139 field_3_xf = LittleEndian.getShort(data, 4 + offset);
140 field_4_value = LittleEndian.getDouble(data, 6 + offset);
141 field_5_options = LittleEndian.getShort(data, 14 + offset);
142 field_6_zero = LittleEndian.getInt(data, 16 + offset);
143 field_7_expression_len = LittleEndian.getShort(data, 20 + offset);
144 field_8_parsed_expr = getParsedExpressionTokens(data, size,
145 offset);
146
147 } else {
148 all_data = new byte[size+4];
149 LittleEndian.putShort(all_data,0,sid);
150 LittleEndian.putShort(all_data,2,size);
151 System.arraycopy(data,offset,all_data,4,size);
152 }
153
154 }
155
156 private Stack getParsedExpressionTokens(byte [] data, short size,
157 int offset)
158 {
159 Stack stack = new Stack();
160 int pos = 22 + offset;
161
162 while (pos < size)
163 {
164 Ptg ptg = Ptg.createPtg(data, pos);
165
166 pos += ptg.getSize();
167 stack.push(ptg);
168 }
169 return stack;
170 }
171
172 public void setRow(short row)
173 {
174 field_1_row = row;
175 }
176
177 public void setColumn(short column)
178 {
179 field_2_column = column;
180 }
181
182 public void setXFIndex(short xf)
183 {
184 field_3_xf = xf;
185 }
186
187
192
193 public void setValue(double value)
194 {
195 field_4_value = value;
196 }
197
198
203
204 public void setOptions(short options)
205 {
206 field_5_options = options;
207 }
208
209
213
214 public void setExpressionLength(short len)
215 {
216 field_7_expression_len = len;
217 }
218
219 public short getRow()
220 {
221 return field_1_row;
222 }
223
224 public short getColumn()
225 {
226 return field_2_column;
227 }
228
229 public short getXFIndex()
230 {
231 return field_3_xf;
232 }
233
234
239
240 public double getValue()
241 {
242 return field_4_value;
243 }
244
245
250
251 public short getOptions()
252 {
253 return field_5_options;
254 }
255
256
260
261 public short getExpressionLength()
262 {
263 return field_7_expression_len;
264 }
265
266
271
272 public void pushExpressionToken(Ptg ptg)
273 {
274 field_8_parsed_expr.push(ptg);
275 }
276
277
282
283 public Ptg popExpressionToken()
284 {
285 return ( Ptg ) field_8_parsed_expr.pop();
286 }
287
288
293
294 public Ptg peekExpressionToken()
295 {
296 return ( Ptg ) field_8_parsed_expr.peek();
297 }
298
299
303
304 public int getNumberOfExpressionTokens()
305 {
306 return field_8_parsed_expr.size();
307 }
308
309
314
315 public List getParsedExpression()
316 {
317 return ( List ) field_8_parsed_expr;
318 }
319
320
326
327 protected void validateSid(short id)
328 {
329 if (id != sid)
330 {
331 throw new RecordFormatException("NOT A FORMULA RECORD");
332 }
333 }
334
335 public short getSid()
336 {
337 return sid;
338 }
339
340
347
348 public int serialize(int offset, byte [] data)
349 {
350 if (EXPERIMENTAL_FORMULA_SUPPORT_ENABLED) {
351 int ptgSize = getTotalPtgSize();
352
353 LittleEndian.putShort(data, 0 + offset, sid);
354 LittleEndian.putShort(data, 2 + offset, ( short ) (22 + ptgSize));
355 LittleEndian.putShort(data, 4 + offset, getRow());
356 LittleEndian.putShort(data, 6 + offset, getColumn());
357 LittleEndian.putShort(data, 8 + offset, getXFIndex());
358 LittleEndian.putDouble(data, 10 + offset, getValue());
359 LittleEndian.putShort(data, 18 + offset, getOptions());
360 LittleEndian.putInt(data, 20 + offset, field_6_zero);
361 LittleEndian.putShort(data, 24 + offset, getExpressionLength());
362 serializePtgs(data, 26+offset);
363 } else {
364 System.arraycopy(all_data,0,data,offset,all_data.length);
365 }
366 return getRecordSize();
367 }
368
369
370
371
372 public int getRecordSize()
373 {
374 int retval =0;
375
376 if (EXPERIMENTAL_FORMULA_SUPPORT_ENABLED) {
377 retval = getTotalPtgSize() + 26;
378 } else {
379 retval =all_data.length;
380 }
381 return retval;
382
383
384 }
385
386 private int getTotalPtgSize()
387 {
388 List list = getParsedExpression();
389 int retval = 0;
390
391 for (int k = 0; k < list.size(); k++)
392 {
393 Ptg ptg = ( Ptg ) list.get(k);
394
395 retval += ptg.getSize();
396 }
397 return retval;
398 }
399
400 private void serializePtgs(byte [] data, int offset)
401 {
402 int pos = offset;
403
404 for (int k = 0; k < field_8_parsed_expr.size(); k++)
405 {
406 Ptg ptg = ( Ptg ) field_8_parsed_expr.get(k);
407
408 ptg.writeBytes(data, pos);
409 pos += ptg.getSize();
410 }
411 }
412
413 public boolean isBefore(CellValueRecordInterface i)
414 {
415 if (this.getRow() > i.getRow())
416 {
417 return false;
418 }
419 if ((this.getRow() == i.getRow())
420 && (this.getColumn() > i.getColumn()))
421 {
422 return false;
423 }
424 if ((this.getRow() == i.getRow())
425 && (this.getColumn() == i.getColumn()))
426 {
427 return false;
428 }
429 return true;
430 }
431
432 public boolean isAfter(CellValueRecordInterface i)
433 {
434 if (this.getRow() < i.getRow())
435 {
436 return false;
437 }
438 if ((this.getRow() == i.getRow())
439 && (this.getColumn() < i.getColumn()))
440 {
441 return false;
442 }
443 if ((this.getRow() == i.getRow())
444 && (this.getColumn() == i.getColumn()))
445 {
446 return false;
447 }
448 return true;
449 }
450
451 public boolean isEqual(CellValueRecordInterface i)
452 {
453 return ((this.getRow() == i.getRow())
454 && (this.getColumn() == i.getColumn()));
455 }
456
457 public boolean isInValueSection()
458 {
459 return true;
460 }
461
462 public boolean isValue()
463 {
464 return true;
465 }
466
467 public int compareTo(Object obj)
468 {
469 CellValueRecordInterface loc = ( CellValueRecordInterface ) obj;
470
471 if ((this.getRow() == loc.getRow())
472 && (this.getColumn() == loc.getColumn()))
473 {
474 return 0;
475 }
476 if (this.getRow() < loc.getRow())
477 {
478 return -1;
479 }
480 if (this.getRow() > loc.getRow())
481 {
482 return 1;
483 }
484 if (this.getColumn() < loc.getColumn())
485 {
486 return -1;
487 }
488 if (this.getColumn() > loc.getColumn())
489 {
490 return 1;
491 }
492 return -1;
493 }
494
495 public boolean equals(Object obj)
496 {
497 if (!(obj instanceof CellValueRecordInterface))
498 {
499 return false;
500 }
501 CellValueRecordInterface loc = ( CellValueRecordInterface ) obj;
502
503 if ((this.getRow() == loc.getRow())
504 && (this.getColumn() == loc.getColumn()))
505 {
506 return true;
507 }
508 return false;
509 }
510
511
512 public String toString()
513 {
514 StringBuffer buffer = new StringBuffer();
515 if (EXPERIMENTAL_FORMULA_SUPPORT_ENABLED) {
516 buffer.append("[FORMULA]\n");
517 buffer.append(" .row = ")
518 .append(Integer.toHexString(getRow())).append("\n");
519 buffer.append(" .column = ")
520 .append(Integer.toHexString(getColumn()))
521 .append("\n");
522 buffer.append(" .xf = ")
523 .append(Integer.toHexString(getXFIndex())).append("\n");
524 buffer.append(" .value = ").append(getValue())
525 .append("\n");
526 buffer.append(" .options = ").append(getOptions())
527 .append("\n");
528 buffer.append(" .zero = ").append(field_6_zero)
529 .append("\n");
530 buffer.append(" .expressionlength= ").append(getExpressionLength())
531 .append("\n");
532 buffer.append(" .numptgsinarray = ").append(field_8_parsed_expr.size())
533 .append("\n");
534
535
536 for (int k = 0; k < field_8_parsed_expr.size(); k++ ) {
537
539 buffer.append("Formula ")
540 .append(k)
541 .append("=")
542 .append(((Ptg)field_8_parsed_expr.get(k)).toString())
543 .append("\n")
544 .append(((Ptg)field_8_parsed_expr.get(k)).toDebugString())
545 .append("\n");
546 }
547
548
549 buffer.append("[/FORMULA]\n");
550 } else {
551 buffer.append(super.toString());
552 }
553 return buffer.toString();
554 }
555
556 }
557