spreadsheet-excel 0.3.4 → 0.3.5

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES CHANGED
@@ -1,3 +1,14 @@
1
+ == 0.3.5 - 18-Aug-2006
2
+ * Instead of making OLEWriter inherit from IO, just have it delegate
3
+ the IO method calls to an IO object reference in an instance variable. That
4
+ way the developer can specify an IO or IO-like object to which OLEWriter will
5
+ write. This allows developers to use StringIO objects (or any IO-like object).
6
+ Thanks go to Daniel Amelang for the feature request, the patch, and most of
7
+ this description.
8
+ * Implemented a Feature Request by Randal Santia: it is now possible to specify
9
+ alignment and border as additional values in the configuration-hash passed to
10
+ Format.new as if alignment= or border= were called.
11
+
1
12
  == 0.3.4 - 17-Feb-2006
2
13
  * Added a workaround for a bug in Ruby 1.8.3 and Ruby 1.8.4 where subclasses
3
14
  of IO are not guaranteed to call IO#close in block form.
@@ -1,10 +1,10 @@
1
1
  /.project/1.2/Tue Oct 11 14:08:38 2005//
2
- /CHANGES/1.14/Fri Feb 17 17:12:54 2006/-kb/
3
2
  /MANIFEST/1.10/Mon Dec 5 02:05:39 2005/-kb/
4
- /README/1.5/Tue Oct 11 17:06:12 2005/-kb/
5
3
  /install.rb/1.8/Mon Dec 5 02:13:14 2005/-ko/
6
- /spreadsheet-excel.gemspec/1.7/Fri Feb 17 03:44:27 2006/-kb/
7
4
  D/doc////
8
5
  D/examples////
9
6
  D/lib////
10
7
  D/test////
8
+ /CHANGES/1.15/Fri Aug 18 13:42:05 2006/-kb/
9
+ /README/1.6/Fri Aug 18 13:38:31 2006/-kb/
10
+ /spreadsheet-excel.gemspec/1.8/Fri Aug 18 13:38:59 2006/-kb/
data/README CHANGED
@@ -13,6 +13,9 @@
13
13
  ruby test/ts_all.rb (optional)
14
14
  ruby spreadsheet-excel.gemspec
15
15
  gem install spreadsheet-excel-x.y.z.gem # where 'x.y.z' is the version
16
+
17
+ or directly via RubyForge:
18
+ gem install spreadsheet-excel
16
19
 
17
20
  == Synopsis
18
21
  require "spreadsheet/excel"
@@ -67,3 +70,7 @@
67
70
  Daniel J. Berger
68
71
  djberg96 at gmail dot com
69
72
  IRC nickname: imperator/mok/rubyhacker1 (freenode)
73
+
74
+ == Maintainer
75
+ Hannes Wyss
76
+ hannes.wyss@gmail.com
@@ -1,7 +1,7 @@
1
1
  /biffwriter.rb/1.1/Tue Oct 11 17:09:08 2005//
2
2
  /excel.rb/1.4/Fri Feb 17 03:34:00 2006//
3
- /format.rb/1.1/Tue Oct 11 17:09:08 2005//
4
- /olewriter.rb/1.3/Mon Dec 5 02:03:48 2005//
5
- /workbook.rb/1.4/Sun Feb 12 16:42:10 2006//
6
3
  /worksheet.rb/1.2/Fri Feb 17 03:33:24 2006//
4
+ /format.rb/1.2/Fri Aug 18 13:15:05 2006//
5
+ /olewriter.rb/1.4/Fri Aug 18 13:20:26 2006//
6
+ /workbook.rb/1.5/Fri Aug 18 13:20:13 2006//
7
7
  D
@@ -8,6 +8,6 @@ require "format"
8
8
 
9
9
  module Spreadsheet
10
10
  class Excel < Workbook
11
- VERSION = "0.3.4"
11
+ VERSION = "0.3.5"
12
12
  end
