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
87 private int field_1_row;
88 private short field_2_column;
89 private short field_3_xf;
90 private double field_4_value;
91 private short field_5_options;
92 private int field_6_zero;
93 private short field_7_expression_len;
94 private Stack field_8_parsed_expr;
95
96 private byte[] all_data;
97
98
99
100
101 public FormulaRecord()
102 {
103 field_8_parsed_expr = new Stack();
104 }
105
106
114
115 public FormulaRecord(short id, short size, byte [] data)
116 {
117 super(id, size, data);
118 }
119
120
129
130 public FormulaRecord(short id, short size, byte [] data, int offset)
131 {
132 super(id, size, data, offset);
133 }
134
135 protected void fillFields(byte [] data, short size, int offset)
136 {
137 try {
138
139 field_1_row = LittleEndian.getUShort(data, 0 + offset);
140 field_2_column = LittleEndian.getShort(data, 2 + offset);
141 field_3_xf = LittleEndian.getShort(data, 4 + offset);
142 field_4_value = LittleEndian.getDouble(data, 6 + offset);
143 field_5_options = LittleEndian.getShort(data, 14 + offset);
144 field_6_zero = LittleEndian.getInt(data, 16 + offset);
145 field_7_expression_len = LittleEndian.getShort(data, 20 + offset);
146 field_8_parsed_expr = getParsedExpressionTokens(data, size,
147 offset);
148
149 } catch (java.lang.UnsupportedOperationException uoe) {
150 field_8_parsed_expr = null;
151 all_data = new byte[size+4];
152 LittleEndian.putShort(all_data,0,sid);
153 LittleEndian.putShort(all_data,2,size);
154 System.arraycopy(data,offset,all_data,4,size);
155 System.err.println("[WARNING] Unknown Ptg "
156 + uoe.getMessage()
157 + " at cell ("+field_1_row+","+field_2_column+")");
158 }
159
160 }
161
162 private Stack getParsedExpressionTokens(byte [] data, short size,
163 int offset)
164 {
165 Stack stack = new Stack();
166 int pos = 22 + offset;
167
168 while (pos < size)
169 {
170 Ptg ptg = Ptg.createPtg(data, pos);
171 pos += ptg.getSize();
172 stack.push(ptg);
173 }
174 return stack;
175 }
176
177
178 public void setRow(int row)
179 {
180 field_1_row = row;
181 }
182
183 public void setColumn(short column)
184 {
185 field_2_column = column;
186 }
187
188 public void setXFIndex(short xf)
189 {
190 field_3_xf = xf;
191 }
192
193
198
199 public void setValue(double value)
200 {
201 field_4_value = value;
202 }
203
204
209
210 public void setOptions(short options)
211 {
212 field_5_options = options;
213 }
214
215
219
220 public void setExpressionLength(short len)
221 {
222 field_7_expression_len = len;
223 }
224
225
226 public int getRow()
227 {
228 return field_1_row;
229 }
230
231 public short getColumn()
232 {
233 return field_2_column;
234 }
235
236 public short getXFIndex()
237 {
238 return field_3_xf;
239 }
240
241
246
247 public double getValue()
248 {
249 return field_4_value;
250 }
251
252
257
258 public short getOptions()
259 {
260 return field_5_options;
261 }
262
263
267
268 public short getExpressionLength()
269 {
270 return field_7_expression_len;
271 }
272
273
278
279 public void pushExpressionToken(Ptg ptg)
280 {
281 field_8_parsed_expr.push(ptg);
282 }
283
284
289
290 public Ptg popExpressionToken()
291 {
292 return ( Ptg ) field_8_parsed_expr.pop();
293 }
294
295
300
301 public Ptg peekExpressionToken()
302 {
303 return ( Ptg ) field_8_parsed_expr.peek();
304 }
305
306
310
311 public int getNumberOfExpressionTokens()
312 {
313 if (this.field_8_parsed_expr == null) {
314 return 0;
315 } else {
316 return field_8_parsed_expr.size();
317 }
318 }
319
320
328
329 public List getParsedExpression()
330 {
331 return ( List ) field_8_parsed_expr;
332 }
333
334
340
341 protected void validateSid(short id)
342 {
343 if (id != sid)
344 {
345 throw new RecordFormatException("NOT A FORMULA RECORD");
346 }
347 }
348
349 public short getSid()
350 {
351 return sid;
352 }
353
354
361
362 public int serialize(int offset, byte [] data)
363 {
364 if (this.field_8_parsed_expr != null) {
365 int ptgSize = getTotalPtgSize();
366
367 LittleEndian.putShort(data, 0 + offset, sid);
368 LittleEndian.putShort(data, 2 + offset, ( short ) (22 + ptgSize));
369
370 LittleEndian.putShort(data, 4 + offset, ( short ) getRow());
371 LittleEndian.putShort(data, 6 + offset, getColumn());
372 LittleEndian.putShort(data, 8 + offset, getXFIndex());
373 LittleEndian.putDouble(data, 10 + offset, getValue());
374 LittleEndian.putShort(data, 18 + offset, getOptions());
375 LittleEndian.putInt(data, 20 + offset, field_6_zero);
376 LittleEndian.putShort(data, 24 + offset, getExpressionLength());
377 serializePtgs(data, 26+offset);
378 } else {
379 System.arraycopy(all_data,0,data,offset,all_data.length);
380 }
381 return getRecordSize();
382 }
383
384
385
386
387 public int getRecordSize()
388 {
389 int retval =0;
390
391 if (this.field_8_parsed_expr != null) {
392 retval = getTotalPtgSize() + 26;
393 } else {
394 retval =all_data.length;
395 }
396 return retval;
397
398
399 }
400
401 private int getTotalPtgSize()
402 {
403 List list = getParsedExpression();
404 int retval = 0;
405
406 for (int k = 0; k < list.size(); k++)
407 {
408 Ptg ptg = ( Ptg ) list.get(k);
409
410 retval += ptg.getSize();
411 }
412 return retval;
413 }
414
415 private void serializePtgs(byte [] data, int offset)
416 {
417 int pos = offset;
418
419 for (int k = 0; k < field_8_parsed_expr.size(); k++)
420 {
421 Ptg ptg = ( Ptg ) field_8_parsed_expr.get(k);
422
423 ptg.writeBytes(data, pos);
424 pos += ptg.getSize();
425 }
426 }
427
428 public boolean isBefore(CellValueRecordInterface i)
429 {
430 if (this.getRow() > i.getRow())
431 {
432 return false;
433 }
434 if ((this.getRow() == i.getRow())
435 && (this.getColumn() > i.getColumn()))
436 {
437 return false;
438 }
439 if ((this.getRow() == i.getRow())
440 && (this.getColumn() == i.getColumn()))
441 {
442 return false;
443 }
444 return true;
445 }
446
447 public boolean isAfter(CellValueRecordInterface i)
448 {
449 if (this.getRow() < i.getRow())
450 {
451 return false;
452 }
453 if ((this.getRow() == i.getRow())
454 && (this.getColumn() < i.getColumn()))
455 {
456 return false;
457 }
458 if ((this.getRow() == i.getRow())
459 && (this.getColumn() == i.getColumn()))
460 {
461 return false;
462 }
463 return true;
464 }
465
466 public boolean isEqual(CellValueRecordInterface i)
467 {
468 return ((this.getRow() == i.getRow())
469 && (this.getColumn() == i.getColumn()));
470 }
471
472 public boolean isInValueSection()
473 {
474 return true;
475 }
476
477 public boolean isValue()
478 {
479 return true;
480 }
481
482 public int compareTo(Object obj)
483 {
484 CellValueRecordInterface loc = ( CellValueRecordInterface ) obj;
485
486 if ((this.getRow() == loc.getRow())
487 && (this.getColumn() == loc.getColumn()))
488 {
489 return 0;
490 }
491 if (this.getRow() < loc.getRow())
492 {
493 return -1;
494 }
495 if (this.getRow() > loc.getRow())
496 {
497 return 1;
498 }
499 if (this.getColumn() < loc.getColumn())
500 {
501 return -1;
502 }
503 if (this.getColumn() > loc.getColumn())
504 {
505 return 1;
506 }
507 return -1;
508 }
509
510 public boolean equals(Object obj)
511 {
512 if (!(obj instanceof CellValueRecordInterface))
513 {
514 return false;
515 }
516 CellValueRecordInterface loc = ( CellValueRecordInterface ) obj;
517
518 if ((this.getRow() == loc.getRow())
519 && (this.getColumn() == loc.getColumn()))
520 {
521 return true;
522 }
523 return false;
524 }
525
526
527 public String toString()
528 {
529 StringBuffer buffer = new StringBuffer();
530 if (EXPERIMENTAL_FORMULA_SUPPORT_ENABLED) {
531 buffer.append("[FORMULA]\n");
532 buffer.append(" .row = ")
533 .append(Integer.toHexString(getRow())).append("\n");
534 buffer.append(" .column = ")
535 .append(Integer.toHexString(getColumn()))
536 .append("\n");
537 buffer.append(" .xf = ")
538 .append(Integer.toHexString(getXFIndex())).append("\n");
539 buffer.append(" .value = ").append(getValue())
540 .append("\n");
541 buffer.append(" .options = ").append(getOptions())
542 .append("\n");
543 buffer.append(" .zero = ").append(field_6_zero)
544 .append("\n");
545 buffer.append(" .expressionlength= ").append(getExpressionLength())
546 .append("\n");
547 buffer.append(" .numptgsinarray = ").append(field_8_parsed_expr.size())
548 .append("\n");
549
550
551 for (int k = 0; k < field_8_parsed_expr.size(); k++ ) {
552
554 buffer.append("Formula ")
555 .append(k)
556 .append("=")
557 .append(((Ptg)field_8_parsed_expr.get(k)).toString())
558 .append("\n")
559 .append(((Ptg)field_8_parsed_expr.get(k)).toDebugString())
560 .append("\n");
561 }
562
563
564 buffer.append("[/FORMULA]\n");
565 } else {
566 buffer.append(super.toString());
567 }
568 return buffer.toString();
569 }
570
571 }
572