workbook 0.4.5.1 → 0.4.6.0

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: 41cf688387503bb0c1f49447b808e8bdec45b9c4
4
- data.tar.gz: 10002b13a02821e187fc333fd0d500a3e5764f34
3
+ metadata.gz: 2d0754f13283c6f5a93dcff9faab6fd3ab404c26
4
+ data.tar.gz: 5c63815a99a9105a4f0eca1a23d0d3f5e67380cd
5
5
  SHA512:
6
- metadata.gz: 7cb62c5b99200c4c6960b4154de58251f5b4b407cf28f9c130d4752f6119c4193c0bba9017f80822225e4c165030b004f615e7c5faabde6cc507e143442b78be
7
- data.tar.gz: 797ea713f1a703172a571ff977c1351dbe3a11911eec2c25f8b818ca9bd93c4cf57127c1cd6539ad05e160d167b16b8f1c8c23bc393e40203f5a17792972b1b2
6
+ metadata.gz: 89e115237295547d0e68b4a9dcaf0e49d8790079d7b92a9e7f3b51b120bafd3cd4cbd73f09a3e326b22acafd85d5f59ed1e7661aa160ff1747acad830787c517
7
+ data.tar.gz: 28b2cecfcf40c8667fb72d1c3850289a4631e845285ef6b9d3b6eea326383607db38e67c7b1042d12776cc6307493317d6912ffe4436eef9d7d573e00c2afa31
data/.gitignore CHANGED
@@ -6,3 +6,7 @@ sharepoint_download_excel.*
6
6
  bin
7
7
  Gemfile.lock
8
8
  *.rb~
9
+ empty.png
10
+ minus.png
11
+ plus.png
12
+ profile.*
data/README.md CHANGED
@@ -5,57 +5,57 @@ Goal of this gem is to make working with workbooks (spreadsheets) as programmer
5
5
  * Book
6
6
  * Sheet (one or more)
7
7
  * Table (one or more)
8
-
8
+
9
9
  Subsequently a table consists of:
10
10
 
11
11
  * Table
12
12
  * Row (one or more)
13
13
  * Cell ( wich has may have a (shared) Format )
14
-
15
- Book, Sheet, Table and Row inherit from the base Array class, and hence walks and quacks as such. The row is extended with hashlike lookups (`row[:id]`) and writers (`row[:id]=`). Values are converted to ruby native types, and optional parsers can be added to improve recognition.
14
+
15
+ Book, Sheet, Table and Row inherit from the base Array class, and hence walks and quacks as such. The row is extended with hashlike lookups (`row[:id]`) and writers (`row[:id]=`). Values are converted to ruby native types, and optional parsers can be added to improve recognition.
16
16
 
17
17
  In addition to offering you this plain structure it allows for importing .xls, .csv, .xlsx, .txt files (more to come), writing .xls, and .csv (more to come) and includes several utilities to easily create an overview of the differences between two tables and output basic cell-styling properties as css.
18
18
 
19
19
  ## The Basics
20
-
20
+
21
21
  Simply initialize a simple spreadsheet using:
22
22
 
23
23
  b = Workbook::Book.new
24
-
24
+
25
25
  or
26
26
 
27
27
  b = Workbook::Book.open filename
28
-
28
+
29
29
  Calling
30
30
 
31
31
  s = b.sheet
32
32
  t = s.table
