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 CHANGED
@@ -4,4 +4,5 @@ compare*.xls
4
4
  sharepoint_download_excel.*
5
5
  *.gem
6
6
  bin
7
+ Gemfile.lock
7
8
  *.rb~
data/.travis.yml CHANGED
@@ -3,4 +3,5 @@ rvm:
3
3
  - 1.9.3
4
4
  - 1.8.7
5
5
  - jruby-18mode
6
+ - 2.0.0
6
7
  # - jruby-19mode
data/Gemfile CHANGED
@@ -1,4 +1,6 @@
1
1
  source "http://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in workbook.gemspec
4
+
4
5
  gemspec
6
+ gem 'rubyzip', :require => 'zip/zip'
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] # can be any, but I typically have a well
64
- # formatted header row + an example template
65
- # row for the data
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 # to use the symbol style header references,
69
- # the row first needs to be added back to the
70
- # table
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) # you don't want the template to show up
74
- # in the endresult
75
- b.write("result.xls") # write it!
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::Cel class in between.
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 # returns a spreadsheet workbook
117
- b.write_to_xls filename # writes to filename
118
- t.to_csv # returns a csv-string (called on tables)
119
-
120
- In case you want to display the 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.
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 and 1.9.3. 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).
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
@@ -9,6 +9,7 @@ require 'workbook/cell'
9
9
  require 'workbook/format'
10
10
  require 'workbook/template'
11
11
  require 'workbook/version'
12
+ require 'workbook/column'
12
13
 
13
14
  module Workbook
14
15
  class << self
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
- # @param [Workbook::Cell] other cell to compare against, can compare different value-types using #compare_on_class
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 = xlsx_spreadsheet.worksheets.first.cols.collect{|a| a[:attributes][:width].to_f if a[:attributes]}
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
@@ -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
@@ -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)
@@ -1,4 +1,4 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
  module Workbook
3
- VERSION = '0.4.3'
3
+ VERSION = '0.4.4'
4
4
  end
@@ -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 Spreadsheet (from the spreadsheet gem) in order to build an XlS
8
+ # Generates an HTML table ()
9
9
  #
10
10
  # @param [Hash] options A hash with options
11
- # @return [Spreadsheet] A Spreadsheet object, ready for writing or more lower level operations
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 Microsoft Excel format (using the spreadsheet gem)
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
@@ -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 test_duca_sheet
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
- assert_equal(true, (html.match(/colspan="2" rowspan="2">13 mrt 12 15 mrt 12 13 mrt 12 15 mrt 12/) ? true : false) )
52
- assert_equal(true, (html.match(/colspan="2">14 90589/) ? true : false) )
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
- s.add_dependency('nokogiri')
21
- s.add_dependency('rubyzip')
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.3
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: rubyXL
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: nokogiri
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: rubyzip
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!