workbook 0.4.9 → 0.4.10

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.
@@ -5,8 +5,9 @@ module Workbook
5
5
  module RawObjectsStorage
6
6
 
7
7
  # A raw is a 'raw' object, representing a workbook, or cell, or whatever... in a particular format (defined by its class)
8
- def add_raw raw_object
9
- raws[raw_object.class]=raw_object
8
+ def add_raw raw_object, options={}
9
+ class_of_obj = options[:raw_object_class] ? options[:raw_object_class] : raw_object.class
10
+ raws[class_of_obj]=raw_object
10
11
  end
11
12
 
12
13
  # Returns true if there is a template for a certain class, otherwise false
@@ -1,5 +1,5 @@
1
1
  # -*- encoding : utf-8 -*-
2
- require 'rubyXL'
2
+ require 'roo'
3
3
  require 'workbook/readers/xls_shared'
4
4
 
5
5
 
@@ -16,55 +16,22 @@ module Workbook
16
16
  end
17
17
  def load_xlsx file_obj
18
18
  file_obj = file_obj.path if file_obj.is_a? File
19
- sp = RubyXL::Parser.parse(file_obj)
20
- template.add_raw sp
19
+ # file_obj = file_obj.match(/^\/(.*)/) ? file_obj : "./#{file_obj}"
20
+ # p "opening #{file_obj}"
21
+ sp = Roo::Excelx.new(file_obj)
22
+ template.add_raw sp, raw_object_class: Roo::Spreadsheet
21
23
  parse_xlsx sp
22
24
  end
23
25
 
24
- def parse_xlsx xlsx_spreadsheet=template.raws[RubyXL::Workbook], options={}
26
+ def parse_xlsx xlsx_spreadsheet=template.raws[Roo::Spreadsheet], options={}
25
27
  options = {:additional_type_parsing=>false}.merge options
26
- #number_of_worksheets = xlsx_spreadsheet.worksheets.count
27
- xlsx_spreadsheet.worksheets.each_with_index do |worksheet, si|
28
- s = create_or_open_sheet_at(si)
29
- col_widths = []
30
- begin
31
- col_widths = xlsx_spreadsheet.worksheets.first.cols.collect{|a| a[:attributes][:width].to_f if a[:attributes]}
32
- rescue
33
- # Column widths couldn't be read, no big deal...
34
- end
35
-
36
- worksheet.each_with_index do |row, ri|
37
- if row
38
- r = s.table.create_or_open_row_at(ri)
39
- row.cells.each_with_index do |cell,ci|
40
- if cell.nil?
41
- r[ci] = Workbook::Cell.new nil
42
- else
43
- r[ci] = Workbook::Cell.new cell.value
44
- r[ci].parse!
45
- xls_format = cell.style_index
46
- col_width = nil
47
-
48
- if ri == 0
49
- col_width = col_widths[ci]
50
- end
51
- f = template.create_or_find_format_by "style_index_#{cell.style_index}", col_width
52
- f[:width]= col_width
53
- background_color = cell.fill_color
54
- background_color = (background_color.length == 8) ? background_color[2..8] : background_color #ignoring alpha for now.
55
- f[:background_color] = "##{background_color}"
56
-
57
- f[:number_format] = ms_formatting_to_strftime(cell.number_format)
58
- # f[:font_family] = cell.font_name
59
- # f[:color] = "##{cell.font_color}"
60
-
61
- f.add_raw xls_format
62
-
63
- r[ci].format = f
64
- end
65
- end
66
- end
28
+ sheet_index = 0
29
+ xlsx_spreadsheet.each_with_pagename do |sheet_name, sheet|
30
+ s = create_or_open_sheet_at(sheet_index)
31
+ sheet.each_with_index do |row, rowi|
32
+ s.table << row
67
33
  end
34
+ sheet_index += 1
68
35
  end
69
36
  end
70
37
  end
