roo 2.3.0 → 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 (95) 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 +4 -0
  8. data/.rubocop.yml +186 -0
  9. data/CHANGELOG.md +148 -0
  10. data/Gemfile +4 -4
  11. data/LICENSE +2 -0
  12. data/README.md +84 -27
  13. data/Rakefile +1 -1
  14. data/lib/roo/base.rb +111 -237
  15. data/lib/roo/constants.rb +5 -3
  16. data/lib/roo/csv.rb +106 -85
  17. data/lib/roo/errors.rb +2 -0
  18. data/lib/roo/excelx/cell/base.rb +26 -12
  19. data/lib/roo/excelx/cell/boolean.rb +9 -6
  20. data/lib/roo/excelx/cell/date.rb +7 -7
  21. data/lib/roo/excelx/cell/datetime.rb +50 -44
  22. data/lib/roo/excelx/cell/empty.rb +3 -2
  23. data/lib/roo/excelx/cell/number.rb +60 -47
  24. data/lib/roo/excelx/cell/string.rb +3 -3
  25. data/lib/roo/excelx/cell/time.rb +17 -16
  26. data/lib/roo/excelx/cell.rb +11 -7
  27. data/lib/roo/excelx/comments.rb +3 -3
  28. data/lib/roo/excelx/coordinate.rb +11 -4
  29. data/lib/roo/excelx/extractor.rb +20 -3
  30. data/lib/roo/excelx/format.rb +38 -31
  31. data/lib/roo/excelx/images.rb +26 -0
  32. data/lib/roo/excelx/relationships.rb +12 -4
  33. data/lib/roo/excelx/shared.rb +10 -3
  34. data/lib/roo/excelx/shared_strings.rb +113 -9
  35. data/lib/roo/excelx/sheet.rb +49 -10
  36. data/lib/roo/excelx/sheet_doc.rb +101 -48
  37. data/lib/roo/excelx/styles.rb +4 -4
  38. data/lib/roo/excelx/workbook.rb +8 -3
  39. data/lib/roo/excelx.rb +85 -42
  40. data/lib/roo/formatters/base.rb +15 -0
  41. data/lib/roo/formatters/csv.rb +84 -0
  42. data/lib/roo/formatters/matrix.rb +23 -0
  43. data/lib/roo/formatters/xml.rb +31 -0
  44. data/lib/roo/formatters/yaml.rb +40 -0
  45. data/lib/roo/helpers/default_attr_reader.rb +20 -0
  46. data/lib/roo/helpers/weak_instance_cache.rb +41 -0
  47. data/lib/roo/open_office.rb +41 -27
  48. data/lib/roo/spreadsheet.rb +8 -2
  49. data/lib/roo/tempdir.rb +24 -0
  50. data/lib/roo/utils.rb +76 -26
  51. data/lib/roo/version.rb +1 -1
  52. data/lib/roo.rb +5 -0
  53. data/roo.gemspec +22 -12
  54. data/spec/lib/roo/base_spec.rb +65 -3
  55. data/spec/lib/roo/csv_spec.rb +19 -0
  56. data/spec/lib/roo/excelx/cell/time_spec.rb +15 -0
  57. data/spec/lib/roo/excelx/relationships_spec.rb +43 -0
  58. data/spec/lib/roo/excelx/sheet_doc_spec.rb +11 -0
  59. data/spec/lib/roo/excelx_spec.rb +237 -5
  60. data/spec/lib/roo/openoffice_spec.rb +2 -2
  61. data/spec/lib/roo/spreadsheet_spec.rb +1 -1
  62. data/spec/lib/roo/strict_spec.rb +43 -0
  63. data/spec/lib/roo/utils_spec.rb +22 -9
  64. data/spec/lib/roo/weak_instance_cache_spec.rb +92 -0
  65. data/spec/lib/roo_spec.rb +0 -0
  66. data/spec/spec_helper.rb +2 -7
  67. data/test/excelx/cell/test_attr_reader_default.rb +72 -0
  68. data/test/excelx/cell/test_base.rb +6 -2
  69. data/test/excelx/cell/test_boolean.rb +1 -3
  70. data/test/excelx/cell/test_date.rb +1 -6
  71. data/test/excelx/cell/test_datetime.rb +7 -10
  72. data/test/excelx/cell/test_empty.rb +12 -2
  73. data/test/excelx/cell/test_number.rb +28 -4
  74. data/test/excelx/cell/test_string.rb +21 -3
  75. data/test/excelx/cell/test_time.rb +7 -10
  76. data/test/excelx/test_coordinate.rb +51 -0
  77. data/test/formatters/test_csv.rb +136 -0
  78. data/test/formatters/test_matrix.rb +76 -0
  79. data/test/formatters/test_xml.rb +78 -0
  80. data/test/formatters/test_yaml.rb +20 -0
  81. data/test/helpers/test_accessing_files.rb +81 -0
  82. data/test/helpers/test_comments.rb +43 -0
  83. data/test/helpers/test_formulas.rb +9 -0
  84. data/test/helpers/test_labels.rb +103 -0
  85. data/test/helpers/test_sheets.rb +55 -0
  86. data/test/helpers/test_styles.rb +62 -0
  87. data/test/roo/test_base.rb +182 -0
  88. data/test/roo/test_csv.rb +88 -0
  89. data/test/roo/test_excelx.rb +360 -0
  90. data/test/roo/test_libre_office.rb +9 -0
  91. data/test/roo/test_open_office.rb +289 -0
  92. data/test/test_helper.rb +129 -14
  93. data/test/test_roo.rb +60 -1765
  94. metadata +91 -21
  95. data/.travis.yml +0 -14
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Roo
2
2
 
