lxl 0.4.2 → 0.4.3
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +4 -0
- data/VERSION +1 -1
- data/lib/lxl.rb +11 -5
- data/test/lxl_spreadsheet_test.rb +2 -0
- data/test/lxl_test.rb +4 -4
- data/test/lxl_win32ole_test.rb +68 -0
- metadata +10 -9
data/CHANGES
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.4.
|
1
|
+
0.4.3
|
data/lib/lxl.rb
CHANGED
@@ -241,8 +241,9 @@ class LXL::Parser
|
|
241
241
|
|
242
242
|
# Initialize namespace and lexer.
|
243
243
|
#
|
244
|
-
def initialize(
|
245
|
-
@namespace = namespace
|
244
|
+
def initialize(options=Hash.new)
|
245
|
+
@namespace = options[:namespace] if options.key?(:namespace)
|
246
|
+
@namespace ||= self.class.namespace_class.new
|
246
247
|
ops = EXCEL_OPERATORS.collect { |v| Regexp.quote(v) }.join('|')
|
247
248
|
xlr = LXL::Range::EXCEL_RANGE
|
248
249
|
@lexer = self.class.lexer_class.new([
|
@@ -306,6 +307,8 @@ class LXL::Parser
|
|
306
307
|
formulas = [[]]
|
307
308
|
separators = [?=, ?;]
|
308
309
|
ops = Hash[*EXCEL_OPERATORS.zip(RUBY_OPERATORS).flatten]
|
310
|
+
ns_const_missing = begin [@namespace.const_get(:ConstMissing),true].last rescue false end
|
311
|
+
ns_method_missing = @namespace.respond_to?(:method_missing)
|
309
312
|
|
310
313
|
# Translate formula prefixes to `= to avoid clashing with the = operator
|
311
314
|
# For lines that start with = (optional leading whitespace)
|
@@ -357,15 +360,14 @@ class LXL::Parser
|
|
357
360
|
upper = token.to_s.upcase
|
358
361
|
lower = token.to_s.downcase
|
359
362
|
raise NoMethodError, "protected method `#{token}` called for #{self}" if @namespace.const_get(:METHODS).include?(lower)
|
360
|
-
custom_const_missing = begin [@namespace.const_get(:ConstMissing),true].last rescue false end
|
361
363
|
# Constants
|
362
364
|
if tokens.first != '('
|
363
|
-
if @namespace.const_defined?(upper) or
|
365
|
+
if @namespace.const_defined?(upper) or ns_const_missing
|
364
366
|
formulas.last << store(?C, "@namespace.const_get(:#{upper})")
|
365
367
|
else formulas.last << t end
|
366
368
|
# Functions
|
367
369
|
else
|
368
|
-
if @namespace.respond_to?(lower) or
|
370
|
+
if @namespace.respond_to?(lower) or ns_method_missing
|
369
371
|
formulas.last << store(?F, "@namespace.#{lower}")
|
370
372
|
else formulas.last << t end
|
371
373
|
end
|
@@ -475,6 +477,10 @@ class LXL::Range < Range
|
|
475
477
|
end
|
476
478
|
end
|
477
479
|
|
480
|
+
def to_s
|
481
|
+
"#{first}:#{last}"
|
482
|
+
end
|
483
|
+
|
478
484
|
end
|
479
485
|
|
480
486
|
# Snapshots the symbol/arguments of a function call for later use.
|
@@ -58,10 +58,12 @@ end
|
|
58
58
|
#++
|
59
59
|
|
60
60
|
class SpreadsheetTest < Test::Unit::TestCase
|
61
|
+
|
61
62
|
def test_range
|
62
63
|
assert_equal(5, MyLXL.eval('=A2'))
|
63
64
|
assert_equal($sheet1[1,2].value, MyLXL.eval('=Sheet1!A2'))
|
64
65
|
assert_equal(8, MyLXL.eval('=Sheet2!C4'))
|
65
66
|
assert_equal($sheet2[3,4].value, MyLXL.eval('=Sheet2!C4'))
|
66
67
|
end
|
68
|
+
|
67
69
|
end
|
data/test/lxl_test.rb
CHANGED
@@ -43,13 +43,13 @@ class LXLTest < Test::Unit::TestCase
|
|
43
43
|
expected += [true, false, :A, :B, false, 6, true, true, [1, 'two', 3.0], true, false, true, 'yes', 'this and that']
|
44
44
|
expected += [8, 0.502, true, true, 'embedded percentages 25% and semi-colons ; are working properly']
|
45
45
|
MyNamespace.register_symbols(:A, :B)
|
46
|
-
lxl = LXL::Parser.new(MyNamespace.new)
|
46
|
+
lxl = LXL::Parser.new(:namespace=>MyNamespace.new)
|
47
47
|
results = lxl.eval(formulas)
|
48
48
|
expected.each_index { |i| assert_equal(expected[i], results[i]) }
|
49
49
|
end
|
50
50
|
|
51
51
|
def test_range
|
52
|
-
lxl = LXL::Parser.new(MyNamespace.new)
|
52
|
+
lxl = LXL::Parser.new(:namespace=>MyNamespace.new)
|
53
53
|
res = lxl.eval('=LIST(d5:b3, "x")')
|
54
54
|
range = res.first
|
55
55
|
assert_equal(LXL::Range, range.class)
|
@@ -70,7 +70,7 @@ class LXLTest < Test::Unit::TestCase
|
|
70
70
|
|
71
71
|
def test_deferred
|
72
72
|
MyNamespace.register_deferred(:TESTING)
|
73
|
-
lxl = LXL::Parser.new(MyNamespace.new)
|
73
|
+
lxl = LXL::Parser.new(:namespace=>MyNamespace.new)
|
74
74
|
res = lxl.eval('=TESTING(1,2,3)')
|
75
75
|
assert_equal(LXL::Deferred, res.class)
|
76
76
|
assert_equal(:testing, res.symbol)
|
@@ -78,7 +78,7 @@ class LXLTest < Test::Unit::TestCase
|
|
78
78
|
end
|
79
79
|
|
80
80
|
def test_range_naming
|
81
|
-
lxl = LXL::Parser.new(MyNamespace.new)
|
81
|
+
lxl = LXL::Parser.new(:namespace=>MyNamespace.new)
|
82
82
|
range = lxl.eval('=B1:D2')
|
83
83
|
assert_equal('B', range.first_column)
|
84
84
|
range = lxl.eval('=Sheet1!B3:D5')
|
@@ -0,0 +1,68 @@
|
|
1
|
+
#--
|
2
|
+
# =LXL Win32OLE Interface
|
3
|
+
#
|
4
|
+
# An LXL interface to an Excel xls file via Win32OLE.
|
5
|
+
#
|
6
|
+
#++
|
7
|
+
|
8
|
+
$LOAD_PATH.unshift('../lib')
|
9
|
+
require 'test/unit'
|
10
|
+
require 'lxl'
|
11
|
+
require 'win32ole'
|
12
|
+
|
13
|
+
#--
|
14
|
+
# Excel workbook
|
15
|
+
#++
|
16
|
+
|
17
|
+
$xl = WIN32OLE.new('Excel.Application')
|
18
|
+
$xl.Visible = false
|
19
|
+
$xl.DisplayAlerts = false
|
20
|
+
$xl.ScreenUpdating = false
|
21
|
+
$xl.Interactive = false
|
22
|
+
$xl.AskToUpdateLinks = false
|
23
|
+
|
24
|
+
workbook = $xl.Workbooks.Add
|
25
|
+
w1 = $xl.Worksheets(1)
|
26
|
+
w2 = $xl.Worksheets(2)
|
27
|
+
w1.Range("A2").Value = 5
|
28
|
+
w2.Range("C4").Value = 8
|
29
|
+
|
30
|
+
#workbook.SaveAs(Dir.getwd+'/workbook.xls')
|
31
|
+
|
32
|
+
#--
|
33
|
+
# LXL Interface
|
34
|
+
#++
|
35
|
+
|
36
|
+
class XLRange < LXL::Range
|
37
|
+
|
38
|
+
def self.new(first, last)
|
39
|
+
range = super
|
40
|
+
sheet = range.sheet || 'Sheet1'
|
41
|
+
$xl.Range("#{sheet}!#{range}").Value
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
class MyLXL < LXL::Parser
|
47
|
+
def self.range_class() XLRange end
|
48
|
+
end
|
49
|
+
|
50
|
+
#--
|
51
|
+
# Test
|
52
|
+
#++
|
53
|
+
|
54
|
+
class XLTest < Test::Unit::TestCase
|
55
|
+
|
56
|
+
def test_range
|
57
|
+
assert_equal(5, MyLXL.eval('=A2'))
|
58
|
+
assert_equal($xl.Range('A2').Value, MyLXL.eval('=Sheet1!A2'))
|
59
|
+
assert_equal(8, MyLXL.eval('=Sheet2!C4'))
|
60
|
+
assert_equal($xl.Range('Sheet2!C4').Value, MyLXL.eval('=Sheet2!C4'))
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_z # finalizer
|
64
|
+
$xl.ActiveWorkbook.Close(0)
|
65
|
+
$xl.Quit
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
metadata
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.8.
|
2
|
+
rubygems_version: 0.8.6
|
3
3
|
specification_version: 1
|
4
4
|
name: lxl
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.4.
|
7
|
-
date: 2005-
|
6
|
+
version: 0.4.3
|
7
|
+
date: 2005-03-07
|
8
8
|
summary: LXL (Like Excel) is a mini-language that mimics Microsoft Excel formulas. Easily extended with new constants and functions.
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -27,17 +27,18 @@ platform: ruby
|
|
27
27
|
authors:
|
28
28
|
- Kevin Howe
|
29
29
|
files:
|
30
|
-
- lib
|
31
|
-
- VERSION
|
32
30
|
- test
|
33
|
-
-
|
31
|
+
- lib
|
34
32
|
- lxl.gemspec
|
35
33
|
- setup.rb
|
34
|
+
- VERSION
|
35
|
+
- CHANGES
|
36
36
|
- README.en
|
37
|
-
- lib/lxl.rb
|
38
|
-
- test/spreadsheet.rb
|
39
|
-
- test/lxl_spreadsheet_test.rb
|
40
37
|
- test/lxl_test.rb
|
38
|
+
- test/lxl_spreadsheet_test.rb
|
39
|
+
- test/spreadsheet.rb
|
40
|
+
- test/lxl_win32ole_test.rb
|
41
|
+
- lib/lxl.rb
|
41
42
|
test_files:
|
42
43
|
- test/lxl_test.rb
|
43
44
|
rdoc_options:
|