data/lib/workbook/row.rb CHANGED
@@ -20,7 +20,7 @@ module Workbook
20
20
  cells.each do |c|
21
21
  c = c.clone if options[:clone_cells]
22
22
  unless c.is_a? Workbook::Cell
23
- c = Workbook::Cell.new(c)
23
+ c = Workbook::Cell.new(c, {row:self})
24
24
  c.parse!(options[:cell_parse_options]) if options[:parse_cells_on_batch_creation]
25
25
  end
26
26
  push c
@@ -62,14 +62,14 @@ module Workbook
62
62
  # Add cell
63
63
  # @param [Workbook::Cell, Numeric,String,Time,Date,TrueClass,FalseClass,NilClass] cell or value to add
64
64
  def push(cell)
65
- cell = Workbook::Cell.new(cell) unless cell.class == Workbook::Cell
65
+ cell = Workbook::Cell.new(cell, {row:self}) unless cell.class == Workbook::Cell
66
66
  super(cell)
67
67
  end
68
68
 
69
69
  # Add cell
70
70
  # @param [Workbook::Cell, Numeric,String,Time,Date,TrueClass,FalseClass,NilClass] cell or value to add
71
71
  def <<(cell)
72
- cell = Workbook::Cell.new(cell) unless cell.class == Workbook::Cell
72
+ cell = Workbook::Cell.new(cell, {row:self}) unless cell.class == Workbook::Cell
73
73
  super(cell)
74
74
  end
75
75
 
@@ -108,7 +108,7 @@ module Workbook
108
108
  end
109
109
  return rv
110
110
  elsif index_or_hash.is_a? String
111
- symbolized = Workbook::Cell.new(index_or_hash).to_sym
111
+ symbolized = Workbook::Cell.new(index_or_hash, {row:self}).to_sym
112
112
  self[symbolized]
113
113
  else
114
114
  if index_or_hash
@@ -131,7 +131,7 @@ module Workbook
131
131
  if index_or_hash.is_a? Symbol
132
132
  index = table_header_keys.index(index_or_hash)
133
133
  elsif index_or_hash.is_a? String
134
- symbolized = Workbook::Cell.new(index_or_hash).to_sym
134
+ symbolized = Workbook::Cell.new(index_or_hash, {row:self}).to_sym
135
135
  index = table_header_keys.index(symbolized)
136
136
  end
137
137
 
@@ -145,6 +145,7 @@ module Workbook
145
145
  end
146
146
  value_celled.value=(value)
147
147
  end
148
+ value_celled.row = self
148
149
  super(index,value_celled)
149
150
  end
150
151
 
@@ -214,6 +215,13 @@ module Workbook
214
215
  return hash
215
216
  end
216
217
 
218
+ # Quick assessor to the book's template, if it exists
219
+ #
220
+ # @return [Workbook::Template]
221
+ def template
222
+ table.template if table
223
+ end
224
+
217
225
  # Returns a hash representation of this row
218
226
  #
219
227
  # it differs from #to_hash as it doesn't contain the Workbook's Workbook::Cell-objects,
@@ -34,6 +34,9 @@ module Workbook
34
34
  first
35
35
  end
36
36
 
37
+ # Returns the name of this sheet
38
+ #
39
+ # @return [String] the name, defaulting to "Sheet {index}" when none is set
37
40
  def name
38
41
  @name ||= "Sheet #{book.index(self)+1}"
39
42
  end
@@ -231,5 +231,19 @@ module Workbook
231
231
  self
232
232
  end
233
233
 
234
+ # Returns The dimensions of this sheet based on longest row
235
+ # @return [Array] x-width, y-height
236
+ def dimensions
237
+ height = self.count
238
+ width = self.collect{|a| a.length}.max
239
+ [width,height]
240
+ end
241
+
242
+ def columns
243
+ @columns ||= header.collect do |header_cell|
244
+ Column.new(self)
245
+ end
246
+ end
247
+
234
248
  end
