roo 1.13.2 → 2.10.1

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 (236) hide show
  1. checksums.yaml +5 -5
  2. data/.codeclimate.yml +17 -0
  3. data/.github/issue_template.md +16 -0
  4. data/.github/pull_request_template.md +14 -0
  5. data/.github/workflows/pull-request.yml +15 -0
  6. data/.github/workflows/ruby.yml +34 -0
  7. data/.gitignore +11 -0
  8. data/.rubocop.yml +186 -0
  9. data/.simplecov +4 -0
  10. data/CHANGELOG.md +702 -0
  11. data/Gemfile +18 -12
  12. data/Guardfile +23 -0
  13. data/LICENSE +5 -1
  14. data/README.md +328 -0
  15. data/Rakefile +23 -23
  16. data/examples/roo_soap_client.rb +28 -31
  17. data/examples/roo_soap_server.rb +4 -6
  18. data/examples/write_me.rb +9 -10
  19. data/lib/roo/base.rb +317 -504
  20. data/lib/roo/constants.rb +7 -0
  21. data/lib/roo/csv.rb +141 -113
  22. data/lib/roo/errors.rb +11 -0
  23. data/lib/roo/excelx/cell/base.rb +108 -0
  24. data/lib/roo/excelx/cell/boolean.rb +30 -0
  25. data/lib/roo/excelx/cell/date.rb +28 -0
  26. data/lib/roo/excelx/cell/datetime.rb +107 -0
  27. data/lib/roo/excelx/cell/empty.rb +20 -0
  28. data/lib/roo/excelx/cell/number.rb +99 -0
  29. data/lib/roo/excelx/cell/string.rb +19 -0
  30. data/lib/roo/excelx/cell/time.rb +44 -0
  31. data/lib/roo/excelx/cell.rb +110 -0
  32. data/lib/roo/excelx/comments.rb +55 -0
  33. data/lib/roo/excelx/coordinate.rb +19 -0
  34. data/lib/roo/excelx/extractor.rb +39 -0
  35. data/lib/roo/excelx/format.rb +71 -0
  36. data/lib/roo/excelx/images.rb +26 -0
  37. data/lib/roo/excelx/relationships.rb +33 -0
  38. data/lib/roo/excelx/shared.rb +39 -0
  39. data/lib/roo/excelx/shared_strings.rb +151 -0
  40. data/lib/roo/excelx/sheet.rb +151 -0
  41. data/lib/roo/excelx/sheet_doc.rb +257 -0
  42. data/lib/roo/excelx/styles.rb +64 -0
  43. data/lib/roo/excelx/workbook.rb +64 -0
  44. data/lib/roo/excelx.rb +407 -601
  45. data/lib/roo/font.rb +17 -0
  46. data/lib/roo/formatters/base.rb +15 -0
  47. data/lib/roo/formatters/csv.rb +84 -0
  48. data/lib/roo/formatters/matrix.rb +23 -0
  49. data/lib/roo/formatters/xml.rb +31 -0
  50. data/lib/roo/formatters/yaml.rb +40 -0
  51. data/lib/roo/helpers/default_attr_reader.rb +20 -0
  52. data/lib/roo/helpers/weak_instance_cache.rb +41 -0
  53. data/lib/roo/libre_office.rb +4 -0
  54. data/lib/roo/link.rb +34 -0
  55. data/lib/roo/open_office.rb +631 -0
  56. data/lib/roo/spreadsheet.rb +28 -23
  57. data/lib/roo/tempdir.rb +24 -0
  58. data/lib/roo/utils.rb +128 -0
  59. data/lib/roo/version.rb +3 -0
  60. data/lib/roo.rb +26 -24
  61. data/roo.gemspec +29 -203
  62. data/spec/helpers.rb +5 -0
  63. data/spec/lib/roo/base_spec.rb +291 -3
  64. data/spec/lib/roo/csv_spec.rb +38 -11
  65. data/spec/lib/roo/excelx/cell/time_spec.rb +15 -0
  66. data/spec/lib/roo/excelx/format_spec.rb +7 -6
  67. data/spec/lib/roo/excelx/relationships_spec.rb +43 -0
  68. data/spec/lib/roo/excelx/sheet_doc_spec.rb +11 -0
  69. data/spec/lib/roo/excelx_spec.rb +672 -11
  70. data/spec/lib/roo/libreoffice_spec.rb +16 -6
  71. data/spec/lib/roo/openoffice_spec.rb +30 -8
  72. data/spec/lib/roo/spreadsheet_spec.rb +60 -12
  73. data/spec/lib/roo/strict_spec.rb +43 -0
  74. data/spec/lib/roo/utils_spec.rb +119 -0
  75. data/spec/lib/roo/weak_instance_cache_spec.rb +92 -0
  76. data/spec/lib/roo_spec.rb +0 -0
  77. data/spec/spec_helper.rb +7 -6
  78. data/test/all_ss.rb +12 -11
  79. data/test/excelx/cell/test_attr_reader_default.rb +72 -0
  80. data/test/excelx/cell/test_base.rb +68 -0
  81. data/test/excelx/cell/test_boolean.rb +36 -0
  82. data/test/excelx/cell/test_date.rb +38 -0
  83. data/test/excelx/cell/test_datetime.rb +45 -0
  84. data/test/excelx/cell/test_empty.rb +18 -0
  85. data/test/excelx/cell/test_number.rb +90 -0
  86. data/test/excelx/cell/test_string.rb +48 -0
  87. data/test/excelx/cell/test_time.rb +30 -0
  88. data/test/excelx/test_coordinate.rb +51 -0
  89. data/test/formatters/test_csv.rb +136 -0
  90. data/test/formatters/test_matrix.rb +76 -0
  91. data/test/formatters/test_xml.rb +78 -0
  92. data/test/formatters/test_yaml.rb +20 -0
  93. data/test/helpers/test_accessing_files.rb +81 -0
  94. data/test/helpers/test_comments.rb +43 -0
  95. data/test/helpers/test_formulas.rb +9 -0
  96. data/test/helpers/test_labels.rb +103 -0
  97. data/test/helpers/test_sheets.rb +55 -0
  98. data/test/helpers/test_styles.rb +62 -0
  99. data/test/roo/test_base.rb +182 -0
  100. data/test/roo/test_csv.rb +88 -0
  101. data/test/roo/test_excelx.rb +360 -0
  102. data/test/roo/test_libre_office.rb +9 -0
  103. data/test/roo/test_open_office.rb +289 -0
  104. data/test/test_helper.rb +123 -59
  105. data/test/test_roo.rb +392 -2292
  106. metadata +153 -298
  107. data/CHANGELOG +0 -417
  108. data/Gemfile.lock +0 -78
  109. data/README.markdown +0 -126
  110. data/VERSION +0 -1
  111. data/lib/roo/excel.rb +0 -355
  112. data/lib/roo/excel2003xml.rb +0 -300
  113. data/lib/roo/google.rb +0 -292
  114. data/lib/roo/openoffice.rb +0 -496
  115. data/lib/roo/roo_rails_helper.rb +0 -83
  116. data/lib/roo/worksheet.rb +0 -18
  117. data/scripts/txt2html +0 -67
  118. data/spec/lib/roo/excel2003xml_spec.rb +0 -15
  119. data/spec/lib/roo/excel_spec.rb +0 -17
  120. data/spec/lib/roo/google_spec.rb +0 -64
  121. data/test/files/1900_base.xls +0 -0
  122. data/test/files/1900_base.xlsx +0 -0
  123. data/test/files/1904_base.xls +0 -0
  124. data/test/files/1904_base.xlsx +0 -0
  125. data/test/files/Bibelbund.csv +0 -3741
  126. data/test/files/Bibelbund.ods +0 -0
  127. data/test/files/Bibelbund.xls +0 -0
  128. data/test/files/Bibelbund.xlsx +0 -0
  129. data/test/files/Bibelbund.xml +0 -62518
  130. data/test/files/Bibelbund1.ods +0 -0
  131. data/test/files/Pfand_from_windows_phone.xlsx +0 -0
  132. data/test/files/bad_excel_date.xls +0 -0
  133. data/test/files/bbu.ods +0 -0
  134. data/test/files/bbu.xls +0 -0
  135. data/test/files/bbu.xlsx +0 -0
  136. data/test/files/bbu.xml +0 -152
  137. data/test/files/bode-v1.ods.zip +0 -0
  138. data/test/files/bode-v1.xls.zip +0 -0
  139. data/test/files/boolean.csv +0 -2
  140. data/test/files/boolean.ods +0 -0
  141. data/test/files/boolean.xls +0 -0
  142. data/test/files/boolean.xlsx +0 -0
  143. data/test/files/boolean.xml +0 -112
  144. data/test/files/borders.ods +0 -0
  145. data/test/files/borders.xls +0 -0
  146. data/test/files/borders.xlsx +0 -0
  147. data/test/files/borders.xml +0 -144
  148. data/test/files/bug-numbered-sheet-names.xlsx +0 -0
  149. data/test/files/bug-row-column-fixnum-float.xls +0 -0
  150. data/test/files/bug-row-column-fixnum-float.xml +0 -127
  151. data/test/files/comments.ods +0 -0
  152. data/test/files/comments.xls +0 -0
  153. data/test/files/comments.xlsx +0 -0
  154. data/test/files/csvtypes.csv +0 -1
  155. data/test/files/datetime.ods +0 -0
  156. data/test/files/datetime.xls +0 -0
  157. data/test/files/datetime.xlsx +0 -0
  158. data/test/files/datetime.xml +0 -142
  159. data/test/files/datetime_floatconv.xls +0 -0
  160. data/test/files/datetime_floatconv.xml +0 -148
  161. data/test/files/dreimalvier.ods +0 -0
  162. data/test/files/emptysheets.ods +0 -0
  163. data/test/files/emptysheets.xls +0 -0
  164. data/test/files/emptysheets.xlsx +0 -0
  165. data/test/files/emptysheets.xml +0 -105
  166. data/test/files/excel2003.xml +0 -21140
  167. data/test/files/false_encoding.xls +0 -0
  168. data/test/files/false_encoding.xml +0 -132
  169. data/test/files/file_item_error.xlsx +0 -0
  170. data/test/files/formula.ods +0 -0
  171. data/test/files/formula.xls +0 -0
  172. data/test/files/formula.xlsx +0 -0
  173. data/test/files/formula.xml +0 -134
  174. data/test/files/formula_parse_error.xls +0 -0
  175. data/test/files/formula_parse_error.xml +0 -1833
  176. data/test/files/formula_string_error.xlsx +0 -0
  177. data/test/files/html-escape.ods +0 -0
  178. data/test/files/link.xls +0 -0
  179. data/test/files/link.xlsx +0 -0
  180. data/test/files/matrix.ods +0 -0
  181. data/test/files/matrix.xls +0 -0
  182. data/test/files/named_cells.ods +0 -0
  183. data/test/files/named_cells.xls +0 -0
  184. data/test/files/named_cells.xlsx +0 -0
  185. data/test/files/no_spreadsheet_file.txt +0 -1
  186. data/test/files/numbers1.csv +0 -18
  187. data/test/files/numbers1.ods +0 -0
  188. data/test/files/numbers1.xls +0 -0
  189. data/test/files/numbers1.xlsx +0 -0
  190. data/test/files/numbers1.xml +0 -312
  191. data/test/files/numeric-link.xlsx +0 -0
  192. data/test/files/only_one_sheet.ods +0 -0
  193. data/test/files/only_one_sheet.xls +0 -0
  194. data/test/files/only_one_sheet.xlsx +0 -0
  195. data/test/files/only_one_sheet.xml +0 -67
  196. data/test/files/paragraph.ods +0 -0
  197. data/test/files/paragraph.xls +0 -0
  198. data/test/files/paragraph.xlsx +0 -0
  199. data/test/files/paragraph.xml +0 -127
  200. data/test/files/prova.xls +0 -0
  201. data/test/files/ric.ods +0 -0
  202. data/test/files/simple_spreadsheet.ods +0 -0
  203. data/test/files/simple_spreadsheet.xls +0 -0
  204. data/test/files/simple_spreadsheet.xlsx +0 -0
  205. data/test/files/simple_spreadsheet.xml +0 -225
  206. data/test/files/simple_spreadsheet_from_italo.ods +0 -0
  207. data/test/files/simple_spreadsheet_from_italo.xls +0 -0
  208. data/test/files/simple_spreadsheet_from_italo.xml +0 -242
  209. data/test/files/so_datetime.csv +0 -7
  210. data/test/files/style.ods +0 -0
  211. data/test/files/style.xls +0 -0
  212. data/test/files/style.xlsx +0 -0
  213. data/test/files/style.xml +0 -154
  214. data/test/files/time-test.csv +0 -2
  215. data/test/files/time-test.ods +0 -0
  216. data/test/files/time-test.xls +0 -0
  217. data/test/files/time-test.xlsx +0 -0
  218. data/test/files/time-test.xml +0 -131
  219. data/test/files/type_excel.ods +0 -0
  220. data/test/files/type_excel.xlsx +0 -0
  221. data/test/files/type_excelx.ods +0 -0
  222. data/test/files/type_excelx.xls +0 -0
  223. data/test/files/type_openoffice.xls +0 -0
  224. data/test/files/type_openoffice.xlsx +0 -0
  225. data/test/files/whitespace.ods +0 -0
  226. data/test/files/whitespace.xls +0 -0
  227. data/test/files/whitespace.xlsx +0 -0
  228. data/test/files/whitespace.xml +0 -184
  229. data/test/rm_sub_test.rb +0 -12
  230. data/test/rm_test.rb +0 -7
  231. data/test/test_generic_spreadsheet.rb +0 -259
  232. data/website/index.html +0 -385
  233. data/website/index.txt +0 -423
  234. data/website/javascripts/rounded_corners_lite.inc.js +0 -285
  235. data/website/stylesheets/screen.css +0 -130
  236. data/website/template.rhtml +0 -48
