workbook 0.4.6.0 → 0.4.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/README.md +14 -15
- data/lib/workbook.rb +22 -11
- data/lib/workbook/book.rb +47 -25
- data/lib/workbook/cell.rb +20 -26
- data/lib/workbook/generatetypes.rb +14 -0
- data/lib/workbook/modules/cache.rb +52 -0
- data/lib/workbook/modules/{table_diff_sort.rb → diff_sort.rb} +64 -16
- data/lib/workbook/modules/raw_objects_storage.rb +7 -2
- data/lib/workbook/readers/ods_reader.rb +1 -1
- data/lib/workbook/readers/xls_reader.rb +55 -55
- data/lib/workbook/readers/xls_shared.rb +47 -0
- data/lib/workbook/readers/xlsx_reader.rb +34 -153
- data/lib/workbook/row.rb +47 -4
- data/lib/workbook/sheet.rb +4 -0
- data/lib/workbook/table.rb +36 -16
- data/lib/workbook/types/Date.rb +9 -0
- data/lib/workbook/types/False.rb +0 -0
- data/lib/workbook/types/FalseClass.rb +9 -0
- data/lib/workbook/types/Nil.rb +0 -0
- data/lib/workbook/types/NilClass.rb +9 -0
- data/lib/workbook/types/Numeric.rb +9 -0
- data/lib/workbook/types/String.rb +9 -0
- data/lib/workbook/types/Time.rb +9 -0
- data/lib/workbook/types/True.rb +0 -0
- data/lib/workbook/types/TrueClass.rb +9 -0
- data/lib/workbook/version.rb +1 -1
- data/lib/workbook/writers/html_writer.rb +40 -18
- data/lib/workbook/writers/xls_writer.rb +47 -5
- data/lib/workbook/writers/xlsx_writer.rb +123 -0
- data/test/artifacts/bigtable.xls +0 -0
- data/test/artifacts/bigtable.xlsx +0 -0
- data/test/artifacts/simple_sheet.xlsx +0 -0
- data/test/artifacts/simple_sheet_many_sheets.xls +0 -0
- data/test/test_book.rb +50 -2
- data/test/test_cell.rb +1 -1
- data/test/test_format.rb +8 -0
- data/test/test_modules_cache.rb +68 -0
- data/test/test_modules_table_diff_sort.rb +12 -1
- data/test/test_readers_xls_reader.rb +6 -0
- data/test/test_readers_xlsx_reader.rb +10 -9
- data/test/test_row.rb +65 -8
- data/test/test_sheet.rb +8 -0
- data/test/test_table.rb +48 -0
- data/test/test_writers_html_writer.rb +18 -8
- data/test/test_writers_xls_writer.rb +90 -0
- data/test/test_writers_xlsx_writer.rb +153 -0
- data/workbook.gemspec +9 -7
- metadata +71 -31
@@ -11,8 +11,7 @@ module Workbook
|
|
11
11
|
|
12
12
|
# Returns true if there is a template for a certain class, otherwise false
|
13
13
|
def has_raw_for? raw_object_class
|
14
|
-
|
15
|
-
return false
|
14
|
+
available_raws.include? raw_object_class
|
16
15
|
end
|
17
16
|
|
18
17
|
# Returns raw data stored for a type of raw object (if available)
|
@@ -27,6 +26,12 @@ module Workbook
|
|
27
26
|
@raws = {}
|
28
27
|
end
|
29
28
|
|
29
|
+
# Lists the classes for which raws are available
|
30
|
+
# @return Array<Object> array with the classes available
|
31
|
+
def available_raws
|
32
|
+
raws.keys
|
33
|
+
end
|
34
|
+
|
30
35
|
# Return all raw data references
|
31
36
|
def raws
|
32
37
|
@raws = {} unless defined? @raws
|
@@ -10,7 +10,7 @@ module Workbook
|
|
10
10
|
file_obj = file_obj.path if file_obj.is_a? File
|
11
11
|
content = ""
|
12
12
|
styles = ""
|
13
|
-
Zip::
|
13
|
+
Zip::File.open(file_obj) do |zipfile|
|
14
14
|
zipfile.entries.each do |file|
|
15
15
|
styles = zipfile.read(file.name) if file.name == "styles.xml"
|
16
16
|
content = zipfile.read(file.name) if file.name == "content.xml"
|
@@ -1,9 +1,12 @@
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
2
2
|
require 'spreadsheet'
|
3
|
+
require 'workbook/readers/xls_shared'
|
4
|
+
|
3
5
|
|
4
6
|
module Workbook
|
5
7
|
module Readers
|
6
8
|
module XlsReader
|
9
|
+
include Workbook::Readers::XlsShared
|
7
10
|
|
8
11
|
def load_xls file_obj
|
9
12
|
begin
|
@@ -27,63 +30,66 @@ module Workbook
|
|
27
30
|
number_of_worksheets = xls_spreadsheet.worksheets.count
|
28
31
|
(0..number_of_worksheets-1).each do |si|
|
29
32
|
xls_sheet = xls_spreadsheet.worksheets[si]
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
33
|
+
if [:visible, :hidden, nil].include? xls_sheet.visibility # don't read :strong_hidden sheets, symmetrical to the writer
|
34
|
+
begin
|
35
|
+
number_of_rows = xls_sheet.count
|
36
|
+
s = create_or_open_sheet_at(si)
|
37
|
+
s.name = xls_sheet.name
|
38
|
+
(0..number_of_rows-1).each do |ri|
|
39
|
+
xls_row = xls_sheet.row(ri)
|
40
|
+
r = s.table.create_or_open_row_at(ri)
|
41
|
+
col_widths = xls_sheet.columns.collect{|c| c.width if c}
|
42
|
+
xls_row.each_with_index do |xls_cell,ci|
|
38
43
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
44
|
+
begin
|
45
|
+
r[ci] = Workbook::Cell.new xls_cell
|
46
|
+
r[ci].parse!
|
47
|
+
rescue ArgumentError => e
|
48
|
+
if e.message.match('not a Spreadsheet::Formula')
|
49
|
+
v = xls_cell.value
|
50
|
+
if v.class == Float and xls_row.format(ci).date?
|
51
|
+
xls_row[ci] = v
|
52
|
+
v = xls_row.datetime(ci)
|
53
|
+
end
|
54
|
+
if v.is_a? Spreadsheet::Excel::Error
|
55
|
+
v = "----!"
|
56
|
+
end
|
57
|
+
r[ci] = Workbook::Cell.new v
|
58
|
+
elsif e.message.match('not a Spreadsheet::Link')
|
59
|
+
r[ci] = Workbook::Cell.new xls_cell.to_s
|
60
|
+
elsif e.message.match('not a Spreadsheet::Link')
|
61
|
+
r[ci] = Workbook::Cell.new xls_cell.to_s
|
62
|
+
elsif e.message.match('not a Spreadsheet::Excel::Error')
|
63
|
+
r[ci] = "._."
|
64
|
+
else
|
65
|
+
r[ci] = "._." # raise e (we're going to be silent for now)
|
51
66
|
end
|
52
|
-
r[ci] = Workbook::Cell.new v
|
53
|
-
elsif e.message.match('not a Spreadsheet::Link')
|
54
|
-
r[ci] = Workbook::Cell.new xls_cell.to_s
|
55
|
-
elsif e.message.match('not a Spreadsheet::Link')
|
56
|
-
r[ci] = Workbook::Cell.new xls_cell.to_s
|
57
|
-
elsif e.message.match('not a Spreadsheet::Excel::Error')
|
58
|
-
r[ci] = "._."
|
59
|
-
else
|
60
|
-
r[ci] = "._." # raise e (we're going to be silent for now)
|
61
67
|
end
|
62
|
-
|
63
|
-
|
64
|
-
col_width = nil
|
68
|
+
xls_format = xls_row.format(ci)
|
69
|
+
col_width = nil
|
65
70
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
71
|
+
if ri == 0
|
72
|
+
col_width = col_widths[ci]
|
73
|
+
end
|
74
|
+
f = template.create_or_find_format_by "object_id_#{xls_format.object_id}",col_width
|
75
|
+
f[:width]= col_width
|
76
|
+
f[:rotation] = xls_format.rotation if xls_format.rotation
|
77
|
+
f[:background_color] = xls_color_to_html_hex(xls_format.pattern_fg_color)
|
78
|
+
f[:number_format] = ms_formatting_to_strftime(xls_format.number_format)
|
79
|
+
f[:text_direction] = xls_format.text_direction
|
80
|
+
f[:font_family] = "#{xls_format.font.name}, #{xls_format.font.family}"
|
81
|
+
f[:font_weight] = xls_format.font.weight
|
82
|
+
f[:color] = xls_color_to_html_hex(xls_format.font.color)
|
78
83
|
|
79
|
-
|
84
|
+
f.add_raw xls_format
|
80
85
|
|
81
|
-
|
86
|
+
r[ci].format = f
|
87
|
+
end
|
82
88
|
end
|
89
|
+
rescue TypeError
|
90
|
+
puts "WARNING: Failed at worksheet (#{si})... ignored"
|
91
|
+
#ignore SpreadsheetGem can be buggy...
|
83
92
|
end
|
84
|
-
rescue TypeError
|
85
|
-
puts "WARNING: Failed at worksheet (#{si})... ignored"
|
86
|
-
#ignore SpreadsheetGem can be buggy...
|
87
93
|
end
|
88
94
|
end
|
89
95
|
end
|
@@ -92,12 +98,6 @@ module Workbook
|
|
92
98
|
def xls_color_to_html_hex color_sym
|
93
99
|
Workbook::Book::XLS_COLORS[color_sym] ? Workbook::Book::XLS_COLORS[color_sym] : "#000000"
|
94
100
|
end
|
95
|
-
|
96
|
-
def ms_formatting_to_strftime ms_nr_format
|
97
|
-
ms_nr_format = ms_nr_format.downcase
|
98
|
-
return nil if ms_nr_format == 'general'
|
99
|
-
ms_nr_format.gsub('yyyy','%Y').gsub('dddd','%A').gsub('mmmm','%B').gsub('ddd','%a').gsub('mmm','%b').gsub('yy','%y').gsub('dd','%d').gsub('mm','%m').gsub('y','%y').gsub('%%y','%y').gsub('d','%e').gsub('%%e','%d').gsub('m','%m').gsub('%%m','%m').gsub(';@','').gsub('\\','')
|
100
|
-
end
|
101
101
|
end
|
102
102
|
end
|
103
103
|
end
|
@@ -2,6 +2,53 @@
|
|
2
2
|
module Workbook
|
3
3
|
module Readers
|
4
4
|
module XlsShared
|
5
|
+
def ms_formatting_to_strftime ms_nr_format
|
6
|
+
if ms_nr_format
|
7
|
+
ms_nr_format = ms_nr_format.to_s.downcase
|
8
|
+
return nil if ms_nr_format == 'general' or ms_nr_format == ""
|
9
|
+
translation_table = {
|
10
|
+
'yyyy'=>'%Y',
|
11
|
+
'dddd'=>'%A',
|
12
|
+
'mmmm'=>'%B',
|
13
|
+
'ddd'=>'%a',
|
14
|
+
'mmm'=>'%b',
|
15
|
+
'yy'=>'%y',
|
16
|
+
'dd'=>'%d',
|
17
|
+
'mm'=>'%m',
|
18
|
+
'y'=>'%y',
|
19
|
+
'%%y'=>'%y',
|
20
|
+
'd'=>'%e',
|
21
|
+
'%%e'=>'%d',
|
22
|
+
'm'=>'%m',
|
23
|
+
'%%m'=>'%m',
|
24
|
+
';@'=>'',
|
25
|
+
'\\'=>''
|
26
|
+
}
|
27
|
+
translation_table.each{|k,v| ms_nr_format.gsub!(k,v) }
|
28
|
+
ms_nr_format
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Attempt to convert html-hex color value to xls color number
|
33
|
+
#
|
34
|
+
# @param [String] hex color
|
35
|
+
# @return [String] xls color
|
36
|
+
def html_color_to_xls_color hex
|
37
|
+
Workbook::Readers::XlsShared::XLS_COLORS.each do |k,v|
|
38
|
+
return k if (v == hex or (hex and hex != "" and k == hex.to_sym))
|
39
|
+
end
|
40
|
+
return nil
|
41
|
+
end
|
42
|
+
|
43
|
+
# Converts standard (ruby/C++/unix/...) strftime formatting to MS's formatting
|
44
|
+
#
|
45
|
+
# @param [String, nil] numberformat (nil returns nil)
|
46
|
+
# @return [String, nil]
|
47
|
+
def strftime_to_ms_format numberformat
|
48
|
+
return nil if numberformat.nil?
|
49
|
+
return numberformat.gsub('%Y','yyyy').gsub('%A','dddd').gsub('%B','mmmm').gsub('%a','ddd').gsub('%b','mmm').gsub('%y','yy').gsub('%d','dd').gsub('%m','mm').gsub('%y','y').gsub('%y','%%y').gsub('%e','d')
|
50
|
+
end
|
51
|
+
|
5
52
|
XLS_COLORS = {:xls_color_1=>'#000000',
|
6
53
|
:xls_color_2=>'#FFFFFF',
|
7
54
|
:xls_color_3=>'#FF0000',
|
@@ -1,136 +1,19 @@
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
2
2
|
require 'rubyXL'
|
3
|
+
require 'workbook/readers/xls_shared'
|
3
4
|
|
4
|
-
# Monkeypatching rubyXL, pull request submitted: https://github.com/gilt/rubyXL/pull/47
|
5
|
-
module RubyXL
|
6
|
-
class Workbook
|
7
|
-
|
8
|
-
# Improves upon date format detection
|
9
|
-
def is_date_format?(num_fmt)
|
10
|
-
num_fmt = num_fmt.to_s
|
11
|
-
num_fmt.downcase!
|
12
|
-
skip_chars = ['$', '-', '+', '/', '(', ')', ':', ' ']
|
13
|
-
num_chars = ['0', '#', '?']
|
14
|
-
non_date_formats = ['0.00e+00', '##0.0e+0', 'general', '@']
|
15
|
-
date_chars = ['y','m','d','h','s']
|
16
|
-
|
17
|
-
state = 0
|
18
|
-
s = ''
|
19
|
-
num_fmt.split(//).each do |c|
|
20
|
-
if state == 0
|
21
|
-
if c == '"'
|
22
|
-
state = 1
|
23
|
-
elsif ['\\', '_', '*'].include?(c)
|
24
|
-
state = 2
|
25
|
-
elsif skip_chars.include?(c)
|
26
|
-
next
|
27
|
-
else
|
28
|
-
s << c
|
29
|
-
end
|
30
|
-
elsif state == 1
|
31
|
-
if c == '"'
|
32
|
-
state = 0
|
33
|
-
end
|
34
|
-
elsif state == 2
|
35
|
-
state = 0
|
36
|
-
end
|
37
|
-
end
|
38
|
-
s.gsub!(/\[[^\]]*\]/, '')
|
39
|
-
if non_date_formats.include?(s)
|
40
|
-
return false
|
41
|
-
end
|
42
|
-
separator = ';'
|
43
|
-
got_sep = 0
|
44
|
-
date_count = 0
|
45
|
-
num_count = 0
|
46
|
-
s.split(//).each do |c|
|
47
|
-
if date_chars.include?(c)
|
48
|
-
date_count += 1
|
49
|
-
elsif num_chars.include?(c)
|
50
|
-
num_count += 1
|
51
|
-
elsif c == separator
|
52
|
-
got_sep = 1
|
53
|
-
end
|
54
|
-
end
|
55
|
-
if date_count > 0 && num_count == 0
|
56
|
-
return true
|
57
|
-
elsif num_count > 0 && date_count == 0
|
58
|
-
return false
|
59
|
-
elsif date_count
|
60
|
-
# ambiguous result
|
61
|
-
elsif got_sep == 0
|
62
|
-
# constant result
|
63
|
-
end
|
64
|
-
return date_count > num_count
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
# end monkey patch submitted
|
69
|
-
|
70
|
-
module RubyXL
|
71
|
-
class Workbook
|
72
|
-
def num_fmts_by_id
|
73
|
-
return @num_fmts_hash unless @num_fmts_hash.nil?
|
74
|
-
@num_fmts_hash={1=>{:attributes=>{:formatCode=>'0'}},
|
75
|
-
2=>{:attributes=>{:formatCode=>'0.00'}},
|
76
|
-
3=>{:attributes=>{:formatCode=>'#, ##0'}},
|
77
|
-
4=>{:attributes=>{:formatCode=>'#, ##0.00'}},
|
78
|
-
5=>{:attributes=>{:formatCode=>'$#, ##0_);($#, ##0)'}},
|
79
|
-
6=>{:attributes=>{:formatCode=>'$#, ##0_);[Red]($#, ##0)'}},
|
80
|
-
7=>{:attributes=>{:formatCode=>'$#, ##0.00_);($#, ##0.00)'}},
|
81
|
-
8=>{:attributes=>{:formatCode=>'$#, ##0.00_);[Red]($#, ##0.00)'}},
|
82
|
-
9=>{:attributes=>{:formatCode=>'0%'}},
|
83
|
-
10=>{:attributes=>{:formatCode=>'0.00%'}},
|
84
|
-
11=>{:attributes=>{:formatCode=>'0.00E+00'}},
|
85
|
-
12=>{:attributes=>{:formatCode=>'# ?/?'}},
|
86
|
-
13=>{:attributes=>{:formatCode=>'# ??/??'}},
|
87
|
-
14=>{:attributes=>{:formatCode=>'m/d/yyyy'}},
|
88
|
-
15=>{:attributes=>{:formatCode=>'d-mmm-yy'}},
|
89
|
-
16=>{:attributes=>{:formatCode=>'d-mmm'}},
|
90
|
-
17=>{:attributes=>{:formatCode=>'mmm-yy'}},
|
91
|
-
18=>{:attributes=>{:formatCode=>'h:mm AM/PM'}},
|
92
|
-
19=>{:attributes=>{:formatCode=>'h:mm:ss AM/PM'}},
|
93
|
-
20=>{:attributes=>{:formatCode=>'h:mm'}},
|
94
|
-
21=>{:attributes=>{:formatCode=>'h:mm:ss'}},
|
95
|
-
22=>{:attributes=>{:formatCode=>'m/d/yyyy h:mm'}},
|
96
|
-
37=>{:attributes=>{:formatCode=>'#, ##0_);(#, ##0)'}},
|
97
|
-
38=>{:attributes=>{:formatCode=>'#, ##0_);[Red](#, ##0)'}},
|
98
|
-
39=>{:attributes=>{:formatCode=>'#, ##0.00_);(#, ##0.00)'}},
|
99
|
-
40=>{:attributes=>{:formatCode=>'#, ##0.00_);[Red](#, ##0.00)'}},
|
100
|
-
45=>{:attributes=>{:formatCode=>'mm:ss'}},
|
101
|
-
46=>{:attributes=>{:formatCode=>'[h]:mm:ss'}},
|
102
|
-
47=>{:attributes=>{:formatCode=>'mm:ss.0'}},
|
103
|
-
48=>{:attributes=>{:formatCode=>'##0.0E+0'}},
|
104
|
-
49=>{:attributes=>{:formatCode=>'@'}}}
|
105
|
-
if num_fmts and num_fmts[:numFmt]
|
106
|
-
num_fmts[:numFmt].each do |num_fmt|
|
107
|
-
@num_fmts_hash[num_fmt[:attributes][:numFmtId]]=num_fmt
|
108
|
-
end
|
109
|
-
end
|
110
|
-
return @num_fmts_hash
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
# other monkey patch
|
116
|
-
module RubyXL
|
117
|
-
class Cell
|
118
|
-
def number_format
|
119
|
-
if !@value.is_a?(String)
|
120
|
-
if @workbook.num_fmts_by_id
|
121
|
-
num_fmt_id = xf_id()[:numFmtId]
|
122
|
-
tmp_num_fmt = @workbook.num_fmts_by_id[num_fmt_id]
|
123
|
-
return (tmp_num_fmt &&tmp_num_fmt[:attributes] && tmp_num_fmt[:attributes][:formatCode]) ? tmp_num_fmt[:attributes][:formatCode] : nil
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
127
|
-
end
|
128
|
-
end
|
129
|
-
# end of monkey patch
|
130
5
|
|
131
6
|
module Workbook
|
132
7
|
module Readers
|
133
8
|
module XlsxReader
|
9
|
+
include Workbook::Readers::XlsShared
|
10
|
+
|
11
|
+
# Load method for .xlsm files, an office open file format, hence compatible with .xlsx (it emphasizes that it contains macros)
|
12
|
+
#
|
13
|
+
# @param [String, File] file_obj a string with a reference to the file to be written to
|
14
|
+
def load_xlsm file_obj
|
15
|
+
self.load_xlsx file_obj
|
16
|
+
end
|
134
17
|
def load_xlsx file_obj
|
135
18
|
file_obj = file_obj.path if file_obj.is_a? File
|
136
19
|
sp = RubyXL::Parser.parse(file_obj)
|
@@ -149,43 +32,41 @@ module Workbook
|
|
149
32
|
rescue
|
150
33
|
# Column widths couldn't be read, no big deal...
|
151
34
|
end
|
35
|
+
|
152
36
|
worksheet.each_with_index do |row, ri|
|
153
|
-
|
37
|
+
if row
|
38
|
+
r = s.table.create_or_open_row_at(ri)
|
39
|
+
row.cells.each_with_index do |cell,ci|
|
40
|
+
if cell.nil?
|
41
|
+
r[ci] = Workbook::Cell.new nil
|
42
|
+
else
|
43
|
+
r[ci] = Workbook::Cell.new cell.value
|
44
|
+
r[ci].parse!
|
45
|
+
xls_format = cell.style_index
|
46
|
+
col_width = nil
|
154
47
|
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
48
|
+
if ri == 0
|
49
|
+
col_width = col_widths[ci]
|
50
|
+
end
|
51
|
+
f = template.create_or_find_format_by "style_index_#{cell.style_index}", col_width
|
52
|
+
f[:width]= col_width
|
53
|
+
background_color = cell.fill_color
|
54
|
+
background_color = (background_color.length == 8) ? background_color[2..8] : background_color #ignoring alpha for now.
|
55
|
+
f[:background_color] = "##{background_color}"
|
163
56
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
f = template.create_or_find_format_by "style_index_#{cell.style_index}", col_width
|
168
|
-
f[:width]= col_width
|
169
|
-
f[:background_color] = "##{cell.fill_color}"
|
170
|
-
f[:number_format] = ms_formatting_to_strftime(cell.number_format)
|
171
|
-
f[:font_family] = cell.font_name
|
172
|
-
f[:color] = "##{cell.font_color}"
|
57
|
+
f[:number_format] = ms_formatting_to_strftime(cell.number_format)
|
58
|
+
# f[:font_family] = cell.font_name
|
59
|
+
# f[:color] = "##{cell.font_color}"
|
173
60
|
|
174
|
-
|
61
|
+
f.add_raw xls_format
|
175
62
|
|
176
|
-
|
63
|
+
r[ci].format = f
|
64
|
+
end
|
177
65
|
end
|
178
66
|
end
|
179
67
|
end
|
180
68
|
end
|
181
69
|
end
|
182
|
-
def ms_formatting_to_strftime ms_nr_format
|
183
|
-
if ms_nr_format
|
184
|
-
ms_nr_format = ms_nr_format.to_s.downcase
|
185
|
-
return nil if ms_nr_format == 'general' or ms_nr_format == ""
|
186
|
-
ms_nr_format.gsub('yyyy','%Y').gsub('dddd','%A').gsub('mmmm','%B').gsub('ddd','%a').gsub('mmm','%b').gsub('yy','%y').gsub('dd','%d').gsub('mm','%m').gsub('y','%y').gsub('%%y','%y').gsub('d','%e').gsub('%%e','%d').gsub('m','%m').gsub('%%m','%m').gsub(';@','').gsub('\\','')
|
187
|
-
end
|
188
|
-
end
|
189
70
|
end
|
190
71
|
end
|
191
72
|
end
|
data/lib/workbook/row.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
2
|
+
|
2
3
|
module Workbook
|
3
4
|
class Row < Array
|
5
|
+
include Workbook::Modules::Cache
|
6
|
+
|
4
7
|
alias_method :compare_without_header, :<=>
|
5
8
|
attr_accessor :placeholder # The placeholder attribute is used in compares (corresponds to newly created or removed lines (depending which side you're on)
|
6
9
|
attr_accessor :format
|
@@ -57,13 +60,45 @@ module Workbook
|
|
57
60
|
end
|
58
61
|
end
|
59
62
|
|
63
|
+
# Add cell
|
64
|
+
# @param [Workbook::Cell, Numeric,String,Time,Date,TrueClass,FalseClass,NilClass] cell or value to add
|
65
|
+
def push(cell)
|
66
|
+
cell = Workbook::Cell.new(cell) unless cell.class == Workbook::Cell
|
67
|
+
super(cell)
|
68
|
+
end
|
69
|
+
|
70
|
+
# Add cell
|
71
|
+
# @param [Workbook::Cell, Numeric,String,Time,Date,TrueClass,FalseClass,NilClass] cell or value to add
|
72
|
+
def <<(cell)
|
73
|
+
cell = Workbook::Cell.new(cell) unless cell.class == Workbook::Cell
|
74
|
+
super(cell)
|
75
|
+
end
|
76
|
+
|
77
|
+
# plus
|
78
|
+
# @param [Workbook::Row, Array] row to add
|
79
|
+
# @return [Workbook::Row] a new row, not linked to the table
|
80
|
+
def +(row)
|
81
|
+
rv = super(row)
|
82
|
+
rv = Workbook::Row.new(rv) unless rv.class == Workbook::Row
|
83
|
+
return rv
|
84
|
+
end
|
85
|
+
|
86
|
+
# concat
|
87
|
+
# @param [Workbook::Row, Array] row to add
|
88
|
+
# @return [self] self
|
89
|
+
def concat(row)
|
90
|
+
row = Workbook::Row.new(row) unless row.class == Workbook::Row
|
91
|
+
super(row)
|
92
|
+
end
|
93
|
+
|
94
|
+
|
60
95
|
# Overrides normal Array's []-function with support for symbols that identify a column based on the header-values
|
61
96
|
#
|
62
97
|
# @example Lookup using fixnum or header value encoded as symbol
|
63
98
|
# row[1] #=> <Cell value="a">
|
64
99
|
# row[:a] #=> <Cell value="a">
|
65
100
|
#
|
66
|
-
# @param [Fixnum, Symbol] index_or_hash
|
101
|
+
# @param [Fixnum, Symbol, String] index_or_hash that identifies the column (strings are converted to symbols)
|
67
102
|
# @return [Workbook::Cell, nil]
|
68
103
|
def [](index_or_hash)
|
69
104
|
if index_or_hash.is_a? Symbol
|
@@ -73,6 +108,9 @@ module Workbook
|
|
73
108
|
rescue NoMethodError
|
74
109
|
end
|
75
110
|
return rv
|
111
|
+
elsif index_or_hash.is_a? String
|
112
|
+
symbolized = Workbook::Cell.new(index_or_hash).to_sym
|
113
|
+
self[symbolized]
|
76
114
|
else
|
77
115
|
if index_or_hash
|
78
116
|
return to_a[index_or_hash]
|
@@ -82,17 +120,20 @@ module Workbook
|
|
82
120
|
|
83
121
|
# Overrides normal Array's []=-function with support for symbols that identify a column based on the header-values
|
84
122
|
#
|
85
|
-
# @example Lookup using fixnum or header value encoded as symbol
|
123
|
+
# @example Lookup using fixnum or header value encoded as symbol (strings are converted to symbols)
|
86
124
|
# row[1] #=> <Cell value="a">
|
87
125
|
# row[:a] #=> <Cell value="a">
|
88
126
|
#
|
89
|
-
# @param [Fixnum, Symbol] index_or_hash
|
127
|
+
# @param [Fixnum, Symbol, String] index_or_hash that identifies the column
|
90
128
|
# @param [String, Fixnum, NilClass, Date, DateTime, Time, Float] value
|
91
129
|
# @return [Workbook::Cell, nil]
|
92
130
|
def []= (index_or_hash, value)
|
93
131
|
index = index_or_hash
|
94
132
|
if index_or_hash.is_a? Symbol
|
95
133
|
index = table_header_keys.index(index_or_hash)
|
134
|
+
elsif index_or_hash.is_a? String
|
135
|
+
symbolized = Workbook::Cell.new(index_or_hash).to_sym
|
136
|
+
index = table_header_keys.index(symbolized)
|
96
137
|
end
|
97
138
|
|
98
139
|
value_celled = Workbook::Cell.new
|
@@ -144,7 +185,9 @@ module Workbook
|
|
144
185
|
# Converts a row to an array of symbol representations of the row content, see also: Workbook::Cell#to_sym
|
145
186
|
# @return [Array<Symbol>] returns row as an array of symbols
|
146
187
|
def to_symbols
|
147
|
-
|
188
|
+
fetch_cache(:to_symbols){
|
189
|
+
collect{|c| c.to_sym}
|
190
|
+
}
|
148
191
|
end
|
149
192
|
|
150
193
|
# Converts the row to an array of Workbook::Cell's
|