13
- end
13
+ end
@@ -41,12 +41,16 @@ class Format
41
41
  defaults.update(:text_h_align => 0, :num_format => 0)
42
42
  defaults.update(:text_justlast => 0, :text_wrap => 0)
43
43
 
44
+ ## convenience methods
45
+ defaults.update(:border => 0, :align => 'left')
46
+
44
47
  ########################################################################
45
48
  # We must manually create accessors for these so that they can handle
46
49
  # both 0/1 and true/false.
47
50
  ########################################################################
48
51
  no_acc = [:bold,:italic,:underline,:strikeout,:text_wrap,:text_justlast]
49
52
  no_acc.push(:fg_color,:bg_color,:color,:font_outline,:font_shadow)
53
+ no_acc.push(:align,:border)
50
54
 
51
55
  args.each{|key,val|
52
56
  key = key.to_s.downcase.intern
@@ -304,19 +308,28 @@ class Format
304
308
  return if location.kind_of?(Fixnum)
305
309
  location.downcase!
306
310
 
307
- @text_h_align = 1 if location == 'left'
308
- @text_h_align = 2 if location == 'centre'
309
- @text_h_align = 2 if location == 'center'
310
- @text_h_align = 3 if location == 'right'
311
- @text_h_align = 4 if location == 'fill'
312
- @text_h_align = 5 if location == 'justify'
313
- @text_h_align = 6 if location == 'merge'
314
-
315
- @text_v_align = 0 if location == 'top'
316
- @text_v_align = 1 if location == 'vcentre'
317
- @text_v_align = 1 if location == 'vcenter'
318
- @text_v_align = 2 if location == 'bottom'
319
- @text_v_align = 3 if location == 'vjustify'
311
+ case location
312
+ when 'left'
313
+ @text_h_align = 1
314
+ when 'center', 'centre'
315
+ @text_h_align = 2
316
+ when 'right'
317
+ @text_h_align = 3
318
+ when 'fill'
319
+ @text_h_align = 4
320
+ when 'justify'
321
+ @text_h_align = 5
322
+ when 'merge'
323
+ @text_h_align = 6
324
+ when 'top'
325
+ @text_v_align = 0
326
+ when 'vcentre', 'vcenter'
327
+ @text_v_align = 1
328
+ when 'bottom'
329
+ @text_v_align = 2
330
+ when 'vjustify'
331
+ @text_v_align = 3
332
+ end
320
333
  end
321
334
 
322
335
  def align
@@ -5,7 +5,7 @@
5
5
 
6
6
  class MaxSizeError < StandardError; end
7
7
 
8
- class OLEWriter < IO
8
+ class OLEWriter
9
9
 
10
10
  # Not meant for public consumption
11
11
  MaxSize = 7087104
@@ -16,16 +16,14 @@ class OLEWriter < IO
16
16
  attr_reader :biff_size, :book_size, :big_blocks, :list_blocks
17
17
  attr_reader :root_start, :size_allowed
18
18
 
19
- # Accept an IO object, a fileno, or a String
20
- def initialize(arg, &block)
19
+ # Accept an IO or IO-like object or a filename (as a String)
20
+ def initialize(arg)
21
21
  if arg.kind_of?(String)
22
- super(File.open(arg, "w+").fileno, "w+", &block)
23
- elsif arg.respond_to?(:fileno)
24
- super(arg.fileno, "w+", &block)
22
+ @io = File.open(arg, "w")
25
23
  else
26
- super(arg, "w+", &block)
24
+ @io = arg
27
25
  end
28
- binmode
26
+ @io.binmode
29
27
 
30
28
  @biff_only = false
31
29
  @size_allowed = true
@@ -37,6 +35,26 @@ class OLEWriter < IO
37
35
  @block_count = 4
38
36
  end
39
37
 
38
+ # Imitate IO.open behavior
39
+ def self.open(arg)
40
+ if block_given?
41
+ ole = self.new(arg)
42
+ result = yield(ole)
43
+ ole.close
44
+ result
45
+ else
46
+ self.new(arg)
47
+ end
48
+ end
49
+
50
+ # Delegate 'write' and 'print' to the internal IO object.
51
+ def write(*args, &block)
52
+ @io.write(*args, &block)
53
+ end
54
+ def print(*args, &block)
55
+ @io.print(*args, &block)
56
+ end
57
+
40
58
  # Set the size of the data to be written to the OLE stream
41
59
  #
42
60
  # @big_blocks = (109 depot block x (128 -1 marker word)
@@ -71,7 +89,7 @@ class OLEWriter < IO
71
89
  write_property_storage
72
90
  write_big_block_depot
73
91
  end
74
- super
92
+ @io.close
75
93
  end
76
94
 
77
95
  # Write the OLE header block
@@ -0,0 +1,196 @@
1
+ # olewriter.rb
2
+ #
3
+ # This class should never be instantiated directly. The entire class, and all
4
+ # its methods should be considered private.
5
+
6
+ class MaxSizeError < StandardError; end
7
+
8
+ class OLEWriter
9
+
10
+ # Not meant for public consumption
11
+ MaxSize = 7087104
12
+ BlockSize = 4096
13
+ BlockDiv = 512
14
+ ListBlocks = 127
15
+
16
+ attr_reader :biff_size, :book_size, :big_blocks, :list_blocks
17
+ attr_reader :root_start, :size_allowed
18
+
19
+ # Accept an IO or IO-like object or a filename (as a String)
20
+ def initialize(arg)
21
+ if arg.kind_of?(String)
22
+ @io = File.open(arg, "w")
23
+ else
24
+ @io = arg
25
+ end
26
+ @io.binmode
27
+
28
+ @biff_only = false
29
+ @size_allowed = true
30
+ @biff_size = 0
31
+ @book_size = 0
32
+ @big_blocks = 0
33
+ @list_blocks = 0
34
+ @root_start = 0
35
+ @block_count = 4
36
+ end
37
+
38
+ # Imitate IO.open behavior
39
+ def self.open(arg)
40
+ if block_given?
41
+ ole = self.new(arg)
42
+ result = yield(ole)
43
+ ole.close
44
+ result
45
+ else
46
+ self.new(arg)
47
+ end
48
+ end
49
+
50
+ # Delegate 'write' and 'print' to the internal IO object.
51
+ def write(*args, &block)
52
+ @io.write(*args, &block)
53
+ end
54
+ def print(*args, &block)
55
+ @io.print(*args, &block)
56
+ end
57
+
58
+ # Set the size of the data to be written to the OLE stream
59
+ #
60
+ # @big_blocks = (109 depot block x (128 -1 marker word)
61
+ # - (1 x end words)) = 13842
62
+ #
63
+ # MaxSize = @big_blocks * 512 bytes = 7087104
64
+ def set_size(size = BlockSize)
65
+ raise MaxSizeError if size > MaxSize
66
+
67
+ @biff_size = size
68
+
69
+ if biff_size > BlockSize
70
+ @book_size = size
71
+ else
72
+ @book_size = BlockSize
73
+ end
74
+
75
+ @size_allowed = true
76
+ end
77
+
78
+ # Calculate various sizes needed for the OLE stream
79
+ def calculate_sizes
80
+ @big_blocks = (@book_size.to_f/BlockDiv.to_f).ceil
81
+ @list_blocks = (@big_blocks / ListBlocks) + 1
82
+ @root_start = @big_blocks
83
+ end
84
+
85
+ # Write root entry, big block list and close the filehandle.
86
+ def close
87
+ if @size_allowed == true
88
+ write_padding
89
+ write_property_storage
90
+ write_big_block_depot
91
+ end
92
+ @io.close
93
+ end
94
+
95
+ # Write the OLE header block
96
+ def write_header
97
+ return if @biff_only == true
98
+ calculate_sizes
99
+ root_start = @root_start
100
+
101
+ write([0xD0CF11E0, 0xA1B11AE1].pack("NN"))
102
+ write([0x00, 0x00, 0x00, 0x00].pack("VVVV"))
103
+ write([0x3E, 0x03, -2, 0x09].pack("vvvv"))
104
+ write([0x06, 0x00, 0x00].pack("VVV"))
105
+ write([@list_blocks, root_start].pack("VV"))
106
+ write([0x00, 0x1000,-2].pack("VVV"))
107
+ write([0x00, -2 ,0x00].pack("VVV"))
108
+
109
+ unused = [-1].pack("V")
110
+
111
+ 1.upto(@list_blocks){
112
+ root_start += 1
113
+ write([root_start].pack("V"))
114
+ }
115
+
116
+ @list_blocks.upto(108){
117
+ write(unused)
118
+ }
119
+ end
120
+
121
+ # Write a big block depot
122
+ def write_big_block_depot
123
+ total_blocks = @list_blocks * 128
124
+ used_blocks = @big_blocks + @list_blocks + 2
125
+
126
+ marker = [-3].pack("V")
127
+ eoc = [-2].pack("V")
128
+ unused = [-1].pack("V")
129
+
130
+ num_blocks = @big_blocks - 1
131
+
132
+ 1.upto(num_blocks){|n|
133
+ write([n].pack("V"))
134
+ }
135
+
136
+ write eoc
137
+ write eoc
138
+
139
+ 1.upto(@list_blocks){ write(marker) }
140
+
141
+ used_blocks.upto(total_blocks){ write(unused) }
142
+
143
+ end
144
+
145
+ # Write property storage
146
+ def write_property_storage
147
+ write_pps('Root Entry', 0x05, 1, -2, 0x00)
148
+ write_pps('Book', 0x02, -1, 0x00, @book_size)
149
+ write_pps("", 0x00, -1, 0x00, 0x0000)
150
+ write_pps("", 0x00, -1, 0x00, 0x0000)
151
+ end
152
+
153
+ # Write property sheet in property storage
154
+ def write_pps(name, type, dir, start, size)
155
+ length = 0
156
+ ord_name = []
157
+ unless name.empty?
158
+ name += "\0"
159
+ ord_name = name.unpack("c*")
160
+ length = name.length * 2
161
+ end
162
+
163
+ zero = [0].pack("C")
164
+ unknown = [0].pack("V")
165
+
166
+ write(ord_name.pack("v*"))
167
+
168
+ for n in 1..64-length
169
+ write(zero)
170
+ end
171
+
172
+ write([length,type,-1,-1,dir].pack("vvVVV"))
173
+
174
+ for n in 1..5
175
+ write(unknown)
176
+ end
177
+
178
+ for n in 1..4
179
+ write([0].pack("V"))
180
+ end
181
+
182
+ write([start,size].pack("VV"))
183
+ write(unknown)
184
+ end
185
+
186
+ # Pad the end of the file
187
+ def write_padding
188
+ min_size = 512
189
+ min_size = BlockSize if @biff_size < BlockSize
190
+
191
+ if @biff_size % min_size != 0
192
+ padding = min_size - (@biff_size % min_size)
193
+ write("\0" * padding)
194
+ end
195
+ end
196
+ end
@@ -0,0 +1,32 @@
1
+ ***************
2
+ *** 83,97 ****
3
+ end
4
+
5
+ # Write root entry, big block list and close the filehandle.
6
+ def close
7
+ - return if @io.closed?
8
+ if @size_allowed == true
9
+ write_padding
10
+ write_property_storage
11
+ write_big_block_depot
12
+ end
13
+ - @io.close
14
+ end
15
+
16
+ # Write the OLE header block
17
+ def write_header
18
+ --- 65,78 ----
19
+ end
20
+
21
+ # Write root entry, big block list and close the filehandle.
22
+ def close
23
+ if @size_allowed == true
24
+ write_padding
25
+ write_property_storage
26
+ write_big_block_depot
27
+ end
28
+ + super
29
+ end
30
+
31
+ # Write the OLE header block
32
+ def write_header
@@ -102,7 +102,6 @@ class Workbook < BIFFWriter
102
102
  @worksheets.each{ |sheet|
103
103
  ole.print(sheet.data)
104
104
  }
105
- ole.close # Added because of bug introduced in Ruby 1.8.3
106
105
  }
