axlsx 1.3.6 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.yardopts_guide +19 -0
- data/CHANGELOG.md +8 -0
- data/README.md +52 -79
- data/Rakefile +0 -5
- data/examples/2010_comments.rb +17 -0
- data/examples/anchor_swapping.rb +28 -0
- data/examples/example.rb +16 -1
- data/examples/pivot_table.rb +2 -0
- data/examples/underline.rb +13 -0
- data/lib/axlsx.rb +8 -0
- data/lib/axlsx/doc_props/core.rb +6 -1
- data/lib/axlsx/drawing/axes.rb +7 -3
- data/lib/axlsx/drawing/bar_3D_chart.rb +2 -2
- data/lib/axlsx/drawing/chart.rb +20 -4
- data/lib/axlsx/drawing/drawing.rb +2 -17
- data/lib/axlsx/drawing/graphic_frame.rb +3 -8
- data/lib/axlsx/drawing/hyperlink.rb +5 -12
- data/lib/axlsx/drawing/marker.rb +25 -5
- data/lib/axlsx/drawing/one_cell_anchor.rb +9 -0
- data/lib/axlsx/drawing/pic.rb +17 -23
- data/lib/axlsx/drawing/two_cell_anchor.rb +7 -27
- data/lib/axlsx/package.rb +31 -11
- data/lib/axlsx/rels/relationship.rb +73 -8
- data/lib/axlsx/rels/relationships.rb +8 -1
- data/lib/axlsx/stylesheet/color.rb +1 -1
- data/lib/axlsx/stylesheet/num_fmt.rb +2 -2
- data/lib/axlsx/stylesheet/styles.rb +5 -3
- data/lib/axlsx/util/serialized_attributes.rb +11 -8
- data/lib/axlsx/util/simple_typed_list.rb +34 -13
- data/lib/axlsx/util/validators.rb +7 -0
- data/lib/axlsx/version.rb +1 -1
- data/lib/axlsx/workbook/defined_name.rb +1 -1
- data/lib/axlsx/workbook/shared_strings_table.rb +12 -3
- data/lib/axlsx/workbook/workbook.rb +31 -8
- data/lib/axlsx/workbook/worksheet/break.rb +37 -0
- data/lib/axlsx/workbook/worksheet/cell.rb +5 -5
- data/lib/axlsx/workbook/worksheet/cell_serializer.rb +1 -1
- data/lib/axlsx/workbook/worksheet/col_breaks.rb +35 -0
- data/lib/axlsx/workbook/worksheet/comment.rb +6 -5
- data/lib/axlsx/workbook/worksheet/comments.rb +3 -3
- data/lib/axlsx/workbook/worksheet/conditional_formatting_rule.rb +1 -1
- data/lib/axlsx/workbook/worksheet/date_time_converter.rb +6 -5
- data/lib/axlsx/workbook/worksheet/pivot_table.rb +32 -18
- data/lib/axlsx/workbook/worksheet/pivot_table_cache_definition.rb +4 -3
- data/lib/axlsx/workbook/worksheet/pivot_tables.rb +1 -1
- data/lib/axlsx/workbook/worksheet/row.rb +1 -1
- data/lib/axlsx/workbook/worksheet/row_breaks.rb +33 -0
- data/lib/axlsx/workbook/worksheet/table.rb +3 -2
- data/lib/axlsx/workbook/worksheet/tables.rb +1 -1
- data/lib/axlsx/workbook/worksheet/worksheet.rb +61 -26
- data/lib/axlsx/workbook/worksheet/worksheet_comments.rb +6 -5
- data/lib/axlsx/workbook/worksheet/worksheet_drawing.rb +3 -9
- data/lib/axlsx/workbook/worksheet/worksheet_hyperlink.rb +5 -10
- data/lib/schema/sml.xsd +4 -0
- data/test/axlsx.qcachegrind +2226 -0
- data/test/doc_props/tc_core.rb +7 -0
- data/test/drawing/tc_axes.rb +8 -0
- data/test/drawing/tc_bar_3D_chart.rb +6 -0
- data/test/drawing/tc_chart.rb +13 -0
- data/test/drawing/tc_drawing.rb +0 -5
- data/test/drawing/tc_graphic_frame.rb +4 -7
- data/test/drawing/tc_hyperlink.rb +0 -4
- data/test/drawing/tc_pic.rb +14 -3
- data/test/drawing/tc_two_cell_anchor.rb +3 -3
- data/test/profile.rb +7 -3
- data/test/rels/tc_relationship.rb +29 -11
- data/test/rels/tc_relationships.rb +12 -1
- data/test/stylesheet/tc_color.rb +6 -0
- data/test/stylesheet/tc_styles.rb +2 -2
- data/test/tc_helper.rb +1 -0
- data/test/tc_package.rb +30 -0
- data/test/util/tc_serialized_attributes.rb +19 -0
- data/test/workbook/tc_shared_strings_table.rb +6 -0
- data/test/workbook/tc_workbook.rb +23 -1
- data/test/workbook/worksheet/tc_break.rb +49 -0
- data/test/workbook/worksheet/tc_comment.rb +17 -6
- data/test/workbook/worksheet/tc_conditional_formatting.rb +2 -2
- data/test/workbook/worksheet/tc_date_time_converter.rb +3 -11
- data/test/workbook/worksheet/tc_pivot_table.rb +40 -22
- data/test/workbook/worksheet/tc_pivot_table_cache_definition.rb +9 -1
- data/test/workbook/worksheet/tc_sheet_view.rb +39 -39
- data/test/workbook/worksheet/tc_table.rb +2 -2
- data/test/workbook/worksheet/tc_worksheet.rb +39 -7
- data/test/workbook/worksheet/tc_worksheet_hyperlink.rb +2 -11
- metadata +37 -10
- data/test/example.xlsx +0 -0
@@ -142,10 +142,10 @@ module Axlsx
|
|
142
142
|
end
|
143
143
|
|
144
144
|
# A hash of axes used by this chart. Bar charts have a value and
|
145
|
-
# category axes specified via
|
145
|
+
# category axes specified via axes[:val_axes] and axes[:cat_axis]
|
146
146
|
# @return [Axes]
|
147
147
|
def axes
|
148
|
-
@axes ||= Axes.new(:
|
148
|
+
@axes ||= Axes.new(:cat_axis => CatAxis, :val_axis => ValAxis)
|
149
149
|
end
|
150
150
|
end
|
151
151
|
end
|
data/lib/axlsx/drawing/chart.rb
CHANGED
@@ -20,6 +20,7 @@ module Axlsx
|
|
20
20
|
@graphic_frame.anchor.drawing.worksheet.workbook.charts << self
|
21
21
|
@series = SimpleTypedList.new Series
|
22
22
|
@show_legend = true
|
23
|
+
@display_blanks_as = :gap
|
23
24
|
@series_type = Series
|
24
25
|
@title = Title.new
|
25
26
|
parse_options options
|
@@ -70,10 +71,19 @@ module Axlsx
|
|
70
71
|
# @return [Boolean]
|
71
72
|
attr_reader :show_legend
|
72
73
|
|
73
|
-
#
|
74
|
-
#
|
74
|
+
# How to display blank values
|
75
|
+
# Options are
|
76
|
+
# * gap: Display nothing
|
77
|
+
# * span: Not sure what this does
|
78
|
+
# * zero: Display as if the value were zero, not blank
|
79
|
+
# @return [Symbol]
|
80
|
+
# Default :gap (although this really should vary by chart type and grouping)
|
81
|
+
attr_reader :display_blanks_as
|
82
|
+
|
83
|
+
# The relationship object for this chart.
|
84
|
+
# @return [Relationship]
|
75
85
|
def relationship
|
76
|
-
Relationship.new(CHART_R, "../#{pn}")
|
86
|
+
Relationship.new(self, CHART_R, "../#{pn}")
|
77
87
|
end
|
78
88
|
|
79
89
|
# The index of this chart in the workbooks charts collection
|
@@ -105,6 +115,12 @@ module Axlsx
|
|
105
115
|
# @return [Boolean]
|
106
116
|
def show_legend=(v) Axlsx::validate_boolean(v); @show_legend = v; end
|
107
117
|
|
118
|
+
# How to display blank values
|
119
|
+
# @see display_blanks_as
|
120
|
+
# @param [Symbol] v
|
121
|
+
# @return [Symbol]
|
122
|
+
def display_blanks_as=(v) Axlsx::validate_display_blanks_as(v); @display_blanks_as = v; end
|
123
|
+
|
108
124
|
# The style for the chart.
|
109
125
|
# see ECMA Part 1 §21.2.2.196
|
110
126
|
# @param [Integer] v must be between 1 and 48
|
@@ -157,7 +173,7 @@ module Axlsx
|
|
157
173
|
str << '</c:legend>'
|
158
174
|
end
|
159
175
|
str << '<c:plotVisOnly val="1"/>'
|
160
|
-
str << '<c:dispBlanksAs val="
|
176
|
+
str << '<c:dispBlanksAs val="' << display_blanks_as.to_s << '"/>'
|
161
177
|
str << '<c:showDLblsOverMax val="1"/>'
|
162
178
|
str << '</c:chart>'
|
163
179
|
str << '<c:printSettings>'
|
@@ -82,7 +82,7 @@ module Axlsx
|
|
82
82
|
TwoCellAnchor.new(self, options).add_pic(options)
|
83
83
|
else
|
84
84
|
OneCellAnchor.new(self, options)
|
85
|
-
end
|
85
|
+
end
|
86
86
|
@anchors.last.object
|
87
87
|
end
|
88
88
|
|
@@ -121,12 +121,6 @@ module Axlsx
|
|
121
121
|
@worksheet.workbook.drawings.index(self)
|
122
122
|
end
|
123
123
|
|
124
|
-
# The relation reference id for this drawing
|
125
|
-
# @return [String]
|
126
|
-
def rId
|
127
|
-
"rId#{index+1}"
|
128
|
-
end
|
129
|
-
|
130
124
|
# The part name for this drawing
|
131
125
|
# @return [String]
|
132
126
|
def pn
|
@@ -140,15 +134,7 @@ module Axlsx
|
|
140
134
|
"#{DRAWING_RELS_PN % (index+1)}"
|
141
135
|
end
|
142
136
|
|
143
|
-
#
|
144
|
-
def index_of(object)
|
145
|
-
child_objects.index(object)
|
146
|
-
end
|
147
|
-
|
148
|
-
|
149
|
-
# An ordered list of objects this drawing holds
|
150
|
-
# It is important that the objects are returned in the same order each time for
|
151
|
-
# releationship indexing in the package
|
137
|
+
# A list of objects this drawing holds.
|
152
138
|
# @return [Array]
|
153
139
|
def child_objects
|
154
140
|
charts + images + hyperlinks
|
@@ -168,7 +154,6 @@ module Axlsx
|
|
168
154
|
def to_xml_string(str = '')
|
169
155
|
str << '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
|
170
156
|
str << '<xdr:wsDr xmlns:xdr="' << XML_NS_XDR << '" xmlns:a="' << XML_NS_A << '">'
|
171
|
-
|
172
157
|
anchors.each { |anchor| anchor.to_xml_string(str) }
|
173
158
|
str << '</xdr:wsDr>'
|
174
159
|
end
|
@@ -22,15 +22,10 @@ module Axlsx
|
|
22
22
|
@chart = chart_type.new(self, options)
|
23
23
|
end
|
24
24
|
|
25
|
-
# The relationship id for this graphic
|
25
|
+
# The relationship id for this graphic frame.
|
26
26
|
# @return [String]
|
27
|
-
#
|
28
|
-
# NOTE: Discontinued. This should not be part of GraphicFrame.
|
29
|
-
# The drawing object maintains relationships and needs to be queried to determine the relationship id of any given graphic data child object.
|
30
|
-
#
|
31
27
|
def rId
|
32
|
-
|
33
|
-
"rId#{@anchor.index+1}"
|
28
|
+
@anchor.drawing.relationships.for(chart).Id
|
34
29
|
end
|
35
30
|
|
36
31
|
# Serializes the object
|
@@ -49,7 +44,7 @@ module Axlsx
|
|
49
44
|
str << '</xdr:xfrm>'
|
50
45
|
str << '<a:graphic>'
|
51
46
|
str << '<a:graphicData uri="' << XML_NS_C << '">'
|
52
|
-
str << '<c:chart xmlns:c="' << XML_NS_C << '" xmlns:r="' << XML_NS_R << '" r:id="
|
47
|
+
str << '<c:chart xmlns:c="' << XML_NS_C << '" xmlns:r="' << XML_NS_R << '" r:id="' << rId << '"/>'
|
53
48
|
str << '</a:graphicData>'
|
54
49
|
str << '</a:graphic>'
|
55
50
|
str << '</xdr:graphicFrame>'
|
@@ -83,27 +83,20 @@ module Axlsx
|
|
83
83
|
# @return [String]
|
84
84
|
attr_accessor :tooltip
|
85
85
|
|
86
|
-
#
|
87
|
-
# @return [
|
86
|
+
# The relationship object for this hyperlink.
|
87
|
+
# @return [Relationship]
|
88
88
|
def relationship
|
89
|
-
Relationship.new(HYPERLINK_R, href, :target_mode => :External)
|
89
|
+
Relationship.new(self, HYPERLINK_R, href, :target_mode => :External)
|
90
90
|
end
|
91
|
+
|
91
92
|
# Serializes the object
|
92
93
|
# @param [String] str
|
93
94
|
# @return [String]
|
94
95
|
def to_xml_string(str = '')
|
95
96
|
str << '<a:hlinkClick '
|
96
|
-
serialized_attributes str, {:'r:id' =>
|
97
|
+
serialized_attributes str, {:'r:id' => relationship.Id, :'xmlns:r' => XML_NS_R }
|
97
98
|
str << '/>'
|
98
99
|
end
|
99
100
|
|
100
|
-
private
|
101
|
-
|
102
|
-
# The relational ID for this hyperlink
|
103
|
-
# @return [Integer]
|
104
|
-
def id
|
105
|
-
@parent.anchor.drawing.index_of(self)+1
|
106
|
-
end
|
107
|
-
|
108
101
|
end
|
109
102
|
end
|
data/lib/axlsx/drawing/marker.rb
CHANGED
@@ -43,11 +43,14 @@ module Axlsx
|
|
43
43
|
def rowOff=(v) Axlsx::validate_int v; @rowOff = v end
|
44
44
|
|
45
45
|
# shortcut to set the column, row position for this marker
|
46
|
-
# @param col the column for the marker
|
47
|
-
#
|
48
|
-
|
49
|
-
|
50
|
-
|
46
|
+
# @param col the column for the marker, a Cell object or a string reference like "B7"
|
47
|
+
# or an Array.
|
48
|
+
# @param row the row of the marker. This is ignored if the col parameter is a Cell or
|
49
|
+
# String or Array.
|
50
|
+
def coord(col, row=0)
|
51
|
+
coordinates = parse_coord_args(col, row)
|
52
|
+
self.col = coordinates[0]
|
53
|
+
self.row = coordinates[1]
|
51
54
|
end
|
52
55
|
|
53
56
|
# Serializes the object
|
@@ -58,6 +61,23 @@ module Axlsx
|
|
58
61
|
str << '<xdr:' << k.to_s << '>' << self.send(k).to_s << '</xdr:' << k.to_s << '>'
|
59
62
|
end
|
60
63
|
end
|
64
|
+
private
|
65
|
+
|
66
|
+
# handles multiple inputs for setting the position of a marker
|
67
|
+
# @see Chart#start_at
|
68
|
+
def parse_coord_args(x, y=0)
|
69
|
+
if x.is_a?(String)
|
70
|
+
x, y = *Axlsx::name_to_indices(x)
|
71
|
+
end
|
72
|
+
if x.is_a?(Cell)
|
73
|
+
x, y = *x.pos
|
74
|
+
end
|
75
|
+
if x.is_a?(Array)
|
76
|
+
x, y = *x
|
77
|
+
end
|
78
|
+
[x, y]
|
79
|
+
end
|
80
|
+
|
61
81
|
|
62
82
|
end
|
63
83
|
|
@@ -48,6 +48,15 @@ module Axlsx
|
|
48
48
|
# @return [Integer]
|
49
49
|
attr_reader :height
|
50
50
|
|
51
|
+
# sets the starting position for the anchor.
|
52
|
+
# You can provide a String like "A1", an array like [0,0] or a cell object for the x parameter.
|
53
|
+
# We just 'figure it out' for you.
|
54
|
+
# @param [Array, String, Cell, Integer] x Accepts many inputs for defining the starting position of the cell.
|
55
|
+
# @param [Integer] y When x is an integer, this value is used for the row index at which the anchor starts.
|
56
|
+
def start_at(x, y=0)
|
57
|
+
from.coord x, y
|
58
|
+
end
|
59
|
+
#
|
51
60
|
# @see height
|
52
61
|
def height=(v) Axlsx::validate_unsigned_int(v); @height = v; end
|
53
62
|
|
data/lib/axlsx/drawing/pic.rb
CHANGED
@@ -37,7 +37,7 @@ module Axlsx
|
|
37
37
|
attr_reader :descr
|
38
38
|
|
39
39
|
# The path to the image you want to include
|
40
|
-
# Only local images are supported at this time
|
40
|
+
# Only local images are supported at this time.
|
41
41
|
# @return [String]
|
42
42
|
attr_reader :image_src
|
43
43
|
|
@@ -67,7 +67,7 @@ module Axlsx
|
|
67
67
|
|
68
68
|
def image_src=(v)
|
69
69
|
Axlsx::validate_string(v)
|
70
|
-
RestrictionValidator.validate 'Pic.image_src', ALLOWED_EXTENSIONS, File.extname(v).delete('.')
|
70
|
+
RestrictionValidator.validate 'Pic.image_src', ALLOWED_EXTENSIONS, File.extname(v.downcase).delete('.')
|
71
71
|
raise ArgumentError, "File does not exist" unless File.exist?(v)
|
72
72
|
@image_src = v
|
73
73
|
end
|
@@ -89,7 +89,8 @@ module Axlsx
|
|
89
89
|
# @return [String]
|
90
90
|
def extname
|
91
91
|
File.extname(image_src).delete('.') unless image_src.nil?
|
92
|
-
end
|
92
|
+
end
|
93
|
+
|
93
94
|
# The index of this image in the workbooks images collections
|
94
95
|
# @return [Index]
|
95
96
|
def index
|
@@ -102,15 +103,10 @@ module Axlsx
|
|
102
103
|
"#{IMAGE_PN % [(index+1), extname]}"
|
103
104
|
end
|
104
105
|
|
105
|
-
# The
|
106
|
-
|
107
|
-
@anchor.drawing.charts.size + @anchor.drawing.images.index(self) + 1
|
108
|
-
end
|
109
|
-
|
110
|
-
# Returns a relationship object for this object
|
111
|
-
# @return Axlsx::Relationship
|
106
|
+
# The relationship object for this pic.
|
107
|
+
# @return [Relationship]
|
112
108
|
def relationship
|
113
|
-
Relationship.new(IMAGE_R, "../#{pn}")
|
109
|
+
Relationship.new(self, IMAGE_R, "../#{pn}")
|
114
110
|
end
|
115
111
|
|
116
112
|
# providing access to the anchor's width attribute
|
@@ -148,9 +144,8 @@ module Axlsx
|
|
148
144
|
# @param [Integer] x The column
|
149
145
|
# @param [Integer] y The row
|
150
146
|
# @return [Marker]
|
151
|
-
def start_at(x, y)
|
152
|
-
@anchor.
|
153
|
-
@anchor.from.row = y
|
147
|
+
def start_at(x, y=nil)
|
148
|
+
@anchor.start_at x, y
|
154
149
|
@anchor.from
|
155
150
|
end
|
156
151
|
|
@@ -158,10 +153,9 @@ module Axlsx
|
|
158
153
|
# @param [Integer] x The column
|
159
154
|
# @param [Integer] y The row
|
160
155
|
# @return [Marker]
|
161
|
-
def end_at(x, y)
|
156
|
+
def end_at(x, y=nil)
|
162
157
|
use_two_cell_anchor unless @anchor.is_a?(TwoCellAnchor)
|
163
|
-
@anchor.
|
164
|
-
@anchor.to.row = y
|
158
|
+
@anchor.end_at x, y
|
165
159
|
@anchor.to
|
166
160
|
end
|
167
161
|
|
@@ -177,7 +171,7 @@ module Axlsx
|
|
177
171
|
picture_locking.to_xml_string(str)
|
178
172
|
str << '</xdr:cNvPicPr></xdr:nvPicPr>'
|
179
173
|
str << '<xdr:blipFill>'
|
180
|
-
str << '<a:blip xmlns:r ="' << XML_NS_R << '" r:embed="
|
174
|
+
str << '<a:blip xmlns:r ="' << XML_NS_R << '" r:embed="' << relationship.Id << '"/>'
|
181
175
|
str << '<a:stretch><a:fillRect/></a:stretch></xdr:blipFill><xdr:spPr>'
|
182
176
|
str << '<a:xfrm><a:off x="0" y="0"/><a:ext cx="2336800" cy="2161540"/></a:xfrm>'
|
183
177
|
str << '<a:prstGeom prst="rect"><a:avLst/></a:prstGeom></xdr:spPr></xdr:pic>'
|
@@ -189,22 +183,22 @@ module Axlsx
|
|
189
183
|
# Changes the anchor to a one cell anchor.
|
190
184
|
def use_one_cell_anchor
|
191
185
|
return if @anchor.is_a?(OneCellAnchor)
|
192
|
-
|
186
|
+
new_anchor = OneCellAnchor.new(@anchor.drawing, :start_at => [@anchor.from.col, @anchor.from.row])
|
187
|
+
swap_anchor(new_anchor)
|
193
188
|
end
|
194
189
|
|
195
190
|
#changes the anchor type to a two cell anchor
|
196
191
|
def use_two_cell_anchor
|
197
192
|
return if @anchor.is_a?(TwoCellAnchor)
|
198
|
-
|
199
|
-
|
200
|
-
new_anchor.from.row = @anchor.from.row
|
201
|
-
end
|
193
|
+
new_anchor = TwoCellAnchor.new(@anchor.drawing, :start_at => [@anchor.from.col, @anchor.from.row])
|
194
|
+
swap_anchor(new_anchor)
|
202
195
|
end
|
203
196
|
|
204
197
|
# refactoring of swapping code, law of demeter be damned!
|
205
198
|
def swap_anchor(new_anchor)
|
206
199
|
new_anchor.drawing.anchors.delete(new_anchor)
|
207
200
|
@anchor.drawing.anchors[@anchor.drawing.anchors.index(@anchor)] = new_anchor
|
201
|
+
new_anchor.instance_variable_set "@object", @anchor.object
|
208
202
|
@anchor = new_anchor
|
209
203
|
end
|
210
204
|
end
|
@@ -5,6 +5,8 @@ module Axlsx
|
|
5
5
|
# @see Worksheet#add_chart
|
6
6
|
class TwoCellAnchor
|
7
7
|
|
8
|
+
include Axlsx::OptionsParser
|
9
|
+
|
8
10
|
# A marker that defines the from cell anchor. The default from column and row are 0 and 0 respectively
|
9
11
|
# @return [Marker]
|
10
12
|
attr_reader :from
|
@@ -34,22 +36,23 @@ module Axlsx
|
|
34
36
|
@drawing = drawing
|
35
37
|
drawing.anchors << self
|
36
38
|
@from, @to = Marker.new, Marker.new(:col => 5, :row=>10)
|
39
|
+
parse_options options
|
37
40
|
end
|
38
41
|
|
39
42
|
# sets the col, row attributes for the from marker.
|
40
43
|
# @note The recommended way to set the start position for graphical
|
41
44
|
# objects is directly thru the object.
|
42
45
|
# @see Chart#start_at
|
43
|
-
def start_at(x, y)
|
44
|
-
|
46
|
+
def start_at(x, y=nil)
|
47
|
+
from.coord x, y
|
45
48
|
end
|
46
49
|
|
47
50
|
# sets the col, row attributes for the to marker
|
48
51
|
# @note the recommended way to set the to position for graphical
|
49
52
|
# objects is directly thru the object
|
50
53
|
# @see Char#end_at
|
51
|
-
def end_at(x, y)
|
52
|
-
|
54
|
+
def end_at(x, y=nil)
|
55
|
+
to.coord x, y
|
53
56
|
end
|
54
57
|
|
55
58
|
# Creates a graphic frame and chart object associated with this anchor
|
@@ -85,28 +88,5 @@ module Axlsx
|
|
85
88
|
str << '<xdr:clientData/>'
|
86
89
|
str << '</xdr:twoCellAnchor>'
|
87
90
|
end
|
88
|
-
private
|
89
|
-
|
90
|
-
# parses coordinates and sets up a marker's row/col propery
|
91
|
-
def set_marker_coords(x, y, marker)
|
92
|
-
marker.col, marker.row = *parse_coord_args(x, y)
|
93
|
-
end
|
94
|
-
|
95
|
-
# handles multiple inputs for setting the position of a marker
|
96
|
-
# @see Chart#start_at
|
97
|
-
def parse_coord_args(x, y=0)
|
98
|
-
if x.is_a?(String)
|
99
|
-
x, y = *Axlsx::name_to_indices(x)
|
100
|
-
end
|
101
|
-
if x.is_a?(Cell)
|
102
|
-
x, y = *x.pos
|
103
|
-
end
|
104
|
-
if x.is_a?(Array)
|
105
|
-
x, y = *x
|
106
|
-
end
|
107
|
-
[x, y]
|
108
|
-
end
|
109
|
-
|
110
|
-
|
111
91
|
end
|
112
92
|
end
|
data/lib/axlsx/package.rb
CHANGED
@@ -17,12 +17,14 @@ module Axlsx
|
|
17
17
|
#
|
18
18
|
# @param [Hash] options A hash that you can use to specify the author and workbook for this package.
|
19
19
|
# @option options [String] :author The author of the document
|
20
|
+
# @option options [Time] :created_at Timestamp in the document properties (defaults to current time).
|
20
21
|
# @option options [Boolean] :use_shared_strings This is passed to the workbook to specify that shared strings should be used when serializing the package.
|
21
22
|
# @example Package.new :author => 'you!', :workbook => Workbook.new
|
22
23
|
def initialize(options={})
|
23
24
|
@workbook = nil
|
24
25
|
@core, @app = Core.new, App.new
|
25
26
|
@core.creator = options[:author] || @core.creator
|
27
|
+
@core.created = options[:created_at]
|
26
28
|
parse_options options
|
27
29
|
yield self if block_given?
|
28
30
|
end
|
@@ -35,12 +37,6 @@ module Axlsx
|
|
35
37
|
end
|
36
38
|
|
37
39
|
|
38
|
-
# Shortcut to specify that the workbook should use shared strings
|
39
|
-
# @see Workbook#use_shared_strings
|
40
|
-
def use_shared_strings=(v)
|
41
|
-
Axlsx::validate_boolean(v);
|
42
|
-
workbook.use_shared_strings = v
|
43
|
-
end
|
44
40
|
|
45
41
|
# Shortcut to determine if the workbook is configured to use shared strings
|
46
42
|
# @see Workbook#use_shared_strings
|
@@ -48,6 +44,12 @@ module Axlsx
|
|
48
44
|
workbook.use_shared_strings
|
49
45
|
end
|
50
46
|
|
47
|
+
# Shortcut to specify that the workbook should use shared strings
|
48
|
+
# @see Workbook#use_shared_strings
|
49
|
+
def use_shared_strings=(v)
|
50
|
+
Axlsx::validate_boolean(v);
|
51
|
+
workbook.use_shared_strings = v
|
52
|
+
end
|
51
53
|
# The workbook this package will serialize or validate.
|
52
54
|
# @return [Workbook] If no workbook instance has been assigned with this package a new Workbook instance is returned.
|
53
55
|
# @raise ArgumentError if workbook parameter is not a Workbook instance.
|
@@ -98,6 +100,7 @@ module Axlsx
|
|
98
100
|
# File.open('example_streamed.xlsx', 'w') { |f| f.write(s.read) }
|
99
101
|
def serialize(output, confirm_valid=false)
|
100
102
|
return false unless !confirm_valid || self.validate.empty?
|
103
|
+
Relationship.clear_cached_instances
|
101
104
|
Zip::ZipOutputStream.open(output) do |zip|
|
102
105
|
write_parts(zip)
|
103
106
|
end
|
@@ -110,6 +113,7 @@ module Axlsx
|
|
110
113
|
# @return [StringIO|Boolean] False if confirm_valid and validation errors exist. rewound string IO if not.
|
111
114
|
def to_stream(confirm_valid=false)
|
112
115
|
return false unless !confirm_valid || self.validate.empty?
|
116
|
+
Relationship.clear_cached_instances
|
113
117
|
zip = write_parts(Zip::ZipOutputStream.new("streamed", true))
|
114
118
|
stream = zip.close_buffer
|
115
119
|
stream.rewind
|
@@ -156,12 +160,12 @@ module Axlsx
|
|
156
160
|
p = parts
|
157
161
|
p.each do |part|
|
158
162
|
unless part[:doc].nil?
|
159
|
-
zip.put_next_entry(part
|
163
|
+
zip.put_next_entry(zip_entry_for_part(part))
|
160
164
|
entry = ['1.9.2', '1.9.3'].include?(RUBY_VERSION) ? part[:doc].force_encoding('BINARY') : part[:doc]
|
161
165
|
zip.puts(entry)
|
162
166
|
end
|
163
167
|
unless part[:path].nil?
|
164
|
-
zip.put_next_entry(part
|
168
|
+
zip.put_next_entry(zip_entry_for_part(part))
|
165
169
|
# binread for 1.9.3
|
166
170
|
zip.write IO.respond_to?(:binread) ? IO.binread(part[:path]) : IO.read(part[:path])
|
167
171
|
end
|
@@ -169,6 +173,22 @@ module Axlsx
|
|
169
173
|
zip
|
170
174
|
end
|
171
175
|
|
176
|
+
# Generate a ZipEntry for the given package part.
|
177
|
+
# The important part here is to explicitly set the timestamp for the zip entry: Serializing axlsx packages
|
178
|
+
# with identical contents should result in identical zip files – however, the timestamp of a zip entry
|
179
|
+
# defaults to the time of serialization and therefore the zip file contents would be different every time
|
180
|
+
# the package is serialized.
|
181
|
+
#
|
182
|
+
# Note: {Core#created} also defaults to the current time – so to generate identical axlsx packages you have
|
183
|
+
# to set this explicitly, too (eg. with `Package.new(created_at: Time.local(2013, 1, 1))`).
|
184
|
+
#
|
185
|
+
# @param part A hash describing a part of this pacakge (see {#parts})
|
186
|
+
# @return [Zip::ZipEntry]
|
187
|
+
def zip_entry_for_part(part)
|
188
|
+
timestamp = Zip::DOSTime.at(@core.created.to_i)
|
189
|
+
Zip::ZipEntry.new("", part[:entry], "", "", 0, 0, Zip::ZipEntry::DEFLATED, 0, timestamp)
|
190
|
+
end
|
191
|
+
|
172
192
|
# The parts of a package
|
173
193
|
# @return [Array] An array of hashes that define the entry, document and schema for each part of the package.
|
174
194
|
# @private
|
@@ -321,9 +341,9 @@ module Axlsx
|
|
321
341
|
# @private
|
322
342
|
def relationships
|
323
343
|
rels = Axlsx::Relationships.new
|
324
|
-
rels << Relationship.new(WORKBOOK_R, WORKBOOK_PN)
|
325
|
-
rels << Relationship.new(CORE_R, CORE_PN)
|
326
|
-
rels << Relationship.new(APP_R, APP_PN)
|
344
|
+
rels << Relationship.new(self, WORKBOOK_R, WORKBOOK_PN)
|
345
|
+
rels << Relationship.new(self, CORE_R, CORE_PN)
|
346
|
+
rels << Relationship.new(self, APP_R, APP_PN)
|
327
347
|
rels.lock
|
328
348
|
rels
|
329
349
|
end
|