235
249
  end
@@ -50,5 +50,10 @@ module Workbook
50
50
  end
51
51
  return @formats[name][variant]
52
52
  end
53
+
54
+ def set_default_formats!
55
+ header_fmt = create_or_find_format_by :header
56
+ header_fmt[:font_weight] = 'bold'
57
+ end
53
58
  end
54
59
  end
@@ -1,9 +1,21 @@
1
- require 'workbook/cell'
1
+ # require 'workbook/modules/cell'
2
2
 
3
3
  module Workbook
4
4
  module Types
5
5
  class Date < Date
6
- include Workbook::Cell
6
+ include Workbook::Modules::Cell
7
+
8
+ def initialize(*args)
9
+ super(*args)
10
+ end
11
+
12
+ def value
13
+ self
14
+ end
15
+
16
+ def value= a
17
+ throw "#value= is no longer available"
18
+ end
7
19
  end
8
20
  end
9
21
  end
@@ -1,9 +1,7 @@
1
- require 'workbook/cell'
2
-
3
1
  module Workbook
4
2
  module Types
5
3
  class FalseClass < FalseClass
6
- include Workbook::Cell
4
+ include Workbook::Modules::Cell
7
5
  end
8
6
  end
9
7
  end
@@ -1,4 +1,4 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
  module Workbook
3
- VERSION = '0.4.9'
3
+ VERSION = '0.4.10'
4
4
  end
@@ -1,82 +1,112 @@
1
1
  # -*- encoding : utf-8 -*-
2
- require 'rubyXL'
2
+ require 'axlsx'
3
3
  require 'workbook/readers/xls_shared'
4
4
 
5
5
  module Workbook
6
6
  module Writers
7
7
  module XlsxWriter
8
8
 
9
- # Generates an RubyXL doc, ready for export to XLSX
9
+ # Generates an axlsx doc, ready for export to XLSX
10
10
  #
11
11
  # @param [Hash] options A hash with options (unused so far)
12
- # @return [Spreadsheet] A Spreadsheet object, ready for writing or more lower level operations
12
+ # @return [Axlsx::Package] An object, ready for writing or more lower level operations
13
13
  def to_xlsx options={}
14
- book = init_xlsx_spreadsheet_template
15
- book.theme = RubyXL::Theme.new unless book.theme #workaround bug in rubyxl
14
+ formats_to_xlsx_format
15
+ book = init_xlsx_spreadsheet_template.workbook
16
16
  book.worksheets.pop(book.worksheets.count - self.count) if book.worksheets and book.worksheets.count > self.count
17
17
  self.each_with_index do |s,si|
18
- xls_sheet = xlsx_sheet(si)
19
- xls_sheet.sheet_name = s.name
20
-
18
+ xlsx_sheet = xlsx_sheet(si)
19
+ xlsx_sheet.name = s.name
21
20
  s.table.each_with_index do |r, ri|
21
+ xlsx_row = xlsx_sheet[ri] ? xlsx_sheet[ri] : xlsx_sheet.add_row
22
+ xlsx_row.height = 16
23
+ xlsx_row_a = xlsx_row.to_ary
22
24
  r.each_with_index do |c, ci|
23
- xls_sheet.add_cell(ri, ci, c.value)
24
-
25
+ xlsx_row.add_cell(c.value) unless xlsx_row_a[ci]
26
+ xlsx_cell = xlsx_row_a[ci]
27
+ xlsx_cell.value = c.value
28
+ xlsx_cell.style = c.format.raws[Fixnum] if c.format.raws[Fixnum]
25
29
  end
30
+ xlsx_sheet.send(:update_column_info, xlsx_row.cells, [])
26
31
  end