107
106
  end
108
107
 
@@ -6,6 +6,7 @@ class Worksheet < BIFFWriter
6
6
  ColMax = 256
7
7
  StrMax = 255
8
8
  Buffer = 4096
9
+ ContMax = 2080
9
10
 
10
11
  attr_reader :name, :xf_index
11
12
  attr_accessor :index, :colinfo, :selection, :offset
@@ -272,12 +273,9 @@ class Worksheet < BIFFWriter
272
273
 
273
274
  def write_string(row, col, str, format)
274
275
  record = 0x0204
275
- length = 0x0008 + str.length
276
276
 
277
277
  xf_index = XF(row, col, format)
278
278
 
279
- strlen = str.length
280
-
281
279
  raise MaxSizeError if row >= RowMax
282
280
  raise MaxSizeError if col >= ColMax
283
281
 
@@ -286,17 +284,20 @@ class Worksheet < BIFFWriter
286
284
  @dim_colmin = col if col < @dim_colmin
287
285
  @dim_colmax = col if col > @dim_colmax
288
286
 
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
-
287
+ strlen = str.size
288
+ pstr = str.slice!(0,StrMax)
289
+ length = 0x0008 + pstr.size
296
290
  header = [record, length].pack("vv")
297
291
  data = [row, col, xf_index, strlen].pack("vvvv")
