osheet 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. data/.bundle/config +2 -0
  2. data/.gitignore +6 -0
  3. data/Gemfile +4 -0
  4. data/Gemfile.lock +33 -0
  5. data/README.rdoc +103 -61
  6. data/Rakefile +5 -56
  7. data/examples/basic.rb +73 -0
  8. data/examples/formats.rb +366 -0
  9. data/examples/trivial.rb +21 -0
  10. data/lib/osheet/associations.rb +62 -0
  11. data/lib/osheet/cell.rb +44 -10
  12. data/lib/osheet/column.rb +34 -7
  13. data/lib/osheet/format/accounting.rb +21 -0
  14. data/lib/osheet/format/currency.rb +23 -0
  15. data/lib/osheet/format/custom.rb +13 -0
  16. data/lib/osheet/format/datetime.rb +13 -0
  17. data/lib/osheet/format/fraction.rb +33 -0
  18. data/lib/osheet/format/general.rb +9 -0
  19. data/lib/osheet/format/number.rb +13 -0
  20. data/lib/osheet/format/numeric.rb +113 -0
  21. data/lib/osheet/format/percentage.rb +25 -0
  22. data/lib/osheet/format/scientific.rb +25 -0
  23. data/lib/osheet/format/special.rb +28 -0
  24. data/lib/osheet/format/text.rb +11 -0
  25. data/lib/osheet/format.rb +30 -0
  26. data/lib/osheet/row.rb +32 -7
  27. data/lib/osheet/style.rb +65 -0
  28. data/lib/osheet/style_set.rb +39 -0
  29. data/lib/osheet/styled_element.rb +18 -0
  30. data/lib/osheet/template.rb +32 -0
  31. data/lib/osheet/template_set.rb +57 -0
  32. data/lib/osheet/version.rb +1 -11
  33. data/lib/osheet/workbook.rb +32 -16
  34. data/lib/osheet/workbook_element.rb +21 -0
  35. data/lib/osheet/worksheet.rb +18 -20
  36. data/lib/osheet/worksheet_element.rb +15 -0
  37. data/lib/osheet/xmlss_writer/base.rb +42 -0
  38. data/lib/osheet/xmlss_writer/elements.rb +68 -0
  39. data/lib/osheet/xmlss_writer/styles.rb +176 -0
  40. data/lib/osheet/xmlss_writer.rb +1 -0
  41. data/lib/osheet.rb +7 -27
  42. data/osheet.gemspec +26 -0
  43. data/test/cell_test.rb +83 -0
  44. data/test/column_test.rb +81 -0
  45. data/test/env.rb +9 -0
  46. data/test/format/accounting_test.rb +158 -0
  47. data/test/format/currency_test.rb +158 -0
  48. data/test/format/custom_test.rb +22 -0
  49. data/test/format/datetime_test.rb +22 -0
  50. data/test/format/fraction_test.rb +84 -0
  51. data/test/format/general_test.rb +21 -0
  52. data/test/format/number_test.rb +93 -0
  53. data/test/format/percentage_test.rb +116 -0
  54. data/test/format/scientific_test.rb +116 -0
  55. data/test/format/special_test.rb +51 -0
  56. data/test/format/text_test.rb +18 -0
  57. data/test/format_test.rb +35 -0
  58. data/test/helper.rb +101 -0
  59. data/test/osheet_test.rb +14 -0
  60. data/test/row_test.rb +78 -0
  61. data/test/style_set_test.rb +50 -0
  62. data/test/style_test.rb +92 -0
  63. data/test/template_set_test.rb +76 -0
  64. data/test/template_test.rb +63 -0
  65. data/test/workbook_test.rb +142 -0
  66. data/test/worksheet_test.rb +77 -0
  67. data/test/xmlss_writer/base_test.rb +92 -0
  68. data/test/xmlss_writer/elements_test.rb +168 -0
  69. data/test/xmlss_writer/styles_test.rb +253 -0
  70. metadata +141 -30
  71. data/lib/osheet/base.rb +0 -95