27
- (xls_sheet.count + 1 - s.table.count).times do |time|
28
- row_to_remove = s.table.count+time
29
-
30
- xls_sheet.delete_row(row_to_remove)
31
- # xls_sheet.row_updated(row_to_remove, xls_sheet.row(row_to_remove))
32
+ (xlsx_sheet.rows.count - s.table.count).times do |time|
33
+ xlsx_sheet.rows.pop
32
34
  end
33
- # xls_sheet.updated_from(s.table.count)
34
- # xls_sheet.dimensions
35
-
36
35
  end
37
- book
36
+ init_xlsx_spreadsheet_template
38
37
  end
39
38
 
40
- # Generates an RubyXL doc, ready for export to XLSX
39
+ # Generates an string ready to be streamed as XLSX
41
40
  #
42
41
  # @param [Hash] options A hash with options (unused so far)
43
42
  # @return [String] A string, ready for streaming, e.g. `send_data workbook.stream_xlsx`
44
43
  def stream_xlsx options = {}
45
- to_xlsx(options).stream.string
44
+ to_xlsx(options).to_stream.string
46
45
  end
47
46
 
48
- # Write the current workbook to Microsoft Excel's new format (using the RubyXL gem)
47
+ # Write the current workbook to Microsoft Excel's XML format (using the Axlsx gem)
49
48
  #
50
49
  # @param [String] filename
51
50
  # @param [Hash] options see #to_xlsx
52
51
  def write_to_xlsx filename="#{title}.xlsx", options={}
53
- if to_xlsx(options).write(filename)
52
+ if to_xlsx(options).serialize(filename)
54
53
  return filename
55
54
  end
56
55
  end
57
56
 
58
57
  def xlsx_sheet a
59
- if xlsx_template.worksheets[a]
60
- return xlsx_template.worksheets[a]
58
+ if xlsx_template.workbook.worksheets[a]
59
+ return xlsx_template.workbook.worksheets[a]
61
60
  else
62
- xlsx_template.create_worksheet
63
- self.xls_sheet a
61
+ xlsx_template.workbook.add_worksheet
62
+ self.xlsx_sheet a
64
63
  end
65
64
  end
66
65
 
67
66
  def xlsx_template
68
- return template.raws[RubyXL::Workbook]
67
+ return template.raws[Axlsx::Package]
69
68
  end
70
69
 
71
70
  def init_xlsx_spreadsheet_template
72
- if self.xlsx_template.is_a? RubyXL::Workbook
71
+ if self.xlsx_template.is_a? Axlsx::Package
73
72
  return self.xlsx_template
74
73
  else
75
- t = RubyXL::Workbook.new
74
+ t = Axlsx::Package.new
76
75
  template.add_raw t
76
+ template.set_default_formats!
77
77
  return t
78
78
  end
79
79
  end
80
+
81
+ def formats_to_xlsx_format
82
+ template.formats.each do |n,v|
83
+ v.each do | t,s |
84
+ format_to_xlsx_format(s)
85
+ end
86
+ end
87
+ end
88
+
89
+ def format_to_xlsx_format f
90
+ xlsfmt = nil
91
+ unless f.is_a? Workbook::Format
92
+ f = Workbook::Format.new f
93
+ end
94
+
95
+ xlsfmt={}
96
+ xlsfmt[:fg_color] = "#{f[:color]}00" if f[:color]
97
+ xlsfmt[:b] = true if f[:font_weight] == "bold" or f[:font_weight].to_i >= 600 or f[:"font_style"].to_s.match "oblique"
98
+ xlsfmt[:i] = true if f[:font_style] == "italic"
99
+ xlsfmt[:u] = true if f[:text_decoration].to_s.match("underline")
100
+ xlsfmt[:bg_color] = f[:background_color] if f[:background_color]
101
+ xlsfmt[:format_code] = strftime_to_ms_format(f[:number_format]) if f[:number_format]
102
+ xlsfmt[:font_name] = f[:font_family].split.first if f[:font_family]
103
+ xlsfmt[:family] = parse_font_family(f) if f[:font_family]
104
+ f.add_raw init_xlsx_spreadsheet_template.workbook.styles.add_style(xlsfmt)
105
+ # wb.styles{|a| p a.add_style({}).class }
106
+
107
+ f.add_raw xlsfmt
108
+ return xlsfmt
109
+ end
80
110
  end