292
+ append(header, data, pstr)
293
+
294
+ record = 0x003C
295
+ until(str.empty?)
296
+ pstr = str.slice!(0,ContMax)
297
+ header = [record, pstr.size].pack("vv")
298
+ append(header, pstr)
299
+ end
298
300
 
299
- append(header, data, str)
300
301
  end
301
302
 
302
303
  # Write a blank cell to the specified row and column (zero indexed).
@@ -1,9 +1,9 @@
1
1
  /tc_all.rb/1.1/Sun Nov 23 03:46:55 2003//
2
2
  /tc_biff.rb/1.3/Wed Oct 12 21:33:36 2005//
3
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
4
  /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
5
  /tc_worksheet.rb/1.3/Wed Oct 12 21:35:11 2005//
8
6
  /ts_all.rb/1.2/Wed Oct 12 21:35:30 2005//
9
7
  D/perl_output////
8
+ /tc_format.rb/1.5/Fri Aug 18 13:15:13 2006//
9
+ /tc_workbook.rb/1.3/Fri Aug 18 13:05:40 2006//
Binary file
File without changes
@@ -21,6 +21,6 @@ require "ftools"
21
21
 
22
22
  class TC_Excel < Test::Unit::TestCase
23
23
  def test_version
24
- assert_equal("0.3.4", Spreadsheet::Excel::VERSION)
24
+ assert_equal("0.3.5", Spreadsheet::Excel::VERSION)
25
25
  end
