workbook 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|