workbook 0.1.2 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
data/lib/workbook/book.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'workbook/writers/xls_writer'
2
2
  require 'workbook/readers/xls_reader'
3
+ require 'workbook/readers/xlsx_reader'
3
4
  require 'workbook/readers/csv_reader'
4
5
  require 'workbook/readers/txt_reader'
5
6
  require 'rchardet'
@@ -8,6 +9,7 @@ module Workbook
8
9
  class Book < Array
9
10
  include Workbook::Writers::XlsWriter
10
11
  include Workbook::Readers::XlsReader
12
+ include Workbook::Readers::XlsxReader
11
13
  include Workbook::Readers::CsvReader
12
14
  include Workbook::Readers::TxtReader
13
15
 
@@ -0,0 +1,146 @@
1
+ require 'rubyXL'
2
+
3
+ #monkeypatching rubyXL, pull request submitted: https://github.com/gilt/rubyXL/pull/47
4
+ module RubyXL
5
+ class Workbook
6
+ def is_date_format?(num_fmt)
7
+ num_fmt.downcase!
8
+ skip_chars = ['$', '-', '+', '/', '(', ')', ':', ' ']
9
+ num_chars = ['0', '#', '?']
10
+ non_date_formats = ['0.00e+00', '##0.0e+0', 'general', '@']
11
+ date_chars = ['y','m','d','h','s']
12
+
13
+ state = 0
14
+ s = ''
15
+ num_fmt.split(//).each do |c|
16
+ if state == 0
17
+ if c == '"'
18
+ state = 1
19
+ elsif ['\\', '_', '*'].include?(c)
20
+ state = 2
21
+ elsif skip_chars.include?(c)
22
+ next
23
+ else
24
+ s << c
25
+ end
26
+ elsif state == 1
27
+ if c == '"'
28
+ state = 0
29
+ end
30
+ elsif state == 2
31
+ state = 0
32
+ end
33
+ end
34
+ s.gsub!(/\[[^\]]*\]/, '')
35
+ if non_date_formats.include?(s)
36
+ return false
37
+ end
38
+ separator = ';'
39
+ got_sep = 0
40
+ date_count = 0
41
+ num_count = 0
42
+ s.split(//).each do |c|
43
+ if date_chars.include?(c)
44
+ date_count += 1
45
+ elsif num_chars.include?(c)
46
+ num_count += 1
47
+ elsif c == separator
48
+ got_sep = 1
49
+ end
50
+ end
51
+ if date_count > 0 && num_count == 0
52
+ return true
53
+ elsif num_count > 0 && date_count == 0
54
+ return false
55
+ elsif date_count
56
+ # ambiguous result
57
+ elsif got_sep == 0
58
+ # constant result
59
+ end
60
+ return date_count > num_count
61
+ end
62
+ end
63
+ end
64
+ # end monkey patch submitted
65
+
66
+ # other monkey patch
67
+ module RubyXL
68
+ class Cell
69
+ def number_format
70
+ if !@value.is_a?(String)
71
+ if @workbook.num_fmts_by_id
72
+ num_fmt_id = xf_id()[:numFmtId]
73
+ tmp_num_fmt = @workbook.num_fmts_by_id[num_fmt_id]
74
+ return (tmp_num_fmt &&tmp_num_fmt[:attributes] && tmp_num_fmt[:attributes][:formatCode]) ? tmp_num_fmt[:attributes][:formatCode] : nil
75
+ end
76
+ end
77
+ end
78
+ def fill_color
79
+ if !@value.is_a?(String)
80
+ if @workbook.num_fmts_by_id
81
+ num_fmt_id = xf_id()[:numFmtId]
82
+ tmp_num_fmt = @workbook.num_fmts_by_id[num_fmt_id]
83
+ return (tmp_num_fmt &&tmp_num_fmt[:attributes] && tmp_num_fmt[:attributes][:formatCode]) ? tmp_num_fmt[:attributes][:formatCode] : nil
84
+ end
85
+ end
86
+ end
87
+
88
+ end
89
+ end
90
+ # end of monkey patch
91
+
92
+ module Workbook
93
+ module Readers
94
+ module XlsxReader
95
+ def load_xlsx file_obj
96
+ file_obj = file_obj.path if file_obj.is_a? File
97
+ sp = RubyXL::Parser.parse(file_obj)
98
+ template.add_raw sp
99
+ parse_xlsx sp
100
+ end
101
+
102
+ def parse_xlsx xlsx_spreadsheet=template.raws[RubyXL::Workbook], options={}
103
+ options = {:additional_type_parsing=>false}.merge options
104
+ #number_of_worksheets = xlsx_spreadsheet.worksheets.count
105
+ xlsx_spreadsheet.worksheets.each_with_index do |worksheet, si|
106
+ s = create_or_open_sheet_at(si)
107
+ col_widths = xlsx_spreadsheet.worksheets.first.cols.collect{|a| a[:attributes][:width].to_f if a[:attributes]}
108
+ worksheet.each_with_index do |row, ri|
109
+ r = s.table.create_or_open_row_at(ri)
110
+
111
+ row.each_with_index do |cell,ci|
112
+
113
+ r[ci] = Workbook::Cell.new cell.value
114
+ r[ci].parse!
115
+
116
+ xls_format = cell.style_index
117
+ col_width = nil
118
+
119
+ if ri == 0
120
+ col_width = col_widths[ci]
121
+ end
122
+ f = template.create_or_find_format_by "style_index_#{cell.style_index}", col_width
123
+ f[:width]= col_width
124
+ f[:background_color] = "##{cell.fill_color}"
125
+ f[:number_format] = ms_formatting_to_strftime(cell.number_format)
126
+ f[:font_family] = cell.font_name
127
+ f[:color] = "##{cell.font_color}"
128
+
129
+ f.add_raw xls_format
130
+
131
+ r[ci].format = f
132
+ end
133
+ end
134
+ end
135
+ end
136
+ private
137
+ def ms_formatting_to_strftime ms_nr_format
138
+ if ms_nr_format
139
+ ms_nr_format = ms_nr_format.downcase
140
+ return nil if ms_nr_format == 'general'
141
+ 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('\\','')
142
+ end
143
+ end
144
+ end
145
+ end
146
+ end
data/readme.markdown CHANGED
@@ -14,7 +14,7 @@ Subsequently a table consists of:
14
14
 
15
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
- In addition to offering you this plain structure it allows for importing and writing .xls and .csv files (more to come), and includes the utility to easily create an overview of the differences between two tables and read out basic cell-styling properties as css.
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
 
@@ -3,7 +3,7 @@ module Modules
3
3
  class TestTypeParser < Test::Unit::TestCase
4
4
  def examples
5
5
  {"2312"=>2312,
6
- "12-12-2012"=>Date.new(2012,12,12),
6
+ # "12-12-2012"=>Date.new(2012,12,12),
7
7
  "12-12-2012 12:24"=>DateTime.new(2012,12,12,12,24),
8
8
  "2012-12-12 12:24"=>DateTime.new(2012,12,12,12,24),
9
9
  "2011-05-19T15_37_49 - 52349.xml"=>"2011-05-19T15_37_49 - 52349.xml",
@@ -0,0 +1,16 @@
1
+ require File.join(File.dirname(__FILE__), 'helper')
2
+ module Readers
3
+ class TestXlsxWriter < Test::Unit::TestCase
4
+ def test_open
5
+ w = Workbook::Book.new
6
+ w.open 'test/artifacts/book_with_tabs_and_colours.xlsx'
7
+ assert_equal([:a, :b, :c, :d, :e],w.sheet.table.header.to_symbols)
8
+ assert_equal(90588,w.sheet.table[2][:b].value)
9
+ assert_equal(DateTime.new(2011,11,15),w.sheet.table[3][:d].value)
10
+ # assert_equal("#CCFFCC",w.sheet.table[3][:c].format[:background_color]) #colour compatibility turned off for now...
11
+ assert_equal(8,w.sheet.table.first[:b].format[:width].round)
12
+ assert_equal(4,w.sheet.table.first[:a].format[:width].round)
13
+ assert_equal(25,w.sheet.table.first[:c].format[:width].round)
14
+ end
15
+ end
16
+ end
data/workbook.gemspec CHANGED
@@ -5,7 +5,7 @@ require "workbook"
5
5
  Gem::Specification.new do |s|
6
6
  s.name = 'workbook'
7
7
  s.rubyforge_project = 'workbook'
8
- s.version = '0.1.2'
8
+ s.version = '0.1.5'
9
9
  s.date = '2012-11-12'
10
10
  s.summary = "Workbook is a datastructure to contain books of tables (an anlogy used in e.g. Excel)"
11
11
  s.description = "Workbook contains workbooks, as in a table, contains rows, contains cells, reads/writes excels and csv's and tab separated, and offers basic diffing and sorting capabilities."
@@ -13,6 +13,7 @@ Gem::Specification.new do |s|
13
13
  s.add_dependency('spreadsheet', '>= 0.6.8')
14
14
  s.add_dependency('fastercsv')
15
15
  s.add_dependency("rchardet", "~> 1.3")
16
+ s.add_dependency('rubyXL')
16
17
  s.platform = Gem::Platform::RUBY
17
18
  s.files = `git ls-files`.split("\n")
18
19
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 2
9
- version: 0.1.2
8
+ - 5
9
+ version: 0.1.5
10
10
  platform: ruby
11
11
  authors:
12
12
  - Maarten Brouwers
@@ -56,6 +56,18 @@ dependencies:
56
56
  version: "1.3"
57
57
  type: :runtime
58
58
  version_requirements: *id003
59
+ - !ruby/object:Gem::Dependency
60
+ name: rubyXL
61
+ prerelease: false
62
+ requirement: &id004 !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ segments:
67
+ - 0
68
+ version: "0"
69
+ type: :runtime
70
+ version_requirements: *id004
59
71
  description: Workbook contains workbooks, as in a table, contains rows, contains cells, reads/writes excels and csv's and tab separated, and offers basic diffing and sorting capabilities.
60
72
  email:
61
73
  - gem@murb.nl
@@ -80,6 +92,7 @@ files:
80
92
  - lib/workbook/readers/csv_reader.rb
81
93
  - lib/workbook/readers/txt_reader.rb
82
94
  - lib/workbook/readers/xls_reader.rb
95
+ - lib/workbook/readers/xlsx_reader.rb
83
96
  - lib/workbook/row.rb
84
97
  - lib/workbook/sheet.rb
85
98
  - lib/workbook/table.rb
@@ -88,6 +101,7 @@ files:
88
101
  - lib/workbook/writers/xls_writer.rb
89
102
  - readme.markdown
90
103
  - test/artifacts/book_with_tabs_and_colours.xls
104
+ - test/artifacts/book_with_tabs_and_colours.xlsx
91
105
  - test/artifacts/complex_types.xls
92
106
  - test/artifacts/excel_different_types.csv
93
107
  - test/artifacts/excel_different_types.txt
@@ -109,6 +123,7 @@ files:
109
123
  - test/test_readers_csv_reader.rb
110
124
  - test/test_readers_txt_reader.rb
111
125
  - test/test_readers_xls_reader.rb
126
+ - test/test_readers_xlsx_reader.rb
112
127
  - test/test_row.rb
113
128
  - test/test_sheet.rb
114
129
  - test/test_table.rb
@@ -147,6 +162,7 @@ specification_version: 3
147
162
  summary: Workbook is a datastructure to contain books of tables (an anlogy used in e.g. Excel)
148
163
  test_files:
149
164
  - test/artifacts/book_with_tabs_and_colours.xls
165
+ - test/artifacts/book_with_tabs_and_colours.xlsx
150
166
  - test/artifacts/complex_types.xls
151
167
  - test/artifacts/excel_different_types.csv
152
168
  - test/artifacts/excel_different_types.txt
@@ -168,6 +184,7 @@ test_files:
168
184
  - test/test_readers_csv_reader.rb
169
185
  - test/test_readers_txt_reader.rb
170
186
  - test/test_readers_xls_reader.rb
187
+ - test/test_readers_xlsx_reader.rb
171
188
  - test/test_row.rb
172
189
  - test/test_sheet.rb
173
190
  - test/test_table.rb