workbook 0.4.3 → 0.4.4
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/.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) [](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!
|