26
26
  end
@@ -120,6 +120,14 @@ class TC_Format < Test::Unit::TestCase
120
120
  assert_equal(true,@format.bold,"Bad bold value")
121
121
  end
122
122
 
123
+ def test_initialize
124
+ assert_nothing_raised {
125
+ Format.new(:bold => true, :size => 10, :color => 'black',
126
+ :fg_color => 43, :align => 'top', :text_wrap => true,
127
+ :border => 1)
128
+ }
129
+ end
130
+
123
131
  def teardown
124
132
  begin
125
133
  @pfh.close
@@ -60,12 +60,27 @@ class TC_Workbook < Test::Unit::TestCase
60
60
  def test_add_format
61
61
  assert_nothing_raised{ @wb.add_format }
62
62
  assert_equal(2,@wb.formats.length,"Bad number of formats")
63
+ assert_nothing_raised{
64
+ @wb.add_format(:bold => true, :size => 10, :color => 'black',
65
+ :fg_color => 43, :align => 'top', :text_wrap => true,
66
+ :border => 1)
67
+ }
68
+ assert_equal(3,@wb.formats.length,"Bad number of formats")
69
+ end
70
+
71
+ def test_write_string_continued
72
+ ws = @wb.add_worksheet
73
+ txt = ''
74
+ 0.upto(256) { |num|
75
+ txt << "." << num.to_s
76
+ }
77
+ ws.write(0,0,txt)
63
78
  end
