roo 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,9 @@
1
+ == 0.5.0 2007-07-20
2
+ * 2 enhancements:
3
+ * Excel-objects: the methods default_sheet= and sheets can now handle names instead of numbers
4
+ * changed the celltype methods to return symbols, not strings anymore (possible values are :formula, :float, :string, :date, :percentage (if you need strings you can convert it with .to_s)
5
+ * tests can now run on the client machine (not only my machine), if there are not public released files involved these tests are skipped
6
+
1
7
  == 0.4.1 2007-06-27
2
8
  * 1 bugfix
3
9
  * there was ONE false require-statement which led to misleading error messageswhen this gem was used
@@ -3,18 +3,24 @@ License.txt
3
3
  Manifest.txt
4
4
  README.txt
5
5
  Rakefile
6
+ base64include.rb
7
+ examples/roo_soap_server.rb
8
+ examples/roo_soap_client.rb
6
9
  lib/roo.rb
7
10
  lib/roo/version.rb
8
11
  lib/roo/openoffice.rb
9
12
  lib/roo/excel.rb
10
13
  lib/roo/google.rb
11
- lib/roo/spreadsheetparser.rb
12
14
  scripts/txt2html
13
15
  setup.rb
14
16
  test/test_helper.rb
15
17
  test/test_roo.rb
16
18
  test/numbers1.ods
17
19
  test/numbers1.xls
20
+ test/borders.ods
21
+ test/borders.xls
22
+ test/formula.ods
23
+ test/formula.xls
18
24
  website/index.html
19
25
  website/index.txt
20
26
  website/javascripts/rounded_corners_lite.inc.js
data/Rakefile CHANGED
@@ -75,11 +75,10 @@ hoe = Hoe.new(GEM_NAME, VERS) do |p|
75
75
  p.extra_deps = [
76
76
  # ['ruport', '>= 1.0.0'],
77
77
  # ['ruport-util', '>= 0.5.0'],
78
- ['parseexcel', '>= 0.5.1.1'],
78
+ ['parseexcel', '>= 0.5.2'],
79
79
  ['rubyzip', '>= 0.9.1'],
80
80
  ['hpricot', '>= 0.5'],
81
81
  ['hoe', '>= 0.0.0'],
82
- ['llip', '>= 0.0.1'],
83
82
  ]
84
83
  #p.spec_extras = {} # A hash of extra values to set in the gemspec.
85
84
  end
@@ -0,0 +1,149 @@
1
+ @@empty_spreadsheet=<<_ENDOFBASE64CODE_
2
+ UEsDBBQAAAAAABWJ4jaFbDmKLgAAAC4AAAAIAAAAbWltZXR5cGVhcHBsaWNh
3
+ dGlvbi92bmQub2FzaXMub3BlbmRvY3VtZW50LnNwcmVhZHNoZWV0UEsDBBQA
4
+ AAAAABWJ4jYAAAAAAAAAAAAAAAAaAAAAQ29uZmlndXJhdGlvbnMyL3N0YXR1
5
+ c2Jhci9QSwMEFAAIAAgAFYniNgAAAAAAAAAAAAAAACcAAABDb25maWd1cmF0
6
+ aW9uczIvYWNjZWxlcmF0b3IvY3VycmVudC54bWwDAFBLBwgAAAAAAgAAAAAA
7
+ AABQSwMEFAAAAAAAFYniNgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9u
8
+ czIvZmxvYXRlci9QSwMEFAAAAAAAFYniNgAAAAAAAAAAAAAAABoAAABDb25m
9
+ aWd1cmF0aW9uczIvcG9wdXBtZW51L1BLAwQUAAAAAAAVieI2AAAAAAAAAAAA
10
+ AAAAHAAAAENvbmZpZ3VyYXRpb25zMi9wcm9ncmVzc2Jhci9QSwMEFAAAAAAA
11
+ FYniNgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9uczIvbWVudWJhci9Q
12
+ SwMEFAAAAAAAFYniNgAAAAAAAAAAAAAAABgAAABDb25maWd1cmF0aW9uczIv
13
+ dG9vbGJhci9QSwMEFAAAAAAAFYniNgAAAAAAAAAAAAAAAB8AAABDb25maWd1
14
+ cmF0aW9uczIvaW1hZ2VzL0JpdG1hcHMvUEsDBBQACAAIABWJ4jYAAAAAAAAA
15
+ AAAAAAALAAAAY29udGVudC54bWzlV7ty2zAQ7PMVHBbpIOjhSWxGkptMKjuN
16
+ k0xaCDxKiPHgAKBo/X0AgqRBWZRZJw01Ouze7S2Op9H6/kXw5AjaMCU36WI2
17
+ TxOQVOVM7jfpzx/f0G16v/2wVkXBKGS5opUAaRFV0rrPxLGlycLpJq20zBQx
18
+ zGSSCDCZpZkqQXasLEZnTa0QMfbEJ9MbcMy28GKnkj12wCW76ZUbcMzONamn
19
+ kj3WmRrTCzWV/GI4KpRzXZTEsjMVL5zJ5016sLbMMK7relavZkrv8eLu7g43
20
+ p71g2uPKSvMGlVMMHHwxgxezBe6wAiyZqs9jY0myEjvQk60hlry5VXPcT56I
21
+ 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
59
+ meexreF3ONDfDT8tBIwKKellSu+s/4NU+q8ydjux/dF6VS9kSDYm5Hk8MkJt
60
+ 6doA074L/TJXeR+tzUdsRf1X7gipwNHj4+PavxTWkuKCg4vQ6zDafk0lTKOn
61
+ XserqGl2f6uPUj9or6vJLQrtfi1ZzwVrqsP5VRf8Ho23mH1HCi6uEjvvEWs7
62
+ f6pbmPbnE7l2nlY4RRVrQ6rnZz0eOjt1ROYGXewOgxQZnalgUmtAnpm74WUi
63
+ CB48/QMnDeaz4GGmJbUXGhh961iHwftwuQoWq+f3jdND2dP174ullOO3geZl
64
+ JVou28BK9i+lnj981/3hz/CjvwBQSwcI7Cj9uWgFAAADGAAAUEsDBBQAAAAA
65
+ ABWJ4jZx0iL8qgMAAKoDAAAIAAAAbWV0YS54bWw8P3htbCB2ZXJzaW9uPSIx
66
+ LjAiIGVuY29kaW5nPSJVVEYtOCI/Pgo8b2ZmaWNlOmRvY3VtZW50LW1ldGEg
67
+ eG1sbnM6b2ZmaWNlPSJ1cm46b2FzaXM6bmFtZXM6dGM6b3BlbmRvY3VtZW50
68
+ OnhtbG5zOm9mZmljZToxLjAiIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3Lncz
69
+ Lm9yZy8xOTk5L3hsaW5rIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2Rj
70
+ L2VsZW1lbnRzLzEuMS8iIHhtbG5zOm1ldGE9InVybjpvYXNpczpuYW1lczp0
71
+ YzpvcGVuZG9jdW1lbnQ6eG1sbnM6bWV0YToxLjAiIHhtbG5zOm9vbz0iaHR0
72
+ cDovL29wZW5vZmZpY2Uub3JnLzIwMDQvb2ZmaWNlIiBvZmZpY2U6dmVyc2lv
73
+ bj0iMS4wIj48b2ZmaWNlOm1ldGE+PG1ldGE6Z2VuZXJhdG9yPk9wZW5PZmZp
74
+ Y2Uub3JnLzIuMCRMaW51eCBPcGVuT2ZmaWNlLm9yZ19wcm9qZWN0LzY4MG01
75
+ JEJ1aWxkLTkwNzM8L21ldGE6Z2VuZXJhdG9yPjxtZXRhOmluaXRpYWwtY3Jl
76
+ YXRvcj5UaG9tYXMgUHJleW1lc3NlcjwvbWV0YTppbml0aWFsLWNyZWF0b3I+
77
+ PG1ldGE6Y3JlYXRpb24tZGF0ZT4yMDA3LTA3LTAyVDE5OjA3OjUxPC9tZXRh
78
+ OmNyZWF0aW9uLWRhdGU+PGRjOmxhbmd1YWdlPmRlLURFPC9kYzpsYW5ndWFn
79
+ ZT48bWV0YTplZGl0aW5nLWN5Y2xlcz4xPC9tZXRhOmVkaXRpbmctY3ljbGVz
80
+ PjxtZXRhOmVkaXRpbmctZHVyYXRpb24+UFQwUzwvbWV0YTplZGl0aW5nLWR1
81
+ cmF0aW9uPjxtZXRhOnVzZXItZGVmaW5lZCBtZXRhOm5hbWU9IkluZm8gMSIv
82
+ PjxtZXRhOnVzZXItZGVmaW5lZCBtZXRhOm5hbWU9IkluZm8gMiIvPjxtZXRh
83
+ OnVzZXItZGVmaW5lZCBtZXRhOm5hbWU9IkluZm8gMyIvPjxtZXRhOnVzZXIt
84
+ ZGVmaW5lZCBtZXRhOm5hbWU9IkluZm8gNCIvPjxtZXRhOmRvY3VtZW50LXN0
85
+ YXRpc3RpYyBtZXRhOnRhYmxlLWNvdW50PSIzIi8+PC9vZmZpY2U6bWV0YT48
86
+ L29mZmljZTpkb2N1bWVudC1tZXRhPlBLAwQUAAgACAAVieI2AAAAAAAAAAAA
87
+ AAAAGAAAAFRodW1ibmFpbHMvdGh1bWJuYWlsLnBuZ+sM8HPn5ZLiYmBg4PX0
88
+ cAkC0iVAvICDDUjeNfWQY2BgbPd0cQypmPP2oiMngwHPgQO2r+4XpScZcJRz
89
+ Mc28a1ty5j3DPSOTYxcknJN5eg1HGTRizODOSmatE5azVwPGDIOnq5/LOqeE
90
+ JgBQSwcItoVPfmoAAADAAQAAUEsDBBQACAAIABWJ4jYAAAAAAAAAAAAAAAAM
91
+ AAAAc2V0dGluZ3MueG1s7Zltc6I6FIC/31/h8PWOFbXbVqe6g/i6Vdd3W78F
92
+ SDVtSNgkiPTX3yC6Y1nZtYgzd3bqDCokec7h5OScE7j/urFxZg0ZR5RUlPyV
93
+ qmQgMamFyLKiTCfN7J3ytfrPPX1+RiYsW9R0bUhElkMhZBeekcMJL4fNFcVl
94
+ pEwBR7xMgA15WZhl6kCyH1Y+7F3eCguvbDAirxVlJYRTzuU8z7vyileULXP5
95
+ UqmU27buu5qUPKPlqaLC3oeiKKU/BQUDQmW2wgqqep0Lz5XMTsl3pqnu7bC/
96
+ /er9TkD4k0UC2oFtMrvLgWoVRYosrxH0flpNOTbu/ZgZ4sjAUGMQTKij7BuF
97
+ 78hGRIRSVe9zv0I+BO7CZ3EZ8hxZYnUMXSh8uTub3oZouTqq+fXt7an0rA2c
98
+ LCIW3EArKgl6x6doO0Y6F/NP0Rd6HSuiJBdMzr9SDRrzH9I0gEb0nABpjz8p
99
+ +n7IeAWhyJ/gfrrLOGUDypGQ3v+Yope8Jz+lSG5Tht4oEQCPHYxEj1owav4V
100
+ ZWf4N2QCmZeiR7TfGyjN9Xmo/wX4minQGm7pI0CWMeYpJIPv9U05Zu2xo7iI
101
+ ciY33di9p9aoENT+APjIxcNYFte8DTqnTvw2HMXEuzDunL0wTEYxNgCLTy+3
102
+ CS27oNSeSE6qSzqAzgB2o9Stqnk1qROAJQzyx2/pNwnh4xX1AgE1mWZfBwwG
103
+ ZUuEb1CKISBK9RlgDpOLWUBGt/rzOAGCuWfw+1RcCt1iKJrZUyAHVJ1iyiJo
104
+ TIMllC/cFGX1dJPCvF7AKm3ApequTUbUa0Ngyar5IkK2gURGmgvQO/y7K+RO
105
+ A45926CYj2E0IaQiZEyAM6EjwAWMTnQaKysEd/iuXL6YhBHkcr5ji0MZ3RJG
106
+ oCj+aIV4Ln7sGhZaIx6rfkrw48ondZ0Qr20QH/vEXDFK0BtMEIgSVgO7zdLx
107
+ DnJre/pmOLzgMhBM8Ed2xZ954y/LG11EXqeOBQSM31AVP1PSZ0r6TEl/dUr6
108
+ kyTNFVQH2HSxDBXp4wdymyrvoy9PYnawdX2QzRdUNSuP26x6k1UT2mwnSi5l
109
+ N/powAAc3lzXEAHMV6qzYfvfnDqqT3V103vRvO6k4/XqpujVn+TR0P5vn2F+
110
+ Npy+OY1hXhO9QFdd9Xt1rdidaAV5bA66zjWtp9leeJLL3dU0bTWWfxuW/Brb
111
+ JTRqNdWnsbbRSc0H8y/q4rFTGjX6w+6kETBFYI++r3p9pHq9obM2bYwNMlpZ
112
+ Lbw2XvJDo/hNNe2mY2nOi1GsOYvHXkn2e3sqNPliIu1Z1x6MedNfFLC7aDV/
113
+ WI991ZjPXKuuet26xnu65+l2f220Sv6iNfOs1rLUexk+mO0+XzwusCH7HbQX
114
+ wLyPBxPtYdqsNYaFkmu1ZtfbexjSSkKHdxzsTzlkdSBA+g6vrwADpvRDndoO
115
+ gzyIDKk//+jwB8iIxhEgA5eYwgVHnjim8jgBrOEsfFHzneiY8kskmbBMaTJq
116
+ T6Dt/C4OnSFEw1gWXEGI+EYNHRAT4gsUXRRYI1kRUYL9BPcQW/7nfnk7lot7
117
+ b1j9D1BLBwhS6dOMhwQAAHkcAABQSwMEFAAIAAgAFYniNgAAAAAAAAAAAAAA
118
+ ABUAAABNRVRBLUlORi9tYW5pZmVzdC54bWy1lUtqwzAQQPc9hdHeVttVMXEC
119
+ LfQE6QEm8tgR6IdmFJLbVw7k0zaUplg7DUjvjUYaabHaW1PtMJL2rhNPzaOo
120
+ 0Cnfazd24mP9Xr+I1fJhYcHpAYnb06DK6xydw06k6FoPpKl1YJFaVq0P6Hqv
121
+ kkXH7df57WRaPlQX8KAN1nliPFQXGfYaaj4E7ASEYLQCznnKneubo6u5VjQU
122
+ IkJPW0QWF8iQjKkD8LYTUsi7nLcpb94NekzxmAs9S2LgRBuIZfCgFBrMoY9S
123
+ pRinneZiFncVEQzGA2MhePAhhXwTUiF89GNEKnfSU+rF4Oy9KQbXFkYk+arZ
124
+ QqCijjvZ358NSm7qnibpRl0L/pbDnXLGPcupV2/Cs5//18y/c4kPBml2rEWG
125
+ 2R6e9TbZjQNtSPJp2AQ3zg2ft7DInP/Fc2kX8se3uPwEUEsHCMwGTWZCAQAA
126
+ UQcAAFBLAQIUABQAAAAAABWJ4jaFbDmKLgAAAC4AAAAIAAAAAAAAAAAAAAAA
127
+ AAAAAABtaW1ldHlwZVBLAQIUABQAAAAAABWJ4jYAAAAAAAAAAAAAAAAaAAAA
128
+ AAAAAAAAAAAAAFQAAABDb25maWd1cmF0aW9uczIvc3RhdHVzYmFyL1BLAQIU
129
+ ABQACAAIABWJ4jYAAAAAAgAAAAAAAAAnAAAAAAAAAAAAAAAAAIwAAABDb25m
130
+ aWd1cmF0aW9uczIvYWNjZWxlcmF0b3IvY3VycmVudC54bWxQSwECFAAUAAAA
131
+ AAAVieI2AAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAADjAAAAQ29uZmlndXJh
132
+ dGlvbnMyL2Zsb2F0ZXIvUEsBAhQAFAAAAAAAFYniNgAAAAAAAAAAAAAAABoA
133
+ AAAAAAAAAAAAAAAAGQEAAENvbmZpZ3VyYXRpb25zMi9wb3B1cG1lbnUvUEsB
134
+ AhQAFAAAAAAAFYniNgAAAAAAAAAAAAAAABwAAAAAAAAAAAAAAAAAUQEAAENv
135
+ bmZpZ3VyYXRpb25zMi9wcm9ncmVzc2Jhci9QSwECFAAUAAAAAAAVieI2AAAA
136
+ AAAAAAAAAAAAGAAAAAAAAAAAAAAAAACLAQAAQ29uZmlndXJhdGlvbnMyL21l
137
+ bnViYXIvUEsBAhQAFAAAAAAAFYniNgAAAAAAAAAAAAAAABgAAAAAAAAAAAAA
138
+ AAAAwQEAAENvbmZpZ3VyYXRpb25zMi90b29sYmFyL1BLAQIUABQAAAAAABWJ
139
+ 4jYAAAAAAAAAAAAAAAAfAAAAAAAAAAAAAAAAAPcBAABDb25maWd1cmF0aW9u
140
+ czIvaW1hZ2VzL0JpdG1hcHMvUEsBAhQAFAAIAAgAFYniNhzWDUr9AgAASQwA
141
+ AAsAAAAAAAAAAAAAAAAANAIAAGNvbnRlbnQueG1sUEsBAhQAFAAIAAgAFYni
142
+ Nuwo/bloBQAAAxgAAAoAAAAAAAAAAAAAAAAAagUAAHN0eWxlcy54bWxQSwEC
143
+ FAAUAAAAAAAVieI2cdIi/KoDAACqAwAACAAAAAAAAAAAAAAAAAAKCwAAbWV0
144
+ YS54bWxQSwECFAAUAAgACAAVieI2toVPfmoAAADAAQAAGAAAAAAAAAAAAAAA
145
+ AADaDgAAVGh1bWJuYWlscy90aHVtYm5haWwucG5nUEsBAhQAFAAIAAgAFYni
146
+ NlLp04yHBAAAeRwAAAwAAAAAAAAAAAAAAAAAig8AAHNldHRpbmdzLnhtbFBL
147
+ AQIUABQACAAIABWJ4jbMBk1mQgEAAFEHAAAVAAAAAAAAAAAAAAAAAEsUAABN
148
+ RVRBLUlORi9tYW5pZmVzdC54bWxQSwUGAAAAAA8ADwDuAwAA0BUAAAAA
149
+ _ENDOFBASE64CODE_
@@ -0,0 +1,53 @@
1
+ require 'soap/rpc/driver'
2
+
3
+ def ferien_fuer_region(proxy, region, year=nil)
4
+ proxy.first_row.upto(proxy.last_row) { |row|
5
+ if proxy.cell(row, 2) == region
6
+ jahr = proxy.cell(row,1).to_i
7
+ if year == nil || jahr == year
8
+ bis_datum = proxy.cell(row,5)
9
+ if DateTime.now > bis_datum
10
+ print '('
11
+ end
12
+ print jahr.to_s+" "
13
+ print proxy.cell(row,2)+" "
14
+ print proxy.cell(row,3)+" "
15
+ print proxy.cell(row,4).to_s+" "
16
+ print bis_datum.to_s+" "
17
+ print (proxy.cell(row,6) || '')+" "
18
+ if DateTime.now > bis_datum
19
+ print ')'
20
+ end
21
+ puts
22
+ end
23
+ end
24
+ }
25
+ end
26
+
27
+ proxy = SOAP::RPC::Driver.new("http://localhost:12321","spreadsheetserver")
28
+ proxy.add_method('cell','row','col')
29
+ proxy.add_method('officeversion')
30
+ proxy.add_method('last_row')
31
+ proxy.add_method('last_column')
32
+ proxy.add_method('first_row')
33
+ proxy.add_method('first_column')
34
+ proxy.add_method('sheets')
35
+ proxy.add_method('set_default_sheet','s')
36
+ proxy.add_method('ferien_fuer_region', 'region')
37
+
38
+ sheets = proxy.sheets
39
+ proxy.set_default_sheet(sheets.first)
40
+
41
+ puts "first row: #{proxy.first_row}"
42
+ puts "first column: #{proxy.first_column}"
43
+ puts "last row: #{proxy.last_row}"
44
+ puts "last column: #{proxy.last_column}"
45
+ puts "cell: #{proxy.cell('C',8)}"
46
+ puts "cell: #{proxy.cell('F',12)}"
47
+ puts "officeversion: #{proxy.officeversion}"
48
+ puts "Bayern:"
49
+
50
+ ferien_fuer_region(proxy, "Bayern")
51
+
52
+
53
+
@@ -0,0 +1,29 @@
1
+ require 'rubygems'
2
+ require 'roo'
3
+ require 'soap/rpc/standaloneServer'
4
+
5
+ NS = "spreadsheetserver" # name of your service = namespace
6
+ class Server2 < SOAP::RPC::StandaloneServer
7
+
8
+ def on_init
9
+ spreadsheet = Openoffice.new("./Ferien-de.ods")
10
+ add_method(spreadsheet, 'cell', 'row', 'col')
11
+ add_method(spreadsheet, 'officeversion')
12
+ add_method(spreadsheet, 'first_row')
13
+ add_method(spreadsheet, 'last_row')
14
+ add_method(spreadsheet, 'first_column')
15
+ add_method(spreadsheet, 'last_column')
16
+ add_method(spreadsheet, 'sheets')
17
+ #add_method(spreadsheet, 'default_sheet=', 's')
18
+ # method with '...=' did not work? alias method 'set_default_sheet' created
19
+ add_method(spreadsheet, 'set_default_sheet', 's')
20
+ end
21
+
22
+ end
23
+
24
+ PORT = 12321
25
+ puts "serving at port #{PORT}"
26
+ svr = Server2.new('Roo', NS, '0.0.0.0', PORT)
27
+
28
+ trap('INT') { svr.shutdown }
29
+ svr.start
data/lib/roo.rb CHANGED
@@ -2,7 +2,7 @@ module Roo
2
2
  end
3
3
 
4
4
  require 'roo/version'
5
- require 'roo/spreadsheetparser'
5
+ # require 'roo/spreadsheetparser' TODO:
6
6
  require 'roo/openoffice'
7
7
  require 'roo/excel'
8
8
  require 'roo/google'
@@ -13,17 +13,19 @@ class Excel < Openoffice
13
13
  @first_row = @last_row = @first_column = @last_column = nil
14
14
  end
15
15
 
16
- # TODO: waiting for
17
- # ich glaube, parseexcel kann keine namen der sheets ???
18
16
  def sheets
19
- if DateTime.now < Date.new(2007,6,10)
20
- return ["Tabelle1", "Name of Sheet 2", "Sheet3"]
21
- else
22
- #worksheet = @workbook.worksheet(0)
23
- # p @workbook
24
- # p @workbook.worksheet(0)
25
- ["aaa","bbb","ccc"]
26
- end
17
+ #if DateTime.now < Date.new(2007,6,10)
18
+ # return ["Tabelle1", "Name of Sheet 2", "Sheet3"]
19
+ #else
20
+ result = []
21
+ 0.upto(@workbook.sheet_count - 1) do |i|
22
+ # TODO: is there a better way to do conversion?
23
+ result << Iconv.new('utf-8','unicode').iconv(
24
+ @workbook.worksheet(i).name
25
+ )
26
+ end
27
+ return result
28
+ #end
27
29
  end
28
30
 
29
31
  # sets the working sheet (1,2,3,..)
@@ -32,10 +34,15 @@ class Excel < Openoffice
32
34
  # von aussen arbeite ich mit (1,2,3... intern wird Index 0,1,2,...
33
35
  # verwendet.
34
36
  def default_sheet=(n)
35
- unless n.kind_of?(Fixnum)
36
- fail ArgumentError.new("Number expected")
37
+ if DateTime.now < Date.new(2007,7,19)
38
+ unless n.kind_of?(Fixnum)
39
+ fail ArgumentError.new("Number expected")
40
+ end
41
+ @default_sheet = n-1
42
+ else
43
+ # parseexcel supports now the name of a sheet
44
+ @default_sheet = n
37
45
  end
38
- @default_sheet = n-1
39
46
  @first_row = @last_row = @first_column = @last_column = nil
40
47
  @cells_read = false
41
48
  end
@@ -43,8 +50,7 @@ class Excel < Openoffice
43
50
  # returns the content of a cell. The upper left corner is (1,1) or ('A',1)
44
51
  def cell(row,col)
45
52
  row,col = normalize(row,col)
46
- default_sheet_check
47
- worksheet = @workbook.worksheet(@default_sheet)
53
+ worksheet = @workbook.worksheet(sheet_no(@default_sheet))
48
54
  skip = 0
49
55
  line = 1
50
56
  worksheet.each(skip) { |row_par|
@@ -70,7 +76,7 @@ class Excel < Openoffice
70
76
  def celltype(row,col)
71
77
  row,col = normalize(row,col)
72
78
  default_sheet_check
73
- worksheet = @workbook.worksheet(@default_sheet)
79
+ worksheet = @workbook.worksheet(sheet_no(@default_sheet))
74
80
  skip = 0
75
81
  line = 1
76
82
  worksheet.each(skip) { |row_par|
@@ -78,10 +84,10 @@ class Excel < Openoffice
78
84
  cell = row_par.at(col-1)
79
85
  return nil unless cell
80
86
  case cell.type
81
- when :numeric then return "float"
82
- when :text then return "string"
83
- when :date then return "date"
84
- else return cell.type
87
+ when :numeric then return :float
88
+ when :text then return :string
89
+ when :date then return :date
90
+ else return cell.type.to_sym
85
91
  end
86
92
  end
87
93
  line += 1
@@ -91,7 +97,7 @@ class Excel < Openoffice
91
97
  # return this row a an array off cells
92
98
  def row(rownumber)
93
99
  default_sheet_check
94
- worksheet = @workbook.worksheet(@default_sheet)
100
+ worksheet = @workbook.worksheet(sheet_no(@default_sheet))
95
101
  therow = worksheet.row(rownumber-1)
96
102
  result = []
97
103
  therow.each {|cell|
@@ -157,7 +163,7 @@ private
157
163
  def get_firsts_lasts
158
164
  fr = fc = 999_999
159
165
  lr = lc = -999_999
160
- worksheet = @workbook.worksheet(@default_sheet)
166
+ worksheet = @workbook.worksheet(sheet_no(@default_sheet))
161
167
  skip = 0
162
168
  line = 1
163
169
  worksheet.each(skip) { |row_par|
@@ -186,4 +192,16 @@ private
186
192
  return fr, lr, fc, lc
187
193
  end
188
194
 
195
+
196
+ # converts name of a sheet to index (0,1,2,..)
197
+ def sheet_no(name)
198
+ return name-1 if name.kind_of?(Fixnum)
199
+ 0.upto(@workbook.sheet_count - 1) do |i|
200
+ # TODO: is there a better way to do conversion?
201
+ return i if name == Iconv.new('utf-8','unicode').iconv(
202
+ @workbook.worksheet(i).name
203
+ )
204
+ end
205
+ raise StandardError, "sheet '#{name}' not found"
206
+ end
189
207
  end
@@ -5,6 +5,7 @@ require 'fileutils'
5
5
  require 'zip/zipfilesystem'
6
6
  require 'date'
7
7
  require 'llip'
8
+ require 'base64'
8
9
 
9
10
  #require 'lib/roo/spreadsheetparser'
10
11
 
@@ -12,10 +13,16 @@ class Openoffice
12
13
 
13
14
  @@nr = 0
14
15
 
15
- def initialize(filename)
16
+ # initialization and opening of a spreasheet file
17
+ # file will be created if 'create' is true
18
+ # and the file does not exist
19
+ def initialize(filename, create = false)
16
20
  if filename[-4..-1] != ".ods"
17
21
  warn "are you sure, this is an openoffice file?"
18
22
  end
23
+ if create and ! File.exists?(filename)
24
+ self.create_openoffice(filename)
25
+ end
19
26
  @cells_read = false
20
27
  @filename = filename
21
28
  @tmpdir = "oo_"+$$.to_s
@@ -31,12 +38,27 @@ class Openoffice
31
38
  @cell = Hash.new
32
39
  @cell_type = Hash.new
33
40
  @formula = Hash.new
34
- # if ENV["roo_local"] != "thomas-p"
41
+ if ENV["roo_local"] != "thomas-p"
35
42
  FileUtils::rm_r(@tmpdir)
36
- # end
37
- @default_sheet = nil
43
+ end
44
+ @default_sheet = nil
38
45
  @first_column = @last_column = nil
39
46
  @first_row = @last_row = nil
47
+ trap('INT') {
48
+ FileUtils::rm_r(@tmpdir)
49
+ }
50
+ end
51
+
52
+ # creates a new empty openoffice-spreadsheet file
53
+ def create_openoffice(filename)
54
+ #TODO: a better way for creating the file contents
55
+ # now you have to call mkbase64...rb to create an include file with all
56
+ # the empty files in an openoffice zip-file
57
+ load 'base64include.rb'
58
+ # puts @@empty_spreadsheet
59
+ f = File.open(filename,'w')
60
+ f.print(Base64.decode64(@@empty_spreadsheet))
61
+ f.close
40
62
  end
41
63
 
42
64
  # reopens and read a spreadsheet document
@@ -75,7 +97,7 @@ class Openoffice
75
97
  def cell(row,col)
76
98
  read_cells unless @cells_read
77
99
  row,col = normalize(row,col)
78
- if celltype(row,col) == "date"
100
+ if celltype(row,col) == :date
79
101
  yyyy,mm,dd = @cell["#{row},#{col}"].split('-')
80
102
  return Date.new(yyyy.to_i,mm.to_i,dd.to_i)
81
103
  end
@@ -104,6 +126,7 @@ class Openoffice
104
126
  # set a cell to a certain value
105
127
  # (this will not be saved back to the spreadsheet file!)
106
128
  def set(row,col,value)
129
+ read_cells unless @cells_read
107
130
  row,col = normalize(row,col)
108
131
  set_value(row,col,value)
109
132
  if value.class == Fixnum
@@ -163,6 +186,8 @@ class Openoffice
163
186
  @formula = Hash.new
164
187
  end
165
188
 
189
+ alias set_default_sheet default_sheet=
190
+
166
191
  # version of the openoffice document
167
192
  # at 2007 this is always "1.0"
168
193
  def officeversion
@@ -284,16 +309,14 @@ class Openoffice
284
309
  def empty?(row, col)
285
310
  read_cells unless @cells_read
286
311
  return true unless cell(row, col)
287
- return true if celltype(row, col) == "string" && cell(row, col).empty?
312
+ return true if celltype(row, col) == :string && cell(row, col).empty?
288
313
  false
289
314
  end
290
315
 
291
- =begin
292
316
  # save spreadsheet
293
317
  def save
294
318
  42
295
319
  end
296
- =end
297
320
 
298
321
  # evaluate the formula at this cell
299
322
  # experimental: DO NOT USE THIS!
@@ -396,13 +419,13 @@ private
396
419
  x += (skip.to_i - 1)
397
420
  else
398
421
  0.upto(skip.to_i-1) do |i|
399
- @cell_type["#{y},#{x+i}"] = vt
422
+ @cell_type["#{y},#{x+i}"] = Openoffice.oo_type_2_roo_type(vt)
400
423
  @formula["#{y},#{x+i}"] = formula if formula
401
- if @cell_type["#{y},#{x+i}"] == 'float'
424
+ if @cell_type["#{y},#{x+i}"] == :float
402
425
  @cell["#{y},#{x+i}"] = v.to_f
403
- elsif @cell_type["#{y},#{x+i}"] == 'string'
426
+ elsif @cell_type["#{y},#{x+i}"] == :string
404
427
  @cell["#{y},#{x+i}"] = v
405
- elsif @cell_type["#{y},#{x+i}"] == 'date'
428
+ elsif @cell_type["#{y},#{x+i}"] == :date
406
429
  @cell["#{y},#{x+i}"] = tr.attributes['date-value']
407
430
  else
408
431
  @cell["#{y},#{x+i}"] = v
@@ -412,16 +435,16 @@ private
412
435
  end
413
436
  end # if skip
414
437
  @formula["#{y},#{x}"] = formula if formula
415
- @cell_type["#{y},#{x}"] = vt
416
- if @cell_type["#{y},#{x}"] == 'float'
438
+ @cell_type["#{y},#{x}"] = Openoffice.oo_type_2_roo_type(vt)
439
+ if @cell_type["#{y},#{x}"] == :float
417
440
  @cell["#{y},#{x}"] = v.to_f
418
- elsif @cell_type["#{y},#{x}"] == 'string'
441
+ elsif @cell_type["#{y},#{x}"] == :string
419
442
  tr.each_element do |str|
420
443
  if str.name == 'p'
421
444
  @cell["#{y},#{x}"] = str.text
422
445
  end
423
446
  end
424
- elsif @cell_type["#{y},#{x}"] == 'date'
447
+ elsif @cell_type["#{y},#{x}"] == :date
425
448
  @cell["#{y},#{x}"] = tr.attributes['date-value']
426
449
  else
427
450
  @cell["#{y},#{x}"] = v
@@ -445,6 +468,7 @@ private
445
468
  end
446
469
 
447
470
  def process_zipfile(zip, path='')
471
+ #p path
448
472
  if zip.file.file? path
449
473
  if path == "content.xml"
450
474
  open(@tmpdir+'/'+@file_nr.to_s+'_roo_content.xml','w') {|f|
@@ -476,7 +500,7 @@ private
476
500
  # ('B', 5) -> (5, 2)
477
501
  row, col = col, row
478
502
  else
479
- raise FormatError
503
+ raise ArgumentError
480
504
  end
481
505
  end
482
506
  if col.class == String
@@ -517,4 +541,14 @@ private
517
541
  @cell_type["#{row},#{col}"] = type
518
542
  end
519
543
 
544
+ A_ROO_TYPE = {
545
+ "float" => :float,
546
+ "string" => :string,
547
+ "date" => :date,
548
+ "percentage" => :percentage,
549
+ }
550
+
551
+ def Openoffice.oo_type_2_roo_type(ootype)
552
+ return A_ROO_TYPE[ootype]
553
+ end
520
554
  end # class