spreadsheet-excel 0.3.4 → 0.3.5

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 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