libexcel 0.1

Sign up to get free protection for your applications and to get access to all the features.
data/lib/libexcel.rb ADDED
@@ -0,0 +1,50 @@
1
+ require 'libxml'
2
+ require 'libexcel/document'
3
+ require 'libexcel/worksheet'
4
+ require 'libexcel/formula'
5
+
6
+ module LibExcel
7
+
8
+ VERSION = "0.1"
9
+
10
+ class << self
11
+
12
+ # Creates the full Excel XML equation string
13
+ #
14
+ # @return [String] the full Excel style equation string
15
+ def range(args)
16
+ if args[:cols].nil?
17
+ (buf = static(args[:rows].first, args[:col])) << ':'
18
+ buf << static(args[:rows].last, args[:col])
19
+ elsif args[:rows].nil?
20
+ (buf = static(args[:row], args[:cols].first)) << ':'
21
+ buf << static(args[:row], args[:cols].last)
22
+ else
23
+ (buf = static(args[:rows].first, args[:cols].first)) << ':'
24
+ buf << static(args[:rows].last, args[:cols].last)
25
+ end
26
+ end
27
+
28
+ # Creates part of the Excel XML style equation string
29
+ #
30
+ # @example
31
+ # static(1, 1) => "R[1]C[1]"
32
+ # static(0, 1) => "R[0]C[1]"
33
+ # static(1) => "R[1]C"
34
+ # static(nil, 1) => "RC[1]"
35
+ #
36
+ # @param [Integer, Integer] the two integer values to be converted
37
+ # @return [String] the Excel style equation string
38
+ def static(row, col)
39
+ if col.nil?
40
+ "R[#{row}]C"
41
+ elsif row.nil?
42
+ "RC[#{col}]"
43
+ else
44
+ "R[#{row}]C[#{col}]"
45
+ end
46
+ end
47
+
48
+ end
49
+
50
+ end
@@ -0,0 +1,86 @@
1
+ module LibExcel
2
+
3
+ # The Document class manages the document section of the Excel XML file.
4
+ class Document < LibXML::XML::Document
5
+ include LibXML
6
+
7
+ attr_accessor :name
8
+
9
+ # Creates the Document object. Calls the +super()+ to get the basics of a
10
+ # XML document. +name+ is the name of the document.
11
+ def initialize(name)
12
+ super()
13
+
14
+ @name = name
15
+ build_document
16
+ build_root
17
+ end
18
+
19
+ # Appends a worksheet to a Document. Requires that they worksheet being
20
+ # appended to the document be a Worksheet.
21
+ #
22
+ # @return [Document] the Full XML document
23
+ def <<(worksheet)
24
+ if not worksheet.is_a? Worksheet
25
+ raise ArgumentError, "Need to have a Excel::Worksheet"
26
+ end
27
+ root << worksheet
28
+ end
29
+
30
+ private
31
+ def root
32
+ super
33
+ end
34
+
35
+ # Setup the common Excel URIs in the root.
36
+ def build_document
37
+ self.root = XML::Node.new('Workbook')
38
+ root['xmlns'] = 'urn:schemas-microsoft-com:office:spreadsheet'
39
+ root['xmlns:o'] = 'urn:schemas-microsoft-com:office:office'
40
+ root['xmlns:x'] = 'urn:schemas-microsoft-com:office:excel'
41
+ root['xmlns:ss'] = 'urn:schemas-microsoft-com:office:spreadsheet'
42
+ root['xmlns:html'] = 'http://www.w3.org/TR/REC-html40'
43
+ end
44
+
45
+ # Setup the document properties of the document.
46
+ def build_root
47
+ root << document_properties = XML::Node.new('DocumentProperties')
48
+ document_properties['xmlns'] = 'urn:schemas-microsoft-com:office:office'
49
+
50
+ document_properties << author = XML::Node.new('Author')
51
+ author << 'Scarlet'
52
+ document_properties << last_author = XML::Node.new('LastAuthor')
53
+ last_author << 'Scarlet'
54
+ document_properties << version = XML::Node.new('Version')
55
+ version << '12.256'
56
+
57
+ root << office_document_settings = XML::Node.new('OfficeDocumentSettings')
58
+ office_document_settings['xmlns'] = 'urn:schemas-microsoft-com:office:office'
59
+ office_document_settings << XML::Node.new('AllowPNG')
60
+
61
+ root << excel_workbook = XML::Node.new('ExcelWorkbook')
62
+ excel_workbook['xmlns'] = 'urn:schemas-microsoft-com:office:excel'
63
+
64
+ excel_workbook << window_height = XML::Node.new('WindowHeight', '20260')
65
+ excel_workbook << window_width = XML::Node.new('WindowWidth', '29600')
66
+ excel_workbook << window_top_x = XML::Node.new('WindowTopX', '3440')
67
+ excel_workbook << window_top_y = XML::Node.new('WindowTopY', '-80')
68
+ excel_workbook << XML::Node.new('Date1904')
69
+ excel_workbook << XML::Node.new('ProtectStructure', 'False')
70
+ excel_workbook << XML::Node.new('ProtectWindows', 'False')
71
+
72
+ root << styles = XML::Node.new('Styles')
73
+ styles << style = XML::Node.new('Style')
74
+ style['ss:ID'] = 'Default'
75
+ style['ss:Name'] = 'Normal'
76
+ style << alignment = XML::Node.new('Alignment')
77
+ alignment['ss:Vertical'] = 'Bottom'
78
+ style << XML::Node.new('Borders')
79
+ style << font = XML::Node.new('Font')
80
+ font['ss:FontName'] = 'Verdana'
81
+ style << XML::Node.new('Interior')
82
+ style << XML::Node.new('NumberFormat')
83
+ style << XML::Node.new('Protection')
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,82 @@
1
+ module LibExcel
2
+ # Manages a Formula object to be used in a {Excel::Worksheet}.
3
+ # Builds an Excel XML formula. The Formula class responds to any
4
+ # +class method+. Such methods should correspond to their Excel
5
+ # counterparts.
6
+ #
7
+ # Some Excel formulas that will work are:
8
+ # * COUNTA
9
+ # * SUM
10
+ # * etc.
11
+ #
12
+ # @example
13
+ # formula = Excel::Formula.counta(:row => 1..2)
14
+ # # Creates an equivalent formula =COUNTA(1:2)
15
+ #
16
+ class Formula
17
+ attr_reader :xml
18
+
19
+ # <b>Should never be called directly.</b>
20
+ # Creates the Formula object
21
+ def initialize(equ)
22
+ @xml = LibXML::XML::Node.new('Cell')
23
+ @xml['ss:Formula'] = equ
24
+ end
25
+
26
+ # Creates a new Formula thats references the division of one Formula
27
+ # by another Formula.
28
+ #
29
+ # @return [Formula] A new Formula reference
30
+ #
31
+ # @example
32
+ # f1 = Excel::Formula.counta(:row => 1..2)
33
+ # f2 = Excel::Formula.counta(:row => 1..2)
34
+ # f1_divided_f2 = f1/f1
35
+ def /(formula)
36
+ org_f = self.xml['ss:Formula']
37
+ org_f << '/' << formula.xml['ss:Formula'][1..-1]
38
+ Formula.new(org_f)
39
+ end
40
+
41
+ def self.node_correct?(node)
42
+ digit_block = /(\[-?\d+\])?/
43
+ r_d_block = /R#{digit_block}C#{digit_block}/
44
+ function = /=[A-Z]+\(#{r_d_block}:#{r_d_block}\)/
45
+
46
+ (node['ss:Formula'] =~ function) != nil
47
+ end
48
+
49
+ def self.partition(node)
50
+ digit_block = /(\[-?\d+\])?/
51
+ big_block = /R#{digit_block}C#{digit_block}:R#{digit_block}C#{digit_block}/
52
+
53
+ m = big_block.match(node['ss:Formula']).to_a[1..4]
54
+ m.map { |bits| bits.nil? ? nil : bits[1..-2].to_i }
55
+ end
56
+
57
+ # A class method that is a catchall for equation names.
58
+ def self.method_missing(meth, *args)
59
+ buffer = "=#{meth.to_s.upcase}(#{LibExcel.range(args.first)})"
60
+
61
+ self.new(buffer)
62
+ end
63
+
64
+ private
65
+ # @deprecated This isn't used in production but still help here
66
+ # for testings purposes.
67
+ #
68
+ # @see Excel.range for the actually production impl
69
+ def self.build_formula(hash)
70
+ if hash.is_a? Hash
71
+ buffer = ""
72
+ buffer << (hash.include?(:r) ? "R[#{hash[:r]}]" : "R")
73
+ buffer << (hash.include?(:c) ? "C[#{hash[:c]}]" : "C")
74
+ buffer << (hash.include?(:r2) ? ":R[#{hash[:r2]}]" : ":R")
75
+ buffer << (hash.include?(:c2) ? "C[#{hash[:c2]}]" : "C")
76
+ else
77
+ buffer = "RC:RC"
78
+ end
79
+ end
80
+
81
+ end
82
+ end
@@ -0,0 +1,103 @@
1
+ module LibExcel
2
+ # Manages the worksheet of an {Excel::Document}
3
+ #
4
+ # A Worksheet works by first creating a row then by adding one cell
5
+ # at a time until you call +add_row+ again to start on a new row.
6
+ #
7
+ # @example Create a Worksheet and add "hello world" to the first cell.
8
+ # worksheet = Excel::Worksheet.new('My worksheet')
9
+ # worksheet.add_row
10
+ # worksheet.add_cell("hello world")
11
+ class Worksheet < LibXML::XML::Node
12
+ include LibXML
13
+ alias_method :append, :<<
14
+
15
+ DEFAULT_COLUMN_WIDTH = '100'
16
+
17
+ # Creates the Worksheet object. +name+ is the name of the Excel Document Tab. +name+ gets truncated to 31 chars.
18
+ def initialize(name)
19
+ super('Worksheet')
20
+ # Excel complains if the name is more than 31 chars.
21
+ self['ss:Name'] = name[0..30]
22
+ self.append table
23
+ @f_column = XML::Node.new('Column')
24
+ @f_column['ss:Width'] = DEFAULT_COLUMN_WIDTH
25
+ @table << @f_column
26
+ end
27
+
28
+ def name
29
+ self['ss:Name']
30
+ end
31
+
32
+ def f_column
33
+ @f_column['ss:Width']
34
+ end
35
+
36
+ # Sets the +name+ and retuncates it to 31 chars.
37
+ def name=(name)
38
+ self['ss:Name'] = name[0..30]
39
+ end
40
+
41
+ def f_column=(value)
42
+ @f_column['ss:Width'] = value.to_s
43
+ end
44
+
45
+ # Creates a row in the Worksheet. This needs to be called before
46
+ # you can add data to the Worksheet.
47
+ def add_row
48
+ @table << @row = XML::Node.new('Row')
49
+ end
50
+
51
+ def add_cell(raw_data, attributes = {})
52
+ @row << cell = XML::Node.new('Cell')
53
+ if attributes[:formula]
54
+ cell['ss:Formula'] = attributes[:formula]
55
+ elsif not raw_data.nil?
56
+ cell << data = XML::Node.new('Data')
57
+ if raw_data.is_a?(Fixnum) or raw_data.is_a?(Float)
58
+ data['ss:Type'] = 'Number'
59
+ elsif raw_data.is_a? String
60
+ data['ss:Type'] = 'String'
61
+ end
62
+
63
+ data << raw_data
64
+ else
65
+ cell << data = XML::Node.new('Data')
66
+ data['ss:Type'] = 'String'
67
+ data << raw_data
68
+ end
69
+ data
70
+ end
71
+
72
+ # A helper method to add an array of data to the Worksheet.
73
+ #
74
+ # @param [Array] the Array of Objects being appended to the Worksheet.
75
+ def add_array(array)
76
+ for item in array
77
+ self.add_cell(item)
78
+ end
79
+ end
80
+
81
+ # Append anything that responds to +:xml+ to the Worksheet
82
+ def <<(raw_data)
83
+ if !raw_data.respond_to?(:xml)
84
+ raise ArgumentError, "Need to have a Excel::Formula"
85
+ end
86
+ @row << raw_data.xml
87
+ end
88
+
89
+ # Creates a reference to a cell in this Worksheet to be used in
90
+ # another Worksheet.
91
+ def reference(args, equal = '=')
92
+ Formula.new("#{equal}'#{name}'!#{LibExcel.static(args[:row], args[:col])}")
93
+ end
94
+
95
+ private
96
+ def table
97
+ table = XML::Node.new('Table')
98
+ table['x:FullColumns'] = '1'
99
+ table['x:FullRows'] = '1'
100
+ @table = table
101
+ end
102
+ end
103
+ end
metadata ADDED
@@ -0,0 +1,80 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: libexcel
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ version: "0.1"
9
+ platform: ruby
10
+ authors:
11
+ - Silas Baronda
12
+ autorequire:
13
+ bindir: bin
14
+ cert_chain: []
15
+
16
+ date: 2010-02-27 00:00:00 -05:00
17
+ default_executable:
18
+ dependencies:
19
+ - !ruby/object:Gem::Dependency
20
+ name: libxml-ruby
21
+ prerelease: false
22
+ requirement: &id001 !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ segments:
27
+ - 1
28
+ - 1
29
+ - 3
30
+ version: 1.1.3
31
+ type: :runtime
32
+ version_requirements: *id001
33
+ description:
34
+ email:
35
+ - silas.baronda@gmail.com
36
+ executables: []
37
+
38
+ extensions: []
39
+
40
+ extra_rdoc_files: []
41
+
42
+ files:
43
+ - lib/libexcel.rb
44
+ - lib/libexcel/worksheet.rb
45
+ - lib/libexcel/document.rb
46
+ - lib/libexcel/formula.rb
47
+ has_rdoc: true
48
+ homepage: http://github.com/silasb/libexcel
49
+ licenses: []
50
+
51
+ post_install_message:
52
+ rdoc_options: []
53
+
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ segments:
61
+ - 0
62
+ version: "0"
63
+ required_rubygems_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ segments:
68
+ - 1
69
+ - 3
70
+ - 5
71
+ version: 1.3.5
72
+ requirements: []
73
+
74
+ rubyforge_project:
75
+ rubygems_version: 1.3.6
76
+ signing_key:
77
+ specification_version: 3
78
+ summary: XML Excel library for ruby
79
+ test_files: []
80
+