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/font.rb ADDED
@@ -0,0 +1,17 @@
1
+ module Roo
2
+ class Font
3
+ attr_accessor :bold, :italic, :underline
4
+
5
+ def bold?
6
+ @bold
7
+ end
8
+
9
+ def italic?
10
+ @italic
11
+ end
12
+
13
+ def underline?
14
+ @underline
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,15 @@
1
+ module Roo
2
+ module Formatters
3
+ module Base
4
+ # converts an integer value to a time string like '02:05:06'
5
+ def integer_to_timestring(content)
6
+ h = (content / 3600.0).floor
7
+ content -= h * 3600
8
+ m = (content / 60.0).floor
9
+ content -= m * 60
10
+ s = content
11
+ Kernel.format("%02d:%02d:%02d", h, m, s)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,84 @@
1
+ module Roo
2
+ module Formatters
3
+ module CSV
4
+ def to_csv(filename = nil, separator = ",", sheet = default_sheet)
5
+ if filename
6
+ File.open(filename, "w") do |file|
7
+ write_csv_content(file, sheet, separator)
8
+ end
9
+ true
10
+ else
11
+ sio = ::StringIO.new
12
+ write_csv_content(sio, sheet, separator)
13
+ sio.rewind
14
+ sio.read
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ # Write all cells to the csv file. File can be a filename or nil. If the
21
+ # file argument is nil the output goes to STDOUT
22
+ def write_csv_content(file = nil, sheet = nil, separator = ",")
23
+ file ||= STDOUT
24
+ return unless first_row(sheet) # The sheet is empty
25
+
26
+ 1.upto(last_row(sheet)) do |row|
27
+ 1.upto(last_column(sheet)) do |col|
28
+ # TODO: use CSV.generate_line
29
+ file.print(separator) if col > 1
30
+ file.print cell_to_csv(row, col, sheet)
31
+ end
32
+ file.print("\n")
33
+ end
34
+ end
35
+
36
+ # The content of a cell in the csv output
37
+ def cell_to_csv(row, col, sheet)
38
+ return "" if empty?(row, col, sheet)
39
+
40
+ onecell = cell(row, col, sheet)
41
+
42
+ case celltype(row, col, sheet)
43
+ when :string
44
+ %("#{onecell.gsub('"', '""')}") unless onecell.empty?
45
+ when :boolean
46
+ # TODO: this only works for excelx
47
+ onecell = self.sheet_for(sheet).cells[[row, col]].formatted_value
48
+ %("#{onecell.gsub('"', '""').downcase}")
49
+ when :float, :percentage
50
+ if onecell == onecell.to_i
51
+ onecell.to_i.to_s
52
+ else
53
+ onecell.to_s
54
+ end
55
+ when :formula
56
+ case onecell
57
+ when String
58
+ %("#{onecell.gsub('"', '""')}") unless onecell.empty?
59
+ when Integer
60
+ onecell.to_s
61
+ when Float
62
+ if onecell == onecell.to_i
63
+ onecell.to_i.to_s
64
+ else
65
+ onecell.to_s
66
+ end
67
+ when Date, DateTime, TrueClass, FalseClass
68
+ onecell.to_s
69
+ else
70
+ fail "unhandled onecell-class #{onecell.class}"
71
+ end
72
+ when :date, :datetime
73
+ onecell.to_s
74
+ when :time
75
+ integer_to_timestring(onecell)
76
+ when :link
77
+ %("#{onecell.url.gsub('"', '""')}")
78
+ else
79
+ fail "unhandled celltype #{celltype(row, col, sheet)}"
80
+ end || ""
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,23 @@
1
+ module Roo
2
+ module Formatters
3
+ module Matrix
4
+ # returns a matrix object from the whole sheet or a rectangular area of a sheet
5
+ def to_matrix(from_row = nil, from_column = nil, to_row = nil, to_column = nil, sheet = default_sheet)
6
+ require 'matrix'
7
+
8
+ return ::Matrix.empty unless first_row
9
+
10
+ from_row ||= first_row(sheet)
11
+ to_row ||= last_row(sheet)
12
+ from_column ||= first_column(sheet)
13
+ to_column ||= last_column(sheet)
14
+
15
+ ::Matrix.rows(from_row.upto(to_row).map do |row|
16
+ from_column.upto(to_column).map do |col|
17
+ cell(row, col, sheet)
18
+ end
19
+ end)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,31 @@
1
+ # returns an XML representation of all sheets of a spreadsheet file
2
+ module Roo
3
+ module Formatters
4
+ module XML
5
+ def to_xml
6
+ Nokogiri::XML::Builder.new do |xml|
7
+ xml.spreadsheet do
8
+ sheets.each do |sheet|
9
+ self.default_sheet = sheet
10
+ xml.sheet(name: sheet) do |x|
11
+ if first_row && last_row && first_column && last_column
12
+ # sonst gibt es Fehler bei leeren Blaettern
13
+ first_row.upto(last_row) do |row|
14
+ first_column.upto(last_column) do |col|
15
+ next if empty?(row, col)
16
+
17
+ x.cell(cell(row, col),
18
+ row: row,
19
+ column: col,
20
+ type: celltype(row, col))
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end.to_xml
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,40 @@
1
+ module Roo
2
+ module Formatters
3
+ module YAML
4
+ # returns a rectangular area (default: all cells) as yaml-output
5
+ # you can add additional attributes with the prefix parameter like:
6
+ # oo.to_yaml({"file"=>"flightdata_2007-06-26", "sheet" => "1"})
7
+ def to_yaml(prefix = {}, from_row = nil, from_column = nil, to_row = nil, to_column = nil, sheet = default_sheet)
8
+ # return an empty string if there is no first_row, i.e. the sheet is empty
9
+ return "" unless first_row
10
+
11
+ from_row ||= first_row(sheet)
12
+ to_row ||= last_row(sheet)
13
+ from_column ||= first_column(sheet)
14
+ to_column ||= last_column(sheet)
15
+
16
+ result = "--- \n"
17
+ from_row.upto(to_row) do |row|
18
+ from_column.upto(to_column) do |col|
19
+ next if empty?(row, col, sheet)
20
+
21
+ result << "cell_#{row}_#{col}: \n"
22
+ prefix.each do|k, v|
23
+ result << " #{k}: #{v} \n"
24
+ end
25
+ result << " row: #{row} \n"
26
+ result << " col: #{col} \n"
27
+ result << " celltype: #{celltype(row, col, sheet)} \n"
28
+ value = cell(row, col, sheet)
29
+ if celltype(row, col, sheet) == :time
30
+ value = integer_to_timestring(value)
31
+ end
32
+ result << " value: #{value} \n"
33
+ end
34
+ end
35
+
36
+ result
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Roo
4
+ module Helpers
5
+ module DefaultAttrReader
6
+ def attr_reader_with_default(attr_hash)
7
+ attr_hash.each do |attr_name, default_value|
8
+ instance_variable = :"@#{attr_name}"
9
+ define_method attr_name do
10
+ if instance_variable_defined? instance_variable
11
+ instance_variable_get instance_variable
12
+ else
13
+ default_value
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "weakref"
4
+
5
+ module Roo
6
+ module Helpers
7
+ module WeakInstanceCache
8
+ private
9
+
10
+ def instance_cache(key)
11
+ object = nil
12
+
13
+ if instance_variable_defined?(key) && (ref = instance_variable_get(key)) && ref.weakref_alive?
14
+ begin
15
+ object = ref.__getobj__
16
+ rescue => e
17
+ unless (defined?(::WeakRef::RefError) && e.is_a?(::WeakRef::RefError)) || (defined?(RefError) && e.is_a?(RefError))
18
+ raise e
19
+ end
20
+ end
21
+ end
22
+
23
+ unless object
24
+ object = yield
25
+ ObjectSpace.define_finalizer(object, instance_cache_finalizer(key))
26
+ instance_variable_set(key, WeakRef.new(object))
27
+ end
28
+
29
+ object
30
+ end
31
+
32
+ def instance_cache_finalizer(key)
33
+ proc do |object_id|
34
+ if instance_variable_defined?(key) && (ref = instance_variable_get(key)) && (!ref.weakref_alive? || ref.__getobj__.object_id == object_id)
35
+ remove_instance_variable(key)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,4 @@
1
+ require 'roo/open_office'
2
+
3
+ # LibreOffice is just an alias for Roo::OpenOffice class
4
+ Roo::LibreOffice = Roo::OpenOffice
data/lib/roo/link.rb ADDED
@@ -0,0 +1,34 @@
1
+ require 'uri'
2
+
3
+ module Roo
4
+ class Link < String
5
+ # FIXME: Roo::Link inherits from String. A link cell is_a?(Roo::Link). **It is
6
+ # the only situation where a cells `value` is always a String**. Link
7
+ # cells have a nifty `to_uri` method, but this method isn't easily
8
+ # reached. (e.g. `sheet.sheet_for(nil).cells[[row,column]]).value.to_uri`;
9
+ # `sheet.hyperlink(row, column)` doesn't use `to_uri`).
10
+ #
11
+ # 1. Add different types of links (String, Numeric, Date, DateTime, etc.)
12
+ # 2. Remove Roo::Link.
13
+ # 3. Don't inherit the string and pass the cell's value.
14
+ #
15
+ # I don't know the historical reasons for the Roo::Link, but right now
16
+ # it seems uneccessary. I'm in favor of keeping it just in case.
17
+ #
18
+ # I'm also in favor of passing the cell's value to Roo::Link. The
19
+ # cell.value's class would still be Roo::Link, but the value itself
20
+ # would depend on what type of cell it is (Numeric, Date, etc.).
21
+ #
22
+ attr_reader :href
23
+ alias_method :url, :href
24
+
25
+ def initialize(href = '', text = href)
26
+ super(text)
27
+ @href = href
28
+ end
29
+
30
+ def to_uri
31
+ URI.parse href
32
+ end
33
+ end
34
+ end