@@ -0,0 +1,366 @@
1
+ # To run:
2
+ # $ bundle install
3
+ # $ bundle exec ruby examples/formats.rb
4
+ # $ open examples/formats.xls
5
+
6
+ require 'rubygems'
7
+ require 'osheet'
8
+
9
+ Osheet::Workbook.new {
10
+ title "formats"
11
+
12
+
13
+
14
+ # number format examples
15
+ worksheet {
16
+ name "number"
17
+
18
+ column {
19
+ width 250
20
+ meta(:label => 'Format')
21
+ }
22
+ [1000, -20000].each do |n|
23
+ column {
24
+ width 125
25
+ meta(:label => n.to_s, :value => n)
26
+ }
27
+ end
28
+
29
+ # header row
30
+ row {
31
+ columns.each do |col|
32
+ cell{ data col.meta[:label] }
33
+ end
34
+ }
35
+
36
+ # data rows
37
+ [
38
+ {},
39
+ {
40
+ :decimal_places => 1,
41
+ :negative_numbers => :red
42
+ },
43
+ {
44
+ :decimal_places => 2,
45
+ :comma_separator => true,
46
+ :negative_numbers => :black_parenth
47
+ },
48
+ {
49
+ :decimal_places => 8,
50
+ :comma_separator => true,
51
+ :negative_numbers => :red_parenth
52
+ }
53
+ ].each do |opts|
54
+ row {
55
+ cell {
56
+ data Osheet::Format.new(:number, opts).key
57
+ }
58
+ columns[1..-1].each do |col|
59
+ cell {
60
+ data col.meta[:value]
61
+ format :number, opts
62
+ }
63
+ end
64
+ }
65
+ end
66
+ }
67
+
68
+
69
+ # currency/accounting format examples
70
+ worksheet {
71
+ name "currency, accounting"
72
+
73
+ column {
74
+ width 250
75
+ meta(:label => 'Format')
76
+ }
77
+ [1000, -20000].each do |n|
78
+ column {
79
+ width 125
80
+ meta(:label => n.to_s, :value => n)
81
+ }
82
+ end
83
+
84
+ # header row
85
+ row {
86
+ columns.each do |col|
87
+ cell{ data col.meta[:label] }
88
+ end
89
+ }
90
+
91
+ data_opts = [
92
+ {},
93
+ {
94
+ :symbol => :euro,
95
+ :decimal_places => 0,
96
+ :negative_numbers => :red
97
+ },
98
+ {
99
+ :decimal_places => 1,
100
+ :comma_separator => false,
101
+ :negative_numbers => :black_parenth
102
+ },
103
+ {
104
+ :decimal_places => 8,
105
+ :comma_separator => true,
106
+ :negative_numbers => :red_parenth
107
+ }
108
+ ]
109
+
110
+ # currency data rows
111
+ data_opts.each do |opts|
112
+ row {
113
+ cell {
114
+ data Osheet::Format.new(:currency, opts).key
115
+ }
116
+ columns[1..-1].each do |col|
117
+ cell {
118
+ data col.meta[:value]
119
+ format :currency, opts
120
+ }
121
+ end
122
+ }
123
+ end
124
+
125
+ # accounting data rows
126
+ data_opts.each do |opts|
127
+ row {
128
+ cell {
129
+ data Osheet::Format.new(:accounting, opts).key
130
+ }
131
+ columns[1..-1].each do |col|
132
+ cell {
133
+ data col.meta[:value]
134
+ format :accounting, opts
135
+ }
136
+ end
137
+ }
138
+ end
139
+ }
140
+
141
+
142
+
143
+ # percentage format examples
144
+ worksheet {
145
+ name "percentage, scientific"
146
+
147
+ column {
148
+ width 250
149
+ meta(:label => 'Format')
150
+ }
151
+ [1000, -20000].each do |n|
152
+ column {
153
+ width 125
154
+ meta(:label => n.to_s, :value => n)
155
+ }
156
+ end
157
+
158
+ # header row
159
+ row {
160
+ columns.each do |col|
161
+ cell{ data col.meta[:label] }
162
+ end
163
+ }
164
+
165
+ data_opts = [
166
+ {},
167
+ {
168
+ :decimal_places => 0,
169
+ :negative_numbers => :red
170
+ },
171
+ {
172
+ :decimal_places => 1,
173
+ :comma_separator => false,
174
+ :negative_numbers => :black_parenth
175
+ },
176
+ {
177
+ :decimal_places => 8,
178
+ :comma_separator => true,
179
+ :negative_numbers => :red_parenth
180
+ }
181
+ ]
182
+
183
+ # percentage data rows
184
+ data_opts.each do |opts|
185
+ row {
186
+ cell {
187
+ data Osheet::Format.new(:percentage, opts).key
188
+ }
189
+ columns[1..-1].each do |col|
190
+ cell {
191
+ data col.meta[:value]
192
+ format :percentage, opts
193
+ }
194
+ end
195
+ }
196
+ end
197
+
198
+ # scientific data rows
199
+ data_opts.each do |opts|
200
+ row {
201
+ cell {
202
+ data Osheet::Format.new(:scientific, opts).key
203
+ }
204
+ columns[1..-1].each do |col|
205
+ cell {
206
+ data col.meta[:value]
207
+ format :scientific, opts
208
+ }
209
+ end
210
+ }
211
+ end
212
+ }
213
+
214
+
215
+
216
+ # fraction format examples
217
+ worksheet {
218
+ name "fractions"
219
+
220
+ column {
221
+ width 250
222
+ meta(:label => 'Format')
223
+ }
224
+ column {
225
+ width 125
226
+ meta(:label => 'Fraction Example')
227
+ }
228
+
229
+ # header row
230
+ row {
231
+ columns.each do |col|
232
+ cell{ data col.meta[:label] }
233
+ end
234
+ }
235
+
236
+ # fraction data rows
237
+ data_opts = {
238
+ :one_digit => 0.5,
239
+ :two_digits => 0.0125,
240
+ :three_digits => 0.01,
241
+ :halves => 0.5,
242
+ :quarters => 0.25,
243
+ :eighths => 0.125,
244
+ :sixteenths => 0.0625,
245
+ :tenths => 0.1,
246
+ :hundredths => 0.01
247
+ }
248
+ data_opts.each do |k,v|
249
+ row {
250
+ cell {
251
+ data Osheet::Format.new(:fraction, :type => k).key
252
+ }
253
+ cell {
254
+ data v
255
+ format :fraction, :type => k
256
+ }
257
+ }
258
+ end
259
+ }
260
+
261
+
262
+
263
+ # text format examples
264
+ worksheet {
265
+ name "text, special, custom"
266
+
267
+ column {
268
+ width 250
269
+ meta(:label => 'Format')
270
+ }
271
+ column {
272
+ width 125
273
+ meta(:label => 'Result')
274
+ }
275
+
276
+ # header row
277
+ row {
278
+ columns.each do |col|
279
+ cell{ data col.meta[:label] }
280
+ end
281
+ }
282
+
283
+ # text data row
284
+ row {
285
+ cell {
286
+ data Osheet::Format.new(:text).key
287
+ }
288
+ cell {
289
+ data "001122 blah blah"
290
+ format :text
291
+ }
292
+ }
293
+
294
+ # special data rows
295
+ {
296
+ :zip_code => 12345,
297
+ :zip_code_plus_4 => 123456789,
298
+ :phone_number => 5551112222,
299
+ :social_security_number => 333224444
300
+ }.each do |k,v|
301
+ row {
302
+ cell {
303
+ data Osheet::Format.new(:special, :type => k).key
304
+ }
305
+ cell {
306
+ data v
307
+ format :special, :type => k
308
+ }
309
+ }
310
+ end
311
+
312
+ # custom data row
313
+ row {
314
+ cell {
315
+ data Osheet::Format.new(:custom, '@').key
316
+ }
317
+ cell {
318
+ data "001122 blah blah"
319
+ format :custom, '@'
320
+ }
321
+ }
322
+ }
323
+
324
+
325
+
326
+ # datetime format examples
327
+ worksheet {
328
+ name "date, time"
329
+
330
+ column {
331
+ width 250
332
+ meta(:label => 'Format')
333
+ }
334
+ column {
335
+ width 125
336
+ meta(:label => 'Datetime')
337
+ }
338
+
339
+ # header row
340
+ row {
341
+ columns.each do |col|
342
+ cell{ data col.meta[:label] }
343
+ end
344
+ }
345
+
346
+ # datetime data row
347
+ [ 'm','d','y', 'mm', 'dd', 'yy', 'yyyy',
348
+ 'mm/dd/yy', 'mm/dd/yyyy', 'mmmm', 'mmmmm', 'mmmmm',
349
+ 'h','m','s', 'hh', 'mm', 'ss',
350
+ 'h:mm:ss', 'h:mm:ss.0', 'hh:mm:ss AM/PM'
351
+ ].each do |s|
352
+ row {
353
+ cell {
354
+ data Osheet::Format.new(:datetime, s).key
355
+ }
356
+ cell {
357
+ data Date.today
358
+ format :datetime, s
359
+ }
360
+ }
361
+ end
362
+ }
363
+
364
+
365
+
366
+ }.to_file('examples/formats.xls')
@@ -0,0 +1,21 @@
1
+ # To run:
2
+ # $ bundle install
3
+ # $ bundle exec ruby examples/trivial.rb
4
+ # $ open examples/trivial.xls
5
+
6
+ require 'rubygems'
7
+ require 'osheet'
8
+
9
+ Osheet::Workbook.new {
10
+ title "basic"
11
+ worksheet {
12
+ name "one dollar"
13
+ column
14
+ row {
15
+ cell {
16
+ data 1
17
+ format :currency
18
+ }
19
+ }
20
+ }
21
+ }.to_file('examples/trivial.xls')
@@ -0,0 +1,62 @@
1
+ module Osheet::Associations
2
+
3
+ def self.included(receiver)
4
+ receiver.send(:extend, ClassMethods)
5
+ end
6
+
7
+ module ClassMethods
8
+
9
+ # A has many esque association helper
10
+ # - will provide a collection reader
11
+ # - will define a 'singular' item method for adding to the collection
12
+ # - will support adding to the collection both by black and template
13
+ def hm(collection)
14
+ unless collection.to_s =~ /s$/
15
+ raise ArgumentError, "association item names must end in 's'"
16
+ end
17
+ plural = collection.to_s
18
+ singular = plural.to_s.sub(/s$/, '')
19
+ klass = Osheet.const_get(singular.capitalize)
20
+
21
+ # define collection reader
22
+ self.send(:define_method, plural, Proc.new do
23
+ if instance_variable_get("@#{plural}").nil?
24
+ instance_variable_set("@#{plural}", [])
25
+ end
26
+ instance_variable_get("@#{plural}")
27
+ end)
28
+
29
+ # define collection item writer
30
+ self.send(:define_method, singular) do |*args, &block|
31
+ if instance_variable_get("@#{plural}").nil?
32
+ instance_variable_set("@#{plural}", [])
33
+ end
34
+ instance_variable_get("@#{plural}") << if self.respond_to?(:workbook)
35
+ # on: worksheet, column, row
36
+ # creating: column, row, cell
37
+ worksheet = self.respond_to?(:worksheet) ? self.worksheet : self
38
+ if self.workbook && (template = self.workbook.templates.get(singular, args.first))
39
+ # add by template
40
+ klass.new(self.workbook, worksheet, *args[1..-1], &template)
41
+ else
42
+ # add by block
43
+ klass.new(self.workbook, worksheet, &block)
44
+ end
45
+ else
46
+ # on: workbook
47
+ # creating: worksheet
48
+ if (template = self.templates.get(singular, args.first))
49
+ # add by template
50
+ klass.new(self, *args[1..-1], &template)
51
+ else
52
+ # add by block
53
+ klass.new(self, &block)
54
+ end
55
+ end
56
+ end
57
+
58
+ end
59
+
60
+ end
61
+
62
+ end
data/lib/osheet/cell.rb CHANGED
@@ -1,18 +1,52 @@
1
- require 'osheet/base'
1
+ require 'date'
2
+ require 'osheet/format'
2
3
 
