workbook 0.4.7 → 0.4.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5d3acc182ee042e589c65b4ddfc3be95015d96fa
4
- data.tar.gz: d23f5bd2cac3dccfb863997fb5e6ea8ced3e70a7
3
+ metadata.gz: d9cf45e1ff6addbcf502334bf786df43a7c7714a
4
+ data.tar.gz: 6f219b42f0c6b17f8ed9ac32c57b3032efe74f12
5
5
  SHA512:
6
- metadata.gz: 8b81415ada844fae07c02d146e4d2a9cbd1898ec0e64a8781ef40fc5c4cb8edbbddba6a83fda301f15666fceae5716c38e198f8769adc238cf4a8822e7aea919
7
- data.tar.gz: eebcd14f3191d8c26654d16b2e71f31863504b773da470d1ab11a5960c021631e614c2a036795eda7138c1d3b38d6c6314fed7c21705ed0dc5d0a512d373e655
6
+ metadata.gz: 8ca18e838d71e6bee71a343728f9d0e7cd5843511e7e2e13c9d5a6432e2ecad2d78dc37913d87b4744f86f4ab46e386449fbf2f9488a143329514704c1221726
7
+ data.tar.gz: db7378ab0541f0f6ecdc0fa66f707f5c58e908da0086d57eac010d8b4057534ac4cb7c3d809520a6702ada150a3f88c141913b4e5bbdf9096d7e3d21db733faa
data/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  # Workbook
2
- [![Code Climate](https://codeclimate.com/github/murb/workbook.png)](https://codeclimate.com/github/murb/workbook) [![Build Status](https://travis-ci.org/murb/workbook.png?branch=master)](https://travis-ci.org/murb/workbook)
2
+ [![Code Climate](https://codeclimate.com/github/murb/workbook.png)](https://codeclimate.com/github/murb/workbook) [![Build Status](https://travis-ci.org/murb/workbook.svg?branch=master)](https://travis-ci.org/murb/workbook) [![Gem Version](https://badge.fury.io/rb/workbook.svg)](http://badge.fury.io/rb/workbook)
3
3
 
4
4
  Goal of this gem is to make working with workbooks (spreadsheets) as programmer friendly as possible. Not reinventing a totally new DSL or all kinds of new methodnames, but just borrowing from known concepts such as hashes and arrays (much like (Faster)CSV does)). Workbook is a gem that mimicks a typical spreadsheet, a bundle of sheets, bundled in a *workbook*. A sheet may contain one or more tables (which might the multi table sheets of Apple Numbers or Excel ranges). Basically:
5
5
 
@@ -130,7 +130,7 @@ In case you want to display a formatted table in HTML, some conversion is offere
130
130
  ## Compatibility
131
131
 
132
132
  Workbook is automatically tested for ruby 1.9, 2.0 and 2.1. Most of it works with 1.8.7 and jruby but not all tests give equal results.
133
- 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).
133
+ Check [Travis for Workbook's current build status](https://travis-ci.org/murb/workbook) [![Build Status](https://travis-ci.org/murb/workbook.svg?branch=master)](https://travis-ci.org/murb/workbook).
134
134
 
135
135
  ## Future
136
136
 
@@ -15,7 +15,21 @@ module Workbook
15
15
  # The Book class is the container of sheets. It can be inialized by either the standard initalizer or the open method. The
16
16
  # Book class can also keep a reference to a template class, storing shared formatting options.
17
17
  #
18
- SUPPORTED_MIME_TYPES = %w(application/zip text/plain application/x-ariadne-download application/vnd.ms-excel application/excel application/vnd.ms-office text/csv text/tab-separated-values application/x-ms-excel application/vnd.openxmlformats-officedocument.spreadsheetml.sheet application/vnd.oasis.opendocument.spreadsheet application/x-vnd.oasis.opendocument.spreadsheet)
18
+ SUPPORTED_MIME_TYPES = [
19
+ "application/zip",
20
+ "text/plain",
21
+ "application/x-ariadne-download",
22
+ "application/vnd.ms-excel",
23
+ "application/excel",
24
+ "application/vnd.ms-office",
25
+ "text/csv",
26
+ "text/tab-separated-values",
27
+ "application/x-ms-excel",
28
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
29
+ "application/vnd.oasis.opendocument.spreadsheet",
30
+ "application/x-vnd.oasis.opendocument.spreadsheet",
31
+ "CDF V2 Document, No summary info"
32
+ ]
19
33
 
20
34
  class Book < Array
21
35
 
@@ -3,9 +3,10 @@ module Workbook
3
3
 
4
4
  # Column helps us to store general properties of a column, and lets us easily perform operations on values within a column
5
5
  class Column
6
- attr_accessor :limit #character limit
6
+ attr_accessor :limit, :table #character limit
7
7
 
8
- def initialize(options={})
8
+ def initialize(table=nil, options={})
9
+ self.table = table
9
10
  options.each{ |k,v| self.public_send("#{k}=",v) }
10
11
  end
11
12
 
@@ -14,6 +15,11 @@ module Workbook
14
15
  @column_type
15
16
  end
16
17
 
18
+ def table= t
19
+ raise(ArgumentError, "value should be nil or Workbook::Table") unless [NilClass,Workbook::Table].include? t.class
20
+ @table = t
21
+ end
22
+
17
23
  def column_type= column_type
18
24
  if [:primary_key, :string, :text, :integer, :float, :decimal, :datetime, :date, :binary, :boolean].include? column_type
19
25
  @column_type = column_type
@@ -2,6 +2,11 @@
2
2
  module Workbook
3
3
  module Readers
4
4
  module XlsShared
5
+
6
+ # Converts standard (ruby/C++/unix/...) strftime formatting to MS's formatting
7
+ #
8
+ # @param [String, nil] numberformat (nil returns nil)
9
+ # @return [String, nil]
5
10
  def ms_formatting_to_strftime ms_nr_format
6
11
  if ms_nr_format
7
12
  ms_nr_format = ms_nr_format.to_s.downcase
@@ -14,13 +14,12 @@ module Workbook
14
14
  # @param [Workbook::Table] table a row normally belongs to a table, reference it here
15
15
  # @param [Hash] options Supprted options: parse_cells_on_batch_creation (parse cell values during row-initalization, default: false), cell_parse_options (default {}, see Workbook::Modules::TypeParser)
16
16
  def initialize cells=[], table=nil, options={}
17
- options=options ? {:parse_cells_on_batch_creation=>false,:cell_parse_options=>{}}.merge(options) : {}
17
+ options=options ? {:parse_cells_on_batch_creation=>false,:cell_parse_options=>{},:clone_cells=>false}.merge(options) : {}
18
18
  cells = [] if cells==nil
19
19
  self.table= table
20
20
  cells.each do |c|
21
- if c.is_a? Workbook::Cell
22
- c = c
23
- else
21
+ c = c.clone if options[:clone_cells]
22
+ unless c.is_a? Workbook::Cell
24
23
  c = Workbook::Cell.new(c)
25
24
  c.parse!(options[:cell_parse_options]) if options[:parse_cells_on_batch_creation]
26
25
  end
@@ -258,7 +257,7 @@ module Workbook
258
257
  #
259
258
  # @return [Workbook::Row] a cloned copy of self with cells
260
259
  def clone
261
- Workbook::Row.new(to_a.collect{|c| c.clone})
260
+ Workbook::Row.new(self, nil, {:clone_cells=>true})
262
261
  end
263
262
 
264
263
  # remove all the trailing nil-cells (returning a trimmed clone)
@@ -41,7 +41,6 @@ module Workbook
41
41
  # Set the first table of this sheet with a table or array of cells/values
42
42
  # @param [Workbook::Table, Array<Array>] table The new first table of this sheet
43
43
  # @param [Hash] options are forwarded to Workbook::Table.new
44
-
45
44
  # @return [Workbook::Table] the first table of this sheet
46
45
  def table= table, options={}
47
46
  if table.is_a? Workbook::Table
@@ -15,15 +15,17 @@ module Workbook
15
15
 
16
16
  attr_accessor :sheet
17
17
  attr_accessor :name
18
+ attr_accessor :columns
18
19
 
19
20
  def initialize row_cel_values=[], sheet=nil, options={}
20
21
  row_cel_values = [] if row_cel_values == nil
21
- row_cel_values.each do |r|
22
+ row_cel_values.each_with_index do |r,ri|
22
23
  if r.is_a? Workbook::Row
23
24
  r.table = self
24
25
  else
25
26
  r = Workbook::Row.new(r,self, options)
26
27
  end
28
+ define_columns_with_row(r) if ri == 0
27
29
  end
28
30
  self.sheet = sheet
29
31
  # Column data is considered as a 'row' with 'cells' that contain 'formatting'
@@ -54,6 +56,12 @@ module Workbook
54
56
  @header = h
55
57
  end
56
58
 
59
+ def define_columns_with_row(r)
60
+ self.columns = r.collect do |column|
61
+ Workbook::Column.new self, {}
62
+ end
63
+ end
64
+
57
65
  # Generates a new row, with optionally predefined cell-values, that is already connected to this table.
58
66
  def new_row cell_values=[]
59
67
  r = Workbook::Row.new(cell_values,self)
@@ -148,10 +156,10 @@ module Workbook
148
156
  # @return [Workbook::Row, Workbook::Cell, nil]
149
157
  def [](index_or_string)
150
158
  if index_or_string.is_a? String
151
- match = index_or_string.upcase.match(/([A-Z]*)([0-9]*)/)
152
- cell_index = alpha_index_to_number_index(match[1])
159
+ match = index_or_string.match(/([A-Z]+)([0-9]*)/i)
160
+ col_index = alpha_index_to_number_index(match[1])
153
161
  row_index = match[2].to_i - 1
154
- return self[row_index][cell_index]
162
+ return self[row_index][col_index]
155
163
  elsif index_or_string.is_a? Range
156
164
  collection = to_a[index_or_string].collect{|a| a.clone}
157
165
  return Workbook::Table.new collection
@@ -1,4 +1,4 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
  module Workbook
3
- VERSION = '0.4.7'
3
+ VERSION = '0.4.8'
4
4
  end
@@ -10,7 +10,6 @@ module Workbook
10
10
  # @param [Hash] options A hash with options
11
11
  # @return [String] A String containing the HTML code
12
12
  def to_html options={}
13
- options = {:style_with_inline_css=>false}.merge(options)
14
13
  builder = Nokogiri::XML::Builder.new do |doc|
15
14
  doc.html {
16
15
  doc.body {
@@ -56,13 +55,9 @@ module Workbook
56
55
  if header
57
56
  doc.tr do
58
57
  header.each do |cell|
59
- classnames = cell.format.all_names.join(" ").strip
60
- td_options = classnames != "" ? {:class=>classnames} : {}
61
- td_options = td_options.merge({:style=>cell.format.to_css}) if options[:style_with_inline_css] and cell.format.to_css != ""
62
- td_options = td_options.merge({:colspan=>cell.colspan}) if cell.colspan
63
- td_options = td_options.merge({:rowspan=>cell.rowspan}) if cell.rowspan
58
+ th_options = build_cell_options cell, options
64
59
  unless cell.value.class == Workbook::NilValue
65
- doc.th(td_options) do
60
+ doc.th(th_options) do
66
61
  doc.text cell.value
67
62
  end
68
63
  end
@@ -75,11 +70,7 @@ module Workbook
75
70
  unless row.header?
76
71
  doc.tr do
77
72
  row.each do |cell|
78
- classnames = cell.format.all_names.join(" ").strip
79
- td_options = classnames != "" ? {:class=>classnames} : {}
80
- td_options = td_options.merge({:style=>cell.format.to_css}) if options[:style_with_inline_css] and cell.format.to_css != ""
81
- td_options = td_options.merge({:colspan=>cell.colspan}) if cell.colspan
82
- td_options = td_options.merge({:rowspan=>cell.rowspan}) if cell.rowspan
73
+ td_options = build_cell_options cell, options
83
74
  unless cell.value.class == Workbook::NilValue
84
75
  doc.td(td_options) do
85
76
  doc.text cell.value
@@ -94,6 +85,15 @@ module Workbook
94
85
  end
95
86
  return builder.doc.to_xhtml
96
87
  end
88
+ private
89
+ def build_cell_options cell, options={}
90
+ classnames = cell.format.all_names.join(" ").strip
91
+ td_options = classnames != "" ? {:class=>classnames} : {}
92
+ td_options = td_options.merge({:style=>cell.format.to_css}) if options[:style_with_inline_css] and cell.format.to_css != ""
93
+ td_options = td_options.merge({:colspan=>cell.colspan}) if cell.colspan
94
+ td_options = td_options.merge({:rowspan=>cell.rowspan}) if cell.rowspan
95
+ return td_options
96
+ end
97
97
  end
98
98
  end
99
99
  end
@@ -30,25 +30,33 @@ module Workbook
30
30
  end
31
31
  (xls_sheet.last_row_index + 1 - s.table.count).times do |time|
32
32
  row_to_remove = s.table.count+time
33
- xls_sheet.row(row_to_remove).each_with_index do |c, ci|
34
- xls_sheet.row(row_to_remove)[ci]=nil
35
- end
36
-
37
- xls_sheet.delete_row(row_to_remove)
38
- xls_sheet.row_updated(row_to_remove, xls_sheet.row(row_to_remove))
33
+ remove_row(xls_sheet,row_to_remove)
39
34
  end
40
35
  xls_sheet.updated_from(s.table.count)
41
36
  xls_sheet.dimensions
42
37
 
43
38
  end
44
- # kind of a hack, delting by popping from xls worksheet results in Excel-errors (not LibreOffice)
39
+ # kind of a hack, deleting by popping from xls worksheet results in errors in MS Excel (not LibreOffice)
45
40
  # book.worksheets.pop(book.worksheets.count - self.count) if book.worksheets and book.worksheets.count > self.count
46
- book.worksheets.each_with_index do |sheet, si|
47
- sheet.visibility = self[si] ? :visible : :strong_hidden
41
+ book.worksheets.each_with_index do |xls_sheet, si|
42
+ if self[si]
43
+ xls_sheet.visibility = :visible
44
+ else
45
+ xls_sheet.visibility = :strong_hidden
46
+ #also make sure all data is removed, in case someone finds out about this 'trick'
47
+ xls_sheet.name = "RemovedSheet#{si}"
48
+ (xls_sheet.last_row_index + 1).times do |row_index|
49
+ remove_row(xls_sheet,row_index)
50
+ end
51
+ end
48
52
  end
53
+ # even after removing the worksheet's content... which solved some incompatibilities, but not for popping worksheets
54
+ # book.worksheets.pop(book.worksheets.count - self.count) if book.worksheets and book.worksheets.count > self.count
49
55
  book
50
56
  end
51
57
 
58
+
59
+
52
60
  # Generates an Spreadsheet (from the spreadsheet gem) in order to build an XlS
53
61
  #
54
62
  # @param [Workbook::Format, Hash] f A Workbook::Format or hash with format-options (:font_weight, :rotation, :background_color, :number_format, :text_direction, :color, :font_family)
@@ -97,27 +105,6 @@ module Workbook
97
105
  end
98
106
  end
99
107
 
100
-
101
- # Attempt to convert html-hex color value to xls color number
102
- #
103
- # @param [String] hex color
104
- # @return [String] xls color
105
- def html_color_to_xls_color hex
106
- Workbook::Readers::XlsShared::XLS_COLORS.each do |k,v|
107
- return k if (v == hex or (hex and hex != "" and k == hex.to_sym))
108
- end
109
- return nil
110
- end
111
-
112
- # Converts standard (ruby/C++/unix/...) strftime formatting to MS's formatting
113
- #
114
- # @param [String, nil] numberformat (nil returns nil)
115
- # @return [String, nil]
116
- def strftime_to_ms_format numberformat
117
- return nil if numberformat.nil?
118
- return numberformat.gsub('%Y','yyyy').gsub('%A','dddd').gsub('%B','mmmm').gsub('%a','ddd').gsub('%b','mmm').gsub('%y','yy').gsub('%d','dd').gsub('%m','mm').gsub('%y','y').gsub('%y','%%y').gsub('%e','d')
119
- end
120
-
121
108
  # Write the current workbook to Microsoft Excel format (using the spreadsheet gem)
122
109
  #
123
110
  # @param [String] filename
@@ -150,6 +137,16 @@ module Workbook
150
137
  return t
151
138
  end
152
139
  end
140
+
141
+ private
142
+
143
+ def remove_row(xls_sheet,row_index)
144
+ xls_sheet.row(row_index).each_with_index do |c, ci|
145
+ xls_sheet.row(row_index)[ci]=nil
146
+ end
147
+ xls_sheet.delete_row(row_index)
148
+ xls_sheet.row_updated(row_index, xls_sheet.row(row_index))
149
+ end
153
150
  end
154
151
  end
155
152
  end
Binary file
@@ -6,10 +6,19 @@ class TestColumn < Test::Unit::TestCase
6
6
  def test_init
7
7
  c = Workbook::Column.new
8
8
  assert_equal(Workbook::Column, c.class)
9
- c = Workbook::Column.new({:limit=>20,:default=>"asdf", :column_type=>:boolean})
9
+ c = Workbook::Column.new(nil, {:limit=>20,:default=>"asdf", :column_type=>:boolean})
10
+ c = Workbook::Column.new(Workbook::Table.new, {:limit=>20,:default=>"asdf", :column_type=>:boolean})
10
11
  assert_equal(20, c.limit)
11
12
  assert_equal(Workbook::Cell.new("asdf"), c.default)
12
13
  assert_equal(:boolean, c.column_type)
13
- assert_raise(ArgumentError) { Workbook::Column.new({:limit=>20,:default=>"asdf", :column_type=>:bodfolean}) }
14
+ assert_raise(ArgumentError) { Workbook::Column.new(true) }
15
+ assert_raise(ArgumentError) { Workbook::Column.new(nil, {:limit=>20,:default=>"asdf", :column_type=>:bodfolean}) }
16
+ end
17
+
18
+ def test_table
19
+ c = Workbook::Column.new
20
+ c.table = Workbook::Table.new
21
+ assert_equal(Workbook::Table.new, c.table)
22
+ assert_raise(ArgumentError) { c.table = false }
14
23
  end
15
24
  end
@@ -29,7 +29,6 @@ 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
-
33
32
  # def test_monkey_patched_ruby_xl_is_date_format?
34
33
  # w = RubyXL::Workbook.new
35
34
  # assert_equal(false, w.is_date_format?(nil))
@@ -186,4 +186,6 @@ class TestTable< Test::Unit::TestCase
186
186
  # puts [first_few_lines,last_few_lines].join(" vs ")
187
187
  assert_equal(true, first_few_lines*1.10 > last_few_lines) # 10% slower is acceptable
188
188
  end
189
+
190
+
189
191
  end
@@ -15,7 +15,7 @@ Gem::Specification.new do |s|
15
15
  s.authors = ["Maarten Brouwers"]
16
16
  s.add_development_dependency 'ruby-prof', '~> 0.14'
17
17
  s.add_dependency('rubyzip', '~>1')
18
- s.add_dependency('spreadsheet', '~> 0.7')
18
+ s.add_dependency('spreadsheet', '~> 1.0')
19
19
  s.add_dependency('fastercsv') if RUBY_VERSION < "1.9"
20
20
  s.add_dependency("rchardet", "~> 1.3")
21
21
  s.add_dependency("rake", '~> 10.0')
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.7
4
+ version: 0.4.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Maarten Brouwers
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '0.7'
47
+ version: '1.0'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '0.7'
54
+ version: '1.0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rchardet
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -250,6 +250,7 @@ files:
250
250
  - test/artifacts/excel_different_types.xls
251
251
  - test/artifacts/excel_different_types.xlsx
252
252
  - test/artifacts/failing_import1.xls
253
+ - test/artifacts/heavy.xlsx
253
254
  - test/artifacts/native_xlsx.xlsx
254
255
  - test/artifacts/sheet_with_combined_cells.ods
255
256
  - test/artifacts/sheetduplication.xls
@@ -305,7 +306,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
305
306
  version: '0'
306
307
  requirements: []
307
308
  rubyforge_project: workbook
308
- rubygems_version: 2.2.0
309
+ rubygems_version: 2.2.2
309
310
  signing_key:
310
311
  specification_version: 4
311
312
  summary: Workbook is a datastructure to contain books of tables (an anlogy used in
@@ -325,6 +326,7 @@ test_files:
325
326
  - test/artifacts/excel_different_types.xls
326
327
  - test/artifacts/excel_different_types.xlsx
327
328
  - test/artifacts/failing_import1.xls
329
+ - test/artifacts/heavy.xlsx
328
330
  - test/artifacts/native_xlsx.xlsx
329
331
  - test/artifacts/sheet_with_combined_cells.ods
330
332
  - test/artifacts/sheetduplication.xls
@@ -359,4 +361,3 @@ test_files:
359
361
  - test/test_writers_json_writer.rb
360
362
  - test/test_writers_xls_writer.rb
361
363
  - test/test_writers_xlsx_writer.rb
362
- has_rdoc: