spreadsheet_builder 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: fe7f21f4fb4946d310186670c4ad30dd48be3052
4
+ data.tar.gz: 024d27e0acf7020f858cd5705778d76efbafc937
5
+ SHA512:
6
+ metadata.gz: e963fc525bf98627b4b1a9d6f01b01186d06c72fcf28dbd47c8b237f472c41ad95f45a8db6731a4c03e9df9390243d926e4e634da2d0786ab7cdb0ec22df5915
7
+ data.tar.gz: 3e36c17975c39fa40e6262529136372373859eebe32cbcf01eaff719ed007266186430cf2c2211c3911bc6d6486c386de36e132b34812b0067cc3190c34012db
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,43 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ spreadsheet_builder (0.0.1)
5
+ css_parser
6
+ nokogiri
7
+ shade
8
+ spreadsheet
9
+
10
+ GEM
11
+ remote: https://rubygems.org/
12
+ specs:
13
+ addressable (2.3.8)
14
+ color (1.7.1)
15
+ css_parser (1.3.6)
16
+ addressable
17
+ ffi (1.9.10)
18
+ ffi-compiler (0.1.3)
19
+ ffi (>= 1.0.0)
20
+ rake
21
+ geokdtree (0.2.0)
22
+ ffi
23
+ ffi-compiler
24
+ rake
25
+ mini_portile (0.6.2)
26
+ nokogiri (1.6.6.2)
27
+ mini_portile (~> 0.6.0)
28
+ rake (10.4.2)
29
+ ruby-ole (1.2.11.8)
30
+ shade (0.0.1)
31
+ color
32
+ geokdtree
33
+ spreadsheet (1.0.4)
34
+ ruby-ole (>= 1.0)
35
+
36
+ PLATFORMS
37
+ ruby
38
+
39
+ DEPENDENCIES
40
+ spreadsheet_builder!
41
+
42
+ BUNDLED WITH
43
+ 1.10.5
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013 John Hager
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/fail_width.xls ADDED
Binary file
@@ -0,0 +1,24 @@
1
+ require 'shade'
2
+ require 'nokogiri'
3
+ require 'css_parser'
4
+ require 'spreadsheet'
5
+
6
+ require_relative 'spreadsheet_builder/builder'
7
+ require_relative 'spreadsheet_builder/css_parser'
8
+ require_relative 'spreadsheet_builder/css_rule'
9
+ require_relative 'spreadsheet_builder/html_parser'
10
+ require_relative 'spreadsheet_builder/border'
11
+ require_relative 'spreadsheet_builder/data'
12
+ require_relative 'spreadsheet_builder/palette'
13
+ require_relative 'spreadsheet_builder/translations'
14
+
15
+ # TODO find out if this is necessary
16
+ include CssParser
17
+
18
+ module SpreadsheetBuilder
19
+
20
+ # Utility
21
+ def self.merge(*options)
22
+ options.inject(&:merge)
23
+ end
24
+ end
@@ -0,0 +1,163 @@
1
+ class Border
2
+
3
+ def initialize(key, val, dir = nil)
4
+ @dir = dir && dir.to_sym
5
+ @vals = val.scan(/[^\s]+/)
6
+ @keys = key.scan(/[^-]+/)
7
+ @border = self
8
+ dir_hash = { top: nil, bottom: nil, left: nil, right: nil }
9
+ @css = {
10
+ color: dir_hash.dup,
11
+ style: dir_hash.dup,
12
+ width: dir_hash.dup
13
+ }
14
+
15
+ case @keys[1]
16
+ when Proc.new { |type| @css.keys.include?(type.to_sym) if type }
17
+ assign_vals_to(@keys[1])
18
+ when nil # "border"
19
+ width, style, color = @vals
20
+ w, s, c = @css[:width], @css[:style], @css[:color]
21
+
22
+ w[:top] = w[:bottom] = w[:left] = w[:right] = width
23
+ s[:top] = s[:bottom] = s[:left] = s[:right] = style
24
+ c[:top] = c[:bottom] = c[:left] = c[:right] = color
25
+ else # "border-left"
26
+ dir = @keys.delete_at(1)
27
+ @border = Border.new(@keys.join('-'), @vals.join(' '), dir)
28
+ end
29
+ end
30
+
31
+ #border: 1px solid black;
32
+ #border-width: 1px 1px 1px 1px;
33
+ #border-width: 1px; // all
34
+ #border-width: 1px 2px; // top and bottom 1px, left and right 2px
35
+ #border-width: 1px 2px 3px; // top 1px, left and right 2px, bottom 3px
36
+ #border-#{direction}-width: 1px;
37
+
38
+ def assign_vals_to(type)
39
+ t = @css[type.to_sym]
40
+ case @vals.length
41
+ when 1
42
+ t[:top] = t[:bottom] = t[:left] = t[:right] = @vals[0]
43
+ when 2
44
+ t[:top] = t[:bottom] = @vals[0]
45
+ t[:left] = t[:right] = @vals[1]
46
+ when 3
47
+ t[:top] = @vals[0]
48
+ t[:left] = t[:right] = @vals[1]
49
+ t[:bottom] = @vals[2]
50
+ when 4
51
+ t[:top], t[:bottom], t[:left], t[:right] = @vals
52
+ end
53
+ end
54
+
55
+ def format
56
+ @border._format
57
+ end
58
+
59
+ SPREADSHEET_VALUES = [
60
+ :none,
61
+ :thin,
62
+ :medium,
63
+ :thick,
64
+ :double,
65
+ :hair,
66
+ :dashed,
67
+ :dotted,
68
+ :thin_dash_dotted,
69
+ :thin_dash_dot_dotted,
70
+ :medium_dashed,
71
+ :medium_dash_dotted,
72
+ :medium_dash_dot_dotted,
73
+ :slanted_medium_dash_dotted
74
+ ]
75
+
76
+ colors_attrs = [
77
+ :bottom_color,
78
+ :top_color,
79
+ :left_color,
80
+ :right_color,
81
+ :pattern_fg_color,
82
+ :pattern_bg_color,
83
+ :diagonal_color
84
+ ]
85
+
86
+ protected
87
+ def _format
88
+ format = {}
89
+
90
+ # merge width and style
91
+ translated_values.values.first.keys.each do |dir|
92
+ width = translated_values[:width][dir]
93
+ style = translated_values[:style][dir]
94
+
95
+ if width && style && width != style
96
+ found = SPREADSHEET_VALUES.find { |val|
97
+ val.to_s =~ /#{width}/ && val.to_s =~ /#{style}/
98
+ }
99
+ if found
100
+ translated_values[:width][dir] = found
101
+ translated_values[:style][dir] = found
102
+ end
103
+ end
104
+ end
105
+
106
+ dirs = @dir ? [@dir] : translated_values.values.first.keys
107
+ dirs.each do |dir|
108
+ style = translated_values[:width][dir] || translated_values[:style][dir]
109
+ color = translated_values[:color][dir]
110
+
111
+ format["#{dir}_color".to_sym] = color if color
112
+ format[dir.to_sym] = style if style
113
+ format[:pattern_fg_color] = color if style.to_s =~ /(dash|dott)/
114
+ end
115
+ format
116
+ end
117
+
118
+ private
119
+ def translated_values
120
+ return @translated_values if @translated_values
121
+
122
+ @translated_values = {}
123
+ @css.each { |k,v| @translated_values[k] = v.dup }
124
+
125
+ @translated_values.each do |type, vals|
126
+ vals.each do |dir, v|
127
+ @translated_values[type][dir] = __send__("translate_#{type}", v)
128
+ end
129
+ end
130
+ end
131
+
132
+ #thin|medium|thick
133
+ def translate_width(val)
134
+ return unless val
135
+
136
+ if val.to_i.to_s == val.to_s
137
+ val = val.to_i
138
+ if val <= 0 then nil
139
+ elsif val 1 then :thin
140
+ elsif val 2 then :medium
141
+ else :thick
142
+ end
143
+ elsif SPREADSHEET_VALUES.include?(val.to_sym)
144
+ val.to_sym
145
+ end
146
+ end
147
+
148
+ def translate_color(val)
149
+ return unless val
150
+
151
+ SpreadsheetBuilder::Palette._color_from_input(val)
152
+ end
153
+
154
+ def translate_style(val)
155
+ return unless val
156
+
157
+ if SPREADSHEET_VALUES.include?(val.to_sym)
158
+ val.to_sym
159
+ else
160
+ :thin
161
+ end
162
+ end
163
+ end
@@ -0,0 +1,194 @@
1
+ module SpreadsheetBuilder
2
+ class Builder
3
+
4
+ attr_accessor :name
5
+ attr_reader :book, :sheets
6
+ def initialize
7
+ @cells = Hash.new { |h,k| h[k] = { value: nil, format: {} } }
8
+ @sheets = []
9
+ @merges = Hash.new { |h,k| h[k] = [] }
10
+ @row_heights = Hash.new { |h,k| h[k] = {} }
11
+ @col_widths = Hash.new { |h,k| h[k] = {} }
12
+ end
13
+
14
+ def _print
15
+ index = current_sheet
16
+ cells = sheet_cells(index)
17
+ 0.upto(sheet_rows(cells).last) do |row|
18
+ cols = []
19
+ 0.upto(sheet_cols(cells).last) do |col|
20
+ cols << @cells[[index, row, col]][:value]
21
+ end
22
+ puts cols.join("\t")
23
+ end
24
+ end
25
+
26
+ def current_sheet
27
+ @current_sheet ||= 0
28
+ end
29
+
30
+ def _cells
31
+ @cells
32
+ end
33
+
34
+ def to_spreadsheet
35
+ @sheets << 'Sheet 1' if @sheets.empty?
36
+
37
+ @book = Spreadsheet::Workbook.new
38
+
39
+ CUSTOM_PALETTE.each do |name, color|
40
+ @book.set_custom_color(name, color.r, color.g, color.b)
41
+ end
42
+
43
+ @book_sheets = @sheets.map { |n| book.create_worksheet(name: n) }
44
+ @book_sheets.each_with_index do |sheet, index|
45
+ build_sheet(sheet, index)
46
+ end
47
+ @book
48
+ end
49
+
50
+ def add_merge(r1, c1, r2, c2)
51
+ @merges[current_sheet] << [r1, c1 ,r2, c2]
52
+ end
53
+
54
+ def set_row_height(row, height)
55
+ @row_heights[current_sheet][row] = Integer(height)
56
+ end
57
+
58
+ def set_col_width(col, width)
59
+ @col_widths[current_sheet][col] = Integer(width)
60
+ end
61
+
62
+ def add_sheet(name)
63
+ @sheets << name.to_s
64
+ end
65
+
66
+ def set_sheet_by_name(name)
67
+ @current_sheet = @sheets.index(name)
68
+ end
69
+
70
+ def set_sheet(index)
71
+ @current_sheet = index
72
+ end
73
+
74
+ def add_blank_row(row)
75
+ sheet_cols(sheet_cells(current_sheet)).each do |col|
76
+ set_cell_value(row, col, '')
77
+ end
78
+ end
79
+
80
+ def set_cell_value(row, col, val)
81
+ @cells[[current_sheet, row, col]][:value] = val
82
+ end
83
+
84
+ def add_format_to_cell(row, col, options)
85
+ @cells[[current_sheet, row, col]][:format].merge!(options)
86
+ end
87
+
88
+ def add_format_to_row(row, options)
89
+ sheet_cols(sheet_cells(current_sheet)).each do |col|
90
+ add_format_to_cell(row, col, options)
91
+ end
92
+ end
93
+
94
+ def add_format_to_col(col, options)
95
+ sheet_rows(sheet_cells(current_sheet)).each do |row|
96
+ add_format_to_cell(row, col, options)
97
+ end
98
+ end
99
+
100
+ def add_format_to_box(r1, c1, r2, c2, options)
101
+ (r1..r2).each do |row|
102
+ (c1..c2).each do |col|
103
+ add_format_to_cell(row, col, options)
104
+ end
105
+ end
106
+ end
107
+
108
+ #private
109
+ def sheet_cells(index)
110
+ @cells.select { |(sheet,_,_),_| sheet == index }
111
+ end
112
+
113
+ def sheet_rows(cells)
114
+ rows = cells.keys.map { |(_,row,_)| row }.sort
115
+ rows.first..rows.last
116
+ end
117
+
118
+ def sheet_cols(cells)
119
+ cols = cells.keys.map { |(_,_,col)| col }.sort
120
+ cols.first..cols.last
121
+ end
122
+
123
+ def add_each_row(sheet, cells, index)
124
+ 0.upto(sheet_rows(cells).last) do |row|
125
+ cols = []
126
+ 0.upto(sheet_cols(cells).last) do |col|
127
+ cols << @cells[[index, row, col]][:value]
128
+ end
129
+ sheet.row(row).concat(cols)
130
+ end
131
+ end
132
+
133
+ def format_each_row(sheet, cells, index)
134
+ sheet_rows(cells).each do |row|
135
+ sheet_cols(cells).each do |col|
136
+ sheet.row(row).set_format(
137
+ col,
138
+ Spreadsheet::Format.new(@cells[[index, row, col]][:format])
139
+ )
140
+ end
141
+ end
142
+ end
143
+
144
+ def merge_cells(sheet, index)
145
+ @merges[index].each do |points|
146
+ sheet.merge_cells(*points)
147
+ end
148
+ end
149
+
150
+ def set_row_heights(sheet, index)
151
+ @row_heights[index].each do |row, height|
152
+ sheet.row(row).height = height
153
+ end
154
+ end
155
+
156
+ def set_col_widths(sheet, index)
157
+ @col_widths[index].each do |col, width|
158
+ sheet.column(col).width = width
159
+ end
160
+ end
161
+
162
+ def handle_height_or_width_format(sheet, cells, index)
163
+ sheet_cells(index).each do |(_, row, col), cell|
164
+ if cell[:format].keys.include?(:height)
165
+ current = @row_heights[index][row]
166
+ if !current || current < Integer(cell[:format][:height])
167
+ @row_heights[index][row] = Integer(cell[:format][:height])
168
+ end
169
+ cell[:format].delete(:height)
170
+ end
171
+ if cell[:format].keys.include?(:width)
172
+ current = @col_widths[index][col]
173
+ if !current || current < Integer(cell[:format][:width])
174
+ @col_widths[index][col] = Integer(cell[:format][:width])
175
+ end
176
+ cell[:format].delete(:width)
177
+ end
178
+ end
179
+ end
180
+
181
+ def build_sheet(sheet, index)
182
+ cells = sheet_cells(index)
183
+
184
+ unless cells.empty?
185
+ add_each_row(sheet, cells, index)
186
+ handle_height_or_width_format(sheet, cells, index)
187
+ format_each_row(sheet, cells, index)
188
+ merge_cells(sheet, index)
189
+ set_row_heights(sheet, index)
190
+ set_col_widths(sheet, index)
191
+ end
192
+ end
193
+ end
194
+ end