3
4
  module Osheet
4
- class Cell < Osheet::Base
5
+ class Cell
6
+ include WorkbookElement
7
+ include WorksheetElement
8
+ include StyledElement
5
9
 
6
- attr_accessor :data
10
+ def initialize(workbook=nil, worksheet=nil, *args, &block)
11
+ @workbook = workbook
12
+ @worksheet = worksheet
13
+ @data = nil
14
+ @format = Format.new(:general)
15
+ @rowspan = 1
16
+ @colspan = 1
17
+ @href = nil
18
+ instance_exec(*args, &block) if block_given?
19
+ end
20
+
21
+ def data(value)
22
+ @data = case value
23
+ when ::String, ::Numeric, ::Date, ::Time, ::DateTime
24
+ value
25
+ when ::Symbol
26
+ value.to_s
27
+ else
28
+ value.inspect.to_s
29
+ end
30
+ end
7
31
 
8
- ATTRS = [:format, :rowspan, :colspan]
9
- ATTRS.each {|a| attr_accessor a}
32
+ def format(type, opts={})
33
+ @format = Format.new(type, opts)
34
+ end
35
+
36
+ def rowspan(value); @rowspan = value; end
37
+ def colspan(value); @colspan = value; end
38
+ def href(value); @href = value; end
10
39
 
