1 /
55
56 package org.apache.poi.hssf.record;
57
58 import org.apache.poi.util.HexDump;
59 import org.apache.poi.util.LittleEndian;
60 import org.apache.poi.util.StringUtil;
61 import java.util.Stack;
62 import org.apache.poi.hssf.record.formula.Ptg;
63 import org.apache.poi.hssf.record.formula.Area3DPtg;
64 import org.apache.poi.hssf.record.formula.Ref3DPtg;
65 import java.util.List;
66 import org.apache.poi.hssf.util.RangeAddress;
67 import org.apache.poi.hssf.util.SheetReferences;
68
69
77
78 public class NameRecord extends Record {
79
81 public final static short sid = 0x18;
82 private short field_1_option_flag;
83 private byte field_2_keyboard_shortcut;
84 private byte field_3_length_name_text;
85 private short field_4_length_name_definition;
86 private short field_5_index_to_sheet;
87 private short field_6_equals_to_index_to_sheet;
88 private byte field_7_length_custom_menu;
89 private byte field_8_length_description_text;
90 private byte field_9_length_help_topic_text;
91 private byte field_10_length_status_bar_text;
92 private byte field_11_compressed_unicode_flag;
93 private byte field_12_builtIn_name;
94 private String field_12_name_text;
95 private Stack field_13_name_definition;
96 private byte[] field_13_raw_name_definition;
97 private String field_14_custom_menu_text;
98 private String field_15_description_text;
99 private String field_16_help_topic_text;
100 private String field_17_status_bar_text;
101
102
103 public NameRecord() {
104 field_13_name_definition = new Stack();
105
106 field_12_name_text = new String();
107 field_14_custom_menu_text = new String();
108 field_15_description_text = new String();
109 field_16_help_topic_text = new String();
110 field_17_status_bar_text = new String();
111 }
112
113
120 public NameRecord(short id, short size, byte [] data) {
121 super(id, size, data);
122 }
123
124
132 public NameRecord(short id, short size, byte [] data, int offset) {
133 super(id, size, data, offset);
134 }
135
136
139 public void setOptionFlag(short flag){
140 field_1_option_flag = flag;
141 }
142
143
146 public void setKeyboardShortcut(byte shortcut){
147 field_2_keyboard_shortcut = shortcut;
148 }
149
150
153 public void setNameTextLength(byte length){
154 field_3_length_name_text = length;
155 }
156
157
160 public void setDefinitionTextLength(short length){
161 field_4_length_name_definition = length;
162 }
163
164
168 public void setIndexToSheet(short index){
169 field_5_index_to_sheet = index;
170
171
172 field_6_equals_to_index_to_sheet = index;
173 }
174
175
178 public void setCustomMenuLength(byte length){
179 field_7_length_custom_menu = length;
180 }
181
182
185 public void setDescriptionTextLength(byte length){
186 field_8_length_description_text = length;
187 }
188
189
192 public void setHelpTopicLength(byte length){
193 field_9_length_help_topic_text = length;
194 }
195
196
199 public void setStatusBarLength(byte length){
200 field_10_length_status_bar_text = length;
201 }
202
203
206 public void setCompressedUnicodeFlag(byte flag) {
207 field_11_compressed_unicode_flag = flag;
208 }
209
210
213 public void setNameText(String name){
214 field_12_name_text = name;
215 }
216
217
218
219
220
221
224 public void setCustomMenuText(String text){
225 field_14_custom_menu_text = text;
226 }
227
228
231 public void setDescriptionText(String text){
232 field_15_description_text = text;
233 }
234
235
238 public void setHelpTopicText(String text){
239 field_16_help_topic_text = text;
240 }
241
242
245 public void setStatusBarText(String text){
246 field_17_status_bar_text = text;
247 }
248
249
252 public short getOptionFlag(){
253 return field_1_option_flag;
254 }
255
256
259 public byte getKeyboardShortcut(){
260 return field_2_keyboard_shortcut ;
261 }
262
263
266 public byte getNameTextLength(){
267 return field_3_length_name_text;
268 }
269
270
273 public short getDefinitionTextLength(){
274 return field_4_length_name_definition;
275 }
276
277
280 public short getIndexToSheet(){
281 return field_5_index_to_sheet;
282 }
283
284
287 public byte getCustomMenuLength(){
288 return field_7_length_custom_menu;
289 }
290
291
294 public byte getDescriptionTextLength(){
295 return field_8_length_description_text;
296 }
297
298
301 public byte getHelpTopicLength(){
302 return field_9_length_help_topic_text;
303 }
304
305
308 public byte getStatusBarLength(){
309 return field_10_length_status_bar_text;
310 }
311
312
315 public byte getCompressedUnicodeFlag() {
316 return field_11_compressed_unicode_flag;
317 }
318
319
322 public String getNameText(){
323 return field_12_name_text;
324 }
325
326
329 protected List getNameDefinition() {
330 return ( List ) field_13_name_definition;
331 }
332
333
336 public String getCustomMenuText(){
337 return field_14_custom_menu_text;
338 }
339
340
343 public String getDescriptionText(){
344 return field_15_description_text;
345 }
346
347
350 public String getHelpTopicText(){
351 return field_16_help_topic_text;
352 }
353
354
357 public String getStatusBarText(){
358 return field_17_status_bar_text;
359 }
360
361
367 protected void validateSid(short id) {
368 if (id != sid) {
369 throw new RecordFormatException("NOT A valid Name RECORD");
370 }
371 }
372
373
382 public int serialize(int offset, byte[] data) {
383 LittleEndian.putShort(data, 0 + offset, sid);
384
385 LittleEndian.putShort(data, 4 + offset, getOptionFlag());
386 data[6 + offset] = getKeyboardShortcut();
387 data[7 + offset] = getNameTextLength();
388 LittleEndian.putShort(data, 8 + offset, getDefinitionTextLength());
389 LittleEndian.putShort(data, 10 + offset, getIndexToSheet());
390 LittleEndian.putShort(data, 12 + offset, getIndexToSheet());
391 data [14 + offset] = getCustomMenuLength();
392 data [15 + offset] = getDescriptionTextLength();
393 data [16 + offset] = getHelpTopicLength();
394 data [17 + offset] = getStatusBarLength();
395 data [18 + offset] = getCompressedUnicodeFlag();
396
397 if ( ( field_1_option_flag & (short)0x20 ) != 0 ) {
398 LittleEndian.putShort(data, 2 + offset, (short)( 16 + field_13_raw_name_definition.length ));
399
400 data [19 + offset] = field_12_builtIn_name;
401 System.arraycopy( field_13_raw_name_definition, 0, data, 20 + offset, field_13_raw_name_definition.length );
402
403 return 20 + field_13_raw_name_definition.length;
404 }
405 else {
406 LittleEndian.putShort(data, 2 + offset, (short)( 15 + getTextsLength()));
407
408
409 StringUtil.putCompressedUnicode(getNameText(), data , 19 + offset);
410
411 int start_of_name_definition = 19 + field_3_length_name_text;
412 if (this.field_13_name_definition != null) {
413 serializePtgs(data, start_of_name_definition + offset);
414 } else {
415 System.arraycopy(field_13_raw_name_definition,0,data
416 ,start_of_name_definition + offset,field_13_raw_name_definition.length);
417 }
418
419 int start_of_custom_menu_text = start_of_name_definition + field_4_length_name_definition;
420 StringUtil.putCompressedUnicode(getCustomMenuText(), data , start_of_custom_menu_text + offset);
421
422 int start_of_description_text = start_of_custom_menu_text + field_8_length_description_text;
423 StringUtil.putCompressedUnicode(getDescriptionText(), data , start_of_description_text + offset);
424
425 int start_of_help_topic_text = start_of_description_text + field_9_length_help_topic_text;
426 StringUtil.putCompressedUnicode(getHelpTopicText(), data , start_of_help_topic_text + offset);
427
428 int start_of_status_bar_text = start_of_help_topic_text + field_10_length_status_bar_text;
429 StringUtil.putCompressedUnicode(getStatusBarText(), data , start_of_status_bar_text + offset);
430
431 return getRecordSize();
432 }
433 }
434
435 private void serializePtgs(byte [] data, int offset) {
436 int pos = offset;
437
438 for (int k = 0; k < field_13_name_definition.size(); k++) {
439 Ptg ptg = ( Ptg ) field_13_name_definition.get(k);
440
441 ptg.writeBytes(data, pos);
442 pos += ptg.getSize();
443 }
444 }
445
446
447
450 public int getTextsLength(){
451 int result;
452
453 result = getNameTextLength() + getDefinitionTextLength() + getDescriptionTextLength() +
454 getHelpTopicLength() + getStatusBarLength();
455
456
457 return result;
458 }
459
460
462 public int getRecordSize(){
463 int result;
464
465 result = 19 + getTextsLength();
466
467 return result;
468 }
469
470
473 public short getExternSheetNumber(){
474 if (field_13_name_definition == null) return 0;
475 Ptg ptg = (Ptg) field_13_name_definition.peek();
476 short result = 0;
477
478 if (ptg.getClass() == Area3DPtg.class){
479 result = ((Area3DPtg) ptg).getExternSheetIndex();
480
481 } else if (ptg.getClass() == Ref3DPtg.class){
482 result = ((Ref3DPtg) ptg).getExternSheetIndex();
483 }
484
485 return result;
486 }
487
488
491 public void setExternSheetNumber(short externSheetNumber){
492 Ptg ptg;
493
494 if (field_13_name_definition == null || field_13_name_definition.isEmpty()){
495 field_13_name_definition = new Stack();
496 ptg = createNewPtg();
497 } else {
498 ptg = (Ptg) field_13_name_definition.peek();
499 }
500
501 if (ptg.getClass() == Area3DPtg.class){
502 ((Area3DPtg) ptg).setExternSheetIndex(externSheetNumber);
503
504 } else if (ptg.getClass() == Ref3DPtg.class){
505 ((Ref3DPtg) ptg).setExternSheetIndex(externSheetNumber);
506 }
507
508 }
509
510 private Ptg createNewPtg(){
511 Ptg ptg = new Area3DPtg();
512 field_13_name_definition.push(ptg);
513
514 return ptg;
515 }
516
517
520 public String getAreaReference(SheetReferences refs){
521 if (field_13_name_definition == null) return "#REF!";
522 Ptg ptg = (Ptg) field_13_name_definition.peek();
523 String result = "";
524
525 if (ptg.getClass() == Area3DPtg.class){
526 result = ((Area3DPtg) ptg).toFormulaString(refs);
527
528 } else if (ptg.getClass() == Ref3DPtg.class){
529 result = ((Ref3DPtg) ptg).toFormulaString(refs);
530 }
531
532 return result;
533 }
534
535
538 public void setAreaReference(String ref){
539
540 RangeAddress ra = new RangeAddress(ref);
541 Ptg oldPtg;
542 Ptg ptg;
543
544 if (field_13_name_definition==null ||field_13_name_definition.isEmpty()){
545 field_13_name_definition = new Stack();
546 oldPtg = createNewPtg();
547 } else {
548
549 oldPtg = (Ptg) field_13_name_definition.pop();
550 }
551
552 short externSheetIndex = 0;
553
554 if (oldPtg.getClass() == Area3DPtg.class){
555 externSheetIndex = ((Area3DPtg) oldPtg).getExternSheetIndex();
556
557 } else if (oldPtg.getClass() == Ref3DPtg.class){
558 externSheetIndex = ((Ref3DPtg) oldPtg).getExternSheetIndex();
559 }
560
561 if (ra.hasRange()) {
562 ptg = new Area3DPtg();
563 ((Area3DPtg) ptg).setExternSheetIndex(externSheetIndex);
564 ((Area3DPtg) ptg).setArea(ref);
565 this.setDefinitionTextLength((short)((Area3DPtg) ptg).getSize());
566 } else {
567 ptg = new Ref3DPtg();
568 ((Ref3DPtg) ptg).setExternSheetIndex(externSheetIndex);
569 ((Ref3DPtg) ptg).setArea(ref);
570 this.setDefinitionTextLength((short)((Ref3DPtg) ptg).getSize());
571 }
572
573 field_13_name_definition.push(ptg);
574
575 }
576
577
585 protected void fillFields(byte[] data, short size, int offset) {
586 field_1_option_flag = LittleEndian.getShort(data, 0 + offset);
587 field_2_keyboard_shortcut = data [2 + offset];
588 field_3_length_name_text = data [3 + offset];
589 field_4_length_name_definition = LittleEndian.getShort(data, 4 + offset);
590 field_5_index_to_sheet = LittleEndian.getShort(data, 6 + offset);
591 field_6_equals_to_index_to_sheet= LittleEndian.getShort(data, 8 + offset);
592 field_7_length_custom_menu = data [10 + offset];
593 field_8_length_description_text = data [11 + offset];
594 field_9_length_help_topic_text = data [12 + offset];
595 field_10_length_status_bar_text = data [13 + offset];
596
597
598 if ( ( field_1_option_flag & (short)0x20 ) != 0 ) {
599
600
601
602 field_11_compressed_unicode_flag = data[ 14 + offset ];
603 field_12_builtIn_name = data[ 15 + offset ];
604
605 if ( (field_12_builtIn_name & (short)0x07) != 0 ) {
606 field_12_name_text = "Print_Titles";
607
608
609
610
611 field_13_raw_name_definition = new byte[ field_4_length_name_definition ];
612 System.arraycopy( data, 16 + offset, field_13_raw_name_definition, 0, field_13_raw_name_definition.length );
613
614
615
616 }
617 }
618 else {
619
620 field_11_compressed_unicode_flag= data [14 + offset];
621 field_12_name_text = new String(data, 15 + offset,
622 LittleEndian.ubyteToInt(field_3_length_name_text));
623
624 int start_of_name_definition = 15 + field_3_length_name_text;
625 field_13_name_definition = getParsedExpressionTokens(data, field_4_length_name_definition,
626 offset, start_of_name_definition);
627
628 int start_of_custom_menu_text = start_of_name_definition + field_4_length_name_definition;
629 field_14_custom_menu_text = new String(data, start_of_custom_menu_text + offset,
630 LittleEndian.ubyteToInt(field_7_length_custom_menu));
631
632 int start_of_description_text = start_of_custom_menu_text + field_8_length_description_text;
633 field_15_description_text = new String(data, start_of_description_text + offset,
634 LittleEndian.ubyteToInt(field_8_length_description_text));
635
636 int start_of_help_topic_text = start_of_description_text + field_9_length_help_topic_text;
637 field_16_help_topic_text = new String(data, start_of_help_topic_text + offset,
638 LittleEndian.ubyteToInt(field_9_length_help_topic_text));
639
640 int start_of_status_bar_text = start_of_help_topic_text + field_10_length_status_bar_text;
641 field_17_status_bar_text = new String(data, start_of_status_bar_text + offset,
642 LittleEndian.ubyteToInt(field_10_length_status_bar_text));
643 }
644 }
645
646 private Stack getParsedExpressionTokens(byte [] data, short size,
647 int offset, int start_of_expression) {
648 Stack stack = new Stack();
649 int pos = start_of_expression + offset;
650 int sizeCounter = 0;
651 try {
652 while (sizeCounter < size) {
653 Ptg ptg = Ptg.createPtg(data, pos);
654
655 pos += ptg.getSize();
656 sizeCounter += ptg.getSize();
657 stack.push(ptg);
658 }
659 } catch (java.lang.UnsupportedOperationException uoe) {
660 System.err.println("[WARNING] Unknown Ptg "
661 + uoe.getMessage() );
662 field_13_raw_name_definition=new byte[size];
663 System.arraycopy(data,offset,field_13_raw_name_definition,0,size);
664 return null;
665 }
666 return stack;
667 }
668
669
670
673 public short getSid() {
674 return this.sid;
675 }
676
710
726
727
730 public String toString() {
731 StringBuffer buffer = new StringBuffer();
732
733 buffer.append("[NAME]\n");
734 buffer.append(" .option flags = ").append( HexDump.toHex( field_1_option_flag ) )
735 .append("\n");
736 buffer.append(" .keyboard shortcut = ").append( HexDump.toHex( field_2_keyboard_shortcut ) )
737 .append("\n");
738 buffer.append(" .length of the name = ").append( field_3_length_name_text )
739 .append("\n");
740 buffer.append(" .size of the formula data = ").append( field_4_length_name_definition )
741 .append("\n");
742 buffer.append(" .unused = ").append( field_5_index_to_sheet )
743 .append("\n");
744 buffer.append(" .( 0 = Global name, otherwise index to sheet (one-based) ) = ").append( field_6_equals_to_index_to_sheet )
745 .append("\n");
746 buffer.append(" .Length of menu text (character count) = ").append( field_7_length_custom_menu )
747 .append("\n");
748 buffer.append(" .Length of description text (character count) = ").append( field_8_length_description_text )
749 .append("\n");
750 buffer.append(" .Length of help topic text (character count) = ").append( field_9_length_help_topic_text )
751 .append("\n");
752 buffer.append(" .Length of status bar text (character count) = ").append( field_10_length_status_bar_text )
753 .append("\n");
754 buffer.append(" .Name (Unicode flag) = ").append( field_11_compressed_unicode_flag )
755 .append("\n");
756 buffer.append(" .Name (Unicode text) = ").append( field_12_name_text )
757 .append("\n");
758 buffer.append(" .Formula data (RPN token array without size field) = ").append( HexDump.toHex( field_13_raw_name_definition ) )
759 .append("\n");
760 buffer.append(" .Menu text (Unicode string without length field) = ").append( field_14_custom_menu_text )
761 .append("\n");
762 buffer.append(" .Description text (Unicode string without length field) = ").append( field_15_description_text )
763 .append("\n");
764 buffer.append(" .Help topic text (Unicode string without length field) = ").append( field_16_help_topic_text )
765 .append("\n");
766 buffer.append(" .Status bar text (Unicode string without length field) = ").append( field_17_status_bar_text )
767 .append("\n");
768 buffer.append("[/NAME]\n");
769
770 return buffer.toString();
771 }
772
773 }
774