roo 1.9.3 → 1.9.4

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.
@@ -1,325 +1,330 @@
1
- #require 'xml'
2
- require "google_spreadsheet"
3
-
4
- class GoogleHTTPError < RuntimeError; end
5
- class GoogleReadError < RuntimeError; end
6
- class GoogleWriteError < RuntimeError; end
7
-
8
- class Google < GenericSpreadsheet
9
- attr_accessor :date_format, :datetime_format
10
-
11
- # Creates a new Google spreadsheet object.
12
- def initialize(spreadsheetkey,user=nil,password=nil)
13
- @filename = spreadsheetkey
14
- @spreadsheetkey = spreadsheetkey
15
- @user = user
16
- @password = password
17
- unless user
18
- user = ENV['GOOGLE_MAIL']
19
- end
20
- unless password
21
- password = ENV['GOOGLE_PASSWORD']
22
- end
23
- @cell = Hash.new {|h,k| h[k]=Hash.new}
24
- @cell_type = Hash.new {|h,k| h[k]=Hash.new}
25
- @formula = Hash.new
26
- @first_row = Hash.new
27
- @last_row = Hash.new
28
- @first_column = Hash.new
29
- @last_column = Hash.new
30
- @cells_read = Hash.new
31
- @header_line = 1
32
- @date_format = '%d/%m/%Y'
33
- @datetime_format = '%d/%m/%Y %H:%M:%S'
34
- @time_format = '%H:%M:%S'
35
- session = GoogleSpreadsheet.login(user, password)
36
- @sheetlist = []
37
- session.spreadsheet_by_key(@spreadsheetkey).worksheets.each { |sheet|
38
- @sheetlist << sheet.title
39
- }
40
- @default_sheet = self.sheets.first
41
- @worksheets = session.spreadsheet_by_key(@spreadsheetkey).worksheets
42
- end
43
-
44
- # returns an array of sheet names in the spreadsheet
45
- def sheets
46
- @sheetlist
47
- end
48
-
49
- def date?(string)
50
- begin
51
- Date.strptime(string, @date_format)
52
- true
53
- rescue
54
- false
55
- end
56
- end
57
-
58
- # is String a time with format HH:MM:SS?
59
- def time?(string)
60
- begin
61
- DateTime.strptime(string, @time_format)
62
- true
63
- rescue
64
- false
65
- end
66
- end
67
-
68
- def datetime?(string)
69
- begin
70
- DateTime.strptime(string, @datetime_format)
71
- true
72
- rescue
73
- false
74
- end
75
- end
76
-
77
- def numeric?(string)
78
- string =~ /^[0-9]+[\.]*[0-9]*$/
79
- end
80
-
81
- def timestring_to_seconds(value)
82
- hms = value.split(':')
83
- hms[0].to_i*3600 + hms[1].to_i*60 + hms[2].to_i
84
- end
85
-
86
- # Returns the content of a spreadsheet-cell.
87
- # (1,1) is the upper left corner.
88
- # (1,1), (1,'A'), ('A',1), ('a',1) all refers to the
89
- # cell at the first line and first row.
90
- def cell(row, col, sheet=nil)
91
- sheet = @default_sheet unless sheet
92
- check_default_sheet #TODO: 2007-12-16
93
- read_cells(sheet) unless @cells_read[sheet]
94
- row,col = normalize(row,col)
95
- value = @cell[sheet]["#{row},#{col}"]
96
- if celltype(row,col,sheet) == :date
97
- begin
98
- return Date.strptime(value, @date_format)
99
- rescue ArgumentError
100
- raise "Invalid Date #{sheet}[#{row},#{col}] #{value} using format '{@date_format}'"
101
- end
102
- elsif celltype(row,col,sheet) == :datetime
103
- begin
104
- return DateTime.strptime(value, @datetime_format)
105
- rescue ArgumentError
106
- raise "Invalid DateTime #{sheet}[#{row},#{col}] #{value} using format '{@datetime_format}'"
107
- end
108
- end
109
- return value
110
- end
111
-
112
- # returns the type of a cell:
113
- # * :float
114
- # * :string
115
- # * :date
116
- # * :percentage
117
- # * :formula
118
- # * :time
119
- # * :datetime
120
- def celltype(row, col, sheet=nil)
121
- sheet = @default_sheet unless sheet
122
- read_cells(sheet) unless @cells_read[sheet]
123
- row,col = normalize(row,col)
124
- if @formula.size > 0 && @formula[sheet]["#{row},#{col}"]
125
- return :formula
126
- else
127
- @cell_type[sheet]["#{row},#{col}"]
128
- end
129
- end
130
-
131
- # Returns the formula at (row,col).
132
- # Returns nil if there is no formula.
133
- # The method #formula? checks if there is a formula.
134
- def formula(row,col,sheet=nil)
135
- sheet = @default_sheet unless sheet
136
- read_cells(sheet) unless @cells_read[sheet]
137
- row,col = normalize(row,col)
138
- if @formula[sheet]["#{row},#{col}"] == nil
139
- return nil
140
- else
141
- return @formula[sheet]["#{row},#{col}"]
142
- end
143
- end
144
-
145
- # true, if there is a formula
146
- def formula?(row,col,sheet=nil)
147
- sheet = @default_sheet unless sheet
148
- read_cells(sheet) unless @cells_read[sheet]
149
- row,col = normalize(row,col)
150
- formula(row,col) != nil
151
- end
152
-
153
- # returns each formula in the selected sheet as an array of elements
154
- # [row, col, formula]
155
- def formulas(sheet=nil)
156
- theformulas = Array.new
157
- sheet = @default_sheet unless sheet
158
- read_cells(sheet) unless @cells_read[sheet]
159
- first_row(sheet).upto(last_row(sheet)) {|row|
160
- first_column(sheet).upto(last_column(sheet)) {|col|
161
- if formula?(row,col,sheet)
162
- f = [row, col, formula(row,col,sheet)]
163
- theformulas << f
164
- end
165
- }
166
- }
167
- theformulas
168
- end
169
-
170
- # true, if the cell is empty
171
- def empty?(row, col, sheet=nil)
172
- value = cell(row, col, sheet)
173
- return true unless value
174
- return false if value.class == Date # a date is never empty
175
- return false if value.class == Float
176
- return false if celltype(row,col,sheet) == :time
177
- value.empty?
178
- end
179
-
180
- # sets the cell to the content of 'value'
181
- # a formula can be set in the form of '=SUM(...)'
182
- def set_value(row,col,value,sheet=nil)
183
- sheet = @default_sheet unless sheet
184
- raise RangeError, "sheet not set" unless sheet
185
- #@@ Set and pass sheet_no
186
- begin
187
- sheet_no = sheets.index(sheet)+1
188
- rescue
189
- raise RangeError, "invalid sheet '"+sheet.to_s+"'"
190
- end
191
- row,col = normalize(row,col)
192
- add_to_cell_roo(row,col,value,sheet_no)
193
- # re-read the portion of the document that has changed
194
- if @cells_read[sheet]
195
- key = "#{row},#{col}"
196
- (value, value_type) = determine_datatype(value.to_s)
197
- @cell[sheet][key] = value
198
- @cell_type[sheet][key] = value_type
199
- end
200
- end
201
-
202
- # returns the first non-empty row in a sheet
203
- def first_row(sheet=nil)
204
- sheet = @default_sheet unless sheet
205
- unless @first_row[sheet]
206
- sheet_no = sheets.index(sheet) + 1
207
- @first_row[sheet], @last_row[sheet], @first_column[sheet], @last_column[sheet] =
208
- oben_unten_links_rechts(sheet_no)
209
- end
210
- return @first_row[sheet]
211
- end
212
-
213
- # returns the last non-empty row in a sheet
214
- def last_row(sheet=nil)
215
- sheet = @default_sheet unless sheet
216
- unless @last_row[sheet]
217
- sheet_no = sheets.index(sheet) + 1
218
- @first_row[sheet], @last_row[sheet], @first_column[sheet], @last_column[sheet] =
219
- oben_unten_links_rechts(sheet_no)
220
- end
221
- return @last_row[sheet]
222
- end
223
-
224
- # returns the first non-empty column in a sheet
225
- def first_column(sheet=nil)
226
- sheet = @default_sheet unless sheet
227
- unless @first_column[sheet]
228
- sheet_no = sheets.index(sheet) + 1
229
- @first_row[sheet], @last_row[sheet], @first_column[sheet], @last_column[sheet] =
230
- oben_unten_links_rechts(sheet_no)
231
- end
232
- return @first_column[sheet]
233
- end
234
-
235
- # returns the last non-empty column in a sheet
236
- def last_column(sheet=nil)
237
- sheet = @default_sheet unless sheet
238
- unless @last_column[sheet]
239
- sheet_no = sheets.index(sheet) + 1
240
- @first_row[sheet], @last_row[sheet], @first_column[sheet], @last_column[sheet] =
241
- oben_unten_links_rechts(sheet_no)
242
- end
243
- return @last_column[sheet]
244
- end
245
-
246
- private
247
-
248
- # read all cells in a sheet.
249
- def read_cells(sheet=nil)
250
- sheet = @default_sheet unless sheet
251
- raise RangeError, "illegal sheet <#{sheet}>" unless sheets.index(sheet)
252
- sheet_no = sheets.index(sheet)
253
- ws = @worksheets[sheet_no]
254
- for row in 1..ws.num_rows
255
- for col in 1..ws.num_cols
256
- key = "#{row},#{col}"
257
- string_value = ws.input_value(row,col) # item['inputvalue'] || item['inputValue']
258
- numeric_value = ws[row,col] #item['numericvalue'] || item['numericValue']
259
- (value, value_type) = determine_datatype(string_value, numeric_value)
260
- @cell[sheet][key] = value unless value == "" or value == nil
261
- @cell_type[sheet][key] = value_type
262
- @formula[sheet] = {} unless @formula[sheet]
263
- @formula[sheet][key] = string_value if value_type == :formula
264
- ############
265
- #$log.debug("key: #{key}")
266
- #$log.debug "#{ws[row,col].inspect}"
267
- #@cell[sheet][key] = ws[row,col]
268
- #$log.debug "@cell[sheet][key]: #{@cell[sheet][key]}"
269
- ############
270
- end
271
- end
272
- @cells_read[sheet] = true
273
- end
274
-
275
- def determine_datatype(val, numval=nil)
276
- # $log.debug "val: #{val} numval: #{numval}"
277
- if val.nil? || val[0,1] == '='
278
- ty = :formula
279
- if numeric?(numval)
280
- val = numval.to_f
281
- else
282
- val = numval
283
- end
284
- else
285
- if datetime?(val)
286
- ty = :datetime
287
- elsif date?(val)
288
- ty = :date
289
- elsif numeric?(val)
290
- ty = :float
291
- val = val.to_f
292
- elsif time?(val)
293
- ty = :time
294
- val = timestring_to_seconds(val)
295
- else
296
- ty = :string
297
- end
298
- end
299
- #$log.debug "val: #{val} ty: #{ty}" if ty == :date
300
- return val, ty
301
- end
302
-
303
- def add_to_cell_roo(row,col,value, sheet_no=1)
304
- sheet_no -= 1
305
- @worksheets[sheet_no][row,col] = value
306
- @worksheets[sheet_no].save
307
- end
308
- def entry_roo(value,row,col)
309
- return value,row,col
310
- end
311
-
312
- def oben_unten_links_rechts(sheet_no)
313
- ws = @worksheets[sheet_no-1]
314
- rows = []
315
- cols = []
316
- for row in 1..ws.num_rows
317
- for col in 1..ws.num_cols
318
- rows << row if ws[row,col] and ws[row,col] != '' #TODO: besser?
319
- cols << col if ws[row,col] and ws[row,col] != '' #TODO: besser?
320
- end
321
- end
322
- return rows.min, rows.max, cols.min, cols.max
323
- end
324
-
325
- end # class
1
+ require "google_spreadsheet"
2
+
3
+ class GoogleHTTPError < RuntimeError; end
4
+ class GoogleReadError < RuntimeError; end
5
+ class GoogleWriteError < RuntimeError; end
6
+
7
+ class Google < GenericSpreadsheet
8
+ attr_accessor :date_format, :datetime_format
9
+
10
+ # Creates a new Google spreadsheet object.
11
+ def initialize(spreadsheetkey,user=nil,password=nil)
12
+ @filename = spreadsheetkey
13
+ @spreadsheetkey = spreadsheetkey
14
+ @user = user
15
+ @password = password
16
+ unless user
17
+ user = ENV['GOOGLE_MAIL']
18
+ end
19
+ unless password
20
+ password = ENV['GOOGLE_PASSWORD']
21
+ end
22
+ unless user and user.size > 0
23
+ warn "user not set"
24
+ end
25
+ unless password and password.size > 0
26
+ warn "password not set"
27
+ end
28
+ @cell = Hash.new {|h,k| h[k]=Hash.new}
29
+ @cell_type = Hash.new {|h,k| h[k]=Hash.new}
30
+ @formula = Hash.new
31
+ @first_row = Hash.new
32
+ @last_row = Hash.new
33
+ @first_column = Hash.new
34
+ @last_column = Hash.new
35
+ @cells_read = Hash.new
36
+ @header_line = 1
37
+ @date_format = '%d/%m/%Y'
38
+ @datetime_format = '%d/%m/%Y %H:%M:%S'
39
+ @time_format = '%H:%M:%S'
40
+ session = GoogleSpreadsheet.login(user, password)
41
+ @sheetlist = []
42
+ session.spreadsheet_by_key(@spreadsheetkey).worksheets.each { |sheet|
43
+ @sheetlist << sheet.title
44
+ }
45
+ @default_sheet = self.sheets.first
46
+ @worksheets = session.spreadsheet_by_key(@spreadsheetkey).worksheets
47
+ end
48
+
49
+ # returns an array of sheet names in the spreadsheet
50
+ def sheets
51
+ @sheetlist
52
+ end
53
+
54
+ def date?(string)
55
+ begin
56
+ Date.strptime(string, @date_format)
57
+ true
58
+ rescue
59
+ false
60
+ end
61
+ end
62
+
63
+ # is String a time with format HH:MM:SS?
64
+ def time?(string)
65
+ begin
66
+ DateTime.strptime(string, @time_format)
67
+ true
68
+ rescue
69
+ false
70
+ end
71
+ end
72
+
73
+ def datetime?(string)
74
+ begin
75
+ DateTime.strptime(string, @datetime_format)
76
+ true
77
+ rescue
78
+ false
79
+ end
80
+ end
81
+
82
+ def numeric?(string)
83
+ string =~ /^[0-9]+[\.]*[0-9]*$/
84
+ end
85
+
86
+ def timestring_to_seconds(value)
87
+ hms = value.split(':')
88
+ hms[0].to_i*3600 + hms[1].to_i*60 + hms[2].to_i
89
+ end
90
+
91
+ # Returns the content of a spreadsheet-cell.
92
+ # (1,1) is the upper left corner.
93
+ # (1,1), (1,'A'), ('A',1), ('a',1) all refers to the
94
+ # cell at the first line and first row.
95
+ def cell(row, col, sheet=nil)
96
+ sheet = @default_sheet unless sheet
97
+ check_default_sheet #TODO: 2007-12-16
98
+ read_cells(sheet) unless @cells_read[sheet]
99
+ row,col = normalize(row,col)
100
+ value = @cell[sheet]["#{row},#{col}"]
101
+ if celltype(row,col,sheet) == :date
102
+ begin
103
+ return Date.strptime(value, @date_format)
104
+ rescue ArgumentError
105
+ raise "Invalid Date #{sheet}[#{row},#{col}] #{value} using format '{@date_format}'"
106
+ end
107
+ elsif celltype(row,col,sheet) == :datetime
108
+ begin
109
+ return DateTime.strptime(value, @datetime_format)
110
+ rescue ArgumentError
111
+ raise "Invalid DateTime #{sheet}[#{row},#{col}] #{value} using format '{@datetime_format}'"
112
+ end
113
+ end
114
+ return value
115
+ end
116
+
117
+ # returns the type of a cell:
118
+ # * :float
119
+ # * :string
120
+ # * :date
121
+ # * :percentage
122
+ # * :formula
123
+ # * :time
124
+ # * :datetime
125
+ def celltype(row, col, sheet=nil)
126
+ sheet = @default_sheet unless sheet
127
+ read_cells(sheet) unless @cells_read[sheet]
128
+ row,col = normalize(row,col)
129
+ if @formula.size > 0 && @formula[sheet]["#{row},#{col}"]
130
+ return :formula
131
+ else
132
+ @cell_type[sheet]["#{row},#{col}"]
133
+ end
134
+ end
135
+
136
+ # Returns the formula at (row,col).
137
+ # Returns nil if there is no formula.
138
+ # The method #formula? checks if there is a formula.
139
+ def formula(row,col,sheet=nil)
140
+ sheet = @default_sheet unless sheet
141
+ read_cells(sheet) unless @cells_read[sheet]
142
+ row,col = normalize(row,col)
143
+ if @formula[sheet]["#{row},#{col}"] == nil
144
+ return nil
145
+ else
146
+ return @formula[sheet]["#{row},#{col}"]
147
+ end
148
+ end
149
+
150
+ # true, if there is a formula
151
+ def formula?(row,col,sheet=nil)
152
+ sheet = @default_sheet unless sheet
153
+ read_cells(sheet) unless @cells_read[sheet]
154
+ row,col = normalize(row,col)
155
+ formula(row,col) != nil
156
+ end
157
+
158
+ # returns each formula in the selected sheet as an array of elements
159
+ # [row, col, formula]
160
+ def formulas(sheet=nil)
161
+ theformulas = Array.new
162
+ sheet = @default_sheet unless sheet
163
+ read_cells(sheet) unless @cells_read[sheet]
164
+ first_row(sheet).upto(last_row(sheet)) {|row|
165
+ first_column(sheet).upto(last_column(sheet)) {|col|
166
+ if formula?(row,col,sheet)
167
+ f = [row, col, formula(row,col,sheet)]
168
+ theformulas << f
169
+ end
170
+ }
171
+ }
172
+ theformulas
173
+ end
174
+
175
+ # true, if the cell is empty
176
+ def empty?(row, col, sheet=nil)
177
+ value = cell(row, col, sheet)
178
+ return true unless value
179
+ return false if value.class == Date # a date is never empty
180
+ return false if value.class == Float
181
+ return false if celltype(row,col,sheet) == :time
182
+ value.empty?
183
+ end
184
+
185
+ # sets the cell to the content of 'value'
186
+ # a formula can be set in the form of '=SUM(...)'
187
+ def set_value(row,col,value,sheet=nil)
188
+ sheet = @default_sheet unless sheet
189
+ raise RangeError, "sheet not set" unless sheet
190
+ #@@ Set and pass sheet_no
191
+ begin
192
+ sheet_no = sheets.index(sheet)+1
193
+ rescue
194
+ raise RangeError, "invalid sheet '"+sheet.to_s+"'"
195
+ end
196
+ row,col = normalize(row,col)
197
+ add_to_cell_roo(row,col,value,sheet_no)
198
+ # re-read the portion of the document that has changed
199
+ if @cells_read[sheet]
200
+ key = "#{row},#{col}"
201
+ (value, value_type) = determine_datatype(value.to_s)
202
+ @cell[sheet][key] = value
203
+ @cell_type[sheet][key] = value_type
204
+ end
205
+ end
206
+
207
+ # returns the first non-empty row in a sheet
208
+ def first_row(sheet=nil)
209
+ sheet = @default_sheet unless sheet
210
+ unless @first_row[sheet]
211
+ sheet_no = sheets.index(sheet) + 1
212
+ @first_row[sheet], @last_row[sheet], @first_column[sheet], @last_column[sheet] =
213
+ oben_unten_links_rechts(sheet_no)
214
+ end
215
+ return @first_row[sheet]
216
+ end
217
+
218
+ # returns the last non-empty row in a sheet
219
+ def last_row(sheet=nil)
220
+ sheet = @default_sheet unless sheet
221
+ unless @last_row[sheet]
222
+ sheet_no = sheets.index(sheet) + 1
223
+ @first_row[sheet], @last_row[sheet], @first_column[sheet], @last_column[sheet] =
224
+ oben_unten_links_rechts(sheet_no)
225
+ end
226
+ return @last_row[sheet]
227
+ end
228
+
229
+ # returns the first non-empty column in a sheet
230
+ def first_column(sheet=nil)
231
+ sheet = @default_sheet unless sheet
232
+ unless @first_column[sheet]
233
+ sheet_no = sheets.index(sheet) + 1
234
+ @first_row[sheet], @last_row[sheet], @first_column[sheet], @last_column[sheet] =
235
+ oben_unten_links_rechts(sheet_no)
236
+ end
237
+ return @first_column[sheet]
238
+ end
239
+
240
+ # returns the last non-empty column in a sheet
241
+ def last_column(sheet=nil)
242
+ sheet = @default_sheet unless sheet
243
+ unless @last_column[sheet]
244
+ sheet_no = sheets.index(sheet) + 1
245
+ @first_row[sheet], @last_row[sheet], @first_column[sheet], @last_column[sheet] =
246
+ oben_unten_links_rechts(sheet_no)
247
+ end
248
+ return @last_column[sheet]
249
+ end
250
+
251
+ private
252
+
253
+ # read all cells in a sheet.
254
+ def read_cells(sheet=nil)
255
+ sheet = @default_sheet unless sheet
256
+ raise RangeError, "illegal sheet <#{sheet}>" unless sheets.index(sheet)
257
+ sheet_no = sheets.index(sheet)
258
+ ws = @worksheets[sheet_no]
259
+ for row in 1..ws.num_rows
260
+ for col in 1..ws.num_cols
261
+ key = "#{row},#{col}"
262
+ string_value = ws.input_value(row,col) # item['inputvalue'] || item['inputValue']
263
+ numeric_value = ws[row,col] #item['numericvalue'] || item['numericValue']
264
+ (value, value_type) = determine_datatype(string_value, numeric_value)
265
+ @cell[sheet][key] = value unless value == "" or value == nil
266
+ @cell_type[sheet][key] = value_type
267
+ @formula[sheet] = {} unless @formula[sheet]
268
+ @formula[sheet][key] = string_value if value_type == :formula
269
+ ############
270
+ #$log.debug("key: #{key}")
271
+ #$log.debug "#{ws[row,col].inspect}"
272
+ #@cell[sheet][key] = ws[row,col]
273
+ #$log.debug "@cell[sheet][key]: #{@cell[sheet][key]}"
274
+ ############
275
+ end
276
+ end
277
+ @cells_read[sheet] = true
278
+ end
279
+
280
+ def determine_datatype(val, numval=nil)
281
+ # $log.debug "val: #{val} numval: #{numval}"
282
+ if val.nil? || val[0,1] == '='
283
+ ty = :formula
284
+ if numeric?(numval)
285
+ val = numval.to_f
286
+ else
287
+ val = numval
288
+ end
289
+ else
290
+ if datetime?(val)
291
+ ty = :datetime
292
+ elsif date?(val)
293
+ ty = :date
294
+ elsif numeric?(val)
295
+ ty = :float
296
+ val = val.to_f
297
+ elsif time?(val)
298
+ ty = :time
299
+ val = timestring_to_seconds(val)
300
+ else
301
+ ty = :string
302
+ end
303
+ end
304
+ #$log.debug "val: #{val} ty: #{ty}" if ty == :date
305
+ return val, ty
306
+ end
307
+
308
+ def add_to_cell_roo(row,col,value, sheet_no=1)
309
+ sheet_no -= 1
310
+ @worksheets[sheet_no][row,col] = value
311
+ @worksheets[sheet_no].save
312
+ end
313
+ def entry_roo(value,row,col)
314
+ return value,row,col
315
+ end
316
+
317
+ def oben_unten_links_rechts(sheet_no)
318
+ ws = @worksheets[sheet_no-1]
319
+ rows = []
320
+ cols = []
321
+ for row in 1..ws.num_rows
322
+ for col in 1..ws.num_cols
323
+ rows << row if ws[row,col] and ws[row,col] != '' #TODO: besser?
324
+ cols << col if ws[row,col] and ws[row,col] != '' #TODO: besser?
325
+ end
326
+ end
327
+ return rows.min, rows.max, cols.min, cols.max
328
+ end
329
+
330
+ end # class