data/lib/roo/google.rb DELETED
@@ -1,292 +0,0 @@
1
- begin
2
- require "google_drive"
3
- rescue LoadError => e
4
- raise e, "Using Roo::Google requires the google_drive gem"
5
- end
6
-
7
- class Roo::Google < Roo::Base
8
- attr_accessor :date_format, :datetime_format
9
-
10
- # Creates a new Google Drive object.
11
- def initialize(spreadsheet_key, options = {})
12
- @filename = spreadsheet_key
13
- @user = options[:user] || ENV['GOOGLE_MAIL']
14
- @password = options[:password] || ENV['GOOGLE_PASSWORD']
15
- @access_token = options[:access_token] || ENV['GOOGLE_TOKEN']
16
-
17
- @worksheets = session.spreadsheet_by_key(@filename).worksheets
18
- @sheets = @worksheets.map {|sheet| sheet.title }
19
- super
20
- @cell = Hash.new {|h,k| h[k]=Hash.new}
21
- @cell_type = Hash.new {|h,k| h[k]=Hash.new}
22
- @formula = Hash.new
23
- @date_format = '%d/%m/%Y'
24
- @datetime_format = '%d/%m/%Y %H:%M:%S'
25
- @time_format = '%H:%M:%S'
26
- end
27
-
28
- # returns an array of sheet names in the spreadsheet
29
- attr_reader :sheets
30
-
31
- def date?(string)
32
- Date.strptime(string, @date_format)
33
- true
34
- rescue
35
- false
36
- end
37
-
38
- # is String a time with format HH:MM:SS?
39
- def time?(string)
40
- DateTime.strptime(string, @time_format)
41
- true
42
- rescue
43
- false
44
- end
45
-
46
- def datetime?(string)
47
- DateTime.strptime(string, @datetime_format)
48
- true
49
- rescue
50
- false
51
- end
52
-
53
- def numeric?(string)
54
- string =~ /^[0-9]+[\.]*[0-9]*$/
55
- end
56
-
57
- def timestring_to_seconds(value)
58
- hms = value.split(':')
59
- hms[0].to_i*3600 + hms[1].to_i*60 + hms[2].to_i
60
- end
61
-
62
- # Returns the content of a spreadsheet-cell.
63
- # (1,1) is the upper left corner.
64
- # (1,1), (1,'A'), ('A',1), ('a',1) all refers to the
65
- # cell at the first line and first row.
66
- def cell(row, col, sheet=nil)
67
- sheet ||= @default_sheet
68
- validate_sheet!(sheet) #TODO: 2007-12-16
69
- read_cells(sheet)
70
- row,col = normalize(row,col)
71
- value = @cell[sheet]["#{row},#{col}"]
72
- if celltype(row,col,sheet) == :date
73
- begin
74
- return Date.strptime(value, @date_format)
75
- rescue ArgumentError
76
- raise "Invalid Date #{sheet}[#{row},#{col}] #{value} using format '{@date_format}'"
77
- end
78
- elsif celltype(row,col,sheet) == :datetime
79
- begin
80
- return DateTime.strptime(value, @datetime_format)
81
- rescue ArgumentError
82
- raise "Invalid DateTime #{sheet}[#{row},#{col}] #{value} using format '{@datetime_format}'"
83
- end
84
- end
85
- return value
86
- end
87
-
88
- # returns the type of a cell:
89
- # * :float
90
- # * :string
91
- # * :date
92
- # * :percentage
93
- # * :formula
94
- # * :time
95
- # * :datetime
96
- def celltype(row, col, sheet=nil)
97
- sheet ||= @default_sheet
98
- read_cells(sheet)
99
- row,col = normalize(row,col)
100
- if @formula.size > 0 && @formula[sheet]["#{row},#{col}"]
101
- :formula
102
- else
103
- @cell_type[sheet]["#{row},#{col}"]
104
- end
105
- end
106
-
107
- # Returns the formula at (row,col).
108
- # Returns nil if there is no formula.
109
- # The method #formula? checks if there is a formula.
110
- def formula(row,col,sheet=nil)
111
- sheet ||= @default_sheet
112
- read_cells(sheet)
113
- row,col = normalize(row,col)
114
- @formula[sheet]["#{row},#{col}"] && @formula[sheet]["#{row},#{col}"]
115
- end
116
- alias_method :formula?, :formula
117
-
118
- # true, if the cell is empty
119
- def empty?(row, col, sheet=nil)
120
- value = cell(row, col, sheet)
121
- return true unless value
122
- return false if value.class == Date # a date is never empty
123
- return false if value.class == Float
124
- return false if celltype(row,col,sheet) == :time
125
- value.empty?
126
- end
127
-
128
- # sets the cell to the content of 'value'
129
- # a formula can be set in the form of '=SUM(...)'
130
- def set(row,col,value,sheet=nil)
131
- sheet ||= @default_sheet
132
- validate_sheet!(sheet)
133
-
134
- sheet_no = sheets.index(sheet)+1
135
- row,col = normalize(row,col)
136
- add_to_cell_roo(row,col,value,sheet_no)
137
- # re-read the portion of the document that has changed
138
- if @cells_read[sheet]
139
- value, value_type = determine_datatype(value.to_s)
140
-
141
- _set_value(row,col,value,sheet)
142
- set_type(row,col,value_type,sheet)
143
- end
144
- end
145
-
146
- # *DEPRECATED*: Use Roo::Google#set instead
147
- def set_value(row,col,value,sheet=nil)
148
- warn "[DEPRECATION] `set_value` is deprecated. Please use `set` instead."
149
- set(row,col,value,sheet)
150
- end
151
-
152
- # returns the first non-empty row in a sheet
153
- def first_row(sheet=nil)
154
- sheet ||= @default_sheet
155
- unless @first_row[sheet]
156
- sheet_no = sheets.index(sheet) + 1
157
- @first_row[sheet], @last_row[sheet], @first_column[sheet], @last_column[sheet] =
158
- oben_unten_links_rechts(sheet_no)
159
- end
160
- return @first_row[sheet]
161
- end
162
-
163
- # returns the last non-empty row in a sheet
164
- def last_row(sheet=nil)
165
- sheet ||= @default_sheet
166
- unless @last_row[sheet]
167
- sheet_no = sheets.index(sheet) + 1
168
- @first_row[sheet], @last_row[sheet], @first_column[sheet], @last_column[sheet] =
169
- oben_unten_links_rechts(sheet_no)
170
- end
171
- return @last_row[sheet]
172
- end
173
-
174
- # returns the first non-empty column in a sheet
175
- def first_column(sheet=nil)
176
- sheet ||= @default_sheet
177
- unless @first_column[sheet]
178
- sheet_no = sheets.index(sheet) + 1
179
- @first_row[sheet], @last_row[sheet], @first_column[sheet], @last_column[sheet] =
180
- oben_unten_links_rechts(sheet_no)
181
- end
182
- return @first_column[sheet]
183
- end
184
-
185
- # returns the last non-empty column in a sheet
186
- def last_column(sheet=nil)
187
- sheet ||= @default_sheet
188
- unless @last_column[sheet]
189
- sheet_no = sheets.index(sheet) + 1
190
- @first_row[sheet], @last_row[sheet], @first_column[sheet], @last_column[sheet] =
191
- oben_unten_links_rechts(sheet_no)
192
- end
193
- return @last_column[sheet]
194
- end
195
-
196
- private
197
-
198
- def _set_value(row,col,value,sheet=nil)
199
- sheet ||= @default_sheet
200
- @cell[sheet][ "#{row},#{col}"] = value
201
- end
202
-
203
- def set_type(row,col,type,sheet=nil)
204
- sheet ||= @default_sheet
205
- @cell_type[sheet]["#{row},#{col}"] = type
206
- end
207
-
208
- # read all cells in a sheet.
209
- def read_cells(sheet=nil)
210
- sheet ||= @default_sheet
211
- validate_sheet!(sheet)
212
- return if @cells_read[sheet]
213
-
214
- sheet_no = sheets.index(sheet)
215
- ws = @worksheets[sheet_no]
216
- for row in 1..ws.num_rows
217
- for col in 1..ws.num_cols
218
- key = "#{row},#{col}"
219
- string_value = ws.input_value(row,col) # item['inputvalue'] || item['inputValue']
220
- numeric_value = ws[row,col] #item['numericvalue'] || item['numericValue']
221
- (value, value_type) = determine_datatype(string_value, numeric_value)
222
- @cell[sheet][key] = value unless value == "" or value == nil
223
- @cell_type[sheet][key] = value_type
224
- @formula[sheet] = {} unless @formula[sheet]
225
- @formula[sheet][key] = string_value if value_type == :formula
226
- end
227
- end
228
- @cells_read[sheet] = true
229
- end
230
-
231
- def determine_datatype(val, numval=nil)
232
- if val.nil? || val[0,1] == '='
233
- ty = :formula
234
- if numeric?(numval)
235
- val = numval.to_f
236
- else
237
- val = numval
238
- end
239
- else
240
- if datetime?(val)
241
- ty = :datetime
242
- elsif date?(val)
243
- ty = :date
244
- elsif numeric?(val)
245
- ty = :float
246
- val = val.to_f
247
- elsif time?(val)
248
- ty = :time
249
- val = timestring_to_seconds(val)
250
- else
251
- ty = :string
252
- end
253
- end
254
- return val, ty
255
- end
256
-
257
- def add_to_cell_roo(row,col,value, sheet_no=1)
258
- sheet_no -= 1
259
- @worksheets[sheet_no][row,col] = value
260
- @worksheets[sheet_no].save
261
- end
262
- def entry_roo(value,row,col)
263
- return value,row,col
264
- end
265
-
266
- def oben_unten_links_rechts(sheet_no)
267
- ws = @worksheets[sheet_no-1]
268
- rows = []
269
- cols = []
270
- for row in 1..ws.num_rows
271
- for col in 1..ws.num_cols
272
- rows << row if ws[row,col] and ws[row,col] != '' #TODO: besser?
273
- cols << col if ws[row,col] and ws[row,col] != '' #TODO: besser?
274
- end
275
- end
276
- return rows.min, rows.max, cols.min, cols.max
277
- end
278
-
279
- def reinitialize
280
- initialize(@filename, user: @user, password: @password, access_token: @access_token)
281
- end
282
-
283
- def session
284
- @session ||= if @user && @password
285
- GoogleDrive.login(@user, @password)
286
- elsif @access_token
287
- GoogleDrive.login_with_oauth(@access_token)
288
- else
289
- warn 'set user and password or access token'
290
- end
291
- end
292
- end