workbook 0.1.1
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.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +22 -0
- data/Rakefile +12 -0
- data/lib/workbook/book.rb +122 -0
- data/lib/workbook/cell.rb +143 -0
- data/lib/workbook/format.rb +35 -0
- data/lib/workbook/modules/raw_objects_storage.rb +31 -0
- data/lib/workbook/modules/table_diff_sort.rb +140 -0
- data/lib/workbook/modules/type_parser.rb +97 -0
- data/lib/workbook/readers/csv_reader.rb +31 -0
- data/lib/workbook/readers/txt_reader.rb +17 -0
- data/lib/workbook/readers/xls_reader.rb +161 -0
- data/lib/workbook/row.rb +101 -0
- data/lib/workbook/sheet.rb +22 -0
- data/lib/workbook/table.rb +67 -0
- data/lib/workbook/template.rb +52 -0
- data/lib/workbook/writers/csv_table_writer.rb +23 -0
- data/lib/workbook/writers/xls_writer.rb +172 -0
- data/lib/workbook.rb +14 -0
- data/readme.markdown +99 -0
- data/test/artifacts/book_with_tabs_and_colours.xls +0 -0
- data/test/artifacts/complex_types.xls +0 -0
- data/test/artifacts/medewerkers.xls +0 -0
- data/test/artifacts/simple_csv.csv +4 -0
- data/test/artifacts/simple_excel_csv.csv +6 -0
- data/test/artifacts/simple_sheet.xls +0 -0
- data/test/artifacts/xls_with_txt_extension.txt +0 -0
- data/test/helper.rb +3 -0
- data/test/test_book.rb +56 -0
- data/test/test_cell.rb +82 -0
- data/test/test_format.rb +59 -0
- data/test/test_functional.rb +30 -0
- data/test/test_modules_table_diff_sort.rb +120 -0
- data/test/test_modules_type_parser.rb +53 -0
- data/test/test_readers_csv_reader.rb +37 -0
- data/test/test_readers_txt_reader.rb +49 -0
- data/test/test_readers_xls_reader.rb +26 -0
- data/test/test_row.rb +114 -0
- data/test/test_sheet.rb +26 -0
- data/test/test_table.rb +43 -0
- data/test/test_template.rb +24 -0
- data/test/test_writers_xls_writer.rb +37 -0
- data/workbook.gemspec +26 -0
- metadata +165 -0
@@ -0,0 +1,161 @@
|
|
1
|
+
require 'spreadsheet'
|
2
|
+
|
3
|
+
module Workbook
|
4
|
+
module Readers
|
5
|
+
module XlsReader
|
6
|
+
XLS_COLORS = {:xls_color_1=>'#000000',
|
7
|
+
:xls_color_2=>'#FFFFFF',
|
8
|
+
:xls_color_3=>'#FF0000',
|
9
|
+
:xls_color_4=>'#00FF00',
|
10
|
+
:xls_color_5=>'#0000FF',
|
11
|
+
:xls_color_6=>'#FFFF00',
|
12
|
+
:xls_color_7=>'#FF00FF',
|
13
|
+
:xls_color_8=>'#00FFFF',
|
14
|
+
:xls_color_9=>'#800000',
|
15
|
+
:xls_color_10=>'#008000',
|
16
|
+
:xls_color_11=>'#000080',
|
17
|
+
:xls_color_12=>'#808000',
|
18
|
+
:xls_color_13=>'#800080',
|
19
|
+
:xls_color_14=>'#008080',
|
20
|
+
:xls_color_15=>'#C0C0C0',
|
21
|
+
:xls_color_16=>'#808080',
|
22
|
+
:xls_color_17=>'#9999FF',
|
23
|
+
:xls_color_18=>'#993366',
|
24
|
+
:xls_color_19=>'#FFFFCC',
|
25
|
+
:xls_color_20=>'#CCFFFF',
|
26
|
+
:xls_color_21=>'#660066',
|
27
|
+
:xls_color_22=>'#FF8080',
|
28
|
+
:xls_color_23=>'#0066CC',
|
29
|
+
:xls_color_24=>'#CCCCFF',
|
30
|
+
:xls_color_25=>'#000080',
|
31
|
+
:xls_color_26=>'#FF00FF',
|
32
|
+
:xls_color_27=>'#FFFF00',
|
33
|
+
:xls_color_28=>'#00FFFF',
|
34
|
+
:xls_color_29=>'#800080',
|
35
|
+
:xls_color_30=>'#800000',
|
36
|
+
:xls_color_31=>'#008080',
|
37
|
+
:xls_color_32=>'#0000FF',
|
38
|
+
:xls_color_33=>'#00CCFF',
|
39
|
+
:xls_color_34=>'#CCFFFF',
|
40
|
+
:xls_color_35=>'#CCFFCC',
|
41
|
+
:xls_color_36=>'#FFFF99',
|
42
|
+
:xls_color_37=>'#99CCFF',
|
43
|
+
:xls_color_38=>'#FF99CC',
|
44
|
+
:xls_color_39=>'#CC99FF',
|
45
|
+
:xls_color_40=>'#FFCC99',
|
46
|
+
:xls_color_41=>'#3366FF',
|
47
|
+
:xls_color_42=>'#33CCCC',
|
48
|
+
:xls_color_43=>'#99CC00',
|
49
|
+
:xls_color_44=>'#FFCC00',
|
50
|
+
:xls_color_45=>'#FF9900',
|
51
|
+
:xls_color_46=>'#FF6600',
|
52
|
+
:xls_color_47=>'#666699',
|
53
|
+
:xls_color_48=>'#969696',
|
54
|
+
:xls_color_49=>'#003366',
|
55
|
+
:xls_color_50=>'#339966',
|
56
|
+
:xls_color_51=>'#003300',
|
57
|
+
:xls_color_52=>'#333300',
|
58
|
+
:xls_color_53=>'#993300',
|
59
|
+
:xls_color_54=>'#993366',
|
60
|
+
:xls_color_55=>'#333399',
|
61
|
+
:xls_color_56=>'#333333',
|
62
|
+
:black=>'#000000',
|
63
|
+
:white=>'#FFFFFF',
|
64
|
+
:red=>'#FF0000',
|
65
|
+
:green=>'#00FF00',
|
66
|
+
:blue=>'#0000FF',
|
67
|
+
:yellow=>'#FFFF00',
|
68
|
+
:magenta=>'#FF00FF',
|
69
|
+
:cyan=>'#00FFFF',
|
70
|
+
:border=>'#FFFFFF',
|
71
|
+
:text=>'#000000',
|
72
|
+
:lime=>'#00f94c'}
|
73
|
+
|
74
|
+
|
75
|
+
|
76
|
+
def load_xls file_obj
|
77
|
+
sp = Spreadsheet.open(file_obj, mode='rb')
|
78
|
+
template.add_raw sp
|
79
|
+
parse_xls sp
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
def parse_xls xls_spreadsheet=template.raws[Spreadsheet::Excel::Workbook], options={}
|
84
|
+
options = {:additional_type_parsing=>true}.merge options
|
85
|
+
number_of_worksheets = xls_spreadsheet.worksheets.count
|
86
|
+
(0..number_of_worksheets-1).each do |si|
|
87
|
+
xls_sheet = xls_spreadsheet.worksheets[si]
|
88
|
+
begin
|
89
|
+
number_of_rows = xls_spreadsheet.worksheets[si].count
|
90
|
+
s = create_or_open_sheet_at(si)
|
91
|
+
(0..number_of_rows-1).each do |ri|
|
92
|
+
xls_row = xls_sheet.row(ri)
|
93
|
+
r = s.table.create_or_open_row_at(ri)
|
94
|
+
col_widths = xls_sheet.columns.collect{|c| c.width if c}
|
95
|
+
xls_row.each_with_index do |xls_cell,ci|
|
96
|
+
|
97
|
+
begin
|
98
|
+
r[ci] = Workbook::Cell.new xls_cell
|
99
|
+
r[ci].parse!
|
100
|
+
rescue ArgumentError => e
|
101
|
+
if e.message.match('not a Spreadsheet::Formula')
|
102
|
+
v = xls_cell.value
|
103
|
+
if v.class == Float and xls_row.format(ci).date?
|
104
|
+
xls_row[ci] = v
|
105
|
+
v = xls_row.datetime(ci)
|
106
|
+
end
|
107
|
+
if v.is_a? Spreadsheet::Excel::Error
|
108
|
+
v = "----!"
|
109
|
+
end
|
110
|
+
r[ci] = Workbook::Cell.new v
|
111
|
+
elsif e.message.match('not a Spreadsheet::Link')
|
112
|
+
r[ci] = Workbook::Cell.new xls_cell.to_s
|
113
|
+
elsif e.message.match('not a Spreadsheet::Link')
|
114
|
+
r[ci] = Workbook::Cell.new xls_cell.to_s
|
115
|
+
elsif e.message.match('not a Spreadsheet::Excel::Error')
|
116
|
+
r[ci] = "._."
|
117
|
+
else
|
118
|
+
r[ci] = "._." # raise e (we're going to be silent for now)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
xls_format = xls_row.format(ci)
|
122
|
+
col_width = nil
|
123
|
+
|
124
|
+
if ri == 0
|
125
|
+
col_width = col_widths[ci]
|
126
|
+
end
|
127
|
+
f = template.create_or_find_format_by "object_id_#{xls_format.object_id}",col_width
|
128
|
+
f[:width]= col_width
|
129
|
+
f[:rotation] = xls_format.rotation if xls_format.rotation
|
130
|
+
f[:background_color] = xls_color_to_html_hex(xls_format.pattern_fg_color)
|
131
|
+
f[:number_format] = ms_formatting_to_strftime(xls_format.number_format)
|
132
|
+
f[:text_direction] = xls_format.text_direction
|
133
|
+
f[:font_family] = "#{xls_format.font.name}, #{xls_format.font.family}"
|
134
|
+
f[:font_weight] = xls_format.font.weight
|
135
|
+
f[:color] = xls_color_to_html_hex(xls_format.font.color)
|
136
|
+
|
137
|
+
f.add_raw xls_format
|
138
|
+
|
139
|
+
r[ci].format = f
|
140
|
+
end
|
141
|
+
end
|
142
|
+
rescue TypeError
|
143
|
+
puts "WARNING: Failed at worksheet (#{si})... ignored"
|
144
|
+
#ignore SpreadsheetGem can be buggy...
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
private
|
150
|
+
def xls_color_to_html_hex color_sym
|
151
|
+
XLS_COLORS[color_sym] ? XLS_COLORS[color_sym] : "#000000"
|
152
|
+
end
|
153
|
+
|
154
|
+
def ms_formatting_to_strftime ms_nr_format
|
155
|
+
ms_nr_format = ms_nr_format.downcase
|
156
|
+
return nil if ms_nr_format == 'general'
|
157
|
+
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('\\','')
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
data/lib/workbook/row.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
module Workbook
|
2
|
+
class Row < Array
|
3
|
+
alias_method :compare_without_header, :<=>
|
4
|
+
|
5
|
+
#used in compares
|
6
|
+
attr_accessor :placeholder
|
7
|
+
attr_accessor :format
|
8
|
+
|
9
|
+
|
10
|
+
def initialize cells=[], table=nil, options={}
|
11
|
+
options=options ? {:parse_cells_on_batch_creation=>false,:cell_parse_options=>{}}.merge(options) : {}
|
12
|
+
cells = [] if cells==nil
|
13
|
+
self.table= table
|
14
|
+
cells.each do |c|
|
15
|
+
if c.is_a? Workbook::Cell
|
16
|
+
c = c
|
17
|
+
else
|
18
|
+
c = Workbook::Cell.new(c)
|
19
|
+
c.parse!(options[:cell_parse_options]) if options[:parse_cells_on_batch_creation]
|
20
|
+
end
|
21
|
+
push c
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def placeholder?
|
26
|
+
placeholder ? true : false
|
27
|
+
end
|
28
|
+
|
29
|
+
def table
|
30
|
+
@table
|
31
|
+
end
|
32
|
+
|
33
|
+
# @param [Workbook::Table] Reference to the table this row belongs to (and adds the row to this table)
|
34
|
+
def table= t
|
35
|
+
raise ArgumentError, "table should be a Workbook::Table (you passed a #{t.class})" unless t.is_a?(Workbook::Table) or t == nil
|
36
|
+
if t
|
37
|
+
@table = t
|
38
|
+
table << self
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def [](index_or_hash)
|
43
|
+
if index_or_hash.is_a? Fixnum
|
44
|
+
return to_a[index_or_hash]
|
45
|
+
elsif index_or_hash.is_a? Symbol
|
46
|
+
rv = nil
|
47
|
+
begin
|
48
|
+
rv = to_hash[index_or_hash]
|
49
|
+
rescue NoMethodError
|
50
|
+
end
|
51
|
+
return rv
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# find_cells_by_color returns an array of cells allows you to find cells by a given color, normally a string containing a hex
|
56
|
+
def find_cells_by_background_color color=:any, options={}
|
57
|
+
options = {:hash_keys=>true}.merge(options)
|
58
|
+
cells = self.collect {|c| c if c.format.has_background_color?(color) }.compact
|
59
|
+
r = Row.new cells
|
60
|
+
options[:hash_keys] ? r.to_symbols : r
|
61
|
+
end
|
62
|
+
|
63
|
+
def header?
|
64
|
+
table != nil and self.object_id == table.header.object_id
|
65
|
+
end
|
66
|
+
|
67
|
+
def to_symbols
|
68
|
+
collect{|c| c.to_sym}
|
69
|
+
end
|
70
|
+
|
71
|
+
def to_a
|
72
|
+
self.collect{|c| c}
|
73
|
+
end
|
74
|
+
|
75
|
+
def to_hash
|
76
|
+
return @hash if @hash
|
77
|
+
keys = table.header.to_symbols
|
78
|
+
values = self
|
79
|
+
@hash = {}
|
80
|
+
keys.each_with_index {|k,i| @hash[k]=values[i]}
|
81
|
+
return @hash
|
82
|
+
end
|
83
|
+
|
84
|
+
def <=> other
|
85
|
+
a = self.header? ? 0 : 1
|
86
|
+
b = other.header? ? 0 : 1
|
87
|
+
return (a <=> b) if (a==0 or b==0)
|
88
|
+
compare_without_header other
|
89
|
+
end
|
90
|
+
|
91
|
+
def key
|
92
|
+
first
|
93
|
+
end
|
94
|
+
|
95
|
+
# Compact detaches the row from the table
|
96
|
+
def compact
|
97
|
+
r = self.clone
|
98
|
+
r = r.collect{|c| c unless c.nil?}.compact
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Workbook
|
2
|
+
class Sheet < Array
|
3
|
+
attr_accessor :book
|
4
|
+
|
5
|
+
def initialize table=Workbook::Table.new([], self), book=nil, options={}
|
6
|
+
if table.is_a? Workbook::Table
|
7
|
+
push table
|
8
|
+
else
|
9
|
+
push Workbook::Table.new(table, self, options)
|
10
|
+
end
|
11
|
+
self.book = book
|
12
|
+
end
|
13
|
+
|
14
|
+
def has_contents?
|
15
|
+
table.has_contents?
|
16
|
+
end
|
17
|
+
|
18
|
+
def table
|
19
|
+
first
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'workbook/modules/table_diff_sort'
|
2
|
+
require 'workbook/writers/csv_table_writer'
|
3
|
+
|
4
|
+
|
5
|
+
module Workbook
|
6
|
+
class Table < Array
|
7
|
+
include Workbook::Modules::TableDiffSort
|
8
|
+
include Workbook::Writers::CsvTableWriter
|
9
|
+
attr_accessor :sheet
|
10
|
+
attr_accessor :header
|
11
|
+
|
12
|
+
def initialize row_cel_values=[], sheet=nil, options={}
|
13
|
+
#@rows = []
|
14
|
+
row_cel_values = [] if row_cel_values == nil
|
15
|
+
row_cel_values.each do |r|
|
16
|
+
if r.is_a? Workbook::Row
|
17
|
+
r.table = self
|
18
|
+
else
|
19
|
+
r = Workbook::Row.new(r,self, options)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
self.sheet = sheet
|
23
|
+
# Column data is considered as a 'row' with 'cells' that contain 'formatting'
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
def header
|
28
|
+
if @header == false
|
29
|
+
false
|
30
|
+
elsif @header
|
31
|
+
@header
|
32
|
+
else
|
33
|
+
first
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# factory pattern...?
|
38
|
+
def new_row cel_values=[]
|
39
|
+
r = Workbook::Row.new(cel_values,self)
|
40
|
+
return r
|
41
|
+
end
|
42
|
+
|
43
|
+
def create_or_open_row_at index
|
44
|
+
r = self[index]
|
45
|
+
if r == nil
|
46
|
+
r = Workbook::Row.new
|
47
|
+
r.table=(self)
|
48
|
+
end
|
49
|
+
r
|
50
|
+
end
|
51
|
+
|
52
|
+
def remove_empty_lines!
|
53
|
+
self.delete_if{|r| r.nil? or r.compact.empty?}
|
54
|
+
self
|
55
|
+
end
|
56
|
+
|
57
|
+
def has_contents?
|
58
|
+
self.clone.remove_empty_lines!.count != 0
|
59
|
+
end
|
60
|
+
|
61
|
+
def contains_row? row
|
62
|
+
raise ArgumentError, "table should be a Workbook::Row (you passed a #{t.class})" unless row.is_a?(Workbook::Row)
|
63
|
+
self.collect{|r| r.object_id}.include? row.object_id
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'workbook/modules/raw_objects_storage'
|
2
|
+
|
3
|
+
module Workbook
|
4
|
+
class Template
|
5
|
+
include Workbook::Modules::RawObjectsStorage
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@formats = {}
|
9
|
+
@has_header = true
|
10
|
+
end
|
11
|
+
|
12
|
+
def has_header?
|
13
|
+
@has_header
|
14
|
+
end
|
15
|
+
|
16
|
+
def has_header= boolean
|
17
|
+
if format.is_a? TrueClass or format.is_a? FalseClass
|
18
|
+
@has_header = boolean
|
19
|
+
else
|
20
|
+
raise ArgumentError, "format should be a boolean, true of false"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def add_format format
|
25
|
+
if format.is_a? Workbook::Format
|
26
|
+
@formats[format.name]=format
|
27
|
+
else
|
28
|
+
raise ArgumentError, "format should be a Workboot::Format"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def formats
|
33
|
+
@formats
|
34
|
+
end
|
35
|
+
|
36
|
+
def create_or_find_format_by name, variant=:default
|
37
|
+
fs = @formats[name]
|
38
|
+
fs = @formats[name] = {} if fs.nil?
|
39
|
+
f = fs[variant]
|
40
|
+
if f.nil?
|
41
|
+
f = Workbook::Format.new
|
42
|
+
if variant != :default and fs[:default]
|
43
|
+
f = fs[:default].clone
|
44
|
+
end
|
45
|
+
@formats[name][variant] = f
|
46
|
+
end
|
47
|
+
return @formats[name][variant]
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'CSV'
|
2
|
+
|
3
|
+
module Workbook
|
4
|
+
module Writers
|
5
|
+
module CsvTableWriter
|
6
|
+
def to_csv options={}
|
7
|
+
csv = ""
|
8
|
+
options = {}.merge options
|
9
|
+
self.each_with_index do |r, ri|
|
10
|
+
line=nil
|
11
|
+
begin
|
12
|
+
line = CSV::generate_line(r.collect{|c| c.value if c},{:row_sep=>""})
|
13
|
+
rescue TypeError
|
14
|
+
line = CSV::generate_line(r.collect{|c| c.value if c})
|
15
|
+
end
|
16
|
+
csv += "#{line}\n"
|
17
|
+
end
|
18
|
+
csv
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,172 @@
|
|
1
|
+
require 'spreadsheet'
|
2
|
+
|
3
|
+
module Workbook
|
4
|
+
module Writers
|
5
|
+
module XlsWriter
|
6
|
+
# TODO: find better way to dupe
|
7
|
+
XLS_COLORS = {:xls_color_1=>'#000000',
|
8
|
+
:xls_color_2=>'#FFFFFF',
|
9
|
+
:xls_color_3=>'#FF0000',
|
10
|
+
:xls_color_4=>'#00FF00',
|
11
|
+
:xls_color_5=>'#0000FF',
|
12
|
+
:xls_color_6=>'#FFFF00',
|
13
|
+
:xls_color_7=>'#FF00FF',
|
14
|
+
:xls_color_8=>'#00FFFF',
|
15
|
+
:xls_color_9=>'#800000',
|
16
|
+
:xls_color_10=>'#008000',
|
17
|
+
:xls_color_11=>'#000080',
|
18
|
+
:xls_color_12=>'#808000',
|
19
|
+
:xls_color_13=>'#800080',
|
20
|
+
:xls_color_14=>'#008080',
|
21
|
+
:xls_color_15=>'#C0C0C0',
|
22
|
+
:xls_color_16=>'#808080',
|
23
|
+
:xls_color_17=>'#9999FF',
|
24
|
+
:xls_color_18=>'#993366',
|
25
|
+
:xls_color_19=>'#FFFFCC',
|
26
|
+
:xls_color_20=>'#CCFFFF',
|
27
|
+
:xls_color_21=>'#660066',
|
28
|
+
:xls_color_22=>'#FF8080',
|
29
|
+
:xls_color_23=>'#0066CC',
|
30
|
+
:xls_color_24=>'#CCCCFF',
|
31
|
+
:xls_color_25=>'#000080',
|
32
|
+
:xls_color_26=>'#FF00FF',
|
33
|
+
:xls_color_27=>'#FFFF00',
|
34
|
+
:xls_color_28=>'#00FFFF',
|
35
|
+
:xls_color_29=>'#800080',
|
36
|
+
:xls_color_30=>'#800000',
|
37
|
+
:xls_color_31=>'#008080',
|
38
|
+
:xls_color_32=>'#0000FF',
|
39
|
+
:xls_color_33=>'#00CCFF',
|
40
|
+
:xls_color_34=>'#CCFFFF',
|
41
|
+
:xls_color_35=>'#CCFFCC',
|
42
|
+
:xls_color_36=>'#FFFF99',
|
43
|
+
:xls_color_37=>'#99CCFF',
|
44
|
+
:xls_color_38=>'#FF99CC',
|
45
|
+
:xls_color_39=>'#CC99FF',
|
46
|
+
:xls_color_40=>'#FFCC99',
|
47
|
+
:xls_color_41=>'#3366FF',
|
48
|
+
:xls_color_42=>'#33CCCC',
|
49
|
+
:xls_color_43=>'#99CC00',
|
50
|
+
:xls_color_44=>'#FFCC00',
|
51
|
+
:xls_color_45=>'#FF9900',
|
52
|
+
:xls_color_46=>'#FF6600',
|
53
|
+
:xls_color_47=>'#666699',
|
54
|
+
:xls_color_48=>'#969696',
|
55
|
+
:xls_color_49=>'#003366',
|
56
|
+
:xls_color_50=>'#339966',
|
57
|
+
:xls_color_51=>'#003300',
|
58
|
+
:xls_color_52=>'#333300',
|
59
|
+
:xls_color_53=>'#993300',
|
60
|
+
:xls_color_54=>'#993366',
|
61
|
+
:xls_color_55=>'#333399',
|
62
|
+
:xls_color_56=>'#333333',
|
63
|
+
:black=>'#000000',
|
64
|
+
:white=>'#FFFFFF',
|
65
|
+
:red=>'#FF0000',
|
66
|
+
:green=>'#00FF00',
|
67
|
+
:blue=>'#0000FF',
|
68
|
+
:yellow=>'#FFFF00',
|
69
|
+
:magenta=>'#FF00FF',
|
70
|
+
:cyan=>'#00FFFF',
|
71
|
+
:border=>'#FFFFFF',
|
72
|
+
:text=>'#000000',
|
73
|
+
:lime=>'#00f94c'}
|
74
|
+
|
75
|
+
def to_xls options={}
|
76
|
+
options = {:rewrite_header=>default_rewrite_header?}.merge options
|
77
|
+
book = init_spreadsheet_template
|
78
|
+
self.each_with_index do |s,si|
|
79
|
+
xls_sheet = book.worksheet si
|
80
|
+
xls_sheet = book.create_worksheet if xls_sheet == nil
|
81
|
+
s.table.each_with_index do |r, ri|
|
82
|
+
write_row = false
|
83
|
+
if r.header?
|
84
|
+
if options[:rewrite_header] == true
|
85
|
+
write_row = true
|
86
|
+
end
|
87
|
+
else
|
88
|
+
write_row = true
|
89
|
+
end
|
90
|
+
if write_row
|
91
|
+
xls_sheet.row(ri).height= r.format[:height] if r.format
|
92
|
+
r.each_with_index do |c, ci|
|
93
|
+
if c
|
94
|
+
if r.header?
|
95
|
+
xls_sheet.columns[ci] ||= Spreadsheet::Column.new(ci,nil)
|
96
|
+
xls_sheet.columns[ci].width= c.format[:width]
|
97
|
+
end
|
98
|
+
xls_sheet.row(ri)[ci] = c.value
|
99
|
+
xls_sheet.row(ri).set_format(ci, format_to_xls_format(c.format))
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
book
|
106
|
+
end
|
107
|
+
|
108
|
+
def format_to_xls_format f
|
109
|
+
xlsfmt = nil
|
110
|
+
unless f.is_a? Workbook::Format
|
111
|
+
f = Workbook::Format.new f
|
112
|
+
end
|
113
|
+
xlsfmt = f.return_raw_for Spreadsheet::Format
|
114
|
+
unless xlsfmt
|
115
|
+
xlsfmt=Spreadsheet::Format.new :weight=>f[:font_weight]
|
116
|
+
xlsfmt.rotation = f[:rotation] if f[:rotation]
|
117
|
+
xlsfmt.pattern_fg_color = html_color_to_xls_color(f[:background_color]) if html_color_to_xls_color(f[:background_color])
|
118
|
+
xlsfmt.pattern = 1 if html_color_to_xls_color(f[:background_color])
|
119
|
+
xlsfmt.number_format = strftime_to_ms_format(f[:number_format]) if f[:number_format]
|
120
|
+
xlsfmt.text_direction = f[:text_direction] if f[:text_direction]
|
121
|
+
xlsfmt.font.name = f[:font_family].split.first if f[:font_family]
|
122
|
+
xlsfmt.font.family = f[:font_family].split.last if f[:font_family]
|
123
|
+
xlsfmt.font.color = html_color_to_xls_color(f[:color]) if f[:color]
|
124
|
+
f.add_raw xlsfmt
|
125
|
+
end
|
126
|
+
return xlsfmt
|
127
|
+
end
|
128
|
+
|
129
|
+
def html_color_to_xls_color hex
|
130
|
+
XLS_COLORS.each do |k,v|
|
131
|
+
return k if (v == hex or (hex and hex != "" and k == hex.to_sym))
|
132
|
+
end
|
133
|
+
return nil
|
134
|
+
end
|
135
|
+
|
136
|
+
def strftime_to_ms_format numberformat
|
137
|
+
return nil if numberformat.nil?
|
138
|
+
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')
|
139
|
+
end
|
140
|
+
|
141
|
+
def write_to_xls options={}
|
142
|
+
filename = options[:filename] ? options[:filename] : "#{title}.xls"
|
143
|
+
if to_xls(options).write(filename)
|
144
|
+
return filename
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def xls_sheet a
|
149
|
+
if xls_template.worksheet(a)
|
150
|
+
return xls_template.worksheet(a)
|
151
|
+
else
|
152
|
+
xls_template.create_worksheet
|
153
|
+
self.xls_sheet a
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def xls_template
|
158
|
+
return template.raws[Spreadsheet::Excel::Workbook] ? template.raws[Spreadsheet::Excel::Workbook] : template.raws[Spreadsheet::Workbook]
|
159
|
+
end
|
160
|
+
|
161
|
+
def init_spreadsheet_template
|
162
|
+
if self.xls_template.is_a? Spreadsheet::Workbook
|
163
|
+
return self.xls_template
|
164
|
+
else
|
165
|
+
t = Spreadsheet::Workbook.new
|
166
|
+
template.add_raw t
|
167
|
+
return t
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
data/lib/workbook.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
$KCODE="u"
|
2
|
+
require 'workbook/book'
|
3
|
+
require 'workbook/sheet'
|
4
|
+
require 'workbook/table'
|
5
|
+
require 'workbook/row'
|
6
|
+
require 'workbook/cell'
|
7
|
+
require 'workbook/format'
|
8
|
+
require 'workbook/template'
|
9
|
+
|
10
|
+
module Workbook
|
11
|
+
class << self
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|