spreadsheet-excel 0.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. data/CHANGES +124 -0
  2. data/CVS/Entries +10 -0
  3. data/CVS/Repository +1 -0
  4. data/CVS/Root +1 -0
  5. data/README +69 -0
  6. data/doc/CVS/Entries +3 -0
  7. data/doc/CVS/Repository +1 -0
  8. data/doc/CVS/Root +1 -0
  9. data/doc/format.txt +330 -0
  10. data/doc/spreadsheet.txt +178 -0
  11. data/examples/CVS/Entries +3 -0
  12. data/examples/CVS/Repository +1 -0
  13. data/examples/CVS/Root +1 -0
  14. data/examples/example_basic.rb +27 -0
  15. data/examples/example_format.rb +69 -0
  16. data/lib/CVS/Entries +1 -0
  17. data/lib/CVS/Repository +1 -0
  18. data/lib/CVS/Root +1 -0
  19. data/lib/spreadsheet/CVS/Entries +7 -0
  20. data/lib/spreadsheet/CVS/Repository +1 -0
  21. data/lib/spreadsheet/CVS/Root +1 -0
  22. data/lib/spreadsheet/biffwriter.rb +46 -0
  23. data/lib/spreadsheet/excel.rb +13 -0
  24. data/lib/spreadsheet/format.rb +359 -0
  25. data/lib/spreadsheet/olewriter.rb +178 -0
  26. data/lib/spreadsheet/workbook.rb +279 -0
  27. data/lib/spreadsheet/worksheet.rb +449 -0
  28. data/test/CVS/Entries +9 -0
  29. data/test/CVS/Repository +1 -0
  30. data/test/CVS/Root +1 -0
  31. data/test/perl_output/CVS/Entries +10 -0
  32. data/test/perl_output/CVS/Repository +1 -0
  33. data/test/perl_output/CVS/Root +1 -0
  34. data/test/perl_output/README +31 -0
  35. data/test/perl_output/f_font_biff +0 -0
  36. data/test/perl_output/f_font_key +1 -0
  37. data/test/perl_output/f_xf_biff +0 -0
  38. data/test/perl_output/ole_write_header +0 -0
  39. data/test/perl_output/ws_colinfo +1 -0
  40. data/test/perl_output/ws_store_dimensions +1 -0
  41. data/test/perl_output/ws_store_selection +1 -0
  42. data/test/perl_output/ws_store_window2 +1 -0
  43. data/test/tc_all.rb +6 -0
  44. data/test/tc_biff.rb +62 -0
  45. data/test/tc_excel.rb +26 -0
  46. data/test/tc_format.rb +133 -0
  47. data/test/tc_ole.rb +125 -0
  48. data/test/tc_workbook.rb +71 -0
  49. data/test/tc_worksheet.rb +142 -0
  50. data/test/ts_all.rb +9 -0
  51. metadata +103 -0
