roo 2.6.0 → 2.8.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.codeclimate.yml +17 -0
- data/.github/issue_template.md +16 -0
- data/.github/pull_request_template.md +14 -0
- data/.rubocop.yml +186 -0
- data/.travis.yml +14 -11
- data/CHANGELOG.md +64 -2
- data/Gemfile +2 -4
- data/LICENSE +2 -0
- data/README.md +36 -10
- data/lib/roo/base.rb +82 -225
- data/lib/roo/constants.rb +5 -3
- data/lib/roo/csv.rb +100 -97
- data/lib/roo/excelx/cell/base.rb +26 -12
- data/lib/roo/excelx/cell/boolean.rb +9 -6
- data/lib/roo/excelx/cell/date.rb +7 -7
- data/lib/roo/excelx/cell/datetime.rb +50 -44
- data/lib/roo/excelx/cell/empty.rb +3 -2
- data/lib/roo/excelx/cell/number.rb +44 -47
- data/lib/roo/excelx/cell/string.rb +3 -3
- data/lib/roo/excelx/cell/time.rb +17 -16
- data/lib/roo/excelx/cell.rb +10 -6
- data/lib/roo/excelx/comments.rb +3 -3
- data/lib/roo/excelx/coordinate.rb +11 -4
- data/lib/roo/excelx/extractor.rb +21 -3
- data/lib/roo/excelx/format.rb +38 -31
- data/lib/roo/excelx/images.rb +26 -0
- data/lib/roo/excelx/relationships.rb +12 -4
- data/lib/roo/excelx/shared.rb +10 -3
- data/lib/roo/excelx/shared_strings.rb +9 -15
- data/lib/roo/excelx/sheet.rb +49 -10
- data/lib/roo/excelx/sheet_doc.rb +89 -48
- data/lib/roo/excelx/styles.rb +3 -3
- data/lib/roo/excelx/workbook.rb +7 -3
- data/lib/roo/excelx.rb +50 -19
- data/lib/roo/formatters/base.rb +15 -0
- data/lib/roo/formatters/csv.rb +84 -0
- data/lib/roo/formatters/matrix.rb +23 -0
- data/lib/roo/formatters/xml.rb +31 -0
- data/lib/roo/formatters/yaml.rb +40 -0
- data/lib/roo/helpers/default_attr_reader.rb +20 -0
- data/lib/roo/helpers/weak_instance_cache.rb +41 -0
- data/lib/roo/open_office.rb +17 -9
- data/lib/roo/spreadsheet.rb +1 -1
- data/lib/roo/tempdir.rb +5 -10
- data/lib/roo/utils.rb +70 -20
- data/lib/roo/version.rb +1 -1
- data/lib/roo.rb +4 -1
- data/roo.gemspec +14 -11
- data/spec/lib/roo/base_spec.rb +45 -3
- data/spec/lib/roo/excelx/relationships_spec.rb +43 -0
- data/spec/lib/roo/excelx/sheet_doc_spec.rb +11 -0
- data/spec/lib/roo/excelx_spec.rb +150 -31
- data/spec/lib/roo/strict_spec.rb +43 -0
- data/spec/lib/roo/utils_spec.rb +25 -3
- data/spec/lib/roo/weak_instance_cache_spec.rb +92 -0
- data/spec/lib/roo_spec.rb +0 -0
- data/spec/spec_helper.rb +2 -6
- data/test/excelx/cell/test_attr_reader_default.rb +72 -0
- data/test/excelx/cell/test_base.rb +5 -0
- data/test/excelx/cell/test_datetime.rb +6 -6
- data/test/excelx/cell/test_empty.rb +11 -0
- data/test/excelx/cell/test_number.rb +9 -0
- data/test/excelx/cell/test_string.rb +20 -0
- data/test/excelx/cell/test_time.rb +5 -5
- data/test/excelx/test_coordinate.rb +51 -0
- data/test/formatters/test_csv.rb +136 -0
- data/test/formatters/test_matrix.rb +76 -0
- data/test/formatters/test_xml.rb +78 -0
- data/test/formatters/test_yaml.rb +20 -0
- data/test/helpers/test_accessing_files.rb +60 -0
- data/test/helpers/test_comments.rb +43 -0
- data/test/helpers/test_formulas.rb +9 -0
- data/test/helpers/test_labels.rb +103 -0
- data/test/helpers/test_sheets.rb +55 -0
- data/test/helpers/test_styles.rb +62 -0
- data/test/roo/test_base.rb +182 -0
- data/test/roo/test_csv.rb +88 -0
- data/test/roo/test_excelx.rb +330 -0
- data/test/roo/test_libre_office.rb +9 -0
- data/test/roo/test_open_office.rb +289 -0
- data/test/test_helper.rb +129 -14
- data/test/test_roo.rb +32 -1787
- metadata +81 -29
- data/.github/ISSUE_TEMPLATE +0 -10
- data/Gemfile_ruby2 +0 -29
@@ -2,12 +2,12 @@ module Roo
|
|
2
2
|
class Excelx
|
3
3
|
class Cell
|
4
4
|
class String < Cell::Base
|
5
|
-
attr_reader :value, :formula, :format, :
|
5
|
+
attr_reader :value, :formula, :format, :cell_value, :coordinate
|
6
|
+
|
7
|
+
attr_reader_with_default default_type: :string, cell_type: :string
|
6
8
|
|
7
9
|
def initialize(value, formula, style, link, coordinate)
|
8
10
|
super(value, formula, nil, style, link, coordinate)
|
9
|
-
@type = @cell_type = :string
|
10
|
-
@value = link? ? Roo::Link.new(link, value) : value
|
11
11
|
end
|
12
12
|
|
13
13
|
def empty?
|
data/lib/roo/excelx/cell/time.rb
CHANGED
@@ -4,15 +4,16 @@ module Roo
|
|
4
4
|
class Excelx
|
5
5
|
class Cell
|
6
6
|
class Time < Roo::Excelx::Cell::DateTime
|
7
|
-
attr_reader :value, :formula, :format, :cell_value, :
|
7
|
+
attr_reader :value, :formula, :format, :cell_value, :coordinate
|
8
|
+
|
9
|
+
attr_reader_with_default default_type: :time
|
8
10
|
|
9
11
|
def initialize(value, formula, excelx_type, style, link, base_date, coordinate)
|
10
12
|
# NOTE: Pass all arguments to DateTime super class.
|
11
13
|
super
|
12
|
-
@type = :time
|
13
14
|
@format = excelx_type.last
|
14
15
|
@datetime = create_datetime(base_date, value)
|
15
|
-
@value = link
|
16
|
+
@value = link ? Roo::Link.new(link, value) : (value.to_f * 86_400).to_i
|
16
17
|
end
|
17
18
|
|
18
19
|
def formatted_value
|
@@ -24,19 +25,19 @@ module Roo
|
|
24
25
|
|
25
26
|
private
|
26
27
|
|
27
|
-
def create_datetime(base_date, value)
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
end
|
34
|
-
|
35
|
-
def round_datetime(datetime_string)
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
end
|
28
|
+
# def create_datetime(base_date, value)
|
29
|
+
# date = base_date + value.to_f.round(6)
|
30
|
+
# datetime_string = date.strftime('%Y-%m-%d %H:%M:%S.%N')
|
31
|
+
# t = round_datetime(datetime_string)
|
32
|
+
#
|
33
|
+
# ::DateTime.civil(t.year, t.month, t.day, t.hour, t.min, t.sec)
|
34
|
+
# end
|
35
|
+
|
36
|
+
# def round_datetime(datetime_string)
|
37
|
+
# /(?<yyyy>\d+)-(?<mm>\d+)-(?<dd>\d+) (?<hh>\d+):(?<mi>\d+):(?<ss>\d+.\d+)/ =~ datetime_string
|
38
|
+
#
|
39
|
+
# ::Time.new(yyyy.to_i, mm.to_i, dd.to_i, hh.to_i, mi.to_i, ss.to_r).round(0)
|
40
|
+
# end
|
40
41
|
end
|
41
42
|
end
|
42
43
|
end
|
data/lib/roo/excelx/cell.rb
CHANGED
@@ -40,19 +40,23 @@ module Roo
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def self.create_cell(type, *values)
|
43
|
+
cell_class(type)&.new(*values)
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.cell_class(type)
|
43
47
|
case type
|
44
48
|
when :string
|
45
|
-
Cell::String
|
49
|
+
Cell::String
|
46
50
|
when :boolean
|
47
|
-
Cell::Boolean
|
51
|
+
Cell::Boolean
|
48
52
|
when :number
|
49
|
-
Cell::Number
|
53
|
+
Cell::Number
|
50
54
|
when :date
|
51
|
-
Cell::Date
|
55
|
+
Cell::Date
|
52
56
|
when :datetime
|
53
|
-
Cell::DateTime
|
57
|
+
Cell::DateTime
|
54
58
|
when :time
|
55
|
-
Cell::Time
|
59
|
+
Cell::Time
|
56
60
|
end
|
57
61
|
end
|
58
62
|
|
data/lib/roo/excelx/comments.rb
CHANGED
@@ -12,10 +12,10 @@ module Roo
|
|
12
12
|
def extract_comments
|
13
13
|
return {} unless doc_exists?
|
14
14
|
|
15
|
-
|
15
|
+
doc.xpath('//comments/commentList/comment').each_with_object({}) do |comment, hash|
|
16
16
|
value = (comment.at_xpath('./text/r/t') || comment.at_xpath('./text/t')).text
|
17
|
-
[::Roo::Utils.ref_to_key(comment
|
18
|
-
end
|
17
|
+
hash[::Roo::Utils.ref_to_key(comment['ref'].to_s)] = value
|
18
|
+
end
|
19
19
|
end
|
20
20
|
end
|
21
21
|
end
|
@@ -1,11 +1,18 @@
|
|
1
1
|
module Roo
|
2
2
|
class Excelx
|
3
|
-
class Coordinate
|
4
|
-
attr_accessor :row, :column
|
3
|
+
class Coordinate < ::Array
|
5
4
|
|
6
5
|
def initialize(row, column)
|
7
|
-
|
8
|
-
|
6
|
+
super() << row << column
|
7
|
+
freeze
|
8
|
+
end
|
9
|
+
|
10
|
+
def row
|
11
|
+
self[0]
|
12
|
+
end
|
13
|
+
|
14
|
+
def column
|
15
|
+
self[1]
|
9
16
|
end
|
10
17
|
end
|
11
18
|
end
|
data/lib/roo/excelx/extractor.rb
CHANGED
@@ -1,16 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "roo/helpers/weak_instance_cache"
|
4
|
+
|
1
5
|
module Roo
|
2
6
|
class Excelx
|
3
7
|
class Extractor
|
4
|
-
|
8
|
+
include Roo::Helpers::WeakInstanceCache
|
9
|
+
|
10
|
+
COMMON_STRINGS = {
|
11
|
+
t: "t",
|
12
|
+
r: "r",
|
13
|
+
s: "s",
|
14
|
+
ref: "ref",
|
15
|
+
html_tag_open: "<html>",
|
16
|
+
html_tag_closed: "</html>"
|
17
|
+
}
|
18
|
+
|
19
|
+
def initialize(path, options = {})
|
5
20
|
@path = path
|
21
|
+
@options = options
|
6
22
|
end
|
7
23
|
|
8
24
|
private
|
9
25
|
|
10
26
|
def doc
|
11
|
-
|
27
|
+
instance_cache(:@doc) do
|
28
|
+
raise FileNotFound, "#{@path} file not found" unless doc_exists?
|
12
29
|
|
13
|
-
|
30
|
+
::Roo::Utils.load_xml(@path).remove_namespaces!
|
31
|
+
end
|
14
32
|
end
|
15
33
|
|
16
34
|
def doc_exists?
|
data/lib/roo/excelx/format.rb
CHANGED
@@ -1,49 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Roo
|
2
4
|
class Excelx
|
3
5
|
module Format
|
6
|
+
extend self
|
4
7
|
EXCEPTIONAL_FORMATS = {
|
5
8
|
'h:mm am/pm' => :date,
|
6
9
|
'h:mm:ss am/pm' => :date
|
7
10
|
}
|
8
11
|
|
9
12
|
STANDARD_FORMATS = {
|
10
|
-
0 => 'General'
|
11
|
-
1 => '0'
|
12
|
-
2 => '0.00'
|
13
|
-
3 => '#,##0'
|
14
|
-
4 => '#,##0.00'
|
15
|
-
9 => '0%'
|
16
|
-
10 => '0.00%'
|
17
|
-
11 => '0.00E+00'
|
18
|
-
12 => '# ?/?'
|
19
|
-
13 => '# ??/??'
|
20
|
-
14 => 'mm-dd-yy'
|
21
|
-
15 => 'd-mmm-yy'
|
22
|
-
16 => 'd-mmm'
|
23
|
-
17 => 'mmm-yy'
|
24
|
-
18 => 'h:mm AM/PM'
|
25
|
-
19 => 'h:mm:ss AM/PM'
|
26
|
-
20 => 'h:mm'
|
27
|
-
21 => 'h:mm:ss'
|
28
|
-
22 => 'm/d/yy h:mm'
|
29
|
-
37 => '#,##0 ;(#,##0)'
|
30
|
-
38 => '#,##0 ;[Red](#,##0)'
|
31
|
-
39 => '#,##0.00;(#,##0.00)'
|
32
|
-
40 => '#,##0.00;[Red](#,##0.00)'
|
33
|
-
45 => 'mm:ss'
|
34
|
-
46 => '[h]:mm:ss'
|
35
|
-
47 => 'mmss.0'
|
36
|
-
48 => '##0.0E+0'
|
37
|
-
49 => '@'
|
13
|
+
0 => 'General',
|
14
|
+
1 => '0',
|
15
|
+
2 => '0.00',
|
16
|
+
3 => '#,##0',
|
17
|
+
4 => '#,##0.00',
|
18
|
+
9 => '0%',
|
19
|
+
10 => '0.00%',
|
20
|
+
11 => '0.00E+00',
|
21
|
+
12 => '# ?/?',
|
22
|
+
13 => '# ??/??',
|
23
|
+
14 => 'mm-dd-yy',
|
24
|
+
15 => 'd-mmm-yy',
|
25
|
+
16 => 'd-mmm',
|
26
|
+
17 => 'mmm-yy',
|
27
|
+
18 => 'h:mm AM/PM',
|
28
|
+
19 => 'h:mm:ss AM/PM',
|
29
|
+
20 => 'h:mm',
|
30
|
+
21 => 'h:mm:ss',
|
31
|
+
22 => 'm/d/yy h:mm',
|
32
|
+
37 => '#,##0 ;(#,##0)',
|
33
|
+
38 => '#,##0 ;[Red](#,##0)',
|
34
|
+
39 => '#,##0.00;(#,##0.00)',
|
35
|
+
40 => '#,##0.00;[Red](#,##0.00)',
|
36
|
+
45 => 'mm:ss',
|
37
|
+
46 => '[h]:mm:ss',
|
38
|
+
47 => 'mmss.0',
|
39
|
+
48 => '##0.0E+0',
|
40
|
+
49 => '@'
|
38
41
|
}
|
39
42
|
|
40
43
|
def to_type(format)
|
44
|
+
@to_type ||= {}
|
45
|
+
@to_type[format] ||= _to_type(format)
|
46
|
+
end
|
47
|
+
|
48
|
+
def _to_type(format)
|
41
49
|
format = format.to_s.downcase
|
42
50
|
if (type = EXCEPTIONAL_FORMATS[format])
|
43
51
|
type
|
44
52
|
elsif format.include?('#')
|
45
53
|
:float
|
46
|
-
elsif !format.match(/d+(?![\]])/).nil?
|
54
|
+
elsif format.include?('y') || !format.match(/d+(?![\]])/).nil?
|
47
55
|
if format.include?('h') || format.include?('s')
|
48
56
|
:datetime
|
49
57
|
else
|
@@ -58,7 +66,6 @@ module Roo
|
|
58
66
|
end
|
59
67
|
end
|
60
68
|
|
61
|
-
module_function :to_type
|
62
69
|
end
|
63
|
-
end
|
70
|
+
end
|
64
71
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'roo/excelx/extractor'
|
2
|
+
|
3
|
+
module Roo
|
4
|
+
class Excelx
|
5
|
+
class Images < Excelx::Extractor
|
6
|
+
|
7
|
+
# Returns: Hash { id1: extracted_file_name1 },
|
8
|
+
# Example: { "rId1"=>"roo_media_image1.png",
|
9
|
+
# "rId2"=>"roo_media_image2.png",
|
10
|
+
# "rId3"=>"roo_media_image3.png" }
|
11
|
+
def list
|
12
|
+
@images ||= extract_images_names
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def extract_images_names
|
18
|
+
return {} unless doc_exists?
|
19
|
+
|
20
|
+
doc.xpath('/Relationships/Relationship').each_with_object({}) do |rel, hash|
|
21
|
+
hash[rel['Id']] = "roo" + rel['Target'].gsub(/\.\.\/|\//, '_')
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'roo/excelx/extractor'
|
2
4
|
|
3
5
|
module Roo
|
@@ -11,14 +13,20 @@ module Roo
|
|
11
13
|
@relationships ||= extract_relationships
|
12
14
|
end
|
13
15
|
|
16
|
+
def include_type?(type)
|
17
|
+
to_a.any? do |_, rel|
|
18
|
+
rel["Type"]&.include? type
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
14
22
|
private
|
15
23
|
|
16
24
|
def extract_relationships
|
17
|
-
return
|
25
|
+
return {} unless doc_exists?
|
18
26
|
|
19
|
-
|
20
|
-
[rel
|
21
|
-
end
|
27
|
+
doc.xpath('/Relationships/Relationship').each_with_object({}) do |rel, hash|
|
28
|
+
hash[rel['Id']] = rel
|
29
|
+
end
|
22
30
|
end
|
23
31
|
end
|
24
32
|
end
|
data/lib/roo/excelx/shared.rb
CHANGED
@@ -4,12 +4,15 @@ module Roo
|
|
4
4
|
# reduce memory usage and reduce the number of objects being passed
|
5
5
|
# to various inititializers.
|
6
6
|
class Shared
|
7
|
-
attr_accessor :comments_files, :sheet_files, :rels_files
|
8
|
-
def initialize(dir)
|
7
|
+
attr_accessor :comments_files, :sheet_files, :rels_files, :image_rels, :image_files
|
8
|
+
def initialize(dir, options = {})
|
9
9
|
@dir = dir
|
10
10
|
@comments_files = []
|
11
11
|
@sheet_files = []
|
12
12
|
@rels_files = []
|
13
|
+
@options = options
|
14
|
+
@image_rels = []
|
15
|
+
@image_files = []
|
13
16
|
end
|
14
17
|
|
15
18
|
def styles
|
@@ -17,7 +20,7 @@ module Roo
|
|
17
20
|
end
|
18
21
|
|
19
22
|
def shared_strings
|
20
|
-
@shared_strings ||= SharedStrings.new(File.join(@dir, 'roo_sharedStrings.xml'))
|
23
|
+
@shared_strings ||= SharedStrings.new(File.join(@dir, 'roo_sharedStrings.xml'), @options)
|
21
24
|
end
|
22
25
|
|
23
26
|
def workbook
|
@@ -27,6 +30,10 @@ module Roo
|
|
27
30
|
def base_date
|
28
31
|
workbook.base_date
|
29
32
|
end
|
33
|
+
|
34
|
+
def base_timestamp
|
35
|
+
workbook.base_timestamp
|
36
|
+
end
|
30
37
|
end
|
31
38
|
end
|
32
39
|
end
|
@@ -1,16 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'roo/excelx/extractor'
|
2
4
|
|
3
5
|
module Roo
|
4
6
|
class Excelx
|
5
7
|
class SharedStrings < Excelx::Extractor
|
6
|
-
|
7
|
-
COMMON_STRINGS = {
|
8
|
-
t: "t",
|
9
|
-
r: "r",
|
10
|
-
html_tag_open: "<html>",
|
11
|
-
html_tag_closed: "</html>"
|
12
|
-
}
|
13
|
-
|
14
8
|
def [](index)
|
15
9
|
to_a[index]
|
16
10
|
end
|
@@ -26,6 +20,7 @@ module Roo
|
|
26
20
|
# Use to_html or to_a for html returns
|
27
21
|
# See what is happening with commit???
|
28
22
|
def use_html?(index)
|
23
|
+
return false if @options[:disable_html_wrapper]
|
29
24
|
to_html[index][/<([biu]|sup|sub)>/]
|
30
25
|
end
|
31
26
|
|
@@ -45,7 +40,7 @@ module Roo
|
|
45
40
|
document = fix_invalid_shared_strings(doc)
|
46
41
|
# read the shared strings xml document
|
47
42
|
document.xpath('/sst/si').map do |si|
|
48
|
-
shared_string =
|
43
|
+
shared_string = +""
|
49
44
|
si.children.each do |elem|
|
50
45
|
case elem.name
|
51
46
|
when 'r'
|
@@ -65,7 +60,7 @@ module Roo
|
|
65
60
|
fix_invalid_shared_strings(doc)
|
66
61
|
# read the shared strings xml document
|
67
62
|
doc.xpath('/sst/si').map do |si|
|
68
|
-
html_string = '<html>'
|
63
|
+
html_string = '<html>'.dup
|
69
64
|
si.children.each do |elem|
|
70
65
|
case elem.name
|
71
66
|
when 'r'
|
@@ -95,7 +90,7 @@ module Roo
|
|
95
90
|
#
|
96
91
|
# Expected Output ::: "<html><sub|sup><b><i><u>TEXT</u></i></b></sub|/sup></html>"
|
97
92
|
def extract_html_r(r_elem)
|
98
|
-
str =
|
93
|
+
str = +""
|
99
94
|
xml_elems = {
|
100
95
|
sub: false,
|
101
96
|
sup: false,
|
@@ -103,7 +98,6 @@ module Roo
|
|
103
98
|
i: false,
|
104
99
|
u: false
|
105
100
|
}
|
106
|
-
b, i, u, sub, sup = false, false, false, false, false
|
107
101
|
r_elem.children.each do |elem|
|
108
102
|
case elem.name
|
109
103
|
when 'rPr'
|
@@ -141,13 +135,13 @@ module Roo
|
|
141
135
|
|
142
136
|
# This will return an html string
|
143
137
|
def create_html(text, formatting)
|
144
|
-
tmp_str =
|
138
|
+
tmp_str = +""
|
145
139
|
formatting.each do |elem, val|
|
146
140
|
tmp_str << "<#{elem}>" if val
|
147
141
|
end
|
148
142
|
tmp_str << text
|
149
|
-
|
150
|
-
|
143
|
+
|
144
|
+
formatting.reverse_each do |elem, val|
|
151
145
|
tmp_str << "</#{elem}>" if val
|
152
146
|
end
|
153
147
|
tmp_str
|
data/lib/roo/excelx/sheet.rb
CHANGED
@@ -4,11 +4,15 @@ module Roo
|
|
4
4
|
class Sheet
|
5
5
|
extend Forwardable
|
6
6
|
|
7
|
-
delegate [:styles, :workbook, :shared_strings, :rels_files, :sheet_files, :comments_files] => :@shared
|
7
|
+
delegate [:styles, :workbook, :shared_strings, :rels_files, :sheet_files, :comments_files, :image_rels] => :@shared
|
8
|
+
|
9
|
+
attr_reader :images
|
8
10
|
|
9
11
|
def initialize(name, shared, sheet_index, options = {})
|
10
12
|
@name = name
|
11
13
|
@shared = shared
|
14
|
+
@sheet_index = sheet_index
|
15
|
+
@images = Images.new(image_rels[sheet_index]).list
|
12
16
|
@rels = Relationships.new(rels_files[sheet_index])
|
13
17
|
@comments = Comments.new(comments_files[sheet_index])
|
14
18
|
@sheet = SheetDoc.new(sheet_files[sheet_index], @rels, shared, options)
|
@@ -19,7 +23,14 @@ module Roo
|
|
19
23
|
end
|
20
24
|
|
21
25
|
def present_cells
|
22
|
-
@present_cells ||=
|
26
|
+
@present_cells ||= begin
|
27
|
+
warn %{
|
28
|
+
[DEPRECATION] present_cells is deprecated. Alternate:
|
29
|
+
with activesupport => cells[key].presence
|
30
|
+
without activesupport => cells[key]&.presence
|
31
|
+
}
|
32
|
+
cells.select { |_, cell| cell&.presence }
|
33
|
+
end
|
23
34
|
end
|
24
35
|
|
25
36
|
# Yield each row as array of Excelx::Cell objects
|
@@ -39,33 +50,33 @@ module Roo
|
|
39
50
|
|
40
51
|
def row(row_number)
|
41
52
|
first_column.upto(last_column).map do |col|
|
42
|
-
cells[[row_number, col]]
|
43
|
-
end
|
53
|
+
cells[[row_number, col]]&.value
|
54
|
+
end
|
44
55
|
end
|
45
56
|
|
46
57
|
def column(col_number)
|
47
58
|
first_row.upto(last_row).map do |row|
|
48
|
-
cells[[row, col_number]]
|
49
|
-
end
|
59
|
+
cells[[row, col_number]]&.value
|
60
|
+
end
|
50
61
|
end
|
51
62
|
|
52
63
|
# returns the number of the first non-empty row
|
53
64
|
def first_row
|
54
|
-
@first_row ||=
|
65
|
+
@first_row ||= first_last_row_col[:first_row]
|
55
66
|
end
|
56
67
|
|
57
68
|
def last_row
|
58
|
-
@last_row ||=
|
69
|
+
@last_row ||= first_last_row_col[:last_row]
|
59
70
|
end
|
60
71
|
|
61
72
|
# returns the number of the first non-empty column
|
62
73
|
def first_column
|
63
|
-
@first_column ||=
|
74
|
+
@first_column ||= first_last_row_col[:first_column]
|
64
75
|
end
|
65
76
|
|
66
77
|
# returns the number of the last non-empty column
|
67
78
|
def last_column
|
68
|
-
@last_column ||=
|
79
|
+
@last_column ||= first_last_row_col[:last_column]
|
69
80
|
end
|
70
81
|
|
71
82
|
def excelx_format(key)
|
@@ -107,6 +118,34 @@ module Roo
|
|
107
118
|
(cell.coordinate.column - 1 - last_column).times { pad << nil }
|
108
119
|
pad
|
109
120
|
end
|
121
|
+
|
122
|
+
def first_last_row_col
|
123
|
+
@first_last_row_col ||= begin
|
124
|
+
first_row = last_row = first_col = last_col = nil
|
125
|
+
|
126
|
+
cells.each do |(row, col), cell|
|
127
|
+
next unless cell&.presence
|
128
|
+
first_row ||= row
|
129
|
+
last_row ||= row
|
130
|
+
first_col ||= col
|
131
|
+
last_col ||= col
|
132
|
+
|
133
|
+
if row > last_row
|
134
|
+
last_row = row
|
135
|
+
elsif row < first_row
|
136
|
+
first_row = row
|
137
|
+
end
|
138
|
+
|
139
|
+
if col > last_col
|
140
|
+
last_col = col
|
141
|
+
elsif col < first_col
|
142
|
+
first_col = col
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
{first_row: first_row, last_row: last_row, first_column: first_col, last_column: last_col}
|
147
|
+
end
|
148
|
+
end
|
110
149
|
end
|
111
150
|
end
|
112
151
|
end
|