osheet 0.1.0 → 0.2.0

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