calco 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +34 -0
  3. data/Gemfile +4 -0
  4. data/Gemfile.lock +26 -0
  5. data/LICENSE +21 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +360 -0
  8. data/Rakefile +1 -0
  9. data/calco.gemspec +23 -0
  10. data/examples/ages.ods +0 -0
  11. data/examples/compute_cells.rb +61 -0
  12. data/examples/data.csv +8 -0
  13. data/examples/example.rb +97 -0
  14. data/examples/multiplication_tables.ods +0 -0
  15. data/examples/multiplication_tables.rb +73 -0
  16. data/examples/register_function.rb +44 -0
  17. data/examples/using_date_functions.rb +42 -0
  18. data/examples/write_csv.rb +68 -0
  19. data/examples/write_ods.rb +69 -0
  20. data/lib/calco.rb +17 -0
  21. data/lib/calco/core_ext/fixnum.rb +22 -0
  22. data/lib/calco/core_ext/float.rb +22 -0
  23. data/lib/calco/core_ext/range.rb +15 -0
  24. data/lib/calco/core_ext/string.rb +20 -0
  25. data/lib/calco/date_functions.rb +13 -0
  26. data/lib/calco/definition_dsl.rb +127 -0
  27. data/lib/calco/elements/aggregator.rb +17 -0
  28. data/lib/calco/elements/builtin_function.rb +84 -0
  29. data/lib/calco/elements/constant.rb +31 -0
  30. data/lib/calco/elements/current.rb +19 -0
  31. data/lib/calco/elements/element.rb +31 -0
  32. data/lib/calco/elements/empty.rb +9 -0
  33. data/lib/calco/elements/formula.rb +42 -0
  34. data/lib/calco/elements/if.rb +26 -0
  35. data/lib/calco/elements/operation.rb +34 -0
  36. data/lib/calco/elements/operator.rb +17 -0
  37. data/lib/calco/elements/or.rb +26 -0
  38. data/lib/calco/elements/value_extractor.rb +42 -0
  39. data/lib/calco/elements/variable.rb +35 -0
  40. data/lib/calco/engines/calculator_builtin_functions.rb +32 -0
  41. data/lib/calco/engines/csv_engine.rb +80 -0
  42. data/lib/calco/engines/default_engine.rb +140 -0
  43. data/lib/calco/engines/office_engine.rb +263 -0
  44. data/lib/calco/engines/simple_calculator_engine.rb +151 -0
  45. data/lib/calco/math_functions.rb +9 -0
  46. data/lib/calco/sheet.rb +363 -0
  47. data/lib/calco/spreadsheet.rb +172 -0
  48. data/lib/calco/string_functions.rb +9 -0
  49. data/lib/calco/style.rb +15 -0
  50. data/lib/calco/time_functions.rb +12 -0
  51. data/lib/calco/version.rb +3 -0
  52. data/spec/absolute_references_spec.rb +86 -0
  53. data/spec/builtin_functions_spec.rb +161 -0
  54. data/spec/calculator_engine_spec.rb +251 -0
  55. data/spec/conditions_spec.rb +118 -0
  56. data/spec/content_change_spec.rb +190 -0
  57. data/spec/csv_engine_spec.rb +324 -0
  58. data/spec/default_engine_spec.rb +135 -0
  59. data/spec/definitions_spec.rb +65 -0
  60. data/spec/errors_spec.rb +189 -0
  61. data/spec/functions_spec.rb +251 -0
  62. data/spec/header_row_spec.rb +63 -0
  63. data/spec/range_spec.rb +189 -0
  64. data/spec/sheet_selections_spec.rb +49 -0
  65. data/spec/sheet_spec.rb +229 -0
  66. data/spec/smart_types_spec.rb +43 -0
  67. data/spec/spreadsheet_spec.rb +80 -0
  68. data/spec/styles_spec.rb +29 -0
  69. data/spec/variables_spec.rb +41 -0
  70. metadata +158 -0
