workbook 0.4.3 → 0.4.4
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/.travis.yml +1 -0
- data/Gemfile +2 -0
- data/README.md +32 -16
- data/lib/workbook.rb +1 -0
- data/lib/workbook/cell.rb +21 -1
- data/lib/workbook/column.rb +30 -0
- data/lib/workbook/readers/ods_reader.rb +3 -3
- data/lib/workbook/readers/xlsx_reader.rb +9 -4
- data/lib/workbook/row.rb +20 -5
- data/lib/workbook/sheet.rb +15 -1
- data/lib/workbook/table.rb +19 -5
- data/lib/workbook/version.rb +1 -1
- data/lib/workbook/writers/csv_table_writer.rb +15 -0
- data/lib/workbook/writers/html_writer.rb +5 -3
- data/lib/workbook/writers/json_table_writer.rb +36 -0
- data/rbeautify.rb +2 -0
- data/test/test_cell.rb +6 -0
- data/test/test_column.rb +15 -0
- data/test/test_readers_ods_reader.rb +3 -2
- data/test/test_readers_xlsx_reader.rb +11 -1
- data/test/test_row.rb +71 -3
- data/test/test_sheet.rb +9 -0
- data/test/test_writers_html_writer.rb +4 -2
- data/test/test_writers_json_writer.rb +19 -0
- data/workbook.gemspec +7 -2
- metadata +26 -5
- data/Gemfile.lock +0 -28
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -60,20 +60,34 @@ simply clone the row, and add it back:
|
|
60
60
|
|
61
61
|
b = Workbook::Book.open("template.xls")
|
62
62
|
table = b.sheet.table
|
63
|
-
template_row = table[1]
|
64
|
-
|
65
|
-
|
63
|
+
template_row = table[1] # can be any, but I typically have a well
|
64
|
+
# formatted header row + an example template
|
65
|
+
# row for the data
|
66
66
|
[1,2,3,4].each do |v|
|
67
67
|
new_row = template_row.clone
|
68
|
-
table << new_row
|
69
|
-
|
70
|
-
|
68
|
+
table << new_row # to use the symbol style header references,
|
69
|
+
# the row first needs to be added back to the
|
70
|
+
# table
|
71
71
|
new_row[:a] = v
|
72
72
|
end
|
73
|
-
table.delete(template_row)
|
74
|
-
|
75
|
-
b.write("result.xls")
|
73
|
+
table.delete(template_row) # you don't want the template to show up
|
74
|
+
# in the endresult
|
75
|
+
b.write("result.xls") # write it!
|
76
76
|
|
77
|
+
Another typical use case is exporting a list of ActiveRecord-objects to xls (it is assumed that the headers of the excel-table correspond
|
78
|
+
(like "Total order price" and `total_order_price` match) to the headers of the database-table ):
|
79
|
+
|
80
|
+
b = Workbook::Book.open("template.xls")
|
81
|
+
table = b.sheet.table
|
82
|
+
template_row = table[1] # see above
|
83
|
+
Order.where("created_at > ?", Time.now - 1.week).each do |order|
|
84
|
+
new_row = template_row.clone
|
85
|
+
new_row.table = table
|
86
|
+
order.to_hash.each{|k,v| row[k]=v}
|
87
|
+
end
|
88
|
+
table.delete(template_row) # you don't want the template to show up
|
89
|
+
# in the endresult
|
90
|
+
b.write("recent_orders.xls") # write it!
|
77
91
|
|
78
92
|
|
79
93
|
<!-- Feature *to implement*:
|
@@ -83,7 +97,7 @@ Feature *to implement*, get a single column:
|
|
83
97
|
t[:b]
|
84
98
|
# returns [<Workbook::Cel @value=2>,<Workbook::Cel @value=4>,<Workbook::Cel @value=6>]
|
85
99
|
|
86
|
-
On my wishlist: In the future I hope to return the cell value directly, without the intermediate Workbook::
|
100
|
+
On my wishlist: In the future I hope to return the cell value directly, without the intermediate Workbook::Cell class in between.
|
87
101
|
|
88
102
|
-->
|
89
103
|
|
@@ -113,15 +127,17 @@ And a new book with a new sheet/table will be returned containing the difference
|
|
113
127
|
|
114
128
|
Currently writing is limited to the following formats. Templating support is still limited.
|
115
129
|
|
116
|
-
b.to_xls
|
117
|
-
b.write_to_xls filename
|
118
|
-
t.to_csv
|
119
|
-
|
120
|
-
|
130
|
+
b.to_xls # returns a spreadsheet workbook
|
131
|
+
b.write_to_xls filename # writes to filename
|
132
|
+
t.(write_)to_csv # returns a csv-string (called on tables)
|
133
|
+
b.(write_)to_html # returns a clean html-page with all tables; unformatted, format-names are used in the classes
|
134
|
+
t.(write_)to_json # returns the values of a table in json
|
135
|
+
|
136
|
+
In case you want to display a formatted table in HTML, some conversion is offered to convert text/background properties to css-entities. Internally the hash storing style elements tries to map to CSS where possible.
|
121
137
|
|
122
138
|
## Compatibility
|
123
139
|
|
124
|
-
Workbook should be compatible with ruby 1.8.7
|
140
|
+
Workbook should be compatible with ruby 1.8.7, 1.9.3, 2.0.0 (jruby 1.8 mode works as well, but currently there are some issues with jruby 1.9 and encoding). Check [Travis for Workbook's current build status](https://travis-ci.org/murb/workbook) [![Build Status](https://travis-ci.org/murb/workbook.png?branch=master)](https://travis-ci.org/murb/workbook).
|
125
141
|
|
126
142
|
## Alternatives
|
127
143
|
|
data/lib/workbook.rb
CHANGED
data/lib/workbook/cell.rb
CHANGED
@@ -36,6 +36,19 @@ module Workbook
|
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
|
+
# Change the current value
|
40
|
+
#
|
41
|
+
# @param [Numeric,String,Time,Date,TrueClass,FalseClass,NilClass] value a valid value
|
42
|
+
def value= value
|
43
|
+
if valid_value? value
|
44
|
+
@value = value
|
45
|
+
else
|
46
|
+
raise ArgumentError, "value should be of a primitive type, e.g. a string, or an integer, not a #{value.class} (is_a? [TrueClass,FalseClass,Date,Time,Numeric,String, NilClass])"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Change the current format
|
51
|
+
#
|
39
52
|
# @param [Workbook::Format, Hash] f set the formatting properties of this Cell
|
40
53
|
def format= f
|
41
54
|
if f.is_a? Workbook::Format
|
@@ -47,10 +60,15 @@ module Workbook
|
|
47
60
|
end
|
48
61
|
end
|
49
62
|
|
63
|
+
# Returns current format
|
64
|
+
#
|
65
|
+
# @returns [Workbook::Format] the current format
|
50
66
|
def format
|
51
67
|
@format ||= Workbook::Format.new
|
52
68
|
end
|
53
69
|
|
70
|
+
# Tests for equality based on its value (formatting is irrelevant)
|
71
|
+
#
|
54
72
|
# @param [Workbook::Cell] other cell to compare against
|
55
73
|
# @return [Boolean]
|
56
74
|
def ==(other)
|
@@ -122,7 +140,9 @@ module Workbook
|
|
122
140
|
v
|
123
141
|
end
|
124
142
|
|
125
|
-
#
|
143
|
+
# Compare
|
144
|
+
# @param [Workbook::Cell] other cell to compare against (based on value), can compare different value-types using #compare_on_class
|
145
|
+
# @returns [Fixnum] -1, 0, 1
|
126
146
|
def <=> other
|
127
147
|
rv = nil
|
128
148
|
begin
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
module Workbook
|
3
|
+
|
4
|
+
# Column helps us to store general properties of a column, and lets us easily perform operations on values within a column
|
5
|
+
class Column
|
6
|
+
attr_accessor :column_type # :primary_key, :string, :text, :integer, :float, :decimal, :datetime, :date, :binary, :boolean.
|
7
|
+
attr_accessor :limit #character limit
|
8
|
+
attr_accessor :default #default cell
|
9
|
+
|
10
|
+
def initialize(options={})
|
11
|
+
options.each{ |k,v| self.public_send("#{k}=",v) }
|
12
|
+
end
|
13
|
+
|
14
|
+
def column_type= column_type
|
15
|
+
if [:primary_key, :string, :text, :integer, :float, :decimal, :datetime, :date, :binary, :boolean].include? column_type
|
16
|
+
@column_type = column_type
|
17
|
+
else
|
18
|
+
raise ArgumentError, "value should be a symbol indicating a primitive type, e.g. a string, or an integer (valid values are: :primary_key, :string, :text, :integer, :float, :decimal, :datetime, :date, :binary, :boolean)"
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def default= value
|
24
|
+
@default = value if value.class == Cell
|
25
|
+
@default = Cell.new(value)
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
@@ -13,7 +13,6 @@ module Workbook
|
|
13
13
|
Zip::ZipFile.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
|
-
|
17
16
|
content = zipfile.read(file.name) if file.name == "content.xml"
|
18
17
|
end
|
19
18
|
end
|
@@ -140,10 +139,11 @@ module Workbook
|
|
140
139
|
value = CGI.unescapeHTML(@cell.xpath("text:p//text()").to_s)
|
141
140
|
value = (value=="") ? nil : value
|
142
141
|
case valuetype
|
143
|
-
when 'float'
|
144
|
-
value = @cell.xpath("@office:value").to_s.to_f
|
145
142
|
when 'integer'
|
146
143
|
value = @cell.xpath("@office:value").to_s.to_i
|
144
|
+
when 'float'
|
145
|
+
value = @cell.xpath("@office:value").to_s.to_f
|
146
|
+
value = value.to_i unless @cell.xpath("@office:value").to_s.match(/\./) #sadly most integers are typed as floats...
|
147
147
|
when 'date'
|
148
148
|
value = DateTime.parse(@cell.xpath("@office:date-value").to_s)
|
149
149
|
end
|
@@ -7,6 +7,7 @@ module RubyXL
|
|
7
7
|
|
8
8
|
# Improves upon date format detection
|
9
9
|
def is_date_format?(num_fmt)
|
10
|
+
num_fmt = num_fmt.to_s
|
10
11
|
num_fmt.downcase!
|
11
12
|
skip_chars = ['$', '-', '+', '/', '(', ')', ':', ' ']
|
12
13
|
num_chars = ['0', '#', '?']
|
@@ -142,7 +143,12 @@ module Workbook
|
|
142
143
|
#number_of_worksheets = xlsx_spreadsheet.worksheets.count
|
143
144
|
xlsx_spreadsheet.worksheets.each_with_index do |worksheet, si|
|
144
145
|
s = create_or_open_sheet_at(si)
|
145
|
-
col_widths =
|
146
|
+
col_widths = []
|
147
|
+
begin
|
148
|
+
col_widths = xlsx_spreadsheet.worksheets.first.cols.collect{|a| a[:attributes][:width].to_f if a[:attributes]}
|
149
|
+
rescue
|
150
|
+
# Column widths couldn't be read, no big deal...
|
151
|
+
end
|
146
152
|
worksheet.each_with_index do |row, ri|
|
147
153
|
r = s.table.create_or_open_row_at(ri)
|
148
154
|
|
@@ -173,11 +179,10 @@ module Workbook
|
|
173
179
|
end
|
174
180
|
end
|
175
181
|
end
|
176
|
-
private
|
177
182
|
def ms_formatting_to_strftime ms_nr_format
|
178
183
|
if ms_nr_format
|
179
|
-
ms_nr_format = ms_nr_format.downcase
|
180
|
-
return nil if ms_nr_format == 'general'
|
184
|
+
ms_nr_format = ms_nr_format.to_s.downcase
|
185
|
+
return nil if ms_nr_format == 'general' or ms_nr_format == ""
|
181
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('\\','')
|
182
187
|
end
|
183
188
|
end
|
data/lib/workbook/row.rb
CHANGED
@@ -161,13 +161,28 @@ module Workbook
|
|
161
161
|
#
|
162
162
|
# @return [Hash]
|
163
163
|
def to_hash
|
164
|
-
return @hash if @hash
|
164
|
+
#return @hash if @hash
|
165
165
|
keys = table_header_keys
|
166
166
|
values = self
|
167
167
|
@hash = {}
|
168
168
|
keys.each_with_index {|k,i| @hash[k]=values[i]}
|
169
169
|
return @hash
|
170
170
|
end
|
171
|
+
|
172
|
+
# Returns a hash representation of this row
|
173
|
+
#
|
174
|
+
# it differs from #to_hash as it doesn't contain the Workbook's Workbook::Cell-objects,
|
175
|
+
# but the actual values contained in these cells
|
176
|
+
#
|
177
|
+
# @return [Hash]
|
178
|
+
|
179
|
+
def to_hash_with_values
|
180
|
+
keys = table_header_keys
|
181
|
+
values = self
|
182
|
+
@hash_with_values = {}
|
183
|
+
keys.each_with_index {|k,i| v=values[i]; v=v.value if v; @hash_with_values[k]=v}
|
184
|
+
return @hash_with_values
|
185
|
+
end
|
171
186
|
|
172
187
|
# Compares one row wiht another
|
173
188
|
#
|
@@ -199,7 +214,7 @@ module Workbook
|
|
199
214
|
def clone
|
200
215
|
Workbook::Row.new(to_a.collect{|c| c.clone})
|
201
216
|
end
|
202
|
-
|
217
|
+
|
203
218
|
# remove all the trailing nil-cells (returning a trimmed clone)
|
204
219
|
#
|
205
220
|
# @param [Integer] desired_length of the new row
|
@@ -207,14 +222,14 @@ module Workbook
|
|
207
222
|
def trim(desired_length=nil)
|
208
223
|
self.clone.trim!(desired_length)
|
209
224
|
end
|
210
|
-
|
225
|
+
|
211
226
|
# remove all the trailing nil-cells (returning a trimmed self)
|
212
227
|
#
|
213
228
|
# @param [Integer] desired_length of the new row
|
214
229
|
# @return [Workbook::Row] self
|
215
230
|
def trim!(desired_length=nil)
|
216
231
|
self_count = self.count-1
|
217
|
-
self.count.times do |index|
|
232
|
+
self.count.times do |index|
|
218
233
|
index = self_count - index
|
219
234
|
if desired_length and index < desired_length
|
220
235
|
break
|
@@ -227,7 +242,7 @@ module Workbook
|
|
227
242
|
end
|
228
243
|
end
|
229
244
|
(desired_length - self.count).times{|a| self << (Workbook::Cell.new(nil))} if desired_length and (desired_length - self.count) > 0
|
230
|
-
self
|
245
|
+
self
|
231
246
|
end
|
232
247
|
end
|
233
248
|
end
|
data/lib/workbook/sheet.rb
CHANGED
@@ -34,7 +34,21 @@ module Workbook
|
|
34
34
|
def table
|
35
35
|
first
|
36
36
|
end
|
37
|
-
|
37
|
+
|
38
|
+
# Set the first table of this sheet with a table or array of cells/values
|
39
|
+
# @param [Workbook::Table, Array<Array>] table The new first table of this sheet
|
40
|
+
# @param [Hash] options are forwarded to Workbook::Table.new
|
41
|
+
|
42
|
+
# @return [Workbook::Table] the first table of this sheet
|
43
|
+
def table= table, options={}
|
44
|
+
if table.is_a? Workbook::Table
|
45
|
+
self[0] = table
|
46
|
+
else
|
47
|
+
self[0] = Workbook::Table.new(table, self, options)
|
48
|
+
end
|
49
|
+
return table
|
50
|
+
end
|
51
|
+
|
38
52
|
# Returns the book this sheet belongs to
|
39
53
|
#
|
40
54
|
# @return [Workbook::Book] the book this sheet belongs to
|
data/lib/workbook/table.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
2
2
|
require 'workbook/modules/table_diff_sort'
|
3
3
|
require 'workbook/writers/csv_table_writer'
|
4
|
+
require 'workbook/writers/json_table_writer'
|
4
5
|
|
5
6
|
|
6
7
|
module Workbook
|
@@ -8,6 +9,7 @@ module Workbook
|
|
8
9
|
class Table < Array
|
9
10
|
include Workbook::Modules::TableDiffSort
|
10
11
|
include Workbook::Writers::CsvTableWriter
|
12
|
+
include Workbook::Writers::JsonTableWriter
|
11
13
|
attr_accessor :sheet
|
12
14
|
attr_accessor :name
|
13
15
|
attr_accessor :header
|
@@ -58,7 +60,7 @@ module Workbook
|
|
58
60
|
self.delete_if{|r| r.nil? or r.compact.empty?}
|
59
61
|
self
|
60
62
|
end
|
61
|
-
|
63
|
+
|
62
64
|
# Add row
|
63
65
|
# @param [Workbook::Table, Array] row to add
|
64
66
|
def push(row)
|
@@ -74,7 +76,19 @@ module Workbook
|
|
74
76
|
super(row)
|
75
77
|
row.set_table(self)
|
76
78
|
end
|
77
|
-
|
79
|
+
|
80
|
+
# Overrides normal Row's []=-function; automatically converting to row and setting
|
81
|
+
# with the label correctly
|
82
|
+
#
|
83
|
+
# @param [Fixnum] index
|
84
|
+
# @param [Workbook::Table, Array] row to set
|
85
|
+
# @return [Workbook::Cell, nil]
|
86
|
+
def []= (index, row)
|
87
|
+
row = Workbook::Row.new(row) if row.class == Array
|
88
|
+
super(index,row)
|
89
|
+
row.set_table(self)
|
90
|
+
end
|
91
|
+
|
78
92
|
def has_contents?
|
79
93
|
self.clone.remove_empty_lines!.count != 0
|
80
94
|
end
|
@@ -152,7 +166,7 @@ module Workbook
|
|
152
166
|
end
|
153
167
|
return sum-1
|
154
168
|
end
|
155
|
-
|
169
|
+
|
156
170
|
# remove all the trailing empty-rows (returning a trimmed clone)
|
157
171
|
#
|
158
172
|
# @param [Integer] desired_row_length of the rows
|
@@ -160,7 +174,7 @@ module Workbook
|
|
160
174
|
def trim(desired_row_length=nil)
|
161
175
|
self.clone.trim!(desired_row_length)
|
162
176
|
end
|
163
|
-
|
177
|
+
|
164
178
|
# remove all the trailing empty-rows (returning a trimmed self)
|
165
179
|
#
|
166
180
|
# @param [Integer] desired_row_length of the new row
|
@@ -168,7 +182,7 @@ module Workbook
|
|
168
182
|
def trim!(desired_row_length=nil)
|
169
183
|
max_length = self.collect{|a| a.trim.length }.max
|
170
184
|
self_count = self.count-1
|
171
|
-
self.count.times do |index|
|
185
|
+
self.count.times do |index|
|
172
186
|
index = self_count - index
|
173
187
|
if self[index].trim.empty?
|
174
188
|
self.delete_at(index)
|
data/lib/workbook/version.rb
CHANGED
@@ -4,6 +4,11 @@ require 'csv'
|
|
4
4
|
module Workbook
|
5
5
|
module Writers
|
6
6
|
module CsvTableWriter
|
7
|
+
# Output the current workbook to CSV format
|
8
|
+
#
|
9
|
+
# @param [String] filename
|
10
|
+
# @param [Hash] options (not used)
|
11
|
+
# @return [String] csv (comma separated values in a string)
|
7
12
|
def to_csv options={}
|
8
13
|
csv = ""
|
9
14
|
options = {}.merge options
|
@@ -18,6 +23,16 @@ module Workbook
|
|
18
23
|
end
|
19
24
|
csv
|
20
25
|
end
|
26
|
+
|
27
|
+
# Write the current workbook to CSV format
|
28
|
+
#
|
29
|
+
# @param [String] filename
|
30
|
+
# @param [Hash] options see #to_csv
|
31
|
+
# @return [String] filename
|
32
|
+
def write_to_csv filename="#{title}.csv", options={}
|
33
|
+
File.open(filename, 'w') {|f| f.write(to_csv(options)) }
|
34
|
+
return filename
|
35
|
+
end
|
21
36
|
|
22
37
|
end
|
23
38
|
end
|
@@ -5,10 +5,10 @@ module Workbook
|
|
5
5
|
module Writers
|
6
6
|
module HtmlWriter
|
7
7
|
|
8
|
-
# Generates an
|
8
|
+
# Generates an HTML table ()
|
9
9
|
#
|
10
10
|
# @param [Hash] options A hash with options
|
11
|
-
# @return [
|
11
|
+
# @return [String] A String containing the HTML code
|
12
12
|
def to_html options={}
|
13
13
|
options = {:style_with_inline_css=>false}.merge(options)
|
14
14
|
builder = Nokogiri::XML::Builder.new do |doc|
|
@@ -50,10 +50,12 @@ module Workbook
|
|
50
50
|
|
51
51
|
|
52
52
|
|
53
|
-
# Write the current workbook to
|
53
|
+
# Write the current workbook to HTML format
|
54
54
|
#
|
55
55
|
# @param [String] filename
|
56
56
|
# @param [Hash] options see #to_xls
|
57
|
+
# @return [String] filename
|
58
|
+
|
57
59
|
def write_to_html filename="#{title}.html", options={}
|
58
60
|
File.open(filename, 'w') {|f| f.write(to_html(options)) }
|
59
61
|
return filename
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module Workbook
|
5
|
+
module Writers
|
6
|
+
module JsonTableWriter
|
7
|
+
# Output the current workbook to JSON format
|
8
|
+
#
|
9
|
+
# @param [Hash] options
|
10
|
+
# @return [String] json string
|
11
|
+
def to_json options={}
|
12
|
+
JSON.generate(to_array_of_hashes_with_values(options))
|
13
|
+
end
|
14
|
+
|
15
|
+
# Output the current workbook to an array_of_hashes_with_values format
|
16
|
+
#
|
17
|
+
# @param [Hash] options
|
18
|
+
# @return [Array<Hash>] array with hashes (comma separated values in a string)
|
19
|
+
def to_array_of_hashes_with_values options={}
|
20
|
+
array_of_hashes = self.collect{|a| a.to_hash_with_values unless a.header?}.compact
|
21
|
+
return array_of_hashes
|
22
|
+
end
|
23
|
+
|
24
|
+
# Write the current workbook to JSON format
|
25
|
+
#
|
26
|
+
# @param [String] filename
|
27
|
+
# @param [Hash] options see #to_json
|
28
|
+
# @return [String] filename
|
29
|
+
def write_to_json filename="#{title}.json", options={}
|
30
|
+
File.open(filename, 'w') {|f| f.write(to_json(options)) }
|
31
|
+
return filename
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/rbeautify.rb
CHANGED
@@ -20,6 +20,8 @@
|
|
20
20
|
* Free Software Foundation, Inc., *
|
21
21
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
22
22
|
***************************************************************************/
|
23
|
+
|
24
|
+
To recursively execute this script run: `find . -name "*.rb"|xargs ./rbeautify.rb`
|
23
25
|
=end
|
24
26
|
|
25
27
|
PVERSION = "Version 2.9, 10/24/2008"
|
data/test/test_cell.rb
CHANGED
@@ -25,6 +25,12 @@ class TestCell < Test::Unit::TestCase
|
|
25
25
|
assert_equal("asdf",w.value)
|
26
26
|
w.value = Date.new
|
27
27
|
assert_equal(Date.new,w.value)
|
28
|
+
w.value = 1
|
29
|
+
assert_equal(1,w.value)
|
30
|
+
assert_equal(Fixnum,w.value.class)
|
31
|
+
w.value = 1.0
|
32
|
+
assert_equal(1.0,w.value)
|
33
|
+
assert_equal(Float,w.value.class)
|
28
34
|
end
|
29
35
|
|
30
36
|
def test_comp
|
data/test/test_column.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require File.join(File.dirname(__FILE__), 'helper')
|
3
|
+
|
4
|
+
class TestRow < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def test_init
|
7
|
+
c = Workbook::Column.new
|
8
|
+
assert_equal(Workbook::Column, c.class)
|
9
|
+
c = Workbook::Column.new({:limit=>20,:default=>"asdf", :column_type=>:boolean})
|
10
|
+
assert_equal(20, c.limit)
|
11
|
+
assert_equal(Workbook::Cell.new("asdf"), c.default)
|
12
|
+
assert_equal(:boolean, c.column_type)
|
13
|
+
assert_raise(ArgumentError) { Workbook::Column.new({:limit=>20,:default=>"asdf", :column_type=>:bodfolean}) }
|
14
|
+
end
|
15
|
+
end
|
@@ -6,6 +6,7 @@ module Readers
|
|
6
6
|
|
7
7
|
w = Workbook::Book.new
|
8
8
|
w.open File.join(File.dirname(__FILE__), 'artifacts/book_with_tabs_and_colours.ods')
|
9
|
+
|
9
10
|
assert_equal([:a, :b, :c, :d, :e],w.sheet.table.header.to_symbols)
|
10
11
|
assert_equal(90588,w.sheet.table[2][:b].value)
|
11
12
|
end
|
@@ -37,7 +38,7 @@ module Readers
|
|
37
38
|
assert_equal(Date.new(2012,2,22),w.sheet.table[1][:a].value)
|
38
39
|
assert_equal("c",w.sheet.table[2][:a].value)
|
39
40
|
assert_equal(DateTime.new(2012,1,22,11),w.sheet.table[3][:a].value)
|
40
|
-
assert_equal(42000,w.sheet.table[3][:b].value)
|
41
|
+
assert_equal("42000",w.sheet.table[3][:b].value.to_s)
|
41
42
|
assert_equal(nil,w.sheet.table[2][:c].value)
|
42
43
|
end
|
43
44
|
|
@@ -55,7 +56,7 @@ module Readers
|
|
55
56
|
assert_equal(2,t["D5"].colspan)
|
56
57
|
end
|
57
58
|
|
58
|
-
def
|
59
|
+
def test_book_with_colspans
|
59
60
|
w = Workbook::Book.new
|
60
61
|
w.open File.join(File.dirname(__FILE__), 'artifacts/book_with_colspans.ods')
|
61
62
|
t = w.sheet.table
|
@@ -24,6 +24,16 @@ module Readers
|
|
24
24
|
assert_equal("2012-12-03T12:30:00+00:00",w.sheet.table[7][:datum_gemeld].value.to_s)
|
25
25
|
assert_equal("2012-12-03T09:4",w.sheet.table[6][:datum_gemeld].value.to_s[0..14])
|
26
26
|
end
|
27
|
-
|
27
|
+
def test_ms_formatting_to_strftime
|
28
|
+
w = Workbook::Book.new
|
29
|
+
assert_equal(nil,w.ms_formatting_to_strftime(nil));
|
30
|
+
assert_equal(nil,w.ms_formatting_to_strftime(""));
|
31
|
+
end
|
32
|
+
def test_monkey_patched_ruby_xl_is_date_format?
|
33
|
+
w = RubyXL::Workbook.new
|
34
|
+
assert_equal(false, w.is_date_format?(nil))
|
35
|
+
assert_equal(false, w.is_date_format?(""))
|
36
|
+
assert_equal(true, w.is_date_format?("D-M-YYY"))
|
37
|
+
end
|
28
38
|
end
|
29
39
|
end
|
data/test/test_row.rb
CHANGED
@@ -104,6 +104,35 @@ class TestRow < Test::Unit::TestCase
|
|
104
104
|
assert_equal(date, r2[:asdfasd].value)
|
105
105
|
assert_equal(date, r2[1].value)
|
106
106
|
end
|
107
|
+
|
108
|
+
|
109
|
+
def test_to_hash_with_values
|
110
|
+
t = Workbook::Table.new
|
111
|
+
r1 = Workbook::Row.new ["test", "asdf-asd"]
|
112
|
+
r1.table = t
|
113
|
+
expected = {:test=>"test", :asdfasd=>"asdf-asd"}
|
114
|
+
assert_equal(expected, r1.to_hash_with_values)
|
115
|
+
date = DateTime.now
|
116
|
+
r2 = Workbook::Row.new [2, date]
|
117
|
+
r2.table = t
|
118
|
+
expected = {:test=>2, :asdfasd=>date}
|
119
|
+
assert_equal(expected, r2.to_hash_with_values)
|
120
|
+
end
|
121
|
+
|
122
|
+
def test_to_hash_cache
|
123
|
+
t = Workbook::Table.new
|
124
|
+
t << ["test", "asdf-asd"]
|
125
|
+
t << [1, 2]
|
126
|
+
r = t.last
|
127
|
+
assert_equal(1, r[:test].value)
|
128
|
+
t.last[0].value = 3
|
129
|
+
assert_equal(3, r[:test].value)
|
130
|
+
assert_equal(3, r[:test].value)
|
131
|
+
t.last[:test] = nil
|
132
|
+
assert_equal(nil, r[:test].value)
|
133
|
+
r[:test] = 5
|
134
|
+
assert_equal(5, r[:test].value)
|
135
|
+
end
|
107
136
|
|
108
137
|
def test_compare
|
109
138
|
r1 = Workbook::Row.new ["test", "asdf-asd"]
|
@@ -156,7 +185,6 @@ class TestRow < Test::Unit::TestCase
|
|
156
185
|
end
|
157
186
|
|
158
187
|
def test_clone_has_no_table
|
159
|
-
# actually not desired, but for now enforced.
|
160
188
|
b = Workbook::Book.new
|
161
189
|
table = b.sheet.table
|
162
190
|
table << Workbook::Row.new(["a","b"])
|
@@ -168,6 +196,46 @@ class TestRow < Test::Unit::TestCase
|
|
168
196
|
assert_equal(2,row[1].value)
|
169
197
|
end
|
170
198
|
|
199
|
+
def test_push
|
200
|
+
b = Workbook::Book.new
|
201
|
+
table = b.sheet.table
|
202
|
+
table << Workbook::Row.new(["a","b"])
|
203
|
+
table << Workbook::Row.new([1,2])
|
204
|
+
assert_equal(1,table[1][:a].value)
|
205
|
+
assert_equal(2,table[1][:b].value)
|
206
|
+
b = Workbook::Book.new
|
207
|
+
table = b.sheet.table
|
208
|
+
table.push Workbook::Row.new(["a","b"])
|
209
|
+
table.push Workbook::Row.new([1,2])
|
210
|
+
assert_equal(1,table[1][:a].value)
|
211
|
+
assert_equal(2,table[1][:b].value)
|
212
|
+
end
|
213
|
+
|
214
|
+
def test_assign
|
215
|
+
b = Workbook::Book.new
|
216
|
+
table = b.sheet.table
|
217
|
+
table.push Workbook::Row.new(["a","b"])
|
218
|
+
table[1] = Workbook::Row.new([1,2])
|
219
|
+
assert_equal(1,table[1][:a].value)
|
220
|
+
assert_equal(2,table[1][:b].value)
|
221
|
+
|
222
|
+
b = Workbook::Book.new
|
223
|
+
table = b.sheet.table
|
224
|
+
table.push Workbook::Row.new(["a","b"])
|
225
|
+
table[1] = [1,2]
|
226
|
+
assert_equal(1,table[1][:a].value)
|
227
|
+
assert_equal(2,table[1][:b].value)
|
228
|
+
end
|
229
|
+
|
230
|
+
def test_preservation_of_format_on_assign
|
231
|
+
row = Workbook::Row.new([1,2])
|
232
|
+
cellformat = row.first.format
|
233
|
+
cellformat["background"]="#f00"
|
234
|
+
row[0] = 3
|
235
|
+
assert_equal(3,row[0].value)
|
236
|
+
assert_equal("#f00",row[0].format["background"])
|
237
|
+
end
|
238
|
+
|
171
239
|
def test_row_hash_index_assignment
|
172
240
|
b = Workbook::Book.new
|
173
241
|
table = b.sheet.table
|
@@ -178,7 +246,7 @@ class TestRow < Test::Unit::TestCase
|
|
178
246
|
row[:b]= 15
|
179
247
|
assert_equal(15, table.last.last.value)
|
180
248
|
end
|
181
|
-
|
249
|
+
|
182
250
|
def test_trim!
|
183
251
|
a = Workbook::Row.new
|
184
252
|
a[0] = 1
|
@@ -230,7 +298,7 @@ class TestRow < Test::Unit::TestCase
|
|
230
298
|
a.trim!(1)
|
231
299
|
assert_equal(b, a)
|
232
300
|
end
|
233
|
-
|
301
|
+
|
234
302
|
def test_trim
|
235
303
|
a = Workbook::Row.new
|
236
304
|
a[0] = nil
|
data/test/test_sheet.rb
CHANGED
@@ -21,7 +21,16 @@ class TestWorkbook < Test::Unit::TestCase
|
|
21
21
|
t = Workbook::Table.new []
|
22
22
|
w = Workbook::Sheet.new t
|
23
23
|
assert_equal(w.table,t)
|
24
|
+
end
|
24
25
|
|
26
|
+
def test_table_assignment
|
27
|
+
t = Workbook::Table.new []
|
28
|
+
s = Workbook::Sheet.new t
|
29
|
+
assert_equal(s.table,t)
|
30
|
+
data = [["a","b"],[1,2]]
|
31
|
+
s.table=data
|
32
|
+
assert_equal("a",s.table["A1"].value)
|
33
|
+
assert_equal(2,s.table["B2"].value)
|
25
34
|
end
|
26
35
|
|
27
36
|
def test_book
|
@@ -48,8 +48,10 @@ module Writers
|
|
48
48
|
w.open File.join(File.dirname(__FILE__), 'artifacts/sheet_with_combined_cells.ods')
|
49
49
|
html = w.to_html
|
50
50
|
assert_equal(true, (html.match(/rowspan="2">15 nov 11 15 nov 11/) ? true : false) )
|
51
|
-
|
52
|
-
|
51
|
+
if RUBY_VERSION >= "1.9"
|
52
|
+
assert_equal(true, (html.match(/colspan="2" rowspan="2">13 mrt 12 15 mrt 12 13 mrt 12 15 mrt 12/) ? true : false) )
|
53
|
+
assert_equal(true, (html.match(/colspan="2">14 90589/) ? true : false) )
|
54
|
+
end
|
53
55
|
end
|
54
56
|
end
|
55
57
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require File.join(File.dirname(__FILE__), 'helper')
|
3
|
+
|
4
|
+
module Writers
|
5
|
+
class TestJsonWriter < Test::Unit::TestCase
|
6
|
+
def test_to_array_of_hashes_with_values
|
7
|
+
assert_equal([],Workbook::Table.new.to_array_of_hashes_with_values)
|
8
|
+
assert_equal([],Workbook::Table.new([["a","b"]]).to_array_of_hashes_with_values)
|
9
|
+
assert_equal([{:a=>1,:b=>2},{:a=>Date.new(2012,1,1),:b=>nil}],
|
10
|
+
Workbook::Table.new([["a","b"],[1,2],[Date.new(2012,1,1),nil]]).to_array_of_hashes_with_values)
|
11
|
+
end
|
12
|
+
def test_to_json
|
13
|
+
assert_equal("[]",Workbook::Table.new.to_json)
|
14
|
+
assert_equal("[]",Workbook::Table.new([["a","b"]]).to_json)
|
15
|
+
assert_equal("[{\"a\":1,\"b\":2},{\"a\":\"2012-01-01\",\"b\":null}]",
|
16
|
+
Workbook::Table.new([["a","b"],[1,2],[Date.new(2012,1,1),nil]]).to_json)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/workbook.gemspec
CHANGED
@@ -12,13 +12,18 @@ Gem::Specification.new do |s|
|
|
12
12
|
s.summary = "Workbook is a datastructure to contain books of tables (an anlogy used in e.g. Excel)"
|
13
13
|
s.description = "Workbook contains workbooks, as in a table, contains rows, contains cells, reads/writes excel, ods and csv and tab separated files, and offers basic diffing and sorting capabilities."
|
14
14
|
s.authors = ["Maarten Brouwers"]
|
15
|
+
s.add_dependency('rubyzip', '0.9.9')
|
15
16
|
s.add_dependency('spreadsheet', '>= 0.7.5')
|
16
17
|
s.add_dependency('fastercsv') if RUBY_VERSION < "1.9"
|
17
18
|
s.add_dependency("rchardet", "~> 1.3")
|
18
19
|
s.add_dependency("rake")
|
20
|
+
s.add_dependency("json")
|
19
21
|
s.add_dependency('rubyXL')
|
20
|
-
|
21
|
-
|
22
|
+
if RUBY_VERSION < "1.9"
|
23
|
+
s.add_dependency('nokogiri', "~> 1.5.10")
|
24
|
+
else
|
25
|
+
s.add_dependency('nokogiri')
|
26
|
+
end
|
22
27
|
s.platform = Gem::Platform::RUBY
|
23
28
|
s.files = `git ls-files`.split($/)
|
24
29
|
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: workbook
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -11,6 +11,22 @@ bindir: bin
|
|
11
11
|
cert_chain: []
|
12
12
|
date: 2013-04-05 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rubyzip
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - '='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.9.9
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - '='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 0.9.9
|
14
30
|
- !ruby/object:Gem::Dependency
|
15
31
|
name: spreadsheet
|
16
32
|
requirement: !ruby/object:Gem::Requirement
|
@@ -60,7 +76,7 @@ dependencies:
|
|
60
76
|
- !ruby/object:Gem::Version
|
61
77
|
version: '0'
|
62
78
|
- !ruby/object:Gem::Dependency
|
63
|
-
name:
|
79
|
+
name: json
|
64
80
|
requirement: !ruby/object:Gem::Requirement
|
65
81
|
none: false
|
66
82
|
requirements:
|
@@ -76,7 +92,7 @@ dependencies:
|
|
76
92
|
- !ruby/object:Gem::Version
|
77
93
|
version: '0'
|
78
94
|
- !ruby/object:Gem::Dependency
|
79
|
-
name:
|
95
|
+
name: rubyXL
|
80
96
|
requirement: !ruby/object:Gem::Requirement
|
81
97
|
none: false
|
82
98
|
requirements:
|
@@ -92,7 +108,7 @@ dependencies:
|
|
92
108
|
- !ruby/object:Gem::Version
|
93
109
|
version: '0'
|
94
110
|
- !ruby/object:Gem::Dependency
|
95
|
-
name:
|
111
|
+
name: nokogiri
|
96
112
|
requirement: !ruby/object:Gem::Requirement
|
97
113
|
none: false
|
98
114
|
requirements:
|
@@ -123,7 +139,6 @@ files:
|
|
123
139
|
- .yardoc/objects/root.dat
|
124
140
|
- .yardoc/proxy_types
|
125
141
|
- Gemfile
|
126
|
-
- Gemfile.lock
|
127
142
|
- LICENSE.txt
|
128
143
|
- README.md
|
129
144
|
- Rakefile
|
@@ -171,6 +186,7 @@ files:
|
|
171
186
|
- lib/workbook.rb
|
172
187
|
- lib/workbook/book.rb
|
173
188
|
- lib/workbook/cell.rb
|
189
|
+
- lib/workbook/column.rb
|
174
190
|
- lib/workbook/format.rb
|
175
191
|
- lib/workbook/modules/raw_objects_storage.rb
|
176
192
|
- lib/workbook/modules/table_diff_sort.rb
|
@@ -189,6 +205,7 @@ files:
|
|
189
205
|
- lib/workbook/version.rb
|
190
206
|
- lib/workbook/writers/csv_table_writer.rb
|
191
207
|
- lib/workbook/writers/html_writer.rb
|
208
|
+
- lib/workbook/writers/json_table_writer.rb
|
192
209
|
- lib/workbook/writers/xls_writer.rb
|
193
210
|
- rbeautify.rb
|
194
211
|
- test/artifacts/book_with_colspans.ods
|
@@ -216,6 +233,7 @@ files:
|
|
216
233
|
- test/helper.rb
|
217
234
|
- test/test_book.rb
|
218
235
|
- test/test_cell.rb
|
236
|
+
- test/test_column.rb
|
219
237
|
- test/test_format.rb
|
220
238
|
- test/test_functional.rb
|
221
239
|
- test/test_modules_table_diff_sort.rb
|
@@ -230,6 +248,7 @@ files:
|
|
230
248
|
- test/test_table.rb
|
231
249
|
- test/test_template.rb
|
232
250
|
- test/test_writers_html_writer.rb
|
251
|
+
- test/test_writers_json_writer.rb
|
233
252
|
- test/test_writers_xls_writer.rb
|
234
253
|
- workbook.gemspec
|
235
254
|
homepage: http://murb.nl/blog?tags=workbook
|
@@ -283,6 +302,7 @@ test_files:
|
|
283
302
|
- test/helper.rb
|
284
303
|
- test/test_book.rb
|
285
304
|
- test/test_cell.rb
|
305
|
+
- test/test_column.rb
|
286
306
|
- test/test_format.rb
|
287
307
|
- test/test_functional.rb
|
288
308
|
- test/test_modules_table_diff_sort.rb
|
@@ -297,5 +317,6 @@ test_files:
|
|
297
317
|
- test/test_table.rb
|
298
318
|
- test/test_template.rb
|
299
319
|
- test/test_writers_html_writer.rb
|
320
|
+
- test/test_writers_json_writer.rb
|
300
321
|
- test/test_writers_xls_writer.rb
|
301
322
|
has_rdoc:
|
data/Gemfile.lock
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
workbook (0.4.2)
|
5
|
-
nokogiri
|
6
|
-
rake
|
7
|
-
rchardet (~> 1.3)
|
8
|
-
rubyXL
|
9
|
-
rubyzip
|
10
|
-
spreadsheet (>= 0.7.5)
|
11
|
-
|
12
|
-
GEM
|
13
|
-
remote: http://rubygems.org/
|
14
|
-
specs:
|
15
|
-
nokogiri (1.5.9)
|
16
|
-
rake (10.0.4)
|
17
|
-
rchardet (1.3.1)
|
18
|
-
ruby-ole (1.2.11.6)
|
19
|
-
rubyXL (1.2.10)
|
20
|
-
rubyzip (0.9.9)
|
21
|
-
spreadsheet (0.8.5)
|
22
|
-
ruby-ole (>= 1.0)
|
23
|
-
|
24
|
-
PLATFORMS
|
25
|
-
ruby
|
26
|
-
|
27
|
-
DEPENDENCIES
|
28
|
-
workbook!
|