axlsx 1.0.12 → 1.0.13
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +7 -3
- data/lib/axlsx.rb +57 -0
- data/lib/axlsx/content_type/content_type.rb +23 -0
- data/lib/axlsx/content_type/default.rb +37 -0
- data/lib/axlsx/content_type/override.rb +37 -0
- data/lib/axlsx/doc_props/app.rb +178 -0
- data/lib/axlsx/doc_props/core.rb +34 -0
- data/lib/axlsx/drawing/axis.rb +90 -0
- data/lib/axlsx/drawing/bar_3D_chart.rb +128 -0
- data/lib/axlsx/drawing/bar_series.rb +64 -0
- data/lib/axlsx/drawing/cat_axis.rb +63 -0
- data/lib/axlsx/drawing/cat_axis_data.rb +35 -0
- data/lib/axlsx/drawing/chart.rb +179 -0
- data/lib/axlsx/drawing/drawing.rb +137 -0
- data/lib/axlsx/drawing/graphic_frame.rb +52 -0
- data/lib/axlsx/drawing/line_3D_chart.rb +106 -0
- data/lib/axlsx/drawing/line_series.rb +46 -0
- data/lib/axlsx/drawing/marker.rb +61 -0
- data/lib/axlsx/drawing/one_cell_anchor.rb +89 -0
- data/lib/axlsx/drawing/pic.rb +153 -0
- data/lib/axlsx/drawing/picture_locking.rb +72 -0
- data/lib/axlsx/drawing/picture_locking.rb~ +36 -0
- data/lib/axlsx/drawing/pie_3D_chart.rb +41 -0
- data/lib/axlsx/drawing/pie_series.rb +56 -0
- data/lib/axlsx/drawing/scaling.rb +59 -0
- data/lib/axlsx/drawing/ser_axis.rb +45 -0
- data/lib/axlsx/drawing/series.rb +71 -0
- data/lib/axlsx/drawing/series_title.rb +22 -0
- data/lib/axlsx/drawing/title.rb +61 -0
- data/lib/axlsx/drawing/two_cell_anchor.rb +76 -0
- data/lib/axlsx/drawing/val_axis.rb +34 -0
- data/lib/axlsx/drawing/val_axis_data.rb +28 -0
- data/lib/axlsx/drawing/view_3D.rb +85 -0
- data/lib/axlsx/package.rb +215 -0
- data/lib/axlsx/rels/relationship.rb +44 -0
- data/lib/axlsx/rels/relationships.rb +25 -0
- data/lib/axlsx/stylesheet/border.rb +57 -0
- data/lib/axlsx/stylesheet/border_pr.rb +68 -0
- data/lib/axlsx/stylesheet/cell_alignment.rb +105 -0
- data/lib/axlsx/stylesheet/cell_protection.rb +36 -0
- data/lib/axlsx/stylesheet/cell_style.rb +65 -0
- data/lib/axlsx/stylesheet/color.rb +69 -0
- data/lib/axlsx/stylesheet/fill.rb +32 -0
- data/lib/axlsx/stylesheet/font.rb +139 -0
- data/lib/axlsx/stylesheet/gradient_fill.rb +76 -0
- data/lib/axlsx/stylesheet/gradient_stop.rb +33 -0
- data/lib/axlsx/stylesheet/num_fmt.rb +63 -0
- data/lib/axlsx/stylesheet/pattern_fill.rb +66 -0
- data/lib/axlsx/stylesheet/styles.rb +298 -0
- data/lib/axlsx/stylesheet/table_style.rb +47 -0
- data/lib/axlsx/stylesheet/table_style_element.rb +71 -0
- data/lib/axlsx/stylesheet/table_styles.rb +39 -0
- data/lib/axlsx/stylesheet/xf.rb +138 -0
- data/lib/axlsx/util/constants.rb +220 -0
- data/lib/axlsx/util/parser.rb +43 -0
- data/lib/axlsx/util/parser.rb~ +6 -0
- data/lib/axlsx/util/simple_typed_list.rb +160 -0
- data/lib/axlsx/util/validators.rb +132 -0
- data/lib/axlsx/version.rb +4 -0
- data/lib/axlsx/workbook/#workbook.rb# +165 -0
- data/lib/axlsx/workbook/workbook.rb +160 -0
- data/lib/axlsx/workbook/worksheet/cell.rb +337 -0
- data/lib/axlsx/workbook/worksheet/row.rb +107 -0
- data/lib/axlsx/workbook/worksheet/worksheet.rb +279 -0
- metadata +93 -141
- data/examples/follow_20111202.xlsx +0 -0
- data/test/content_type/tc_content_type.rb +0 -81
- data/test/content_type/tc_default.rb +0 -40
- data/test/content_type/tc_override.rb +0 -40
- data/test/doc_props/tc_app.rb +0 -19
- data/test/doc_props/tc_core.rb +0 -34
- data/test/drawing/tc_axis.rb +0 -40
- data/test/drawing/tc_bar_3D_chart.rb +0 -66
- data/test/drawing/tc_bar_series.rb +0 -34
- data/test/drawing/tc_cat_axis.rb +0 -32
- data/test/drawing/tc_cat_axis_data.rb +0 -18
- data/test/drawing/tc_chart.rb +0 -73
- data/test/drawing/tc_drawing.rb +0 -80
- data/test/drawing/tc_graphic_frame.rb +0 -26
- data/test/drawing/tc_line_3d_chart.rb +0 -48
- data/test/drawing/tc_line_series.rb +0 -27
- data/test/drawing/tc_marker.rb +0 -45
- data/test/drawing/tc_one_cell_anchor.rb +0 -67
- data/test/drawing/tc_pic.rb +0 -71
- data/test/drawing/tc_picture_locking.rb +0 -73
- data/test/drawing/tc_pie_3D_chart.rb +0 -33
- data/test/drawing/tc_pie_series.rb +0 -35
- data/test/drawing/tc_scaling.rb +0 -37
- data/test/drawing/tc_ser_axis.rb +0 -31
- data/test/drawing/tc_series.rb +0 -24
- data/test/drawing/tc_series_title.rb +0 -34
- data/test/drawing/tc_title.rb +0 -34
- data/test/drawing/tc_two_cell_anchor.rb +0 -38
- data/test/drawing/tc_val_axis.rb +0 -25
- data/test/drawing/tc_val_axis_data.rb +0 -18
- data/test/drawing/tc_view_3D.rb +0 -55
- data/test/rels/tc_relationship.rb +0 -16
- data/test/rels/tc_relationships.rb +0 -27
- data/test/stylesheet/tc_border.rb +0 -38
- data/test/stylesheet/tc_border_pr.rb +0 -33
- data/test/stylesheet/tc_cell_alignment.rb +0 -77
- data/test/stylesheet/tc_cell_protection.rb +0 -30
- data/test/stylesheet/tc_cell_style.rb +0 -58
- data/test/stylesheet/tc_color.rb +0 -38
- data/test/stylesheet/tc_fill.rb +0 -19
- data/test/stylesheet/tc_font.rb +0 -114
- data/test/stylesheet/tc_gradient_fill.rb +0 -65
- data/test/stylesheet/tc_gradient_stop.rb +0 -32
- data/test/stylesheet/tc_num_fmt.rb +0 -31
- data/test/stylesheet/tc_pattern_fill.rb +0 -38
- data/test/stylesheet/tc_styles.rb +0 -52
- data/test/stylesheet/tc_table_style.rb +0 -37
- data/test/stylesheet/tc_table_style_element.rb +0 -37
- data/test/stylesheet/tc_table_styles.rb +0 -30
- data/test/stylesheet/tc_xf.rb +0 -121
- data/test/tc_package.rb +0 -68
- data/test/util/tc_simple_typed_list.rb +0 -66
- data/test/util/tc_validators.rb +0 -76
- data/test/workbook/tc_workbook.rb +0 -60
- data/test/workbook/worksheet/tc_cell.rb +0 -179
- data/test/workbook/worksheet/tc_row.rb +0 -36
- data/test/workbook/worksheet/tc_worksheet.rb +0 -138
@@ -0,0 +1,43 @@
|
|
1
|
+
module Axlsx
|
2
|
+
# The Parser module mixes in a number of methods to help in generating a model from xml
|
3
|
+
# This module is not included in the axlsx library at this time. It is for future development only,
|
4
|
+
module Parser
|
5
|
+
|
6
|
+
# The xml to be parsed
|
7
|
+
attr_accessor :parser_xml
|
8
|
+
|
9
|
+
# parse and assign string attribute
|
10
|
+
def parse_string attr_name, xpath
|
11
|
+
send("#{attr_name.to_s}=", parse_value(xpath))
|
12
|
+
end
|
13
|
+
|
14
|
+
# parse convert and assign node text to symbol
|
15
|
+
def parse_symbol attr_name, xpath
|
16
|
+
v = parse_value xpath
|
17
|
+
v = v.to_sym unless v.nil?
|
18
|
+
send("#{attr_name.to_s}=", v)
|
19
|
+
end
|
20
|
+
|
21
|
+
# parse, convert and assign note text to integer
|
22
|
+
def parse_integer attr_name, xpath
|
23
|
+
v = parse_value xpath
|
24
|
+
v = v.to_i if v.respond_to?(:to_i)
|
25
|
+
send("#{attr_name.to_s}=", v)
|
26
|
+
end
|
27
|
+
|
28
|
+
# parse, convert and assign node text to float
|
29
|
+
def parse_float attr_name, xpath
|
30
|
+
v = parse_value xpath
|
31
|
+
v = v.to_f if v.respond_to?(:to_f)
|
32
|
+
send("#{attr_name.to_s}=", v)
|
33
|
+
end
|
34
|
+
|
35
|
+
# return node text based on xpath
|
36
|
+
def parse_value xpath
|
37
|
+
node = parser_xml.xpath(xpath)
|
38
|
+
return nil if node.empty?
|
39
|
+
node.text.strip
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,160 @@
|
|
1
|
+
module Axlsx
|
2
|
+
# A SimpleTypedList is a type restrictive collection that allows some of the methods from Array and supports basic xml serialization.
|
3
|
+
# @private
|
4
|
+
class SimpleTypedList
|
5
|
+
# The class constants of allowed types
|
6
|
+
# @return [Array]
|
7
|
+
attr_reader :allowed_types
|
8
|
+
|
9
|
+
# The index below which items cannot be removed
|
10
|
+
# @return [Integer]
|
11
|
+
attr_reader :locked_at
|
12
|
+
|
13
|
+
# The tag name to use when serializing this object
|
14
|
+
# by default the parent node for all items in the list is the classname of the first allowed type with the first letter in lowercase.
|
15
|
+
# @return [String]
|
16
|
+
attr_reader :serialize_as
|
17
|
+
|
18
|
+
# Creats a new typed list
|
19
|
+
# @param [Array, Class] type An array of Class objects or a single Class object
|
20
|
+
# @param [String] serialize The tag name to use in serialization
|
21
|
+
# @raise [ArgumentError] if all members of type are not Class objects
|
22
|
+
def initialize type, serialize_as=nil
|
23
|
+
if type.is_a? Array
|
24
|
+
type.each { |item| raise ArgumentError, "All members of type must be Class objects" unless item.is_a? Class }
|
25
|
+
@allowed_types = type
|
26
|
+
else
|
27
|
+
raise ArgumentError, "Type must be a Class object or array of Class objects" unless type.is_a? Class
|
28
|
+
@allowed_types = [type]
|
29
|
+
end
|
30
|
+
@list = []
|
31
|
+
@locked_at = nil
|
32
|
+
@serialize_as = serialize_as
|
33
|
+
end
|
34
|
+
|
35
|
+
# Lock this list at the current size
|
36
|
+
# @return [self]
|
37
|
+
def lock
|
38
|
+
@locked_at = @list.size
|
39
|
+
self
|
40
|
+
end
|
41
|
+
|
42
|
+
def to_ary
|
43
|
+
@list
|
44
|
+
end
|
45
|
+
|
46
|
+
# Unlock the list
|
47
|
+
# @return [self]
|
48
|
+
def unlock
|
49
|
+
@locked_at = nil
|
50
|
+
self
|
51
|
+
end
|
52
|
+
|
53
|
+
# Concat operator
|
54
|
+
# @param [Any] v the data to be added
|
55
|
+
# @raise [ArgumentError] if the value being added is not one fo the allowed types
|
56
|
+
# @return [Integer] returns the index of the item added.
|
57
|
+
def <<(v)
|
58
|
+
DataTypeValidator.validate "SimpleTypedList.<<", @allowed_types, v
|
59
|
+
@list << v
|
60
|
+
@list.size - 1
|
61
|
+
end
|
62
|
+
|
63
|
+
# alternate of << method
|
64
|
+
# @see <<
|
65
|
+
def push(v)
|
66
|
+
self.<< v
|
67
|
+
end
|
68
|
+
|
69
|
+
# delete the item from the list
|
70
|
+
# @param [Any] v The item to be deleted.
|
71
|
+
# @raise [ArgumentError] if the item's index is protected by locking
|
72
|
+
# @return [Any] The item deleted
|
73
|
+
def delete(v)
|
74
|
+
return unless @list.include? v
|
75
|
+
raise ArgumentError, "Item is protected and cannot be deleted" if protected? @list.index(v)
|
76
|
+
@list.delete v
|
77
|
+
end
|
78
|
+
|
79
|
+
# delete the item from the list at the index position provided
|
80
|
+
# @raise [ArgumentError] if the index is protected by locking
|
81
|
+
# @return [Any] The item deleted
|
82
|
+
def delete_at(index)
|
83
|
+
@list[index]
|
84
|
+
raise ArgumentError, "Item is protected and cannot be deleted" if protected? index
|
85
|
+
@list.delete_at index
|
86
|
+
end
|
87
|
+
|
88
|
+
# positional assignment. Adds the item at the index specified
|
89
|
+
# @param [Integer] index
|
90
|
+
# @param [Any] v
|
91
|
+
# @raise [ArgumentError] if the index is protected by locking
|
92
|
+
# @raise [ArgumentError] if the item is not one of the allowed types
|
93
|
+
def []=(index, v)
|
94
|
+
DataTypeValidator.validate "SimpleTypedList.<<", @allowed_types, v
|
95
|
+
raise ArgumentError, "Item is protected and cannot be changed" if protected? index
|
96
|
+
@list[index] = v
|
97
|
+
v
|
98
|
+
end
|
99
|
+
|
100
|
+
# determines if the index is protected
|
101
|
+
# @param [Integer] index
|
102
|
+
def protected? index
|
103
|
+
return false unless @locked_at.is_a? Fixnum
|
104
|
+
index < @locked_at
|
105
|
+
end
|
106
|
+
|
107
|
+
# override the equality method so that this object can be compared to a simple array.
|
108
|
+
# if this object's list is equal to the specifiec array, we return true.
|
109
|
+
def ==(v)
|
110
|
+
v == @list
|
111
|
+
end
|
112
|
+
# method_mission override to pass allowed methods to the list.
|
113
|
+
# @note
|
114
|
+
# the following methods are not allowed
|
115
|
+
# :replace
|
116
|
+
# :insert
|
117
|
+
# :collect!
|
118
|
+
# :map!
|
119
|
+
# :pop
|
120
|
+
# :delete_if
|
121
|
+
# :reverse!
|
122
|
+
# :shift
|
123
|
+
# :shuffle!
|
124
|
+
# :slice!
|
125
|
+
# :sort!
|
126
|
+
# :uniq!
|
127
|
+
# :unshift
|
128
|
+
# :zip
|
129
|
+
# :flatten!
|
130
|
+
# :fill
|
131
|
+
# :drop
|
132
|
+
# :drop_while
|
133
|
+
# :delete_if
|
134
|
+
# :clear
|
135
|
+
def method_missing(meth, *args, &block)
|
136
|
+
raise ArgumentError, "#{meth} not supported" if [:replace, :insert, :collect!, :map!, :pop, :delete_if, :reverse!, :shift, :shuffle!, :slice!, :sort!, :uniq!, :unshift, :zip, :flatten!, :fill, :drop, :drop_while, :delete_if, :clear].include? meth.to_sym
|
137
|
+
if @list.respond_to? meth
|
138
|
+
@list.send(meth, *args, &block)
|
139
|
+
else
|
140
|
+
puts "method:#{meth.inspect}"
|
141
|
+
super
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
# Serializes the list
|
146
|
+
# If the serialize_as property is set, it is used as the parent node name.
|
147
|
+
# If the serialize_as property is nil, the first item in the list of allowed_types will be used, having the first letter of the class changed to lower case.
|
148
|
+
# @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to.
|
149
|
+
# @return [String]
|
150
|
+
def to_xml(xml)
|
151
|
+
classname = @allowed_types[0].name.split('::').last
|
152
|
+
el_name = serialize_as || (classname[0,1].downcase + classname[1..-1]).pluralize
|
153
|
+
xml.send(el_name, :count=>@list.size) {
|
154
|
+
@list.each { |item| item.to_xml(xml) }
|
155
|
+
}
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
|
160
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
module Axlsx
|
2
|
+
# Validate a value against a specific list of allowed values.
|
3
|
+
class RestrictionValidator
|
4
|
+
# Perform validation
|
5
|
+
# @param [String] name The name of what is being validatied. This is included in the error message
|
6
|
+
# @param [Array] choices The list of choices to validate against
|
7
|
+
# @param [Any] v The value to be validated
|
8
|
+
# @raise [ArgumentError] Raised if the value provided is not in the list of choices.
|
9
|
+
# @return [Boolean] true if validation succeeds.
|
10
|
+
def self.validate(name, choices, v)
|
11
|
+
raise ArgumentError, (ERR_RESTRICTION % [v.to_s, name, choices.inspect]) unless choices.include?(v)
|
12
|
+
true
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# Validates the value against the regular expression provided.
|
17
|
+
class RegexValidator
|
18
|
+
# @param [String] name The name of what is being validated. This is included in the output when the value is invalid
|
19
|
+
# @param [Regexp] regex The regular expression to evaluate
|
20
|
+
# @param [Any] v The value to validate.
|
21
|
+
def self.validate(name, regex, v)
|
22
|
+
raise ArgumentError, (ERR_REGEX % [v.inspect, regex.to_s]) unless (v.respond_to?(:=~) && v =~ regex)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
# Validate that the class of the value provided is either an instance or the class of the allowed types and that any specified additional validation returns true.
|
26
|
+
class DataTypeValidator
|
27
|
+
# Perform validation
|
28
|
+
# @param [String] name The name of what is being validated. This is included in the error message
|
29
|
+
# @param [Array, Class] types A single class or array of classes that the value is validated against.
|
30
|
+
# @param [Block] other Any block that must evaluate to true for the value to be valid
|
31
|
+
# @raise [ArugumentError] Raised if the class of the value provided is not in the specified array of types or the block passed returns false
|
32
|
+
# @return [Boolean] true if validation succeeds.
|
33
|
+
# @see validate_boolean
|
34
|
+
def self.validate(name, types, v, other= lambda{|arg| true })
|
35
|
+
types = [types] unless types.is_a? Array
|
36
|
+
valid_type = false
|
37
|
+
if v.class == Class
|
38
|
+
types.each { |t| valid_type = true if v.ancestors.include?(t) }
|
39
|
+
else
|
40
|
+
types.each { |t| valid_type = true if v.is_a?(t) }
|
41
|
+
end
|
42
|
+
raise ArgumentError, (ERR_TYPE % [v.inspect, name, types.inspect]) unless (other.call(v) && valid_type)
|
43
|
+
end
|
44
|
+
true
|
45
|
+
end
|
46
|
+
|
47
|
+
# Requires that the value is a Fixnum or Integer and is greater or equal to 0
|
48
|
+
# @param [Any] v The value validated
|
49
|
+
# @raise [ArgumentError] raised if the value is not a Fixnum or Integer value greater or equal to 0
|
50
|
+
# @return [Boolean] true if the data is valid
|
51
|
+
def self.validate_unsigned_int(v)
|
52
|
+
DataTypeValidator.validate(:unsigned_int, [Fixnum, Integer], v, lambda { |arg| arg.respond_to?(:>=) && arg >= 0 })
|
53
|
+
end
|
54
|
+
|
55
|
+
# Requires that the value is a Fixnum or Integer
|
56
|
+
# @param [Any] v The value validated
|
57
|
+
def self.validate_int(v)
|
58
|
+
DataTypeValidator.validate :unsigned_int, [Fixnum, Integer], v
|
59
|
+
end
|
60
|
+
|
61
|
+
# Requires that the value is a form that can be evaluated as a boolean in an xml document.
|
62
|
+
# The value must be an instance of Fixnum, String, Integer, Symbol, TrueClass or FalseClass and
|
63
|
+
# it must be one of 0, 1, "true", "false", :true, :false, true, false, "0", or "1"
|
64
|
+
# @param [Any] v The value validated
|
65
|
+
def self.validate_boolean(v)
|
66
|
+
DataTypeValidator.validate(:boolean, [Fixnum, String, Integer, Symbol, TrueClass, FalseClass], v, lambda { |arg| [0, 1, "true", "false", :true, :false, true, false, "0", "1"].include?(arg) })
|
67
|
+
end
|
68
|
+
|
69
|
+
# Requires that the value is a String
|
70
|
+
# @param [Any] v The value validated
|
71
|
+
def self.validate_string(v)
|
72
|
+
DataTypeValidator.validate :string, String, v
|
73
|
+
end
|
74
|
+
|
75
|
+
# Requires that the value is a Float
|
76
|
+
# @param [Any] v The value validated
|
77
|
+
def self.validate_float(v)
|
78
|
+
DataTypeValidator.validate :float, Float, v
|
79
|
+
end
|
80
|
+
|
81
|
+
# Requires that the value is valid pattern type.
|
82
|
+
# valid pattern types must be one of :none, :solid, :mediumGray, :darkGray, :lightGray, :darkHorizontal, :darkVertical, :darkDown,
|
83
|
+
# :darkUp, :darkGrid, :darkTrellis, :lightHorizontal, :lightVertical, :lightDown, :lightUp, :lightGrid, :lightTrellis, :gray125, or :gray0625.
|
84
|
+
# @param [Any] v The value validated
|
85
|
+
def self.validate_pattern_type(v)
|
86
|
+
RestrictionValidator.validate :pattern_type, [:none, :solid, :mediumGray, :darkGray, :lightGray, :darkHorizontal, :darkVertical, :darkDown, :darkUp, :darkGrid,
|
87
|
+
:darkTrellis, :lightHorizontal, :lightVertical, :lightDown, :lightUp, :lightGrid, :lightTrellis, :gray125, :gray0625], v
|
88
|
+
end
|
89
|
+
|
90
|
+
# Requires that the value is a gradient_type.
|
91
|
+
# valid types are :linear and :path
|
92
|
+
# @param [Any] v The value validated
|
93
|
+
def self.validate_gradient_type(v)
|
94
|
+
RestrictionValidator.validate :gradient_type, [:linear, :path], v
|
95
|
+
end
|
96
|
+
|
97
|
+
# Requires that the value is a valid horizontal_alignment
|
98
|
+
# :general, :left, :center, :right, :fill, :justify, :centerContinuous, :distributed are allowed
|
99
|
+
# @param [Any] v The value validated
|
100
|
+
def self.validate_horizontal_alignment(v)
|
101
|
+
RestrictionValidator.validate :horizontal_alignment, [:general, :left, :center, :right, :fill, :justify, :centerContinuous, :distributed], v
|
102
|
+
end
|
103
|
+
|
104
|
+
# Requires that the value is a valid vertical_alignment
|
105
|
+
# :top, :center, :bottom, :justify, :distributed are allowed
|
106
|
+
# @param [Any] v The value validated
|
107
|
+
def self.validate_vertical_alignment(v)
|
108
|
+
RestrictionValidator.validate :vertical_alignment, [:top, :center, :bottom, :justify, :distributed], v
|
109
|
+
end
|
110
|
+
|
111
|
+
# Requires that the value is a valid content_type
|
112
|
+
# TABLE_CT, WORKBOOK_CT, APP_CT, RELS_CT, STYLES_CT, XML_CT, WORKSHEET_CT, SHARED_STRINGS_CT, CORE_CT, CHART_CT, DRAWING_CT are allowed
|
113
|
+
# @param [Any] v The value validated
|
114
|
+
def self.validate_content_type(v)
|
115
|
+
RestrictionValidator.validate :content_type, [TABLE_CT, WORKBOOK_CT, APP_CT, RELS_CT, STYLES_CT, XML_CT, WORKSHEET_CT, SHARED_STRINGS_CT, CORE_CT, CHART_CT, JPEG_CT, GIF_CT, PNG_CT, DRAWING_CT], v
|
116
|
+
end
|
117
|
+
|
118
|
+
# Requires that the value is a valid relationship_type
|
119
|
+
# XML_NS_R, TABLE_R, WORKBOOK_R, WORKSHEET_R, APP_R, RELS_R, CORE_R, STYLES_R, CHART_R, DRAWING_R are allowed
|
120
|
+
# @param [Any] v The value validated
|
121
|
+
def self.validate_relationship_type(v)
|
122
|
+
RestrictionValidator.validate :relationship_type, [XML_NS_R, TABLE_R, WORKBOOK_R, WORKSHEET_R, APP_R, RELS_R, CORE_R, STYLES_R, CHART_R, DRAWING_R, IMAGE_R], v
|
123
|
+
end
|
124
|
+
|
125
|
+
# Requires that the value is a valid table element type
|
126
|
+
# :wholeTable, :headerRow, :totalRow, :firstColumn, :lastColumn, :firstRowStripe, :secondRowStripe, :firstColumnStripe, :secondColumnStripe, :firstHeaderCell, :lastHeaderCell, :firstTotalCell, :lastTotalCell, :firstSubtotalColumn, :secondSubtotalColumn, :thirdSubtotalColumn, :firstSubtotalRow, :secondSubtotalRow, :thirdSubtotalRow, :blankRow, :firstColumnSubheading, :secondColumnSubheading, :thirdColumnSubheading, :firstRowSubheading, :secondRowSubheading, :thirdRowSubheading, :pageFieldLabels, :pageFieldValues are allowed
|
127
|
+
# @param [Any] v The value validated
|
128
|
+
def self.validate_table_element_type(v)
|
129
|
+
RestrictionValidator.validate :table_element_type, [:wholeTable, :headerRow, :totalRow, :firstColumn, :lastColumn, :firstRowStripe, :secondRowStripe, :firstColumnStripe, :secondColumnStripe, :firstHeaderCell, :lastHeaderCell, :firstTotalCell, :lastTotalCell, :firstSubtotalColumn, :secondSubtotalColumn, :thirdSubtotalColumn, :firstSubtotalRow, :secondSubtotalRow, :thirdSubtotalRow, :blankRow, :firstColumnSubheading, :secondColumnSubheading, :thirdColumnSubheading, :firstRowSubheading, :secondRowSubheading, :thirdRowSubheading, :pageFieldLabels, :pageFieldValues], v
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
@@ -0,0 +1,165 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
module Axlsx
|
3
|
+
|
4
|
+
require 'axlsx/workbook/worksheet/cell.rb'
|
5
|
+
require 'axlsx/workbook/worksheet/row.rb'
|
6
|
+
require 'axlsx/workbook/worksheet/worksheet.rb'
|
7
|
+
|
8
|
+
# The Workbook class is an xlsx workbook that manages worksheets, charts, drawings and styles.
|
9
|
+
# The following parts of the Office Open XML spreadsheet specification are not implimented in this version.
|
10
|
+
#
|
11
|
+
# bookViews
|
12
|
+
# calcPr
|
13
|
+
# customWorkbookViews
|
14
|
+
# definedNames
|
15
|
+
# externalReferences
|
16
|
+
# extLst
|
17
|
+
# fileRecoveryPr
|
18
|
+
# fileSharing
|
19
|
+
# fileVersion
|
20
|
+
# functionGroups
|
21
|
+
# oleSize
|
22
|
+
# pivotCaches
|
23
|
+
# smartTagPr
|
24
|
+
# smartTagTypes
|
25
|
+
# webPublishing
|
26
|
+
# webPublishObjects
|
27
|
+
# workbookProtection
|
28
|
+
# workbookPr*
|
29
|
+
#
|
30
|
+
# *workbookPr is only supported to the extend of date1904
|
31
|
+
class Workbook
|
32
|
+
|
33
|
+
# A collection of worksheets associated with this workbook.
|
34
|
+
# @note The recommended way to manage worksheets is add_worksheet
|
35
|
+
# @see Workbook#add_worksheet
|
36
|
+
# @see Worksheet
|
37
|
+
# @return [SimpleTypedList]
|
38
|
+
attr_reader :worksheets
|
39
|
+
|
40
|
+
# A colllection of charts associated with this workbook
|
41
|
+
# @note The recommended way to manage charts is Worksheet#add_chart
|
42
|
+
# @see Worksheet#add_chart
|
43
|
+
# @see Chart
|
44
|
+
# @return [SimpleTypedList]
|
45
|
+
attr_reader :charts
|
46
|
+
|
47
|
+
# A colllection of images associated with this workbook
|
48
|
+
# @note The recommended way to manage images is Worksheet#add_image
|
49
|
+
# @see Worksheet#add_image
|
50
|
+
# @see Pic
|
51
|
+
# @return [SimpleTypedList]
|
52
|
+
attr_reader :images
|
53
|
+
|
54
|
+
# A colllection of drawings associated with this workbook
|
55
|
+
# @note The recommended way to manage drawings is Worksheet#add_chart
|
56
|
+
# @see Worksheet#add_chart
|
57
|
+
# @see Drawing
|
58
|
+
# @return [SimpleTypedList]
|
59
|
+
attr_reader :drawings
|
60
|
+
|
61
|
+
# The styles associated with this workbook
|
62
|
+
# @note The recommended way to manage styles is Styles#add_style
|
63
|
+
# @see Style#add_style
|
64
|
+
# @see Style
|
65
|
+
# @return [Styles]
|
66
|
+
def styles
|
67
|
+
yield @styles if block_given?
|
68
|
+
@styles
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
# Indicates if the epoc date for serialization should be 1904. If false, 1900 is used.
|
73
|
+
@@date1904 = false
|
74
|
+
|
75
|
+
# lets come back to this later when we are ready for parsing.
|
76
|
+
#def self.parse entry
|
77
|
+
# io = entry.get_input_stream
|
78
|
+
# w = self.new
|
79
|
+
# w.parser_xml = Nokogiri::XML(io.read)
|
80
|
+
# w.parse_string :date1904, "//xmlns:workbookPr/@date1904"
|
81
|
+
# w
|
82
|
+
#end
|
83
|
+
|
84
|
+
# Creates a new Workbook
|
85
|
+
# @option options [Boolean] date1904
|
86
|
+
def initialize(options={})
|
87
|
+
@styles = Styles.new
|
88
|
+
@worksheets = SimpleTypedList.new Worksheet
|
89
|
+
@drawings = SimpleTypedList.new Drawing
|
90
|
+
@charts = SimpleTypedList.new Chart
|
91
|
+
@images = SimpleTypedList.new Pic
|
92
|
+
self.date1904= options[:date1904] unless options[:date1904].nil?
|
93
|
+
yield self if block_given?
|
94
|
+
end
|
95
|
+
|
96
|
+
# Instance level access to the class variable 1904
|
97
|
+
# @return [Boolean]
|
98
|
+
def date1904() @@date1904; end
|
99
|
+
|
100
|
+
# see @date1904
|
101
|
+
def date1904=(v) Axlsx::validate_boolean v; @@date1904 = v; end
|
102
|
+
|
103
|
+
# Sets the date1904 attribute to the provided boolean
|
104
|
+
# @return [Boolean]
|
105
|
+
def self.date1904=(v) Axlsx::validate_boolean v; @@date1904 = v; end
|
106
|
+
|
107
|
+
# retrieves the date1904 attribute
|
108
|
+
# @return [Boolean]
|
109
|
+
def self.date1904() @@date1904; end
|
110
|
+
|
111
|
+
# Adds a worksheet to this workbook
|
112
|
+
# @return [Worksheet]
|
113
|
+
# @option options [String] name The name of the worksheet.
|
114
|
+
# @see Worksheet#initialize
|
115
|
+
def add_worksheet(options={})
|
116
|
+
worksheet = Worksheet.new(self, options)
|
117
|
+
yield worksheet if block_given?
|
118
|
+
worksheet
|
119
|
+
end
|
120
|
+
|
121
|
+
# The workbook relationships. This is managed automatically by the workbook
|
122
|
+
# @return [Relationships]
|
123
|
+
def relationships
|
124
|
+
r = Relationships.new
|
125
|
+
@worksheets.each do |sheet|
|
126
|
+
r << Relationship.new(WORKSHEET_R, WORKSHEET_PN % (r.size+1))
|
127
|
+
end
|
128
|
+
r << Relationship.new(STYLES_R, STYLES_PN)
|
129
|
+
r
|
130
|
+
end
|
131
|
+
|
132
|
+
# returns a range of cells in a worksheet
|
133
|
+
# @param [String] cell_def The excel style reference defining the worksheet and cells. The range must specify the sheet to
|
134
|
+
# retrieve the cells from. e.g. range('Sheet1!A1:B2') will return an array of four cells [A1, A2, B1, B2] while range('Sheet1!A1') will return a single Cell.
|
135
|
+
# @return [Cell, Array]
|
136
|
+
def [](cell_def)
|
137
|
+
sheet_name = cell_def.split('!')[0] if cell_def.match('!')
|
138
|
+
worksheet = self.worksheets.select { |s| s.name == sheet_name }.first
|
139
|
+
raise ArgumentError, 'Unknown Sheet' unless sheet_name && worksheet.is_a?(Worksheet)
|
140
|
+
worksheet[cell_def.gsub(/.+!/,"")]
|
141
|
+
end
|
142
|
+
|
143
|
+
# Serializes the workbook document
|
144
|
+
# @return [String]
|
145
|
+
def to_xml()
|
146
|
+
add_worksheet unless worksheets.size > 0
|
147
|
+
builder = Nokogiri::XML::Builder.new(:encoding => ENCODING) do |xml|
|
148
|
+
xml.workbook(:xmlns => XML_NS, :'xmlns:r' => XML_NS_R) {
|
149
|
+
xml.workbookPr(:date1904=>@@date1904, :defaultThemeVersion=>"124226")
|
150
|
+
xml.bookViews {
|
151
|
+
xml.workbookView(:xWindow=>"420", :yWindow=>"405", :windowWidth=>"24480", :windowHeight=>"9885")
|
152
|
+
}
|
153
|
+
xml.sheets {
|
154
|
+
@worksheets.each_with_index do |sheet, index|
|
155
|
+
xml.sheet(:name=>sheet.name, :sheetId=>index+1, :"r:id"=>sheet.rId)
|
156
|
+
end
|
157
|
+
}
|
158
|
+
xml.calcPr(:calcId=>"124519")
|
159
|
+
xml.fileRecoveryPr(:repairLoad=>"1")
|
160
|
+
}
|
161
|
+
end
|
162
|
+
builder.to_xml
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|