KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jxl > read > biff > NameRecord


1 /*********************************************************************
2 *
3 * Copyright (C) 2002 Andrew Khan
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 ***************************************************************************/

19
20 package jxl.read.biff;
21
22 import java.util.ArrayList JavaDoc;
23
24 import common.Assert;
25 import common.Logger;
26
27 import jxl.WorkbookSettings;
28 import jxl.biff.RecordData;
29 import jxl.biff.StringHelper;
30 import jxl.biff.IntegerHelper;
31
32 /**
33  * Holds an excel name record, and the details of the cells/ranges it refers
34  * to
35  */

36 public class NameRecord extends RecordData
37 {
38   /**
39    * The logger
40    */

41   private static Logger logger = Logger.getLogger(NameRecord.class);
42
43   /**
44    * The name
45    */

46   private String JavaDoc name;
47
48   /**
49    * The 0-based index in the name table
50    */

51   private int index;
52   
53   /**
54    * The 0-based index sheet reference for a record name
55    * 0 is for a global reference
56    */

57   private int sheetRef = 0;
58
59   /**
60    * Indicates whether this is a biff8 name record. Used during copying
61    */

62   private boolean isbiff8;
63
64   /**
65    * Dummy indicators for overloading the constructor
66    */

67   private static class Biff7 {};
68   public static Biff7 biff7 = new Biff7();
69
70   // Constants which refer to the name type
71
private static final int commandMacro = 0xc;
72   private static final int builtIn = 0x20;
73
74   // Constants which refer to the parse tokens after the string
75
private static final int cellReference = 0x3a;
76   private static final int areaReference = 0x3b;
77   private static final int subExpression = 0x29;
78   private static final int union = 0x10;
79
80   /**
81    * A nested class to hold range information
82    */

83   public class NameRange
84   {
85     /**
86      * The first column
87      */

88     private int columnFirst;
89
90     /**
91      * The first row
92      */

93     private int rowFirst;
94
95     /**
96      * The last column
97      */

98     private int columnLast;
99
100     /**
101      * The last row
102      */

103     private int rowLast;
104
105     /**
106      * The first sheet
107      */

108     private int externalSheet;
109
110     /**
111      * Constructor
112      *
113      * @param s1 the sheet
114      * @param c1 the first column
115      * @param r1 the first row
116      * @param c2 the last column
117      * @param r2 the last row
118      */

119     NameRange(int s1, int c1, int r1, int c2, int r2)
120     {
121       columnFirst = c1;
122       rowFirst = r1;
123       columnLast = c2;
124       rowLast = r2;
125       externalSheet = s1;
126     }
127
128     /**
129      * Accessor for the first column
130      *
131      * @return the index of the first column
132      */

133     public int getFirstColumn()
134     {
135       return columnFirst;
136     }
137
138     /**
139      * Accessor for the first row
140      *
141      * @return the index of the first row
142      */

143     public int getFirstRow()
144     {
145       return rowFirst;
146     }
147
148     /**
149      * Accessor for the last column
150      *
151      * @return the index of the last column
152      */

153     public int getLastColumn()
154     {
155       return columnLast;
156     }
157
158     /**
159      * Accessor for the last row
160      *
161      * @return the index of the last row
162      */

163     public int getLastRow()
164     {
165       return rowLast;
166     }
167
168     /**
169      * Accessor for the first sheet
170      *
171      * @return the index of the external sheet
172      */

173     public int getExternalSheet()
174     {
175       return externalSheet;
176     }
177   }
178
179   /**
180    * The ranges referenced by this name
181    */

182   private ArrayList JavaDoc ranges;
183
184   /**
185    * The list of built in names
186    */

187   private static final String JavaDoc[] builtInNames =
188     { "Consolidate_Area",
189       "Auto_Open",
190       "Auto_Close",
191       "Extract",
192       "Database",
193       "Criteria",
194       "Print_Area",
195       "Print_Titles",
196       "Recorder",
197       "Data_Form",
198       "Auto_Activate",
199       "Auto_Deactivate",
200       "Sheet_Title",
201       "_FilterDatabase" };
202
203   /**
204    * Constructs this object from the raw data
205    *
206    * @param t the raw data
207    * @param ws the workbook settings
208    * @param ind the index in the name table
209    */

210   NameRecord(Record t, WorkbookSettings ws, int ind)
211   {
212     super(t);
213     index = ind;
214     isbiff8 = true;
215
216     try
217     {
218       ranges = new ArrayList JavaDoc();
219
220       byte[] data = getRecord().getData();
221       int option = IntegerHelper.getInt(data[0], data[1]);
222       int length = data[3];
223       sheetRef = IntegerHelper.getInt(data[8],data[9]);
224
225       if ((option & builtIn) != 0)
226       {
227         // This is a built in name
228
name = (data[15] < 0x0d) ? builtInNames[data[15]] :
229           "Builtin_" + Integer.toString(data[15], 16);
230         return;
231       }
232
233       name = StringHelper.getString(data, length, 15, ws);
234
235       if ((option & commandMacro) != 0)
236       {
237         // This is a command macro, so it has no cell references
238
return;
239       }
240
241       int pos = length + 15;
242       
243       if (data[pos] == cellReference)
244       {
245         int sheet = IntegerHelper.getInt(data[pos + 1], data[pos + 2]);
246         int row = IntegerHelper.getInt(data[pos + 3], data[pos + 4]);
247         int columnMask = IntegerHelper.getInt(data[pos + 5], data[pos + 6]);
248         int column = columnMask & 0xff;
249
250         // Check that we are not dealing with offsets
251
Assert.verify((columnMask & 0xc0000) == 0);
252
253         NameRange r = new NameRange(sheet, column, row, column, row);
254         ranges.add(r);
255       }
256       else if (data[pos] == areaReference)
257       {
258         int sheet1 = 0;
259         int sheet2 = 0;
260         int r1 = 0;
261         int columnMask = 0;
262         int c1 = 0;
263         int r2 = 0;
264         int c2 = 0;
265         NameRange range = null;
266
267         while (pos < data.length)
268         {
269           sheet1 = IntegerHelper.getInt(data[pos + 1], data[pos + 2]);
270           r1 = IntegerHelper.getInt(data[pos + 3], data[pos + 4]);
271           r2 = IntegerHelper.getInt(data[pos + 5], data[pos + 6]);
272
273           columnMask = IntegerHelper.getInt(data[pos + 7], data[pos + 8]);
274           c1 = columnMask & 0xff;
275
276           // Check that we are not dealing with offsets
277
Assert.verify((columnMask & 0xc0000) == 0);
278
279           columnMask = IntegerHelper.getInt(data[pos + 9], data[pos + 10]);
280           c2 = columnMask & 0xff;
281
282           // Check that we are not dealing with offsets
283
Assert.verify((columnMask & 0xc0000) == 0);
284
285           range = new NameRange(sheet1, c1, r1, c2, r2);
286           ranges.add(range);
287
288           pos += 11;
289         }
290       }
291       else if (data[pos] == subExpression)
292       {
293         int sheet1 = 0;
294         int sheet2 = 0;
295         int r1 = 0;
296         int columnMask = 0;
297         int c1 = 0;
298         int r2 = 0;
299         int c2 = 0;
300         NameRange range = null;
301
302         // Consume unnecessary parsed tokens
303
if (pos < data.length &&
304             data[pos] != cellReference &&
305             data[pos] != areaReference)
306         {
307           if (data[pos] == subExpression)
308           {
309             pos += 3;
310           }
311           else if (data[pos] == union)
312           {
313             pos += 1;
314           }
315         }
316
317         while (pos < data.length)
318         {
319           sheet1 = IntegerHelper.getInt(data[pos + 1], data[pos + 2]);
320           r1 = IntegerHelper.getInt(data[pos + 3], data[pos + 4]);
321           r2 = IntegerHelper.getInt(data[pos + 5], data[pos + 6]);
322
323           columnMask = IntegerHelper.getInt(data[pos + 7], data[pos + 8]);
324           c1 = columnMask & 0xff;
325
326           // Check that we are not dealing with offsets
327
Assert.verify((columnMask & 0xc0000) == 0);
328
329           columnMask = IntegerHelper.getInt(data[pos + 9], data[pos + 10]);
330           c2 = columnMask & 0xff;
331
332           // Check that we are not dealing with offsets
333
Assert.verify((columnMask & 0xc0000) == 0);
334
335           range = new NameRange(sheet1, c1, r1, c2, r2);
336           ranges.add(range);
337
338           pos += 11;
339
340           // Consume unnecessary parsed tokens
341
if (pos < data.length &&
342               data[pos] != cellReference &&
343               data[pos] != areaReference)
344           {
345             if (data[pos] == subExpression)
346             {
347               pos += 3;
348             }
349             else if (data[pos] == union)
350             {
351               pos += 1;
352             }
353           }
354         }
355       }
356     }
357     catch (Throwable JavaDoc t1)
358     {
359       // Generate a warning
360
// Names are really a nice to have, and we don't want to halt the
361
// reading process for functionality that probably won't be used
362
logger.warn("Cannot read name");
363       name = "ERROR";
364     }
365   }
366
367   /**
368    * Constructs this object from the raw data
369    *
370    * @param t the raw data
371    * @param ws the workbook settings
372    * @param ind the index in the name table
373    * @param dummy dummy parameter to indicate a biff7 workbook
374    */

375   NameRecord(Record t, WorkbookSettings ws, int ind, Biff7 dummy)
376   {
377     super(t);
378     index = ind;
379     isbiff8 = false;
380
381     try
382     {
383       ranges = new ArrayList JavaDoc();
384       byte[] data = getRecord().getData();
385       int length = data[3];
386       sheetRef = IntegerHelper.getInt(data[8], data[9]);
387       name = StringHelper.getString(data, length, 14, ws);
388
389       int pos = length + 14;
390
391       if (pos >= data.length)
392       {
393         // There appears to be nothing after the name, so return
394
return;
395       }
396
397       if (data[pos] == cellReference)
398       {
399         int sheet = IntegerHelper.getInt(data[pos + 11], data[pos + 12]);
400         int row = IntegerHelper.getInt(data[pos + 15], data[pos + 16]);
401         int column = data[pos + 17];
402
403         NameRange r = new NameRange(sheet, column, row, column, row);
404         ranges.add(r);
405       }
406       else if (data[pos] == areaReference)
407       {
408         int sheet1 = 0;
409         int sheet2 = 0;
410         int r1 = 0;
411         int c1 = 0;
412         int r2 = 0;
413         int c2 = 0;
414         NameRange range = null;
415
416         while (pos < data.length)
417         {
418           sheet1 = IntegerHelper.getInt(data[pos + 11], data[pos + 12]);
419           sheet2 = IntegerHelper.getInt(data[pos + 13], data[pos + 14]);
420           r1 = IntegerHelper.getInt(data[pos + 15], data[pos + 16]);
421           r2 = IntegerHelper.getInt(data[pos + 17], data[pos + 18]);
422
423           c1 = data[pos + 19];
424           c2 = data[pos + 20];
425
426           range = new NameRange(sheet1, c1, r1, c2, r2);
427           ranges.add(range);
428
429           pos += 21;
430         }
431       }
432       else if (data[pos] == subExpression)
433       {
434         int sheet1 = 0;
435         int sheet2 = 0;
436         int r1 = 0;
437         int c1 = 0;
438         int r2 = 0;
439         int c2 = 0;
440         NameRange range = null;
441
442         // Consume unnecessary parsed tokens
443
if (pos < data.length &&
444             data[pos] != cellReference &&
445             data[pos] != areaReference)
446         {
447           if (data[pos] == subExpression)
448           {
449             pos += 3;
450           }
451           else if (data[pos] == union)
452           {
453             pos += 1;
454           }
455         }
456
457         while (pos < data.length)
458         {
459           sheet1 = IntegerHelper.getInt(data[pos + 11], data[pos + 12]);
460           sheet2 = IntegerHelper.getInt(data[pos + 13], data[pos + 14]);
461           r1 = IntegerHelper.getInt(data[pos + 15], data[pos + 16]);
462           r2 = IntegerHelper.getInt(data[pos + 17], data[pos + 18]);
463
464           c1 = data[pos + 19];
465           c2 = data[pos + 20];
466
467           range = new NameRange(sheet1, c1, r1, c2, r2);
468           ranges.add(range);
469
470           pos += 21;
471
472           // Consume unnecessary parsed tokens
473
if (pos < data.length &&
474               data[pos] != cellReference &&
475               data[pos] != areaReference)
476           {
477             if (data[pos] == subExpression)
478             {
479               pos += 3;
480             }
481             else if (data[pos] == union)
482             {
483               pos += 1;
484             }
485           }
486         }
487       }
488     }
489     catch (Throwable JavaDoc t1)
490     {
491       // Generate a warning
492
// Names are really a nice to have, and we don't want to halt the
493
// reading process for functionality that probably won't be used
494
logger.warn("Cannot read name.");
495       name = "ERROR";
496     }
497   }
498
499   /**
500    * Gets the name
501    *
502    * @return the strings
503    */

504   public String JavaDoc getName()
505   {
506     return name;
507   }
508
509   /**
510    * Gets the array of ranges for this name. This method is public as it is
511    * used from the writable side when copying ranges
512    *
513    * @return the ranges
514    */

515   public NameRange[] getRanges()
516   {
517     NameRange[] nr = new NameRange[ranges.size()];
518     return (NameRange[]) ranges.toArray(nr);
519   }
520
521   /**
522    * Accessor for the index into the name table
523    *
524    * @return the 0-based index into the name table
525    */

526   int getIndex()
527   {
528     return index;
529   }
530   
531   /**
532    * The 0-based index sheet reference for a record name
533    * 0 is for a global reference
534    *
535    * @return the sheet reference for name formula
536    */

537   public int getSheetRef()
538   {
539     return sheetRef;
540   }
541   
542   /**
543    * Set the index sheet reference for a record name
544    * 0 is for a global reference
545    *
546    */

547   public void setSheetRef(int i)
548   {
549     sheetRef = i;
550   }
551
552   /**
553    * Called when copying a sheet. Just returns the raw data
554    *
555    * @return the raw data
556    */

557   public byte[] getData()
558   {
559     return getRecord().getData();
560   }
561   
562   /**
563    * Called when copying to determine whether this is a biff8 name
564    *
565    * @return TRUE if this is a biff8 name record, FALSE otherwise
566    */

567   public boolean isBiff8()
568   {
569     return isbiff8;
570   }
571 }
572
573
Popular Tags