81
111
  end
82
112
  end
data/test/test_column.rb CHANGED
@@ -3,6 +3,16 @@ require File.join(File.dirname(__FILE__), 'helper')
3
3
 
4
4
  class TestColumn < Minitest::Test
5
5
 
6
+ def new_table
7
+ Workbook::Table.new([
8
+ ["a","b","c","d"],
9
+ [true,3.2,"asdf",1],
10
+ [true,3.2,"asdf",1],
11
+ [false,3.2,"asdf",1],
12
+ [true,3.2,"asdf",1]
13
+ ])
14
+ end
15
+
6
16
  def test_init
7
17
  c = Workbook::Column.new
8
18
  assert_equal(Workbook::Column, c.class)
@@ -21,4 +31,24 @@ class TestColumn < Minitest::Test
21
31
  assert_equal(Workbook::Table.new, c.table)
22
32
  assert_raises(ArgumentError) { c.table = false }
23
33
  end
34
+
35
+ def test_index
36
+ t = new_table
37
+ assert_equal(t.columns.first.index, 0)
38
+ assert_equal(t.columns.last.index, 3)
39
+ end
40
+
41
+ def test_column_type
42
+ t = new_table
43
+ assert_equal([:boolean, :float, :string, :integer], t.columns.collect{|a| a.column_type})
44
+ t = new_table
45
+ t.last.last.value = 1.1
46
+ assert_equal([:boolean, :float, :string, :string], t.columns.collect{|a| a.column_type})
47
+ t = new_table
48
+ t[2][3] = nil
49
+ assert_equal([:boolean, :float, :string, :integer], t.columns.collect{|a| a.column_type})
50
+ t = new_table
51
+ t[2].delete_at(3)
52
+ assert_equal([:boolean, :float, :string, :integer], t.columns.collect{|a| a.column_type})
53
+ end
24
54
  end
@@ -1,7 +1,7 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
  require File.join(File.dirname(__FILE__), 'helper')
3
3
 
4
- class TestCell < Minitest::Test
4
+ class TestModulesCell < Minitest::Test
5
5
 
6
6
 
7
7
  def test_init
@@ -115,4 +115,11 @@ class TestCell < Minitest::Test
115
115
  assert_equal(3,c.rowspan)
116
116
  assert_equal(nil,c.colspan)
117
117
  end
118
+
119
+ def cell_type
120
+ {1 => :integer, 3.2 => :float, true => :boolean, "asdf" => :string}.each do |k,v|
121
+ c = Workbook::Cel.new(k)
122
+ assert_equal(v,c.cell_type)
123
+ end
124
+ end
118
125
  end
@@ -9,7 +9,7 @@ module Readers
9
9
  assert_equal(90588,w.sheet.table[2][:b].value)
10
10
  assert_equal(DateTime.new(2011,11,15),w.sheet.table[3][:d].value)
11
11
  # assert_equal("#CCFFCC",w.sheet.table[3][:c].format[:background_color]) #colour compatibility turned off for now...
12
- # assert_equal(8,w.sheet.table.first[:b].format[:width].round)
12
+ #assert_equal(8,w.sheet.table.first[:b].format[:width].round)
13
13
  # assert_equal(4,w.sheet.table.first[:a].format[:width].round)
14
14
  # assert_equal(25,w.sheet.table.first[:c].format[:width].round)
15
15
  end
@@ -29,11 +29,5 @@ module Readers
29
29
  assert_equal(nil,w.ms_formatting_to_strftime(nil));
30
30
  assert_equal(nil,w.ms_formatting_to_strftime(""));
31
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
38
32
  end
39
33
  end