11
- def initialize(data='', args={})
12
- @data = data
13
- set_args ATTRS, args
14
- super(args)
40
+ def attributes
41
+ {
42
+ :style_class => @style_class,
43
+ :data => @data,
44
+ :format => @format,
45
+ :colspan => @colspan,
46
+ :rowspan => @rowspan,
47
+ :href => @href,
48
+ }
15
49
  end
16
-
50
+
17
51
  end
18
52
  end
data/lib/osheet/column.rb CHANGED
@@ -1,11 +1,38 @@
1
- require 'osheet/base'
2
-
3
1
  module Osheet
4
- class Column < Osheet::Base
5
-
6
- def initialize(args={})
7
- super(args)
2
+ class Column
3
+ include WorkbookElement
4
+ include WorksheetElement
5
+ include StyledElement
6
+
7
+ def initialize(workbook=nil, worksheet=nil, *args, &block)
8
+ @workbook = workbook
9
+ @worksheet = worksheet
10
+ @width = nil
11
+ @autofit = false
12
+ @hidden = false
13
+ @meta = nil
14
+ instance_exec(*args, &block) if block_given?
15
+ end
16
+
17
+ def width(value=nil)
18
+ !value.nil? ? @width = value : @width
19
+ end
20
+ def autofit(value); @autofit = !!value; end
21
+ def autofit?; @autofit; end
22
+ def hidden(value); @hidden = !!value; end
23
+ def hidden?; @hidden; end
24
+
25
+ def attributes
26
+ {
27
+ :style_class => @style_class,
28
+ :width => @width,
29
+ :autofit => @autofit,
30
+ :hidden => @hidden
31
+ }
32
+ end
33
+
34
+ def meta(value=nil)
35
+ value.nil? ? @meta : (@meta = value)
8
36
  end
