workbook 0.1.6.2 → 0.2.0
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.
- data/Gemfile.lock +8 -6
- data/lib/workbook/book.rb +14 -6
- data/lib/workbook/readers/xlsx_reader.rb +2 -0
- data/lib/workbook/row.rb +25 -3
- data/lib/workbook/table.rb +7 -4
- data/lib/workbook/writers/xls_writer.rb +20 -22
- data/readme.markdown +9 -1
- data/test/test_modules_table_diff_sort.rb +1 -1
- data/test/test_readers_csv_reader.rb +1 -1
- data/test/test_readers_xls_reader.rb +1 -1
- data/test/test_writers_xls_writer.rb +10 -0
- data/workbook.gemspec +3 -3
- metadata +6 -7
data/Gemfile.lock
CHANGED
@@ -1,18 +1,20 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
workbook (0.
|
4
|
+
workbook (0.2.0)
|
5
5
|
fastercsv
|
6
6
|
rchardet (~> 1.3)
|
7
|
-
|
7
|
+
rubyXL
|
8
|
+
spreadsheet (>= 0.7.5)
|
8
9
|
|
9
10
|
GEM
|
10
11
|
remote: http://rubygems.org/
|
11
12
|
specs:
|
12
|
-
fastercsv (1.5.
|
13
|
-
rchardet (1.3)
|
14
|
-
ruby-ole (1.2.11.
|
15
|
-
|
13
|
+
fastercsv (1.5.5)
|
14
|
+
rchardet (1.3.1)
|
15
|
+
ruby-ole (1.2.11.6)
|
16
|
+
rubyXL (1.2.10)
|
17
|
+
spreadsheet (0.7.5)
|
16
18
|
ruby-ole (>= 1.0)
|
17
19
|
|
18
20
|
PLATFORMS
|
data/lib/workbook/book.rb
CHANGED
@@ -6,6 +6,9 @@ require 'workbook/readers/txt_reader'
|
|
6
6
|
require 'rchardet'
|
7
7
|
|
8
8
|
module Workbook
|
9
|
+
# The Book class is the container of sheets. It can be inialized by either the standard initalizer or the open method. The
|
10
|
+
# Book class can also keep a reference to a template class, storing shared formatting options.
|
11
|
+
#
|
9
12
|
class Book < Array
|
10
13
|
include Workbook::Writers::XlsWriter
|
11
14
|
include Workbook::Readers::XlsReader
|
@@ -15,7 +18,6 @@ module Workbook
|
|
15
18
|
|
16
19
|
attr_accessor :title
|
17
20
|
attr_accessor :template
|
18
|
-
attr_accessor :default_rewrite_header
|
19
21
|
|
20
22
|
# @param [Workbook::Sheet, Array] Create a new workbook based on an existing sheet, or initialize a sheet based on the array
|
21
23
|
# @return [Workbook::Book]
|
@@ -53,13 +55,16 @@ module Workbook
|
|
53
55
|
first
|
54
56
|
end
|
55
57
|
|
58
|
+
# @return [Boolean] returns true if the first sheet has contents
|
56
59
|
def has_contents?
|
57
60
|
sheet.has_contents?
|
58
61
|
end
|
59
62
|
|
60
63
|
# Loads an external file into an existing worbook
|
64
|
+
#
|
61
65
|
# @param [String] a string with a reference to the file to be opened
|
62
66
|
# @param [String] an optional string enforcing a certain parser (based on the file extension, e.g. 'txt', 'csv' or 'xls')
|
67
|
+
# @return [Workbook::Book] A new instance, based on the filename
|
63
68
|
def open filename, ext=nil
|
64
69
|
ext = file_extension(filename) unless ext
|
65
70
|
if ['txt','csv','xml'].include?(ext)
|
@@ -70,8 +75,10 @@ module Workbook
|
|
70
75
|
end
|
71
76
|
|
72
77
|
# Open the file in binary, read-only mode, do not read it, but pas it throug to the extension determined loaded
|
78
|
+
#
|
73
79
|
# @param [String] a string with a reference to the file to be opened
|
74
80
|
# @param [String] an optional string enforcing a certain parser (based on the file extension, e.g. 'txt', 'csv' or 'xls')
|
81
|
+
# @return [Workbook::Book] A new instance, based on the filename
|
75
82
|
def open_binary filename, ext=nil
|
76
83
|
ext = file_extension(filename) unless ext
|
77
84
|
f = File.open(filename,'rb')
|
@@ -79,6 +86,7 @@ module Workbook
|
|
79
86
|
end
|
80
87
|
|
81
88
|
# Open the file in non-binary, read-only mode, read it and parse it to UTF-8
|
89
|
+
#
|
82
90
|
# @param [String] a string with a reference to the file to be opened
|
83
91
|
# @param [String] an optional string enforcing a certain parser (based on the file extension, e.g. 'txt', 'csv' or 'xls')
|
84
92
|
def open_text filename, ext=nil
|
@@ -91,12 +99,16 @@ module Workbook
|
|
91
99
|
end
|
92
100
|
|
93
101
|
# @param [String] The full filename, or path
|
102
|
+
#
|
94
103
|
# @return [String] The file extension
|
95
104
|
def file_extension(filename)
|
96
105
|
File.extname(filename).gsub('.','').downcase if filename
|
97
106
|
end
|
98
107
|
|
99
108
|
# Create an instance from a file, using open.
|
109
|
+
#
|
110
|
+
# @param [String] the filename of the document
|
111
|
+
# @param [String] (not required) enforce a certain extension, the parser is based on the extension of the file
|
100
112
|
# @return [Workbook::Book] A new instance, based on the filename
|
101
113
|
def self.open filename, ext=nil
|
102
114
|
wb = self.new
|
@@ -114,11 +126,7 @@ module Workbook
|
|
114
126
|
def sort
|
115
127
|
raise Exception("Books can't be sorted")
|
116
128
|
end
|
117
|
-
|
118
|
-
def default_rewrite_header?
|
119
|
-
return true if default_rewrite_header.nil?
|
120
|
-
default_rewrite_header
|
121
|
-
end
|
129
|
+
|
122
130
|
|
123
131
|
end
|
124
132
|
end
|
@@ -62,6 +62,7 @@ module RubyXL
|
|
62
62
|
end
|
63
63
|
end
|
64
64
|
# end monkey patch submitted
|
65
|
+
|
65
66
|
module RubyXL
|
66
67
|
class Workbook
|
67
68
|
def num_fmts_by_id
|
@@ -106,6 +107,7 @@ module RubyXL
|
|
106
107
|
end
|
107
108
|
end
|
108
109
|
end
|
110
|
+
|
109
111
|
# other monkey patch
|
110
112
|
module RubyXL
|
111
113
|
class Cell
|
data/lib/workbook/row.rb
CHANGED
@@ -2,11 +2,14 @@ module Workbook
|
|
2
2
|
class Row < Array
|
3
3
|
alias_method :compare_without_header, :<=>
|
4
4
|
|
5
|
-
#used in compares
|
5
|
+
# The placeholder attribute is used in compares (corresponds to newly created or removed lines (depending which side you're on)
|
6
6
|
attr_accessor :placeholder
|
7
7
|
attr_accessor :format
|
8
8
|
|
9
9
|
|
10
|
+
# @param [Workbook::Row, Array<Workbook::Cell>, Array] list of cells to initialize the row with, default is empty
|
11
|
+
# @param [Workbook::Table] a row normally belongs to a table, reference it here
|
12
|
+
# @param [Hash], option hash. Supprted options: parse_cells_on_batch_creation (parse cell values during row-initalization, default: false), cell_parse_options (default {}, see Workbook::Modules::TypeParser)
|
10
13
|
def initialize cells=[], table=nil, options={}
|
11
14
|
options=options ? {:parse_cells_on_batch_creation=>false,:cell_parse_options=>{}}.merge(options) : {}
|
12
15
|
cells = [] if cells==nil
|
@@ -30,7 +33,9 @@ module Workbook
|
|
30
33
|
@table
|
31
34
|
end
|
32
35
|
|
33
|
-
#
|
36
|
+
# Set reference to the table this row belongs to (and adds the row to this table)
|
37
|
+
#
|
38
|
+
# @param [Workbook::Table]
|
34
39
|
def table= t
|
35
40
|
raise ArgumentError, "table should be a Workbook::Table (you passed a #{t.class})" unless t.is_a?(Workbook::Table) or t == nil
|
36
41
|
if t
|
@@ -39,6 +44,14 @@ module Workbook
|
|
39
44
|
end
|
40
45
|
end
|
41
46
|
|
47
|
+
# Overrides normal Array's []-function with support for symbols that identify a column based on the header-values
|
48
|
+
#
|
49
|
+
# @example Lookup using fixnum or header value encoded as symbol
|
50
|
+
# row[1] #=> <Cell value="a">
|
51
|
+
# row[:a] #=> <Cell value="a">
|
52
|
+
#
|
53
|
+
# @param [Fixnum, Symbol]
|
54
|
+
# @return [Workbook::Cell, nil]
|
42
55
|
def [](index_or_hash)
|
43
56
|
if index_or_hash.is_a? Fixnum
|
44
57
|
return to_a[index_or_hash]
|
@@ -52,7 +65,11 @@ module Workbook
|
|
52
65
|
end
|
53
66
|
end
|
54
67
|
|
55
|
-
#
|
68
|
+
# Returns an array of cells allows you to find cells by a given color, normally a string containing a hex
|
69
|
+
#
|
70
|
+
# @param [String] default :any colour, can be a CSS-style hex-string
|
71
|
+
# @param [Hash] options. Option :hash_keys (default true) returns row as an array of symbols
|
72
|
+
# @return [Array<Symbol>, Workbook::Row<Workbook::Cell>]
|
56
73
|
def find_cells_by_background_color color=:any, options={}
|
57
74
|
options = {:hash_keys=>true}.merge(options)
|
58
75
|
cells = self.collect {|c| c if c.format.has_background_color?(color) }.compact
|
@@ -60,14 +77,19 @@ module Workbook
|
|
60
77
|
options[:hash_keys] ? r.to_symbols : r
|
61
78
|
end
|
62
79
|
|
80
|
+
# Returns true when the row belongs to a table and it is the header row (typically the first row)
|
81
|
+
#
|
82
|
+
# @return [Boolean]
|
63
83
|
def header?
|
64
84
|
table != nil and self.object_id == table.header.object_id
|
65
85
|
end
|
66
86
|
|
87
|
+
# @return [Array<Symbol>] returns row as an array of symbols
|
67
88
|
def to_symbols
|
68
89
|
collect{|c| c.to_sym}
|
69
90
|
end
|
70
91
|
|
92
|
+
# @return [Array<Workbook::Cell>] returns row as an array of symbols
|
71
93
|
def to_a
|
72
94
|
self.collect{|c| c}
|
73
95
|
end
|
data/lib/workbook/table.rb
CHANGED
@@ -21,9 +21,12 @@ module Workbook
|
|
21
21
|
end
|
22
22
|
self.sheet = sheet
|
23
23
|
# Column data is considered as a 'row' with 'cells' that contain 'formatting'
|
24
|
-
|
25
24
|
end
|
26
25
|
|
26
|
+
# Returns the header of this table (typically the first row, but can be a different row).
|
27
|
+
# The header row is also used for finding values in a aribrary row.
|
28
|
+
#
|
29
|
+
# @return [Workbook::Row] The header
|
27
30
|
def header
|
28
31
|
if @header == false
|
29
32
|
false
|
@@ -34,9 +37,9 @@ module Workbook
|
|
34
37
|
end
|
35
38
|
end
|
36
39
|
|
37
|
-
#
|
38
|
-
def new_row
|
39
|
-
r = Workbook::Row.new(
|
40
|
+
# Generates a new row, with optionally predefined cell-values, that is already connected to this table.
|
41
|
+
def new_row cell_values=[]
|
42
|
+
r = Workbook::Row.new(cell_values,self)
|
40
43
|
return r
|
41
44
|
end
|
42
45
|
|
@@ -70,34 +70,28 @@ module Workbook
|
|
70
70
|
:cyan=>'#00FFFF',
|
71
71
|
:border=>'#FFFFFF',
|
72
72
|
:text=>'#000000',
|
73
|
-
:lime=>'#00f94c'
|
73
|
+
:lime=>'#00f94c'
|
74
|
+
}
|
74
75
|
|
76
|
+
# Generates an Spreadsheet (from the spreadsheet gem) in order to build an XlS
|
77
|
+
#
|
78
|
+
# @params [Hash] A hash with options (unused so far)
|
79
|
+
# @return [Spreadsheet] A Spreadsheet object, ready for writing or more lower level operations
|
75
80
|
def to_xls options={}
|
76
|
-
options = {:rewrite_header=>default_rewrite_header?}.merge options
|
77
81
|
book = init_spreadsheet_template
|
78
82
|
self.each_with_index do |s,si|
|
79
83
|
xls_sheet = book.worksheet si
|
80
84
|
xls_sheet = book.create_worksheet if xls_sheet == nil
|
81
85
|
s.table.each_with_index do |r, ri|
|
82
|
-
|
83
|
-
|
84
|
-
if
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
write_row = true
|
89
|
-
end
|
90
|
-
if write_row
|
91
|
-
xls_sheet.row(ri).height= r.format[:height] if r.format
|
92
|
-
r.each_with_index do |c, ci|
|
93
|
-
if c
|
94
|
-
if r.header?
|
95
|
-
xls_sheet.columns[ci] ||= Spreadsheet::Column.new(ci,nil)
|
96
|
-
xls_sheet.columns[ci].width= c.format[:width]
|
97
|
-
end
|
98
|
-
xls_sheet.row(ri)[ci] = c.value
|
99
|
-
xls_sheet.row(ri).set_format(ci, format_to_xls_format(c.format))
|
86
|
+
xls_sheet.row(ri).height= r.format[:height] if r.format
|
87
|
+
r.each_with_index do |c, ci|
|
88
|
+
if c
|
89
|
+
if r.header?
|
90
|
+
xls_sheet.columns[ci] ||= Spreadsheet::Column.new(ci,nil)
|
91
|
+
xls_sheet.columns[ci].width= c.format[:width]
|
100
92
|
end
|
93
|
+
xls_sheet.row(ri)[ci] = c.value
|
94
|
+
xls_sheet.row(ri).set_format(ci, format_to_xls_format(c.format))
|
101
95
|
end
|
102
96
|
end
|
103
97
|
end
|
@@ -138,8 +132,12 @@ module Workbook
|
|
138
132
|
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')
|
139
133
|
end
|
140
134
|
|
141
|
-
|
142
|
-
|
135
|
+
# Write the current workbook to Microsoft Excel format (using the spreadsheet gem)
|
136
|
+
#
|
137
|
+
# @param [String] the filename
|
138
|
+
# @param [Hash] options, see #to_xls
|
139
|
+
|
140
|
+
def write_to_xls filename="#{title}.xls", options={}
|
143
141
|
if to_xls(options).write(filename)
|
144
142
|
return filename
|
145
143
|
end
|
data/readme.markdown
CHANGED
@@ -96,4 +96,12 @@ The [ruby toolbox lists plenty of alternatives](https://www.ruby-toolbox.com/sea
|
|
96
96
|
|
97
97
|
## License
|
98
98
|
|
99
|
-
MIT
|
99
|
+
This code MIT (but see below) (c) murb / Maarten Brouwers, 2011-2013
|
100
|
+
|
101
|
+
Workbook uses the following gems:
|
102
|
+
|
103
|
+
* [Spreadsheet](https://github.com/zdavatz/spreadsheet) (Copyright (c) 2010 ywesee GmbH (mhatakeyama@ywesee.com, zdavatz@ywesee.com); GPL3 (License required for closed implementations))
|
104
|
+
* [FasterCSV](http://fastercsv.rubyforge.org/) (Copyright (c) James Edward Gray II; GPL2 & Ruby License)
|
105
|
+
* [rchardet](http://rubyforge.org/projects/rchardet) (Copyright (c) JMHodges; LGPL)
|
106
|
+
* [ruby-ole](http://code.google.com/p/ruby-ole/) (Copyright (c) 2007-2010 Charles Lowe; MIT)
|
107
|
+
* [RubyXL](https://github.com/gilt/rubyXL) (Copyright (c) 2011 Vivek Bhagwat; MIT-Licensed)
|
@@ -99,7 +99,7 @@ module Modules
|
|
99
99
|
diff_result = tself.diff tother
|
100
100
|
assert_equal('a',diff_result.sheet.table.header[0].value)
|
101
101
|
assert_equal("a,b,c,d\n1,2,3,4\n3,2,3,4\n3,3 (was: 2),3,4\n4,2,3,4\n(was: 5),(was: 2),(was: 3),(was: 4)\n",diff_result.sheet.table.to_csv)
|
102
|
-
diff_result.write_to_xls
|
102
|
+
diff_result.write_to_xls
|
103
103
|
end
|
104
104
|
end
|
105
105
|
end
|
@@ -31,7 +31,7 @@ module Readers
|
|
31
31
|
assert_equal(Date.new(2001,1,1),w.sheet.table[1][:a].value)
|
32
32
|
assert_equal(DateTime.new(2011,2,12,12,23),w.sheet.table[4][:c].value)
|
33
33
|
assert_equal("6/12 ovk getekend terugontv.+>acq ter tekening. 13/12 ovk getekend terugontv.+>Fred ter tekening.", w.sheet.table[5][:b].value)
|
34
|
-
assert_equal(
|
34
|
+
assert_equal(DateTime.new(Time.now.year,6,12),w.sheet.table[5][:c].value)
|
35
35
|
end
|
36
36
|
def test_excel_standardized_open
|
37
37
|
w = Workbook::Book.new
|
@@ -44,7 +44,7 @@ module Readers
|
|
44
44
|
w = Workbook::Book.new
|
45
45
|
w.open("test/artifacts/txt_in_xls.xls")
|
46
46
|
assert_equal([:naam,:nummer,:ilt,:corporate_key,:naam_medewerker, nil, nil, :telefoon, :openingsdatum],w.sheet.table.header.to_symbols)
|
47
|
-
assert_equal(["dddd",2222,"i9000","asd","Anita",nil,"Betera",
|
47
|
+
assert_equal(["dddd",2222,"i9000","asd","Anita",nil,"Betera","012-3456789",Date.new(2011,10,5)],w.sheet.table[1].collect{|a| a.value})
|
48
48
|
end
|
49
49
|
def test_zip_in_xls_open
|
50
50
|
w = Workbook::Book.new
|
@@ -20,6 +20,16 @@ module Writers
|
|
20
20
|
b = Workbook::Book.open filename
|
21
21
|
assert_equal(3.85546875,b.sheet.table.first[:a].format[:width])
|
22
22
|
end
|
23
|
+
def test_cloning_roundtrip
|
24
|
+
b = Workbook::Book.open('test/artifacts/book_with_tabs_and_colours.xls')
|
25
|
+
b.sheet.table << b.sheet.table[2]
|
26
|
+
assert_equal(90588,b.sheet.table[5][:b].value)
|
27
|
+
assert_equal("#FFFF00",b.sheet.table[5][:c].format[:background_color])
|
28
|
+
filename = b.write_to_xls
|
29
|
+
b = Workbook::Book.open filename
|
30
|
+
assert_equal(90588,b.sheet.table[5][:b].value)
|
31
|
+
assert_equal("#FFFF00",b.sheet.table[5][:c].format[:background_color])
|
32
|
+
end
|
23
33
|
|
24
34
|
def test_init_spreadsheet_template
|
25
35
|
b = Workbook::Book.new
|
data/workbook.gemspec
CHANGED
@@ -5,12 +5,12 @@ require "workbook"
|
|
5
5
|
Gem::Specification.new do |s|
|
6
6
|
s.name = 'workbook'
|
7
7
|
s.rubyforge_project = 'workbook'
|
8
|
-
s.version = '0.
|
9
|
-
s.date = '
|
8
|
+
s.version = '0.2.0'
|
9
|
+
s.date = '2013-01-10'
|
10
10
|
s.summary = "Workbook is a datastructure to contain books of tables (an anlogy used in e.g. Excel)"
|
11
11
|
s.description = "Workbook contains workbooks, as in a table, contains rows, contains cells, reads/writes excels and csv's and tab separated, and offers basic diffing and sorting capabilities."
|
12
12
|
s.authors = ["Maarten Brouwers"]
|
13
|
-
s.add_dependency('spreadsheet', '>= 0.
|
13
|
+
s.add_dependency('spreadsheet', '>= 0.7.5')
|
14
14
|
s.add_dependency('fastercsv')
|
15
15
|
s.add_dependency("rchardet", "~> 1.3")
|
16
16
|
s.add_dependency('rubyXL')
|
metadata
CHANGED
@@ -4,10 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
- 1
|
8
|
-
- 6
|
9
7
|
- 2
|
10
|
-
|
8
|
+
- 0
|
9
|
+
version: 0.2.0
|
11
10
|
platform: ruby
|
12
11
|
authors:
|
13
12
|
- Maarten Brouwers
|
@@ -15,7 +14,7 @@ autorequire:
|
|
15
14
|
bindir: bin
|
16
15
|
cert_chain: []
|
17
16
|
|
18
|
-
date:
|
17
|
+
date: 2013-01-10 00:00:00 +01:00
|
19
18
|
default_executable:
|
20
19
|
dependencies:
|
21
20
|
- !ruby/object:Gem::Dependency
|
@@ -27,9 +26,9 @@ dependencies:
|
|
27
26
|
- !ruby/object:Gem::Version
|
28
27
|
segments:
|
29
28
|
- 0
|
30
|
-
-
|
31
|
-
-
|
32
|
-
version: 0.
|
29
|
+
- 7
|
30
|
+
- 5
|
31
|
+
version: 0.7.5
|
33
32
|
type: :runtime
|
34
33
|
version_requirements: *id001
|
35
34
|
- !ruby/object:Gem::Dependency
|