rexcel 0.1.0

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.
@@ -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