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
78
79 public class NameRecord extends Record {
80
82 public final static short sid = 0x18;
83 private short field_1_option_flag;
84 private byte field_2_keyboard_shortcut;
85 private byte field_3_length_name_text;
86 private short field_4_length_name_definition;
87 private short field_5_index_to_sheet;
88 private short field_6_equals_to_index_to_sheet;
89 private byte field_7_length_custom_menu;
90 private byte field_8_length_description_text;
91 private byte field_9_length_help_topic_text;
92 private byte field_10_length_status_bar_text;
93 private byte field_11_compressed_unicode_flag;
94 private byte field_12_builtIn_name;
95 private String field_12_name_text;
96 private Stack field_13_name_definition;
97 private byte[] field_13_raw_name_definition;
98 private String field_14_custom_menu_text;
99 private String field_15_description_text;
100 private String field_16_help_topic_text;
101 private String field_17_status_bar_text;
102
103
104
105 public NameRecord() {
106 field_13_name_definition = new Stack();
107
108 field_12_name_text = new String();
109 field_14_custom_menu_text = new String();
110 field_15_description_text = new String();
111 field_16_help_topic_text = new String();
112 field_17_status_bar_text = new String();
113 }
114
115
122 public NameRecord(short id, short size, byte [] data) {
123 super(id, size, data);
124 }
125
126
134 public NameRecord(short id, short size, byte [] data, int offset) {
135 super(id, size, data, offset);
136 }
137
138
141 public void setOptionFlag(short flag){
142 field_1_option_flag = flag;
143 }
144
145
148 public void setKeyboardShortcut(byte shortcut){
149 field_2_keyboard_shortcut = shortcut;
150 }
151
152
155 public void setNameTextLength(byte length){
156 field_3_length_name_text = length;
157 }
158
159
162 public void setDefinitionTextLength(short length){
163 field_4_length_name_definition = length;
164 }
165
166
170 public void setUnused(short index){
171 field_5_index_to_sheet = index;
172
173
174
175 }
176
177 public short getEqualsToIndexToSheet()
178 {
179 return field_6_equals_to_index_to_sheet;
180 }
181
182 public void setEqualsToIndexToSheet(short value)
183 {
184 field_6_equals_to_index_to_sheet = value;
185 }
186
187
188
191 public void setCustomMenuLength(byte length){
192 field_7_length_custom_menu = length;
193 }
194
195
198 public void setDescriptionTextLength(byte length){
199 field_8_length_description_text = length;
200 }
201
202
205 public void setHelpTopicLength(byte length){
206 field_9_length_help_topic_text = length;
207 }
208
209
212 public void setStatusBarLength(byte length){
213 field_10_length_status_bar_text = length;
214 }
215
216
219 public void setCompressedUnicodeFlag(byte flag) {
220 field_11_compressed_unicode_flag = flag;
221 }
222
223
226 public void setNameText(String name){
227 field_12_name_text = name;
228 }
229
230
231
232
233
234
237 public void setCustomMenuText(String text){
238 field_14_custom_menu_text = text;
239 }
240
241
244 public void setDescriptionText(String text){
245 field_15_description_text = text;
246 }
247
248
251 public void setHelpTopicText(String text){
252 field_16_help_topic_text = text;
253 }
254
255
258 public void setStatusBarText(String text){
259 field_17_status_bar_text = text;
260 }
261
262
265 public short getOptionFlag(){
266 return field_1_option_flag;
267 }
268
269
272 public byte getKeyboardShortcut(){
273 return field_2_keyboard_shortcut ;
274 }
275
276
279 public byte getNameTextLength(){
280 return field_3_length_name_text;
281 }
282
283
286 public short getDefinitionTextLength(){
287 return field_4_length_name_definition;
288 }
289
290
293 public short getUnused(){
294 return field_5_index_to_sheet;
295 }
296
297
300 public byte getCustomMenuLength(){
301 return field_7_length_custom_menu;
302 }
303
304
307 public byte getDescriptionTextLength(){
308 return field_8_length_description_text;
309 }
310
311
314 public byte getHelpTopicLength(){
315 return field_9_length_help_topic_text;
316 }
317
318
321 public byte getStatusBarLength(){
322 return field_10_length_status_bar_text;
323 }
324
325
328 public byte getCompressedUnicodeFlag() {
329 return field_11_compressed_unicode_flag;
330 }
331
332
335 public String getNameText(){
336 return field_12_name_text;
337 }
338
339
342 public List getNameDefinition() {
343 return field_13_name_definition;
344 }
345
346 public void setNameDefinition(Stack nameDefinition) {
347 field_13_name_definition = nameDefinition;
348 }
349
350
353 public String getCustomMenuText(){
354 return field_14_custom_menu_text;
355 }
356
357
360 public String getDescriptionText(){
361 return field_15_description_text;
362 }
363
364
367 public String getHelpTopicText(){
368 return field_16_help_topic_text;
369 }
370
371
374 public String getStatusBarText(){
375 return field_17_status_bar_text;
376 }
377
378
384 protected void validateSid(short id) {
385 if (id != sid) {
386 throw new RecordFormatException("NOT A valid Name RECORD");
387 }
388 }
389
390
399 public int serialize( int offset, byte[] data )
400 {
401 LittleEndian.putShort( data, 0 + offset, sid );
402
403 LittleEndian.putShort( data, 4 + offset, getOptionFlag() );
404 data[6 + offset] = getKeyboardShortcut();
405 data[7 + offset] = getNameTextLength();
406 LittleEndian.putShort( data, 8 + offset, getDefinitionTextLength() );
407 LittleEndian.putShort( data, 10 + offset, getUnused() );
408 LittleEndian.putShort( data, 12 + offset, getEqualsToIndexToSheet() );
409 data[14 + offset] = getCustomMenuLength();
410 data[15 + offset] = getDescriptionTextLength();
411 data[16 + offset] = getHelpTopicLength();
412 data[17 + offset] = getStatusBarLength();
413 data[18 + offset] = getCompressedUnicodeFlag();
414
415
427 LittleEndian.putShort( data, 2 + offset, (short) ( 15 + getTextsLength() ) );
428
429
430 StringUtil.putCompressedUnicode( getNameText(), data, 19 + offset );
431
432 int start_of_name_definition = 19 + field_3_length_name_text;
433 if ( this.field_13_name_definition != null )
434 {
435 serializePtgs( data, start_of_name_definition + offset );
436 }
437 else
438 {
439 System.arraycopy( field_13_raw_name_definition, 0, data
440 , start_of_name_definition + offset, field_13_raw_name_definition.length );
441 }
442
443 int start_of_custom_menu_text = start_of_name_definition + field_4_length_name_definition;
444 StringUtil.putCompressedUnicode( getCustomMenuText(), data, start_of_custom_menu_text + offset );
445
446 int start_of_description_text = start_of_custom_menu_text + field_8_length_description_text;
447 StringUtil.putCompressedUnicode( getDescriptionText(), data, start_of_description_text + offset );
448
449 int start_of_help_topic_text = start_of_description_text + field_9_length_help_topic_text;
450 StringUtil.putCompressedUnicode( getHelpTopicText(), data, start_of_help_topic_text + offset );
451
452 int start_of_status_bar_text = start_of_help_topic_text + field_10_length_status_bar_text;
453 StringUtil.putCompressedUnicode( getStatusBarText(), data, start_of_status_bar_text + offset );
454
455 return getRecordSize();
456
457 }
458
459 private void serializePtgs(byte [] data, int offset) {
460 int pos = offset;
461
462 for (int k = 0; k < field_13_name_definition.size(); k++) {
463 Ptg ptg = ( Ptg ) field_13_name_definition.get(k);
464
465 ptg.writeBytes(data, pos);
466 pos += ptg.getSize();
467 }
468 }
469
470
471
474 public int getTextsLength(){
475 int result;
476
477 result = getNameTextLength() + getDefinitionTextLength() + getDescriptionTextLength() +
478 getHelpTopicLength() + getStatusBarLength();
479
480
481 return result;
482 }
483
484
486 public int getRecordSize(){
487 int result;
488
489 result = 19 + getTextsLength();
490
491 return result;
492 }
493
494
497 public short getExternSheetNumber(){
498 if (field_13_name_definition == null) return 0;
499 Ptg ptg = (Ptg) field_13_name_definition.peek();
500 short result = 0;
501
502 if (ptg.getClass() == Area3DPtg.class){
503 result = ((Area3DPtg) ptg).getExternSheetIndex();
504
505 } else if (ptg.getClass() == Ref3DPtg.class){
506 result = ((Ref3DPtg) ptg).getExternSheetIndex();
507 }
508
509 return result;
510 }
511
512
515 public void setExternSheetNumber(short externSheetNumber){
516 Ptg ptg;
517
518 if (field_13_name_definition == null || field_13_name_definition.isEmpty()){
519 field_13_name_definition = new Stack();
520 ptg = createNewPtg();
521 } else {
522 ptg = (Ptg) field_13_name_definition.peek();
523 }
524
525 if (ptg.getClass() == Area3DPtg.class){
526 ((Area3DPtg) ptg).setExternSheetIndex(externSheetNumber);
527
528 } else if (ptg.getClass() == Ref3DPtg.class){
529 ((Ref3DPtg) ptg).setExternSheetIndex(externSheetNumber);
530 }
531
532 }
533
534 private Ptg createNewPtg(){
535 Ptg ptg = new Area3DPtg();
536 field_13_name_definition.push(ptg);
537
538 return ptg;
539 }
540
541
544 public String getAreaReference(SheetReferences refs){
545 if (field_13_name_definition == null) return "#REF!";
546 Ptg ptg = (Ptg) field_13_name_definition.peek();
547 String result = "";
548
549 if (ptg.getClass() == Area3DPtg.class){
550 result = ptg.toFormulaString(refs);
551
552 } else if (ptg.getClass() == Ref3DPtg.class){
553 result = ptg.toFormulaString(refs);
554 }
555
556 return result;
557 }
558
559
562 public void setAreaReference(String ref){
563
564 RangeAddress ra = new RangeAddress(ref);
565 Ptg oldPtg;
566 Ptg ptg;
567
568 if (field_13_name_definition==null ||field_13_name_definition.isEmpty()){
569 field_13_name_definition = new Stack();
570 oldPtg = createNewPtg();
571 } else {
572
573 oldPtg = (Ptg) field_13_name_definition.pop();
574 }
575
576 short externSheetIndex = 0;
577
578 if (oldPtg.getClass() == Area3DPtg.class){
579 externSheetIndex = ((Area3DPtg) oldPtg).getExternSheetIndex();
580
581 } else if (oldPtg.getClass() == Ref3DPtg.class){
582 externSheetIndex = ((Ref3DPtg) oldPtg).getExternSheetIndex();
583 }
584
585 if (ra.hasRange()) {
586 ptg = new Area3DPtg();
587 ((Area3DPtg) ptg).setExternSheetIndex(externSheetIndex);
588 ((Area3DPtg) ptg).setArea(ref);
589 this.setDefinitionTextLength((short)ptg.getSize());
590 } else {
591 ptg = new Ref3DPtg();
592 ((Ref3DPtg) ptg).setExternSheetIndex(externSheetIndex);
593 ((Ref3DPtg) ptg).setArea(ref);
594 this.setDefinitionTextLength((short)ptg.getSize());
595 }
596
597 field_13_name_definition.push(ptg);
598
599 }
600
601
609 protected void fillFields(byte[] data, short size, int offset) {
610 field_1_option_flag = LittleEndian.getShort(data, 0 + offset);
611 field_2_keyboard_shortcut = data [2 + offset];
612 field_3_length_name_text = data [3 + offset];
613 field_4_length_name_definition = LittleEndian.getShort(data, 4 + offset);
614 field_5_index_to_sheet = LittleEndian.getShort(data, 6 + offset);
615 field_6_equals_to_index_to_sheet= LittleEndian.getShort(data, 8 + offset);
616 field_7_length_custom_menu = data [10 + offset];
617 field_8_length_description_text = data [11 + offset];
618 field_9_length_help_topic_text = data [12 + offset];
619 field_10_length_status_bar_text = data [13 + offset];
620
621
622
645
646 field_11_compressed_unicode_flag= data [14 + offset];
647 field_12_name_text = new String(data, 15 + offset,
648 LittleEndian.ubyteToInt(field_3_length_name_text));
649
650 int start_of_name_definition = 15 + field_3_length_name_text;
651 field_13_name_definition = getParsedExpressionTokens(data, field_4_length_name_definition,
652 offset, start_of_name_definition);
653
654 int start_of_custom_menu_text = start_of_name_definition + field_4_length_name_definition;
655 field_14_custom_menu_text = new String(data, start_of_custom_menu_text + offset,
656 LittleEndian.ubyteToInt(field_7_length_custom_menu));
657
658 int start_of_description_text = start_of_custom_menu_text + field_8_length_description_text;
659 field_15_description_text = new String(data, start_of_description_text + offset,
660 LittleEndian.ubyteToInt(field_8_length_description_text));
661
662 int start_of_help_topic_text = start_of_description_text + field_9_length_help_topic_text;
663 field_16_help_topic_text = new String(data, start_of_help_topic_text + offset,
664 LittleEndian.ubyteToInt(field_9_length_help_topic_text));
665
666 int start_of_status_bar_text = start_of_help_topic_text + field_10_length_status_bar_text;
667 field_17_status_bar_text = new String(data, start_of_status_bar_text + offset,
668 LittleEndian.ubyteToInt(field_10_length_status_bar_text));
669
670 }
671
672 private Stack getParsedExpressionTokens(byte [] data, short size,
673 int offset, int start_of_expression) {
674 Stack stack = new Stack();
675 int pos = start_of_expression + offset;
676 int sizeCounter = 0;
677 try {
678 while (sizeCounter < size) {
679 Ptg ptg = Ptg.createPtg(data, pos);
680
681 pos += ptg.getSize();
682 sizeCounter += ptg.getSize();
683 stack.push(ptg);
684 }
685 } catch (java.lang.UnsupportedOperationException uoe) {
686 System.err.println("[WARNING] Unknown Ptg "
687 + uoe.getMessage() );
688 field_13_raw_name_definition=new byte[size];
689 System.arraycopy(data,offset,field_13_raw_name_definition,0,size);
690 return null;
691 }
692 return stack;
693 }
694
695
696
699 public short getSid() {
700 return this.sid;
701 }
702
736
752
753
756 public String toString() {
757 StringBuffer buffer = new StringBuffer();
758
759 buffer.append("[NAME]\n");
760 buffer.append(" .option flags = ").append( HexDump.toHex( field_1_option_flag ) )
761 .append("\n");
762 buffer.append(" .keyboard shortcut = ").append( HexDump.toHex( field_2_keyboard_shortcut ) )
763 .append("\n");
764 buffer.append(" .length of the name = ").append( field_3_length_name_text )
765 .append("\n");
766 buffer.append(" .size of the formula data = ").append( field_4_length_name_definition )
767 .append("\n");
768 buffer.append(" .unused = ").append( field_5_index_to_sheet )
769 .append("\n");
770 buffer.append(" .( 0 = Global name, otherwise index to sheet (one-based) ) = ").append( field_6_equals_to_index_to_sheet )
771 .append("\n");
772 buffer.append(" .Length of menu text (character count) = ").append( field_7_length_custom_menu )
773 .append("\n");
774 buffer.append(" .Length of description text (character count) = ").append( field_8_length_description_text )
775 .append("\n");
776 buffer.append(" .Length of help topic text (character count) = ").append( field_9_length_help_topic_text )
777 .append("\n");
778 buffer.append(" .Length of status bar text (character count) = ").append( field_10_length_status_bar_text )
779 .append("\n");
780 buffer.append(" .Name (Unicode flag) = ").append( field_11_compressed_unicode_flag )
781 .append("\n");
782 buffer.append(" .Name (Unicode text) = ").append( field_12_name_text )
783 .append("\n");
784 buffer.append(" .Formula data (RPN token array without size field) = ").append( HexDump.toHex(
785 ((field_13_raw_name_definition != null) ? field_13_raw_name_definition : new byte[0] ) ) )
786 .append("\n");
787 buffer.append(" .Menu text (Unicode string without length field) = ").append( field_14_custom_menu_text )
788 .append("\n");
789 buffer.append(" .Description text (Unicode string without length field) = ").append( field_15_description_text )
790 .append("\n");
791 buffer.append(" .Help topic text (Unicode string without length field) = ").append( field_16_help_topic_text )
792 .append("\n");
793 buffer.append(" .Status bar text (Unicode string without length field) = ").append( field_17_status_bar_text )
794 .append("\n");
795 buffer.append("[/NAME]\n");
796
797 return buffer.toString();
798 }
799
800 }
801