33
-
33
+
34
34
  will give you an the first Sheet and Table (if one doesn't exist it is created on the fly).
35
35
 
36
36
  You can initialize with simple 2-d array like this:
37
37
 
38
38
  b = Workbook::Book.new [['a','b'],[1,2],[3,4],[5,6]]
39
39
  t = s.sheet.table
40
-
40
+
41
41
  Subsequently you look up values in the table like this:
42
42
 
43
- t[1][:b]
43
+ t[1][:b]
44
44
  # returns <Workbook::Cel @value=2>
45
45
 
46
46
  which is equivalent to
47
47
 
48
- t[1][1]
49
-
48
+ t[1][1]
49
+
50
50
  Of course you'll be able to write a new value back to it. If you just enter a value, formatting of the original cell will be maintained.
51
51
 
52
52
  t[1][:b] = 5
53
-
53
+
54
54
  Alternatively (more spreadsheet like) you can read cells like this (writing to be supported, not implemented yet)
55
-
55
+
56
56
  t['A2']
57
-
58
- If you want to use an existing file as a template (which you can create in Excel to create nice looking templates),
57
+
58
+ If you want to use an existing file as a template (which you can create in Excel to create nice looking templates),
59
59
  simply clone the row, and add it back:
60
60
 
61
61
  b = Workbook::Book.open("template.xls")
@@ -65,16 +65,16 @@ simply clone the row, and add it back:
65
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
68
+ table << new_row # to use the symbol style header references,
69
+ # the row first needs to be added back to the
70
70
  # table
71
71
  new_row[:a] = v
72
72
  end
73
73
  table.delete(template_row) # you don't want the template to show up
74
74
  # in the endresult
75
75
  b.write("result.xls") # write it!
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
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
78
  (like "Total order price" and `total_order_price` match) to the headers of the database-table ):
79
79
 
80
80
  b = Workbook::Book.open("template.xls")
@@ -90,54 +90,54 @@ Another typical use case is exporting a list of ActiveRecord-objects to xls (it
90
90
  b.write("recent_orders.xls") # write it!
91
91
 
92
92
 
93
- <!-- Feature *to implement*:
94
-
93
+ <!-- Feature *to implement*:
94
+
95
95
  Feature *to implement*, get a single column:
96
96
 
97
97
  t[:b]
98
- # returns [<Workbook::Cel @value=2>,<Workbook::Cel @value=4>,<Workbook::Cel @value=6>]
99
-
98
+ # returns [<Workbook::Cel @value=2>,<Workbook::Cel @value=4>,<Workbook::Cel @value=6>]
99
+
100
100
  On my wishlist: In the future I hope to return the cell value directly, without the intermediate Workbook::Cell class in between.
101
-
101
+
102
102
  -->
103
-
103
+
104
104
  ## Utilities
105
105
 
106
106
  ### Sorting
107
107
 
108
108
  Sorting leaves the header alone, if it exists, and doesn't complain about comparing strings with dates with floats (Ever found OpenOffice Calc or Excel complainging about its inability to compare integers and strings? We're talking spreadsheet here). When classes are different the following (default) order is used: Numbers, Strings, Dates and Times, Booleans and Nils (empty values).
109
109
 
110
- t.sort
111
-
110
+ t.sort
111
+
112
112
  *To implement*:
113
113
 
114
- To some extent, sort_by works, it doesn't, however, adhere to the header settings...
115
-
114
+ To some extent, sort_by works, it doesn't, however, adhere to the header settings...
115
+
116
116
  t.sort_by {|r| r[:b]}
117
-
117
+
118
118
  ### Comparing tables
119
-
119
+
120
120
  Simply call on a Workbook::Table
121
121
 
122
122
  t1.diff t2
123
-
123
+
124
124
  And a new book with a new sheet/table will be returned containing the differences between the two tables.
125
-
125
+
126
126
  ## Writing
127
127
 
128
128
  Currently writing is limited to the following formats. Templating support is still limited.
129
-
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
-
129
+
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
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.
137
-
137
+
138
138
  ## Compatibility
139
139
 
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).
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).
141
141
 
142
142
  ## Alternatives
143
143
 
@@ -27,6 +27,7 @@ module Workbook
27
27
  if valid_value? value
28
28
  self.format = options[:format]
29
29
  @value = value
30
+ @to_sym = nil
30
31
  else
31
32
  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])"
32
33
  end
@@ -38,6 +39,7 @@ module Workbook
38
39
  def value= value
39
40
  if valid_value? value
40
41
  @value = value
42
+ @to_sym = nil
41
43
  else
42
44
  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])"
43
45
  end
@@ -94,13 +96,14 @@ module Workbook
94
96
  #