64
79
 
65
80
  def teardown
66
81
  @wb.close
67
82
  @wb = nil
68
- File.delete("test.xls") if File.exists?("test.xls")
83
+ #File.delete("test.xls") if File.exists?("test.xls")
69
84
  end
70
85
 
71
86
  end
Binary file
metadata CHANGED
@@ -3,12 +3,12 @@ rubygems_version: 0.8.11
3
3
  specification_version: 1
4
4
  name: spreadsheet-excel
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.3.4
7
- date: 2006-06-06 00:00:00 +02:00
6
+ version: 0.3.5
7
+ date: 2006-08-23 00:00:00 +02:00
8
8
  summary: Creates Excel documents on any platform
9
9
  require_paths:
10
10
  - lib
11
- email: djberg96@gmail.com
11
+ email: hannes.wyss@gmail.com
12
12
  homepage: http://rubyspreadsheet.sf.net
13
13
  rubyforge_project:
14
14
  description: Creates Excel documents on any platform
@@ -26,7 +26,7 @@ platform: ruby
26
26
  signing_key:
27
27
  cert_chain:
28
28
  authors:
29
- - Daniel Berger
29
+ - Hannes Wyss
30
30
  files:
31
31
  - CVS/Root
32
32
  - CVS/Repository
@@ -50,24 +50,29 @@ files:
50
50
  - lib/CVS/Entries
51
51
  - lib/spreadsheet/CVS
52
52
  - lib/spreadsheet/biffwriter.rb
53
- - lib/spreadsheet/excel.rb
53
+ - lib/spreadsheet/worksheet.rb
54
54
  - lib/spreadsheet/format.rb
55
- - lib/spreadsheet/olewriter.rb
55
+ - lib/spreadsheet/olewriter.rb.orig
56
+ - lib/spreadsheet/olewriter.rb.rej
56
57
  - lib/spreadsheet/workbook.rb
57
- - lib/spreadsheet/worksheet.rb
58
+ - lib/spreadsheet/olewriter.rb
59
+ - lib/spreadsheet/excel.rb
58
60
  - lib/spreadsheet/CVS/Root
59
61
  - lib/spreadsheet/CVS/Repository
60
62
  - lib/spreadsheet/CVS/Entries
61
63
  - test/CVS
62
64
  - test/tc_all.rb
63
65
  - test/tc_biff.rb
64
- - test/tc_excel.rb
65
- - test/tc_format.rb
66
66
  - test/tc_ole.rb
67
- - test/tc_workbook.rb
68
- - test/tc_worksheet.rb
69
67
  - test/ts_all.rb
70
68
  - test/perl_output
69
+ - test/foo.ole
70
+ - test/tc_format.rb
71
+ - test/delete_this
72
+ - test/test.xls
73
+ - test/tc_workbook.rb
74
+ - test/tc_worksheet.rb
75
+ - test/tc_excel.rb
71
76
  - test/CVS/Root
72
77
  - test/CVS/Repository
73
78
  - test/CVS/Entries