@@ -0,0 +1,449 @@
1
+ class MaxSizeError < StandardError; end
2
+
3
+ class Worksheet < BIFFWriter
4
+
5
+ RowMax = 65536
6
+ ColMax = 256
7
+ StrMax = 255
8
+ Buffer = 4096
9
+
10
+ attr_reader :name, :xf_index
11
+ attr_accessor :index, :colinfo, :selection, :offset
12
+
13
+ def initialize(name, index=0, active_sheet=0, first_sheet=0, url_format=nil)
14
+ super(name,index)
15
+
16
+ @name = name
17
+ @index = index
18
+ @active_sheet = active_sheet
19
+ @first_sheet = first_sheet
20
+ @url_format = url_format
21
+
22
+ @offset = 0
23
+
24
+ @dim_rowmin = RowMax + 1
25
+ @dim_rowmax = 0
26
+ @dim_colmin = ColMax + 1
27
+ @dim_colmax = 0
28
+
29
+ @colinfo = []
30
+ @selection = [0,0]
31
+ @row_formats = {}
32
+ @column_formats = {}
33
+ @outline_row_level = 0
34
+ end
35
+
36
+ def close
37
+ store_dimensions
38
+
39
+ unless @colinfo.empty?
40
+ while @colinfo.length > 0
41
+ store_colinfo(*@colinfo.pop)
42
+ end
43
+ store_defcol
44
+ end
45
+
46
+ store_guts
47
+ store_bof(0x0010)
48
+
49
+ store_window2
50
+ store_selection(*@selection)
51
+ store_eof
52
+ end
53
+
54
+ def data
55
+ if @data && @data.length > 0
56
+ tmp = @data
57
+ @data = ""
58
+ return tmp
59
+ end
60
+ end
61
+
62
+ def activate
63
+ @active_sheet = @index
64
+ end
65
+
66
+ def set_first_sheet
67
+ @first_sheet = @index
68
+ end
69
+
70
+ def column(*range)
71
+ @colinfo = *range
72
+ end
73
+
74
+ def store_dimensions
75
+ record = 0x0000
76
+ length = 0x000A
77
+ reserved = 0x0000
78
+
79
+ header = [record, length].pack("vv")
80
+ fields = [@dim_rowmin, @dim_rowmax, @dim_colmin, @dim_colmax, reserved]
81
+ data = fields.pack("vvvvv")
82
+
83
+ prepend(header, data)
84
+ end
85
+
86
+ def store_guts
87
+ record = 0x0080 # record identifier
88
+ length = 0x0008 # bytes to follow
89
+
90
+ dxRwGut = 0x0000 # size of row gutter
91
+ dxColGut = 0x0000 # size of col gutter
92
+
93
+ row_level = @outline_row_level
94
+ col_level = 0
95
+
96
+ @colinfo.each do |colinfo|
97
+ next if colinfo.length < 6
98
+ col_level = colinfo[5] if colinfo[5] > col_level
99
+ end
100
+
101
+ col_level = 0 if col_level < 0
102
+ col_level = 7 if col_level > 7
103
+
104
+ row_level += 1 if row_level > 0
105
+ col_level += 1 if col_level > 0
106
+
107
+ header = [record, length].pack("vv")
108
+ fields = [dxRwGut, dxColGut, row_level, col_level]
109
+ data = fields.pack("vvvv")
110
+
111
+ prepend(header, data)
112
+ end
113
+
114
+ def store_window2
115
+ record = 0x023E
116
+ length = 0x000A
117
+
118
+ grbit = 0x00B6
119
+ rwTop = 0x0000
120
+ colLeft = 0x0000
121
+ rgbHdr = 0x00000000
122
+
123
+ if @active_sheet == @index
124
+ grbit = 0x06B6
125
+ end
126
+
127
+ header = [record, length].pack("vv")
128
+ data = [grbit, rwTop, colLeft, rgbHdr].pack("vvvV")
129
+
130
+ append(header, data)
131
+ end
132
+
133
+ def store_defcol
134
+ record = 0x0055
135
+ length = 0x0002
136
+
137
+ colwidth = 0x0008
138
+
139
+ header = [record, length].pack("vv")
140
+ data = [colwidth].pack("v")
141
+
142
+ prepend(header, data)
143
+ end
144
+
145
+ def store_colinfo(first=0, last=0, coldx=8.43, ixfe=0x0F, grbit=0)
146
+ record = 0x007D
147
+ length = 0x000B
148
+
149
+ coldx += 0.72
150
+ coldx *= 256
151
+ reserved = 0x00
152
+
153
+ if ixfe.kind_of?(Format)
154
+ ixfe = ixfe.xf_index
155
+ end
156
+
157
+ header = [record, length].pack("vv")
158
+ data = [first, last, coldx, ixfe, grbit, reserved].pack("vvvvvC")
159
+
160
+ prepend(header,data)
161
+ end
162
+
163
+ # I think this may have problems
164
+ def store_selection(row=0, col=0, row_last=0, col_last=0)
165
+ record = 0x001D
166
+ length = 0x000F
167
+
168
+ pnn = 3
169
+ rwAct = row
170
+ colAct = col
171
+ irefAct = 0
172
+ cref = 1
173
+
174
+ rwFirst = row
175
+ colFirst = col
176
+
177
+ if row_last != 0
178
+ rwLast = row_last
179
+ else
180
+ rwLast = rwFirst
181
+ end
182
+
183
+ if col_last != 0
184
+ colLast = col_last
185
+ else
186
+ colLast = colFirst
187
+ end
188
+
189
+ if rwFirst > rwLast
190
+ rwFirst,rwLast = rwLast,rwFirst
191
+ end
192
+
193
+ if colFirst > colLast
194
+ colFirst,colLast = colLast,colFirst
195
+ end
196
+
197
+ header = [record, length].pack("vv")
198
+ fields = [pnn,rwAct,colAct,irefAct,cref,rwFirst,rwLast,colFirst,colLast]
199
+ data = fields.pack("CvvvvvvCC")
200
+
201
+ append(header, data)
202
+ end
203
+
204
+ def write(row, col, data=nil, format=nil)
205
+ if data.nil?
206
+ write_blank(row, col, format)
207
+ elsif data.kind_of?(Array)
208
+ write_row(row, col, data, format)
209
+ elsif data.kind_of?(Numeric)
210
+ write_number(row, col, data, format)
211
+ else
212
+ write_string(row, col, data, format)
213
+ end
214
+ end
215
+
216
+ def write_row(row, col, tokens=nil, format=nil)
217
+ if tokens.nil?
218
+ write(row,col,tokens,format)
219
+ return
220
+ end
221
+
222
+ tokens.each{ |token|
223
+ if token.kind_of?(Array)
224
+ write_column(row,col,token,format)
225
+ else
226
+ write(row,col,token,format)
227
+ end
228
+ col += 1
229
+ }
230
+ end
231
+
232
+ def write_column(row, col, tokens=nil, format=nil)
233
+ if tokens.nil?
234
+ write(row,col,tokens,format)
235
+ return
236
+ end
237
+
238
+ tokens.each{ |token|
239
+ if token.kind_of?(Array)
240
+ write_row(row, col, token, format)
241
+ else
242
+ write(row, col, token, format)
243
+ end
244
+ row += 1
245
+ }
246
+ end
247
+
248
+ def write_number(row, col, num, format=nil)
249
+ record = 0x0203
250
+ length = 0x000E
251
+
252
+ xf_index = XF(row,col,format)
253
+
254
+ raise MaxSizeError if row >= RowMax
255
+ raise MaxSizeError if col >= ColMax
256
+
257
+ @dim_rowmin = row if row < @dim_rowmin
258
+ @dim_rowmax = row if row > @dim_rowmax
259
+ @dim_colmin = col if col < @dim_colmin
260
+ @dim_colmax = col if col > @dim_colmax
261
+
262
+ header = [record,length].pack("vv")
263
+ data = [row,col,xf_index].pack("vvv")
264
+ xl_double = [num].pack("d")
265
+
266
+ if BigEndian
267
+ xl_double.reverse!
268
+ end
269
+
270
+ append(header,data,xl_double)
271
+ end
272
+
273
+ def write_string(row, col, str, format)
274
+ record = 0x0204
275
+ length = 0x0008 + str.length
276
+
277
+ xf_index = XF(row, col, format)
278
+
279
+ strlen = str.length
280
+
281
+ raise MaxSizeError if row >= RowMax
282
+ raise MaxSizeError if col >= ColMax
283
+
284
+ @dim_rowmin = row if row < @dim_rowmin
285
+ @dim_rowmax = row if row > @dim_rowmax
286
+ @dim_colmin = col if col < @dim_colmin
287
+ @dim_colmax = col if col > @dim_colmax
288
+
289
+ # Truncate strings over 255 characters
290
+ if strlen > StrMax
291
+ str = str[0..StrMax-1]
292
+ length = 0x0008 + StrMax
293
+ strlen = StrMax
294
+ end
295
+
296
+ header = [record, length].pack("vv")
297
+ data = [row, col, xf_index, strlen].pack("vvvv")
298
+
299
+ append(header, data, str)
300
+ end
301
+
302
+ # Write a blank cell to the specified row and column (zero indexed).
303
+ # A blank cell is used to specify formatting without adding data.
304
+ def write_blank(row, col, format)
305
+ record = 0x0201
306
+ length = 0x0006
307
+
308
+ xf_index = XF(row, col, format)
309
+
310
+ raise MaxSizeError if row >= RowMax
311
+ raise MaxSizeError if col >= ColMax
312
+
313
+ @dim_rowmin = row if row < @dim_rowmin
314
+ @dim_rowmax = row if row > @dim_rowmax
315
+ @dim_colmin = col if col < @dim_colmin
316
+ @dim_colmax = col if col > @dim_colmax
317
+
318
+ header = [record, length].pack("vv")
319
+ data = [row, col, xf_index].pack("vvv")
320
+
321
+ append(header, data)
322
+ end
323
+
324
+ # Format a rectangular section of cells. Note that you should call this
325
+ # method only after you have written data to it, or the formatting will
326
+ # be lost.
327
+ def format_rectangle(x1, y1, x2, y2, format)
328
+ raise TypeError, "invalid format" unless format.kind_of?(Format)
329
+
330
+ x1.upto(x2){ |row|
331
+ y1.upto(y2){ |col|
332
+ write_blank(row, col, format)
333
+ }
334
+ }
335
+ end
336
+
337
+ def write_url(row, col, url, string=url, format=nil)
338
+ record = 0x01B8
339
+ length = 0x0034 + 2 * (1+url.length)
340
+
341
+ write_string(row,col,string,format)
342
+
343
+ header = [record, length].pack("vv")
344
+ data = [row, row, col, col].pack("vvvv")
345
+
346
+ unknown = "D0C9EA79F9BACE118C8200AA004BA90B02000000"
347
+ unknown += "03000000E0C9EA79F9BACE118C8200AA004BA90B"
348
+
349
+ stream = [unknown].pack("H*")
350
+
351
+ url = url.split('').join("\0")
352
+ url += "\0\0\0"
353
+
354
+ len = url.length
355
+ url_len = [len].pack("V")
356
+
357
+ append(header + data)
358
+ append(stream)
359
+ append(url_len)
360
+ append(url)
361
+ end
362
+
363
+ def format_row(row, height=nil, format=nil, hidden=false, level=0)
364
+ unless row.kind_of?(Range) || row.kind_of?(Integer)
365
+ raise TypeError, 'row must be an Integer or Range'
366
+ end
367
+
368
+ if hidden.nil? || hidden == false
369
+ hidden = 0
370
+ end
371
+
372
+ record = 0x0208 # record identifier
373
+ length = 0x0010 # number of bytes to follow
374
+
375
+ col_first = 0x0000 # first defined column
376
+ col_last = 0x0000 # last defined column
377
+ irwmac = 0x0000 # used by Excel to optimize loading
378
+ reserved = 0x0000 # reservered
379
+ grbit = 0x0000 # option flags
380
+ xf_index = nil
381
+
382
+ grbit |= level
383
+ if hidden > 0
384
+ grbit |= 0x0020
385
+ end
386
+ grbit |= 0x0040 #unsynched
387
+ grbit |= 0x0100
388
+
389
+ @outline_row_level = level if level > @outline_row_level
390
+
391
+ if format.nil?
392
+ xf_index = 0x0F
393
+ else
394
+ xf_index = format.xf_index
395
+ grbit |= 0x80
396
+ end
397
+
398
+ if height.nil?
399
+ height = 0xff
400
+ else
401
+ height = height * 20
402
+ end
403
+
404
+ row = row..row if row.kind_of?(Fixnum) # Avoid an if..else clause :)
405
+ row.each{ |r|
406
+ header = [record, length].pack("vv")
407
+ fields = [r,col_first,col_last,height,irwmac,reserved,grbit,xf_index]
408
+ data = fields.pack("vvvvvvvv")
409
+
410
+ @row_formats[r] = format if format
411
+ append(header + data)
412
+ }
413
+ end
414
+
415
+ # private - adapted from .37 of Spreadsheet::WriteExcel
416
+ def XF(row, col, xf=nil)
417
+ if xf.kind_of?(Format)
418
+ return xf.xf_index
419
+ elsif @row_formats.has_key?(row)
420
+ return @row_formats[row].xf_index
421
+ elsif @column_formats.has_key?(col)
422
+ return @column_formats[col].xf_index
423
+ else
424
+ return 0x0F
425
+ end
426
+ end
427
+
428
+ def format_column(column, width=nil, format=nil)
429
+ unless column.kind_of?(Range) || column.kind_of?(Fixnum)
430
+ raise TypeError
431
+ end
432
+
433
+ width = 8.43 if width.nil?
434
+ column = column..column if column.kind_of?(Fixnum)
435
+
436
+ column.each{ |e|
437
+ @column_formats[e] = format unless format.nil?
438
+ }
439
+ @colinfo.push([column.begin, column.end, width, format])
440
+ end
441
+
442
+ end
443
+ =begin
444
+ = Differences between Worksheet.pm and worksheet.rb
445
+ ---write_url
446
+ I made this a public method to be called directly by the user if they want
447
+ to write a url string. A variable number of arguments made it a pain to
448
+ integrate into the 'write' method.
449
+ =end
data/test/CVS/Entries ADDED
@@ -0,0 +1,9 @@
1
+ /tc_all.rb/1.1/Sun Nov 23 03:46:55 2003//
2
+ /tc_biff.rb/1.3/Wed Oct 12 21:33:36 2005//
3
+ /tc_excel.rb/1.7/Fri Feb 17 03:36:41 2006//
4
+ /tc_format.rb/1.4/Wed Oct 12 21:34:22 2005//
5
+ /tc_ole.rb/1.4/Wed Oct 12 21:33:05 2005//
6
+ /tc_workbook.rb/1.2/Wed Oct 12 21:34:46 2005//
7
+ /tc_worksheet.rb/1.3/Wed Oct 12 21:35:11 2005//
8
+ /ts_all.rb/1.2/Wed Oct 12 21:35:30 2005//
9
+ D/perl_output////