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.
- data/CHANGES +124 -0
- data/CVS/Entries +10 -0
- data/CVS/Repository +1 -0
- data/CVS/Root +1 -0
- data/README +69 -0
- data/doc/CVS/Entries +3 -0
- data/doc/CVS/Repository +1 -0
- data/doc/CVS/Root +1 -0
- data/doc/format.txt +330 -0
- data/doc/spreadsheet.txt +178 -0
- data/examples/CVS/Entries +3 -0
- data/examples/CVS/Repository +1 -0
- data/examples/CVS/Root +1 -0
- data/examples/example_basic.rb +27 -0
- data/examples/example_format.rb +69 -0
- data/lib/CVS/Entries +1 -0
- data/lib/CVS/Repository +1 -0
- data/lib/CVS/Root +1 -0
- data/lib/spreadsheet/CVS/Entries +7 -0
- data/lib/spreadsheet/CVS/Repository +1 -0
- data/lib/spreadsheet/CVS/Root +1 -0
- data/lib/spreadsheet/biffwriter.rb +46 -0
- data/lib/spreadsheet/excel.rb +13 -0
- data/lib/spreadsheet/format.rb +359 -0
- data/lib/spreadsheet/olewriter.rb +178 -0
- data/lib/spreadsheet/workbook.rb +279 -0
- data/lib/spreadsheet/worksheet.rb +449 -0
- data/test/CVS/Entries +9 -0
- data/test/CVS/Repository +1 -0
- data/test/CVS/Root +1 -0
- data/test/perl_output/CVS/Entries +10 -0
- data/test/perl_output/CVS/Repository +1 -0
- data/test/perl_output/CVS/Root +1 -0
- data/test/perl_output/README +31 -0
- data/test/perl_output/f_font_biff +0 -0
- data/test/perl_output/f_font_key +1 -0
- data/test/perl_output/f_xf_biff +0 -0
- data/test/perl_output/ole_write_header +0 -0
- data/test/perl_output/ws_colinfo +1 -0
- data/test/perl_output/ws_store_dimensions +1 -0
- data/test/perl_output/ws_store_selection +1 -0
- data/test/perl_output/ws_store_window2 +1 -0
- data/test/tc_all.rb +6 -0
- data/test/tc_biff.rb +62 -0
- data/test/tc_excel.rb +26 -0
- data/test/tc_format.rb +133 -0
- data/test/tc_ole.rb +125 -0
- data/test/tc_workbook.rb +71 -0
- data/test/tc_worksheet.rb +142 -0
- data/test/ts_all.rb +9 -0
- 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////
|