95
97
  # <Workbook::Cell value="yet another value">.to_sym # returns :yet_another_value
96
98
  def to_sym
99
+ return @to_sym if @to_sym
97
100
  #mb_chars.normalize(:kd).
98
101
  v = nil
99
102
  if value
103
+ ends_with_exclamationmark = (value[-1] == '!')
104
+ ends_with_questionmark = (value[-1] == '?')
100
105
  v = value.to_s.downcase
101
- v = v.gsub(' (j/?/leeg)','').gsub(/dd-mm-(.*)/,'').gsub(/ja\/nee/,'').gsub(/\(\)/,'').gsub(/[\(\)]+/, '')
102
- v = v.strip.gsub(/(\.|\?|,|\=)/,'').
103
- gsub('$','').
106
+ v = v.strip.gsub(/[\(\)\.\?\,\!\=\$]/,'').
104
107
  gsub(/\&/,'en').
105
108
  gsub(/\+/,'_plus_').
106
109
  gsub(/\s/, "_").
@@ -113,8 +116,8 @@ module Workbook
113
116
  gsub('-','')
114
117
 
115
118
  accents = {
116
- ['á','à','â','ä','ã'] => 'a',
117
- ['Ã','Ä','Â','À','�?'] => 'A',
119
+ ['á','à','â','ä','ã','å'] => 'a',
120
+ ['Ã','Ä','Â','À','�?','Å'] => 'A',
118
121
  ['é','è','ê','ë'] => 'e',
119
122
  ['Ë','É','È','Ê'] => 'E',
120
123
  ['í','ì','î','ï'] => 'i',
@@ -123,8 +126,14 @@ module Workbook
123
126
  ['Õ','Ö','Ô','Ò','Ó'] => 'O',
124
127
  ['ú','ù','û','ü'] => 'u',
125
128
  ['Ú','Û','Ù','Ü'] => 'U',
126
- ['ç'] => 'c', ['Ç'] => 'C',
127
- ['ñ'] => 'n', ['Ñ'] => 'N'
129
+ ['ç'] => 'c',
130
+ ['Ç'] => 'C',
131
+ ['š', 'ś'] => 's',
132
+ ['Š', 'Ś'] => 'S',
133
+ ['ž','ź'] => 'z',
134
+ ['Ž','Ź'] => 'Z',
135
+ ['ñ'] => 'n',
136
+ ['Ñ'] => 'N'
128
137
  }
129
138
  accents.each do |ac,rep|
130
139
  ac.each do |s|
@@ -138,9 +147,12 @@ module Workbook
138
147
  encoding_options = {:invalid => :replace, :undef => :replace, :replace => ''}
139
148
  v = v.encode(Encoding.find('ASCII'), encoding_options)
140
149
  end
150
+ v = "#{v}!" if ends_with_exclamationmark
151
+ v = "#{v}?" if ends_with_questionmark
141
152
  v = v.downcase.to_sym
142
153
  end
143
- v
154
+ @to_sym = v
155
+ return @to_sym
144
156
  end
145
157
 
146
158
  # Compare
@@ -124,7 +124,7 @@ module Workbook
124
124
  #
125
125
  # @return [Boolean]
126
126
  def header?
127
- table != nil and self.object_id == table.header.object_id
127
+ table != nil and self.object_id == table_header.object_id
128
128
  end
129
129
 
130
130
  # Is this the first row in the table
@@ -153,25 +153,28 @@ module Workbook
153
153
  self.collect{|c| c}
154
154
  end
155
155
 
156
+ def table_header
157
+ table.header
158
+ end
159
+
156
160
  def table_header_keys
157
- table.header.to_symbols
161
+ table_header.to_symbols
158
162
  end
159
163
 
160
164
  # Returns a hash representation of this row
161
165
  #
162
166
  # @return [Hash]
163
167
  def to_hash
164
- #return @hash if @hash
165
168
  keys = table_header_keys
166
169
  values = self
