calco 0.1.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 (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