9
-
10
37
  end
11
38
  end
@@ -0,0 +1,21 @@
1
+ require 'enumeration'
2
+ require 'osheet/format/currency'
3
+
4
+ module Osheet::Format
5
+
6
+ class Accounting < Osheet::Format::Currency
7
+
8
+ protected
9
+
10
+ # used by 'key' in Numeric base class
11
+ def key_prefix
12
+ "accounting"
13
+ end
14
+
15
+ # used by 'numeric_style' in Numeric base class
16
+ def symbol_suffix
17
+ "* "
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,23 @@
1
+ require 'enumeration'
2
+ require 'osheet/format/numeric'
3
+
4
+ module Osheet::Format
5
+
6
+ class Currency < Osheet::Format::Numeric
7
+ def initialize(opts={})
8
+ super({
9
+ :symbol => :dollar,
10
+ :decimal_places => 2,
11
+ :comma_separator => true
12
+ }.merge(opts))
13
+ end
14
+
15
+ protected
16
+
17
+ # used by 'key' in Numeric base class
18
+ def key_prefix
19
+ "currency"
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,13 @@
1
+ module Osheet::Format
2
+
3
+ class Custom
4
+
5
+ def initialize(type)
6
+ @type = type
7
+ end
8
+
9
+ def style; @type; end
10
+ def key; "custom_#{@type}"; end
11
+
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module Osheet::Format
2
+
3
+ class Datetime
4
+
5
+ def initialize(string)
6
+ @string = string
7
+ end
8
+
9
+ def style; @string; end
10
+ def key; "datetime_#{@string}"; end
11
+
12
+ end
13
+ end
@@ -0,0 +1,33 @@
1
+ require 'enumeration'
2
+
3
+ module Osheet::Format
4
+
5
+ class Fraction
6
+ include Enumeration
7
+
8
+ enum(:type, {
9
+ :one_digit => '?/?',
10
+ :two_digits => '??/??',
11
+ :three_digits => '???/???',
12
+ :halves => '?/2',
13
+ :quarters => '?/4',
14
+ :eighths => '?/8',
15
+ :sixteenths => '??/16',
16
+ :tenths => '?/10',
17
+ :hundredths => '??/100'
18
+ })
19
+
20
+ def initialize(opts={})
21
+ self.type = opts[:type] || :two_digits
22
+ end
23
+
24
+ def style
25
+ "#\ #{type}"
26
+ end
27
+
28
+ def key
29
+ "fraction_#{type_key.to_s.gsub('_', '')}"
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,9 @@
1
+ module Osheet::Format
2
+
3
+ class General
4
+ def initialize(opts={}); end
5
+ def style; nil; end
6
+ def key; ''; end
7
+ end
8
+
9
+ end
@@ -0,0 +1,13 @@
1
+ require 'enumeration'
2
+ require 'osheet/format/numeric'
3
+
4
+ module Osheet::Format
5
+
6
+ class Number < Osheet::Format::Numeric
7
+
8
+ def initialize(opts={})
9
+ super
10
+ end
11
+
12
+ end
13
+ end