@@ -0,0 +1,324 @@
1
+ require 'date'
2
+ require 'time'
3
+ require 'stringio'
4
+
5
+ require 'calco/engines/csv_engine'
6
+
7
+ module Calco
8
+
9
+ describe CSVEngine do
10
+
11
+ it "writes header when writing row 0" do
12
+
13
+ create_spreadsheet_and_save do |spreadsheet|
14
+
15
+ sheet = spreadsheet.sheet('A').current
16
+
17
+ sheet.write_row 0
18
+
19
+ end
20
+
21
+ expect(@result).to eq('c1,,c3,c4,c5')
22
+
23
+ end
24
+
25
+ it "writes empty values, numbers and functions" do
26
+
27
+ create_spreadsheet_and_save do |spreadsheet|
28
+
29
+ sheet = spreadsheet.sheet('B').current
30
+
31
+ sheet.write_row 1
32
+
33
+ end
34
+
35
+ expect(@result).to eq('"",=2*C1,11')
36
+
37
+ end
38
+
39
+ it "writes functions for times" do
40
+
41
+ create_spreadsheet_and_save do |spreadsheet|
42
+
43
+ sheet = spreadsheet.sheet('time').current
44
+
45
+ sheet.write_row 1
46
+
47
+ end
48
+
49
+ expect(@result).to eq('"=TIMEVALUE(""13:45:00"")"')
50
+
51
+ end
52
+
53
+ it "writes functions for dates" do
54
+
55
+ create_spreadsheet_and_save do |spreadsheet|
56
+
57
+ sheet = spreadsheet.sheet('date').current
58
+
59
+ sheet.write_row 1
60
+
61
+ end
62
+
63
+ expect(@result).to eq('"=DATEVALUE(""2013-07-27"")"')
64
+
65
+ end
66
+
67
+ it "writes functions for dates and style" do
68
+
69
+ create_spreadsheet_and_save do |spreadsheet|
70
+
71
+ sheet = spreadsheet.sheet('date-style').current
72
+
73
+ sheet.write_row 1
74
+
75
+ end
76
+
77
+ expect(@result).to eq('"=DATEVALUE(""2013-07-27"")+STYLE(IF(CURRENT()=TODAY();""red"";""default""))"')
78
+
79
+ end
80
+
81
+ it "writes functions for times and style" do
82
+
83
+ create_spreadsheet_and_save do |spreadsheet|
84
+
85
+ sheet = spreadsheet.sheet('time-style').current
86
+
87
+ sheet.write_row 1
88
+
89
+ end
90
+
91
+ expect(@result).to eq('"=TIMEVALUE(""13:45:00"")+STYLE(IF(CURRENT()=NOW();""red"";""default""))"')
92
+
93
+ end
94
+
95
+ it "writes functions for money" do
96
+
97
+ create_spreadsheet_and_save do |spreadsheet|
98
+
99
+ sheet = spreadsheet.sheet('dollar').current
100
+
101
+ sheet.write_row 1
102
+
103
+ end
104
+
105
+ expect(@result).to eq('=DOLLAR(11)')
106
+
107
+ end
108
+
109
+ it "writes money even for formulas" do
110
+
111
+ create_spreadsheet_and_save do |spreadsheet|
112
+
113
+ sheet = spreadsheet.sheet('dollar-formulas').current
114
+
115
+ sheet.write_row 1
116
+
117
+ end
118
+
119
+ expect(@result.split(',')).to eq(['=DOLLAR(11)', '=DOLLAR(2*A1)'])
120
+
121
+ end
122
+
123
+ it "surrounds formulas and style with money" do
124
+
125
+ create_spreadsheet_and_save do |spreadsheet|
126
+
127
+ sheet = spreadsheet.sheet('dollar-conditional').current
128
+
129
+ sheet.write_row 1
130
+
131
+ end
132
+
133
+ expect(@result).to eq('=DOLLAR(11),"=DOLLAR(2*A1+STYLE(IF(CURRENT()>2;""big"";""default"")))"')
134
+
135
+ end
136
+
137
+ it "writes % values" do
138
+
139
+ create_spreadsheet_and_save do |spreadsheet|
140
+
141
+ sheet = spreadsheet.sheet('%').current
142
+
143
+ sheet.write_row 1
144
+
145
+ end
146
+
147
+ expect(@result).to eq('=(0.3*100)%')
148
+
149
+ end
150
+
151
+ it "writes % functions" do
152
+
153
+ create_spreadsheet_and_save do |spreadsheet|
154
+
155
+ sheet = spreadsheet.sheet('%-formulas').current
156
+
157
+ sheet.write_row 1
158
+
159
+ end
160
+
161
+ expect(@result).to eq('11,=(2*A1)%')
162
+
163
+ end
164
+
165
+ it "writes sum aggregation" do
166
+
167
+ create_spreadsheet_and_save do |spreadsheet|
168
+
169
+ sheet = spreadsheet.sheet('sum').current
170
+
171
+ sheet.write_row 1
172
+ sheet.write_row 2
173
+ sheet.write_row 3
174
+
175
+ sheet.replace_content :values, :total
176
+
177
+ sheet.write_row 4
178
+
179
+ end
180
+
181
+ expect(@result.split).to match_array(['=DOLLAR(11)'] * 3 + ['=DOLLAR(SUM(A1:A3))'])
182
+
183
+ end
184
+
185
+ it "writes empty rows" do
186
+
187
+ create_spreadsheet_and_save do |spreadsheet|
188
+
189
+ sheet = spreadsheet.sheet('B').current
190
+
191
+ sheet.write_row 1
192
+ sheet.empty_row
193
+ sheet.write_row 3
194
+
195
+ end
196
+
197
+ expect(@result).to eq('"",=2*C1,11' "\n\n" '"",=2*C3,11')
198
+
199
+ end
200
+
201
+ it "supports constants in column layouts" do
202
+
203
+ create_spreadsheet_and_save do |spreadsheet|
204
+
205
+ sheet = spreadsheet.sheet('constants').current
206
+
207
+ sheet.write_row 1
208
+
209
+ end
210
+
211
+ expect(@result).to eq('11,x 2,=2*A1')
212
+
213
+ end
214
+
215
+ before do
216
+ @engine = Calco::CSVEngine.new
217
+ end
218
+
219
+ def create_spreadsheet_and_save &block
220
+
221
+ @doc = spreadsheet(@engine) do
222
+
223
+ definitions do
224
+
225
+ set a: ''
226
+ set b: 11
227
+ set c: Time.parse('13:45')
228
+ set d: Date.parse('2013-07-27')
229
+ set e: 0.3
230
+
231
+ function double: 2 * b
232
+
233
+ function total: sum(b[(1..-1).as_grouping])
234
+
235
+ end
236
+
237
+ sheet "A" do
238
+
239
+ column value_of(:a), :title => "c1"
240
+
241
+ column :double
242
+
243
+ column value_of(:b), :title => "c3"
244
+ column value_of(:c), :title => "c4"
245
+ column value_of(:d), :title => "c5"
246
+
247
+ end
248
+
249
+ sheet "B" do
250
+
251
+ column value_of(:a)
252
+
253
+ column :double
254
+
255
+ column value_of(:b)
256
+
257
+ end
258
+
259
+ sheet "time" do
260
+ column value_of(:c)
261
+ end
262
+
263
+ sheet "date" do
264
+ column value_of(:d)
265
+ end
266
+
267
+ sheet "time-style" do
268
+ column value_of(:c), style: _if(current == now(), 'red', 'default')
269
+ end
270
+
271
+ sheet "date-style" do
272
+ column value_of(:d), style: _if(current == today(), 'red', 'default')
273
+ end
274
+
275
+ sheet "dollar" do
276
+ column value_of(:b), :type => '$'
277
+ end
278
+
279
+ sheet "dollar-formulas" do
280
+ column value_of(:b), :type => '$'
281
+ column :double, :type => '$'
282
+ end
283
+
284
+ sheet "dollar-conditional" do
285
+ column value_of(:b), :type => '$'
286
+ column :double, :type => '$', style: _if(current > 2, 'big', 'default')
287
+ end
288
+
289
+ sheet "%" do
290
+ column value_of(:e), :type => '%'
291
+ end
292
+
293
+ sheet "%-formulas" do
294
+ column value_of(:b)
295
+ column :double, :type => '%'
296
+ end
297
+
298
+ sheet "sum" do
299
+ column value_of(:b), :type => '$', :id => :values
300
+ end
301
+
302
+ sheet "constants" do
303
+
304
+ column value_of(:b)
305
+
306
+ column "x 2"
307
+
308
+ column :double
309
+
310
+ end
311
+
312
+ end
313
+
314
+ buffer = StringIO.new
315
+
316
+ @doc.save buffer, &block
317
+
318
+ @result = buffer.string.strip
319
+
320
+ end
321
+
322
+ end
323
+
324
+ end
@@ -0,0 +1,135 @@
1
+ require 'calco'
2
+
3
+ module Calco
4
+
5
+ describe DefaultEngine do
6
+
7
+ it 'generates value of var for "column value_of(:var)"' do
8
+
9
+ doc = spreadsheet do
10
+
11
+ definitions do
12
+
13
+ set a: "12:58"
14
+
15
+ end
16
+
17
+ sheet do
18
+
19
+ column value_of(:a)
20
+
21
+ end
22
+
23
+ end
24
+
25
+ row = doc.current.row(1)
26
+
27
+ expect(row[0]).to eq('12:58:00')
28
+
29
+ end
30
+
31
+ it 'generates (invalid) reference to same cell for "column :var"' do
32
+
33
+ doc = spreadsheet do
34
+
35
+ definitions do
36
+
37
+ set a: "12:58"
38
+
39
+ end
40
+
41
+ sheet do
42
+
43
+ column :a
44
+
45
+ end
46
+
47
+ end
48
+
49
+ row = doc.current.row(1)
50
+
51
+ expect(row[0]).to eq('A1')
52
+
53
+ end
54
+
55
+ it 'generates "" for "column skip"' do
56
+
57
+ doc = spreadsheet do
58
+
59
+ definitions do
60
+
61
+ set a: "12:58"
62
+
63
+ end
64
+
65
+ sheet do
66
+
67
+ column skip
68
+ column value_of(:a)
69
+
70
+ end
71
+
72
+ end
73
+
74
+ row = doc.current.row(1)
75
+
76
+ expect(row[0]).to eq('')
77
+ expect(row[1]).to eq('12:58:00')
78
+
79
+ end
80
+
81
+ it "generates all values as string literals" do
82
+
83
+ doc = spreadsheet do
84
+
85
+ definitions do
86
+
87
+ set a: 'Hello'
88
+ set b: 12
89
+
90
+ function c: a + "Hi"
91
+ function d: b + 123
92
+ function e: 76.9
93
+ function f: "Max"
94
+
95
+ set g: "2013-09-29"
96
+ set h: "12:58"
97
+
98
+ end
99
+
100
+ sheet do
101
+
102
+ column value_of(:a)
103
+ column value_of(:b)
104
+
105
+ column :c
106
+ column :d
107
+ column :e
108
+ column :f
109
+
110
+ column value_of(:g)
111
+ column value_of(:h)
112
+
113
+ column :h
114
+
115
+ end
116
+
117
+ end
118
+
119
+ row = doc.current.row(1)
120
+
121
+ expect(row[0]).to eq('"Hello"')
122
+ expect(row[1]).to eq('12')
123
+ expect(row[2]).to eq('A1+"Hi"')
124
+ expect(row[3]).to eq('B1+123')
125
+ expect(row[4]).to eq('76.9')
126
+ expect(row[5]).to eq('"Max"')
127
+ expect(row[6]).to eq('2013-09-29')
128
+ expect(row[7]).to eq('12:58:00')
129
+ expect(row[8]).to eq('I1')
130
+
131
+ end
132
+
133
+ end
134
+
135
+ end