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 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!