rexcel 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,70 @@
1
+ require 'benchmark'
2
+ $:.unshift("../lib")
3
+ require 'rexcel'
4
+ Excel::LOGGER.level = Log4r::OFF #no messages
5
+
6
+ def delete_testfiles()
7
+ %w{test.xml test.xls test.xlsx}.each{|fn|
8
+ File.delete(fn) if File.exist?(fn)
9
+ }
10
+ end #delete_testfiles
11
+ delete_testfiles
12
+
13
+ def test(rownumber)
14
+ puts "======Test with #{rownumber} rows"
15
+ wb = Excel::Workbook.new()
16
+ rownumber.times{
17
+ wb << [1,2,3,4,5,6,7]
18
+ wb << [:a, :b, :c, :d, :e, :f]
19
+ }
20
+
21
+ Benchmark.bm do |x|
22
+ x.report('xml ') { wb.save('test.xml') }
23
+ x.report('xml2xls ') { wb.save('test.xls', 'test.xml')}
24
+ x.report('xml2xlsx') { wb.save('test.xlsx', 'test.xml')}
25
+
26
+ delete_testfiles
27
+ x.report('xls ') { wb.save('test.xls') }
28
+ delete_testfiles
29
+ x.report('xlsx ') { wb.save('test.xlsx') }
30
+ delete_testfiles
31
+ end
32
+ end
33
+
34
+ test( 10)
35
+ test( 500)
36
+ test(1000)
37
+ test(5000)
38
+
39
+
40
+ __END__
41
+ My Testresult:
42
+
43
+ ======Test with 10 rows
44
+ user system total real
45
+ xml 0.031000 0.078000 0.109000 ( 0.124771)
46
+ xml2xls 0.000000 0.015000 0.015000 ( 2.760563)
47
+ xml2xlsx 0.000000 0.016000 0.016000 ( 0.452296)
48
+ xls 0.016000 0.000000 0.016000 ( 0.701838)
49
+ xlsx 0.031000 0.015000 0.046000 ( 0.717435)
50
+ ======Test with 500 rows
51
+ user system total real
52
+ xml 0.875000 0.016000 0.891000 ( 0.951380)
53
+ xml2xls 0.000000 0.016000 0.016000 ( 0.483488)
54
+ xml2xlsx 0.000000 0.000000 0.000000 ( 0.452296)
55
+ xls 1.000000 0.265000 1.265000 ( 6.316542)
56
+ xlsx 1.062000 0.375000 1.437000 ( 6.456910)
57
+ ======Test with 1000 rows
58
+ user system total real
59
+ xml 1.813000 0.015000 1.828000 ( 1.840375)
60
+ xml2xls 0.000000 0.000000 0.000000 ( 0.530278)
61
+ xml2xlsx 0.000000 0.000000 0.000000 ( 0.561470)
62
+ xls 2.015000 0.766000 2.781000 ( 13.366115)
63
+ xlsx 2.688000 0.906000 3.594000 ( 14.676212)
64
+ ======Test with 5000 rows
65
+ user system total real
66
+ xml 9.594000 0.062000 9.656000 ( 9.841328)
67
+ xml2xls 0.000000 0.000000 0.000000 ( 1.575237)
68
+ xml2xlsx 0.000000 0.000000 0.000000 ( 1.138537)
69
+ xls 24.234000 4.500000 28.734000 (145.873129)
70
+ xlsx 31.938000 4.453000 36.391000 (161.625493)
@@ -0,0 +1,29 @@
1
+ $:.unshift('../lib') if $0 == __FILE__
2
+ require 'rexcel'
3
+ Excel::LOGGER.level = Log4r::DEBUG
4
+
5
+ wb = Excel::Workbook.new('data')
6
+
7
+ wb << [1,2,3,4,5,6,7]
8
+ wb << [:a, :b, :c, :d, :e, :f]
9
+
10
+
11
+ wb << ws = Excel::Worksheet.new('Formats')
12
+ ws << row = Excel::Row.new
13
+ row << cell = Excel::Cell.new(1)
14
+
15
+ wb << style = Excel::Style.new('bold', :bold=> true, :backgroundcolor => 15)
16
+ row << cell = Excel::Cell.new('Bold', :style => style)
17
+ #~ puts wb.build_excel_xml('ss')
18
+
19
+ wb << style = Excel::Style.new('boldit', :bold=> true, :bold => true, :italic => true)
20
+ row << cell = Excel::Cell.new('Bold and italic', :style => style)
21
+
22
+ wb << style = Excel::Style.new('gray', :color => 18, :backgroundcolor => 27)
23
+ row << cell = Excel::Cell.new('grau text', :style => style)
24
+
25
+
26
+ wb.save('test.xml')
27
+ wb.save('test_xml.xls', 'test.xml')
28
+ wb.save('test.xls')
29
+ wb.save('test.xlsx')
@@ -0,0 +1,43 @@
1
+ $:.unshift('../lib') if $0 == __FILE__
2
+ require 'rexcel'
3
+
4
+ wb = Excel::Workbook.new()
5
+ wb << ws = Excel::Worksheet.new('Colors')
6
+
7
+ # For each color in color index
8
+ 1.upto(56) do |i|
9
+ wb << style = Excel::Style.new("color%02i" % i, :color => i)
10
+ wb << styleback = Excel::Style.new("backgroundcolor%02i" % i, :backgroundcolor => i)
11
+
12
+ ws << row = Excel::Row.new
13
+ row << cell = Excel::Cell.new("Font color %02i" % i, :style => style)
14
+ row << cell = Excel::Cell.new("Background %02i" % i, :style => styleback)
15
+ end
16
+
17
+ #
18
+ #Color matrix
19
+ #
20
+ wb << ws = Excel::Worksheet.new('Color matrix')
21
+ ws << firstrow = Excel::Row.new
22
+ firstrow << cell = Excel::Cell.new
23
+ 1.upto(56) do |i2|
24
+ firstrow << Excel::Cell.new("Background %02i" % i2)
25
+ end
26
+
27
+ 1.upto(56) do |i1|
28
+ ws << row = Excel::Row.new
29
+ row << Excel::Cell.new("Font color %02i" % i1)
30
+ 1.upto(56) do |i2|
31
+ wb << style = Excel::Style.new("color%02i-%02i" % [i1, i2], :color => i1, :backgroundcolor => i2)
32
+ row << Excel::Cell.new("Color %02i/%02i" % [i1, i2], :style => style, :string => true)
33
+ end
34
+ end
35
+
36
+
37
+ wb.save('colors.xml')
38
+ wb.save('colors_xml.xlsx', 'colors.xml')
39
+ wb.save('colors.xls')
40
+ wb.save('colors.xlsx')
41
+
42
+ Excel::Excel.instance.close
43
+
@@ -0,0 +1,23 @@
1
+ $:.unshift('../lib') if $0 == __FILE__
2
+ require 'rexcel'
3
+ Excel::LOGGER.level = Log4r::DEBUG
4
+
5
+ wb << ws = Excel::Worksheet.new('Formats')
6
+ ws << row = Excel::Row.new
7
+ row << cell = Excel::Cell.new(1)
8
+
9
+ wb << style = Excel::Style.new('bold', :bold=> true, :backgroundcolor => 15)
10
+ row << cell = Excel::Cell.new('Bold', :style => style)
11
+ #~ puts wb.build_excel_xml('ss')
12
+
13
+ wb << style = Excel::Style.new('boldit', :bold=> true, :bold => true, :italic => true)
14
+ row << cell = Excel::Cell.new('Bold and italic', :style => style)
15
+
16
+ wb << style = Excel::Style.new('gray', :color => 18, :backgroundcolor => 27)
17
+ row << cell = Excel::Cell.new('grau text', :style => style)
18
+
19
+
20
+ wb.save('test_format.xml')
21
+ wb.save('test_xml.xls', 'test_format.xml')
22
+ wb.save('test_format.xls')
23
+ wb.save('test_format.xlsx')
@@ -0,0 +1,166 @@
1
+ #encoding: utf-8
2
+ =begin rdoc
3
+ :title:Create Excel-documents with ruby
4
+ Build Excel documents via win32ole.
5
+
6
+ ==Example 1 (Simple Spreadsheet):
7
+ require 'excel'
8
+
9
+ wb = Excel::Workbook.new()
10
+
11
+ wb << [1,2,3,4,5,6,7]
12
+ wb << [:a, :b, :c, :d, :e, :f]
13
+
14
+ #Save as excel spreadsheets
15
+ wb.save('test.xls') #excel97_2003_format
16
+ wb.save('test.xlsx') #Excel 2007
17
+
18
+ wb.save('test.xml') #Microsoft Office Word 2003 XML Format
19
+ wb.save('test.xls', 'test.xml')#Build xls from xlm
20
+
21
+ ==Example 2 (Access to Worksheets, Rows and Cells):
22
+ require 'excel'
23
+
24
+ wb = Excel::Workbook.new()
25
+
26
+ wb << ws = Excel::Worksheet.new('My Spreadsheet')
27
+ ws << row = Excel::Row.new()
28
+ row << Excel::Cell.new(1)
29
+ row << Excel::Cell.new(2)
30
+ row << Excel::Cell.new(4)
31
+
32
+ #Save as excel spreadsheets
33
+ wb.save('test.xls') #excel97_2003_format
34
+ wb.save('test.xlsx') #Excel 2007
35
+
36
+ wb.save('test.xml') #Microsoft Office Word 2003 XML Format
37
+ wb.save('test.xls', 'test.xml')#Build xls from xlm
38
+
39
+ ==Example 3 (With Format options):
40
+ require 'excel'
41
+
42
+ wb = Excel::Workbook.new()
43
+ wb << style = Excel::Style.new('fett', :bold => true)
44
+
45
+ wb << ws = Excel::Worksheet.new('My Spreadsheet')
46
+ ws << row = Excel::Row.new()
47
+ row << Excel::Cell.new(1)
48
+ row << Excel::Cell.new(2)
49
+ row << Excel::Cell.new(999, :style => style)
50
+
51
+ #Save as excel spreadsheets
52
+ wb.save('test.xls') #excel97_2003_format
53
+ wb.save('test.xlsx') #Excel 2007
54
+
55
+ wb.save('test.xml') #Microsoft Office Word 2003 XML Format
56
+ wb.save('test.xls', 'test.xml')#Build xls from xlm
57
+
58
+
59
+ 'Big' spreadsheets needs a long time to be build.
60
+ (20000 lines need 2 hours)
61
+
62
+ When you build the xml, and then the xls from xlm, the wor is done in seconds.
63
+
64
+
65
+ =end
66
+ require 'win32ole'
67
+ require 'log4r'
68
+ require 'singleton'
69
+
70
+ =begin rdoc
71
+ Frame for Excel-tools.
72
+ =end
73
+ module Excel
74
+ VERSION = '0.1.0'
75
+
76
+ LOGGER = Log4r::Logger.new( name )#, Log4r::DEBUG, :trunc => true )
77
+ LOGGER.outputters << Log4r::StdoutOutputter.new('std', :level => Log4r::WARN )
78
+
79
+ =begin rdoc
80
+ Singleton for Excel.
81
+
82
+ Will be closed at END.
83
+ =end
84
+ class Excel
85
+ include Singleton
86
+ def initialize()
87
+ reconnect()
88
+ end
89
+ =begin rdoc
90
+ Create OLE-object.
91
+ =end
92
+ def reconnect()
93
+ return @xl if @xl
94
+ # Create an instance of the Excel application object
95
+ @xl = WIN32OLE.new('Excel.Application')
96
+ # Make Excel visible 1=visible 0=not visible
97
+ @xl.Visible = 0
98
+ #~ xl.Interactive = false #visible, but no input allowed
99
+ #~ xl.ScreenUpdating = false #make it faster
100
+ @xl.DisplayAlerts = false #No alerts like "don't overwrite
101
+
102
+ end
103
+ #OLE-object
104
+ attr_reader :xl
105
+ =begin rdoc
106
+ Make sure Excel is closed.
107
+
108
+ Called at END to be sure it's really closed.
109
+
110
+ See http://forum.ruby-portal.de/viewtopic.php?f=22&t=11667
111
+
112
+ When closed once: Don't create it again. There may be errors.
113
+ =end
114
+ def close()
115
+ return unless @xl
116
+ @xl.Quit #Leider Kein effekt.
117
+ WIN32OLE.ole_free(@xl)
118
+ @xl = nil
119
+ end
120
+ end #class Excel
121
+ =begin rdoc
122
+ Exceptionclass for empty Workbook, Worksheet, Row
123
+ =end
124
+ class EmptyError < Exception; end
125
+ end #module Excel
126
+
127
+ =begin
128
+ makes problems in unit test
129
+ =end
130
+ #~ at_exit {
131
+ #~ Excel::Excel.instance.close
132
+ #~ }
133
+
134
+
135
+ require 'rexcel/workbook'
136
+ require 'rexcel/worksheet'
137
+ require 'rexcel/row'
138
+ require 'rexcel/cell'
139
+ require 'rexcel/style'
140
+
141
+ =begin
142
+ Open:
143
+ * Height (only Row)
144
+ * Width (Column)
145
+
146
+ Styles??
147
+ class Style
148
+ def initialize(name)
149
+
150
+ end
151
+ #Bold
152
+ attr_accessor :bold
153
+ #Italic
154
+ attr_accessor :italic
155
+ #Color
156
+ attr_accessor :color
157
+ #Background Color
158
+ attr_accessor :backgroundcolor
159
+ end
160
+
161
+ Columns
162
+ (actual only sequence.
163
+ missing:
164
+ * title
165
+ * width
166
+ =end
@@ -0,0 +1,130 @@
1
+ module Excel
2
+ =begin rdoc
3
+ Cell of a Worksheet.
4
+
5
+ A cell is part of a Row.
6
+
7
+ Cells define
8
+ * Type .
9
+ The type is defined by the type of the content.
10
+ * String
11
+ * Number
12
+ * DateTime (not supported/tested yet)
13
+ * Style (Reference to Excel::Style instance)
14
+ =end
15
+ class Cell
16
+ TYPES = [
17
+ nil, #
18
+ :string,
19
+ ]
20
+
21
+ =begin rdoc
22
+ Define a cell and add the content.
23
+
24
+ Options:
25
+ * :string [true/false]
26
+ * :log: Replacement for the default Logger.
27
+ * :style see Excel::Style
28
+ =end
29
+ def initialize( content = nil, options = {})
30
+ @log = options[:log] || LOGGER
31
+ options.each{|key,value|
32
+ case key
33
+ when :log
34
+ when :string
35
+ @type = 'String' if value
36
+ when :style
37
+ @style = value
38
+ raise ArgumentError, "Style is no Excel::Style" unless @style.is_a?(Style)
39
+ else
40
+ @log.warn("Excel::Cell: undefined option #{options}")
41
+ end
42
+ }
43
+ @content = content
44
+ @type = get_excel_type() unless @type
45
+ end
46
+ #Content of the cell
47
+ attr_reader :content
48
+ #Target type for Excel
49
+ attr_reader :type
50
+ #Style
51
+ attr_reader :style
52
+
53
+ =begin rdoc
54
+ Supported Excel types:
55
+ * Number
56
+ * String
57
+ * DateTime
58
+ Example: 2010-02-01T00:00:00.000
59
+ =end
60
+ def get_excel_type()
61
+ case content
62
+ #~ when Rational #-> Formula?
63
+ when Numeric #Fixnum, Bignum, Float
64
+ @type = 'Number'
65
+ when Time #Date
66
+ @type = 'DateTime'
67
+ @log.warn("Cell type DateTime not tested")
68
+ else
69
+ @type = 'String'
70
+ end
71
+ end #def get_excel_type()
72
+ protected :get_excel_type
73
+
74
+ =begin rdoc
75
+ Build the xml a work sheet row,
76
+
77
+ ns must be a method-object to implement the namespace definitions.
78
+ =end
79
+ def to_xml(xmlbuilder, ns, row = nil)
80
+ #~ ns.call(:StyleID)=>"1"
81
+
82
+ cell_options = {}
83
+ if @style
84
+ cell_options[ns.call('StyleID')] = @style.style_id
85
+ #~ elsif row and row.style
86
+ #~ cell_options[ns.call('StyleID')] = row.style.style_id
87
+ end
88
+ xmlbuilder[ns.call].Cell(cell_options){
89
+ #~ options[ns.call('Type')] = @type
90
+ xmlbuilder[ns.call].Data(@content, ns.call('Type') => @type )
91
+ }
92
+ end #to_xml
93
+
94
+ =begin rdoc
95
+ Fill an Excel field.
96
+ Receives a OLE-cell and optional a row.
97
+
98
+ * value is added
99
+ * format is set (depending on cell and row format).
100
+
101
+ =end
102
+ def to_xls(cell, row = nil)
103
+ case @type
104
+ when 'String' #Suppress automatic conversion from Excel
105
+ cell.NumberFormat = "@" #as String
106
+ cell.Value = @content.to_s
107
+ when 'Number'
108
+ cell.Value = @content
109
+ when 'DateTime'
110
+ @log.warn("Cell type DateTime not tested")
111
+ cell.Value = @content
112
+ when nil #no conversion
113
+ cell.Value = @content
114
+ else
115
+ raise ArgumentError, "#{self.class}##{__method__}: Undefined Excel type #{@type}"
116
+ end
117
+ #Style must be defined in Workbook
118
+ #As long I don't know how to do it, I will use Style#to_xls_direct
119
+ if @style
120
+ #~ cell.Style = @style.style_id #
121
+ @style.to_xls_direct(cell)
122
+ elsif row and row.style
123
+ row.style.to_xls_direct(cell)
124
+ end
125
+ cell
126
+ end #to_xls
127
+
128
+
129
+ end #class Cell
130
+ end #module Excel