3
- [![Build Status](https://img.shields.io/travis/roo-rb/roo.svg?style=flat-square)](https://travis-ci.org/roo-rb/roo) [![Code Climate](https://img.shields.io/codeclimate/github/roo-rb/roo.svg?style=flat-square)](https://codeclimate.com/github/roo-rb/roo) [![Coverage Status](https://img.shields.io/coveralls/roo-rb/roo.svg?style=flat-square)](https://coveralls.io/r/roo-rb/roo) [![Gem Version](https://img.shields.io/gem/v/roo.svg?style=flat-square)](https://rubygems.org/gems/roo)
3
+ [![Build Status](https://img.shields.io/travis/roo-rb/roo.svg?style=flat-square)](https://travis-ci.org/roo-rb/roo) [![Maintainability](https://api.codeclimate.com/v1/badges/be8d7bf34e2aeaf67c62/maintainability)](https://codeclimate.com/github/roo-rb/roo/maintainability) [![Coverage Status](https://img.shields.io/coveralls/roo-rb/roo.svg?style=flat-square)](https://coveralls.io/r/roo-rb/roo) [![Gem Version](https://img.shields.io/gem/v/roo.svg?style=flat-square)](https://rubygems.org/gems/roo)
4
4
 
5
5
  Roo implements read access for all common spreadsheet types. It can handle:
6
6
  * Excel 2007 - 2013 formats (xlsx, xlsm)
@@ -18,26 +18,41 @@ Install as a gem
18
18
  Or add it to your Gemfile
19
19
 
20
20
  ```ruby
21
- gem 'roo', '~> 2.1.0'
21
+ gem "roo", "~> 2.10.0"
22
22
  ```
23
23
  ## Usage
24
24
 
25
- Opening a spreadsheet
25
+ ### Opening a spreadsheet
26
26
 
27
+ You can use the `Roo::Spreadsheet` class so `roo` automatically detects which [parser class](https://github.com/roo-rb/roo/blob/master/lib/roo.rb#L17) to use for you.
27
28
  ```ruby
28
29
  require 'roo'
29
30
 
30
- xlsx = Roo::Spreadsheet.open('./new_prices.xlsx')
31
- xlsx = Roo::Excelx.new("./new_prices.xlsx")
31
+ file_name = './new_prices.xlsx'
32
+ xlsx = Roo::Spreadsheet.open(file_name)
33
+ xlsx.info
34
+ # => Returns basic info about the spreadsheet file
35
+ ```
32
36
 
33
- # Use the extension option if the extension is ambiguous.
34
- xlsx = Roo::Spreadsheet.open('./rails_temp_upload', extension: :xlsx)
37
+ ``Roo::Spreadsheet.open`` can accept both string paths and ``File`` instances. Also, you can provide the extension of the file as an option:
35
38
 
39
+ ```ruby
40
+ require 'roo'
41
+
42
+ file_name = './rails_temp_upload'
43
+ xlsx = Roo::Spreadsheet.open(file_name, extension: :xlsx)
36
44
  xlsx.info
37
45
  # => Returns basic info about the spreadsheet file
38
46
  ```
39
47
 
40
- ``Roo::Spreadsheet.open`` can accept both paths and ``File`` instances.
48
+ On the other hand, if you know what the file extension is, you can use the specific parser class instead:
49
+ ```ruby
50
+ require 'roo'
51
+
52
+ xlsx = Roo::Excelx.new("./new_prices.xlsx")
53
+ xlsx.info
54
+ # => Returns basic info about the spreadsheet file
55
+ ```
41
56
 
42
57
  ### Working with sheets
43
58
 
@@ -50,7 +65,7 @@ ods.sheet(0).row(1)
50
65
 
51
66
  # Set the last sheet as the default sheet.
52
67
  ods.default_sheet = ods.sheets.last
53
- ods.default_sheet = s.sheets[3]
68
+ ods.default_sheet = ods.sheets[2]
54
69
  ods.default_sheet = 'Sheet 3'
55
70
 
56
71
  # Iterate through each sheet
@@ -89,13 +104,13 @@ sheet.last_column
89
104
  You can access the top-left cell in the following ways
90
105
 
91
106
  ```ruby
92
- s.cell(1,1)
93
- s.cell('A',1)
94
- s.cell(1,'A')
95
- s.a1
107
+ sheet.cell(1,1)
108
+ sheet.cell('A',1)
109
+ sheet.cell(1,'A')
110
+ sheet.a1
96
111
 
97
112
  # Access the second sheet's top-left cell.
98
- s.cell(1,'A',s.sheets[1])
113
+ sheet.cell(1,'A',sheet.sheets[1])
99
114
  ```
100
115
 
101
116
  #### Querying a spreadsheet
@@ -113,8 +128,14 @@ end
113
128
  Use ``sheet.parse`` to return an array of rows. Column names can be a ``String`` or a ``Regexp``.
114
129
 
115
130
  ```ruby
116
- sheet.parse(:id => /UPC|SKU/,:qty => /ATS*\sATP\s*QTY\z/)
117
- # => [{:upc => 727880013358, :qty => 12}, ...]
131
+ sheet.parse(id: /UPC|SKU/, qty: /ATS*\sATP\s*QTY\z/)
132
+ # => [{:id => 727880013358, :qty => 12}, ...]
133
+ ```
134
+
135
+ Use the ``:headers`` option to include the header row in the parsed content.
136
+
137
+ ```ruby
138
+ sheet.parse(headers: true)
118
139
  ```
119
140
 
120
141
  Use the ``:header_search`` option to locate the header row and assign the header names.
@@ -126,7 +147,17 @@ sheet.parse(header_search: [/UPC*SKU/,/ATS*\sATP\s*QTY\z/])
126
147
  Use the ``:clean`` option to strip out control characters and surrounding white space.
127
148
 
128
149
  ```ruby
129
- sheet.parse(:clean => true)
150
+ sheet.parse(clean: true)
151
+ ```
152
+
153
+ #### Options
154
+
155
+ When opening the file you can add a hash of options.
156
+
157
+ ##### expand_merged_ranges
158
+ If you open a document with merged cells and do not want to end up with nil values for the rows after the first one.
159
+ ```ruby
160
+ xlsx = Roo::Excelx.new('./roo_error.xlsx', {:expand_merged_ranges => true})
130
161
  ```
131
162
 
132
163
  ### Exporting spreadsheets
@@ -189,6 +220,9 @@ xlsx.cell(3, 'C')
189
220
  # => 600000383.0
190
221
 
191
222
  xlsx.excelx_value(row,col)
223
+ # => '600000383'
224
+
225
+ xlsx.formatted_value(row,col)
192
226
  # => '0600000383'
193
227
  ```
194
228
 
@@ -206,7 +240,7 @@ Roo::OpenOffice has support for encrypted OpenOffice spreadsheets.
206
240
 
207
241
  ```ruby
208
242
  # Load an encrypted OpenOffice Spreadsheet
209
- ods = Roo::OpenOffice.new("myspreadsheet.ods", :password => "password")
243
+ ods = Roo::OpenOffice.new("myspreadsheet.ods", password: "password")
210
244
  ```
211
245
 
212
246
  ``Roo::OpenOffice`` can access celltype, comments, font information, formulas and labels.
@@ -227,20 +261,32 @@ ods.formula('A', 2)
227
261
 
228
262
  ```ruby
229
263
  # Load a CSV file
230
- s = Roo::CSV.new("mycsv.csv")
264
+ csv = Roo::CSV.new("mycsv.csv")
231
265
  ```
232
266
 
233
- Because Roo uses the [standard CSV library](), you can use options available to that library to parse csv files. You can pass options using the ``csv_options`` key.
267
+ Because Roo uses the standard CSV library, you can use options available to that library to parse csv files. You can pass options using the ``csv_options`` key.
234
268
 
235
269
  For instance, you can load tab-delimited files (``.tsv``), and you can use a particular encoding when opening the file.
236
270
 
237
271
 
238
272
  ```ruby
239
273
  # Load a tab-delimited csv
240
- s = Roo::CSV.new("mytsv.tsv", csv_options: {col_sep: "\t"})
274
+ csv = Roo::CSV.new("mytsv.tsv", csv_options: {col_sep: "\t"})
241
275
 
242
276
  # Load a csv with an explicit encoding
243
- s = Roo::CSV.new("mycsv.csv", csv_options: {encoding: Encoding::ISO_8859_1})
277
+ csv = Roo::CSV.new("mycsv.csv", csv_options: {encoding: Encoding::ISO_8859_1})
278
+ ```
279
+
280
+ You can also open csv files through the Roo::Spreadsheet class (useful if you accept both CSV and Excel types from a user file upload, for example).
281
+
282
+ ```ruby
283
+ # Load a spreadsheet from a file path
284
+ # Roo figures out the right parser based on file extension
285
+ spreadsheet = Roo::Spreadsheet.open(csv_or_xlsx_file)
286
+
287
+ # Load a csv and auto-strip the BOM (byte order mark)
288
+ # csv files saved from MS Excel typically have the BOM marker at the beginning of the file
289
+ spreadsheet = Roo::Spreadsheet.open("mycsv.csv", { csv_options: { encoding: 'bom|utf-8' } })
244
290
  ```
245
291
 
246
292
  ## Upgrading from Roo 1.13.x
@@ -252,11 +298,22 @@ Roo's public methods have stayed relatively consistent between 1.13.x and 2.0.0,
252
298
 
253
299
  ## Contributing
254
300
  ### Features
255
- 1. Fork it ( https://github.com/[my-github-username]/roo/fork )
256
- 2. Create your feature branch (`git checkout -b my-new-feature`)
257
- 3. Commit your changes (`git commit -am 'My new feature'`)
258
- 4. Push to the branch (`git push origin my-new-feature`)
259
- 5. Create a new Pull Request
301
+ 1. Fork it ( https://github.com/roo-rb/roo/fork )
302
+ 2. Install it (`bundle install --with local_development`)
303
+ 3. Create your feature branch (`git checkout -b my-new-feature`)
304
+ 4. Commit your changes (`git commit -am 'My new feature'`)
305
+ 5. Push to the branch (`git push origin my-new-feature`)
306
+ 6. Create a new Pull Request
307
+
308
+ ### Testing
309
+ Roo uses Minitest and RSpec. The best of both worlds! Run `bundle exec rake` to
310
+ run the tests/examples.
311
+
312
+ You can run the tests/examples with Rspec like reporters by running
313
+ `USE_REPORTERS=true bundle exec rake`
314
+
315
+ Roo also has a few tests that take a long time (5+ seconds). To run these, use
316
+ `LONG_RUN=true bundle exec rake`
260
317
 
261
318
  ### Issues
262
319
 
data/Rakefile CHANGED
@@ -7,7 +7,7 @@ require 'coveralls/rake/task'
7
7
  # Test unit
8
8
  Rake::TestTask.new do |t|
9
9
  t.libs << 'test'
10
- t.test_files = FileList['test/test*.rb']
10
+ t.test_files = FileList['test/**/test*.rb']
11
11
  t.verbose = true
12
12
  end
13
13