axlsx 1.3.6 → 2.0.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.
- 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
|