167
- @hash = {}
168
- keys.each_with_index {|k,i| @hash[k]=values[i]}
169
- return @hash
170
+ hash = {}
171
+ keys.each_with_index {|k,i| hash[k]=values[i]}
172
+ return hash
170
173
  end
171
-
174
+
172
175
  # Returns a hash representation of this row
173
176
  #
174
- # it differs from #to_hash as it doesn't contain the Workbook's Workbook::Cell-objects,
177
+ # it differs from #to_hash as it doesn't contain the Workbook's Workbook::Cell-objects,
175
178
  # but the actual values contained in these cells
176
179
  #
177
180
  # @return [Hash]
@@ -181,7 +184,7 @@ module Workbook
181
184
  values = self
182
185
  @hash_with_values = {}
183
186
  keys.each_with_index {|k,i| v=values[i]; v=v.value if v; @hash_with_values[k]=v}
184
- return @hash_with_values
187
+ return @hash_with_values
185
188
  end
186
189
 
187
190
  # Compares one row wiht another
@@ -1,4 +1,4 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
  module Workbook
3
- VERSION = '0.4.5.1'
3
+ VERSION = '0.4.6.0'
4
4
  end
@@ -73,12 +73,19 @@ class TestCell < Test::Unit::TestCase
73
73
  end
74
74
 
75
75
  def test_to_sym
76
- c = Workbook::Cell.new "A - B"
77
- assert_equal(:a_b, c.to_sym)
78
- c = Workbook::Cell.new "A-B"
79
- assert_equal(:ab, c.to_sym)
80
- c = Workbook::Cell.new "A - c (B123)"
81
- assert_equal(:a_c_b123, c.to_sym)
76
+ examples = {
77
+ "A - B" => :a_b,
78
+ "A-B" => :ab,
79
+ "A - c (B123)" => :a_c_b123,
80
+ "A - c (B123)!" => :a_c_b123!,
81
+ "A-B?" => :ab?,
82
+ "A-B!" => :ab!,
83
+ "éåšžÌ?" => :easzi?
84
+ }
85
+ examples.each do |k,v|
86
+ assert_equal(v, Workbook::Cell.new(k).to_sym)
87
+ end
88
+
82
89
 
83
90
  end
84
91
 
@@ -61,6 +61,17 @@ class TestWorkbook < Test::Unit::TestCase
61
61
  assert_equal(s, table1.sheet)
62
62
  table1<<Workbook::Row.new([1,2,3,4])
63
63
  assert_equal(false, table1 == table0)
64
+ end
65
+ def test_profile_speed
66
+ w = Workbook::Book.new [["a","b"],[1,2],[3,4],[1,2],[3,4],[1,2],[3,4],[1,2],[3,4],[1,2],[3,4],[1,2],[3,4],[1,2],[3,4],[1,2],[3,4],[1,2],[3,4],[1,2],[3,4],[1,2],[3,4],[1,2],[3,4],[1,2],[3,4],[1,2],[3,4],[1,2],[3,4],[1,2],[3,4],[1,2],[3,4],[1,2],[3,4]]
67
+ require 'ruby-prof'
68
+ RubyProf.start
69
+ w.sheet.table.each do |row|
70
+ row[:a].value
71
+ end
72
+ result = RubyProf.stop
73
+ printer = RubyProf::MultiPrinter.new(result)
74
+ printer.print(:path => ".", :profile => "profile")
64
75
 
65
76
  end
66
77
  end
@@ -12,6 +12,7 @@ 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_development_dependency 'ruby-prof'
15
16
  s.add_dependency('rubyzip', '0.9.9')
16
17
  s.add_dependency('spreadsheet', '>= 0.7.5')
17
18
  s.add_dependency('fastercsv') if RUBY_VERSION < "1.9"
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.5.1
4
+ version: 0.4.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Maarten Brouwers
@@ -10,6 +10,20 @@ bindir: bin
10
10
  cert_chain: []
11
11
  date: 2013-04-05 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: ruby-prof
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: rubyzip
15
29
  requirement: !ruby/object:Gem::Requirement