axlsx 1.0.12 → 1.0.14
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.
- data/README.md +165 -134
- data/examples/example.rb +133 -153
- data/lib/axlsx/#cfb.xlsx# +0 -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 +93 -0
- data/lib/axlsx/drawing/bar_3D_chart.rb +136 -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 +193 -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 +114 -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 +65 -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 +26 -0
- data/lib/axlsx/drawing/view_3D.rb +85 -0
- data/lib/axlsx/package.rb +223 -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 +216 -0
- data/lib/axlsx/util/ms_off_crypto.rb +88 -0
- data/lib/axlsx/util/ms_off_crypto.rb~ +3 -0
- data/lib/axlsx/util/ms_offcrypto.rb~ +0 -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 +161 -0
- data/lib/axlsx/workbook/worksheet/cell.rb +350 -0
- data/lib/axlsx/workbook/worksheet/row.rb +107 -0
- data/lib/axlsx/workbook/worksheet/worksheet.rb +335 -0
- data/lib/axlsx.rb +59 -0
- data/test/drawing/tc_axis.rb +1 -1
- data/test/drawing/tc_cat_axis.rb +1 -1
- data/test/drawing/tc_line_series.tc~ +34 -0
- data/test/drawing/tc_picture_locking.rb~ +77 -0
- data/test/tc_package.rb +10 -0
- data/test/workbook/worksheet/tc_cell.rb +15 -0
- data/test/workbook/worksheet/tc_worksheet.rb +22 -1
- metadata +117 -5
- data/examples/follow_20111202.xlsx +0 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
module Axlsx
|
|
2
|
+
require 'axlsx/drawing/title.rb'
|
|
3
|
+
require 'axlsx/drawing/series_title.rb'
|
|
4
|
+
require 'axlsx/drawing/series.rb'
|
|
5
|
+
require 'axlsx/drawing/pie_series.rb'
|
|
6
|
+
require 'axlsx/drawing/bar_series.rb'
|
|
7
|
+
require 'axlsx/drawing/line_series.rb'
|
|
8
|
+
|
|
9
|
+
require 'axlsx/drawing/scaling.rb'
|
|
10
|
+
require 'axlsx/drawing/axis.rb'
|
|
11
|
+
require 'axlsx/drawing/ser_axis.rb'
|
|
12
|
+
require 'axlsx/drawing/cat_axis.rb'
|
|
13
|
+
require 'axlsx/drawing/val_axis.rb'
|
|
14
|
+
|
|
15
|
+
require 'axlsx/drawing/cat_axis_data.rb'
|
|
16
|
+
require 'axlsx/drawing/val_axis_data.rb'
|
|
17
|
+
|
|
18
|
+
require 'axlsx/drawing/marker.rb'
|
|
19
|
+
|
|
20
|
+
require 'axlsx/drawing/one_cell_anchor.rb'
|
|
21
|
+
require 'axlsx/drawing/two_cell_anchor.rb'
|
|
22
|
+
require 'axlsx/drawing/graphic_frame.rb'
|
|
23
|
+
|
|
24
|
+
require 'axlsx/drawing/view_3D.rb'
|
|
25
|
+
require 'axlsx/drawing/chart.rb'
|
|
26
|
+
require 'axlsx/drawing/pie_3D_chart.rb'
|
|
27
|
+
require 'axlsx/drawing/bar_3D_chart.rb'
|
|
28
|
+
require 'axlsx/drawing/line_3D_chart.rb'
|
|
29
|
+
|
|
30
|
+
require 'axlsx/drawing/picture_locking.rb'
|
|
31
|
+
require 'axlsx/drawing/pic.rb'
|
|
32
|
+
|
|
33
|
+
# A Drawing is a canvas for charts. Each worksheet has a single drawing that manages anchors.
|
|
34
|
+
# The anchors reference the charts via graphical frames. This is not a trivial relationship so please do follow the advice in the note.
|
|
35
|
+
# @note The recommended way to manage drawings is to use the Worksheet.add_chart method.
|
|
36
|
+
# @see Worksheet#add_chart
|
|
37
|
+
# @see Chart
|
|
38
|
+
# see README for an example of how to create a chart.
|
|
39
|
+
class Drawing
|
|
40
|
+
|
|
41
|
+
# The worksheet that owns the drawing
|
|
42
|
+
# @return [Worksheet]
|
|
43
|
+
attr_reader :worksheet
|
|
44
|
+
|
|
45
|
+
# A collection of anchors for this drawing
|
|
46
|
+
# only TwoCellAnchors are supported in this version
|
|
47
|
+
# @return [SimpleTypedList]
|
|
48
|
+
attr_reader :anchors
|
|
49
|
+
|
|
50
|
+
# Creates a new Drawing object
|
|
51
|
+
# @param [Worksheet] worksheet The worksheet that owns this drawing
|
|
52
|
+
def initialize(worksheet)
|
|
53
|
+
DataTypeValidator.validate "Drawing.worksheet", Worksheet, worksheet
|
|
54
|
+
@worksheet = worksheet
|
|
55
|
+
@worksheet.workbook.drawings << self
|
|
56
|
+
@anchors = SimpleTypedList.new [TwoCellAnchor, OneCellAnchor]
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Adds an image to the chart
|
|
60
|
+
# @note The recommended way to manage images is to use Worksheet.add_image. Please refer to that method for documentation.
|
|
61
|
+
# @see Worksheet#add_image
|
|
62
|
+
def add_image(options={})
|
|
63
|
+
OneCellAnchor.new(self, options)
|
|
64
|
+
@anchors.last.object
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Adds a chart to the drawing.
|
|
68
|
+
# @note The recommended way to manage charts is to use Worksheet.add_chart. Please refer to that method for documentation.
|
|
69
|
+
# @see Worksheet#add_chart
|
|
70
|
+
def add_chart(chart_type, options={})
|
|
71
|
+
TwoCellAnchor.new(self, options)
|
|
72
|
+
@anchors.last.add_chart(chart_type, options)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# An array of charts that are associated with this drawing's anchors
|
|
76
|
+
# @return [Array]
|
|
77
|
+
def charts
|
|
78
|
+
charts = @anchors.select { |a| a.object.is_a?(GraphicFrame) }
|
|
79
|
+
charts.map { |a| a.object.chart }
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# An array of image objects that are associated with this drawing's anchors
|
|
83
|
+
# @return [Array]
|
|
84
|
+
def images
|
|
85
|
+
images = @anchors.select { |a| a.object.is_a?(Pic) }
|
|
86
|
+
images.map { |a| a.object }
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# The index of this drawing in the owning workbooks's drawings collection.
|
|
90
|
+
# @return [Integer]
|
|
91
|
+
def index
|
|
92
|
+
@worksheet.workbook.drawings.index(self)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# The relation reference id for this drawing
|
|
96
|
+
# @return [String]
|
|
97
|
+
def rId
|
|
98
|
+
"rId#{index+1}"
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# The part name for this drawing
|
|
102
|
+
# @return [String]
|
|
103
|
+
def pn
|
|
104
|
+
"#{DRAWING_PN % (index+1)}"
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# The relational part name for this drawing
|
|
108
|
+
# @return [String]
|
|
109
|
+
def rels_pn
|
|
110
|
+
"#{DRAWING_RELS_PN % (index+1)}"
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# The drawing's relationships.
|
|
114
|
+
# @return [Relationships]
|
|
115
|
+
def relationships
|
|
116
|
+
r = Relationships.new
|
|
117
|
+
charts.each do |chart|
|
|
118
|
+
r << Relationship.new(CHART_R, "../#{chart.pn}")
|
|
119
|
+
end
|
|
120
|
+
images.each do |image|
|
|
121
|
+
r << Relationship.new(IMAGE_R, "../#{image.pn}")
|
|
122
|
+
end
|
|
123
|
+
r
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Serializes the drawing
|
|
127
|
+
# @return [String]
|
|
128
|
+
def to_xml
|
|
129
|
+
builder = Nokogiri::XML::Builder.new(:encoding => ENCODING) do |xml|
|
|
130
|
+
xml.send('xdr:wsDr', :'xmlns:xdr'=>XML_NS_XDR, :'xmlns:a'=>XML_NS_A, :'xmlns:c'=>XML_NS_C) {
|
|
131
|
+
anchors.each {|anchor| anchor.to_xml(xml) }
|
|
132
|
+
}
|
|
133
|
+
end
|
|
134
|
+
builder.to_xml
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
module Axlsx
|
|
2
|
+
# A graphic frame defines a container for a chart object
|
|
3
|
+
# @note The recommended way to manage charts is Worksheet#add_chart
|
|
4
|
+
# @see Worksheet#add_chart
|
|
5
|
+
class GraphicFrame
|
|
6
|
+
|
|
7
|
+
# A reference to the chart object associated with this frame
|
|
8
|
+
# @return [Chart]
|
|
9
|
+
attr_reader :chart
|
|
10
|
+
|
|
11
|
+
# A anchor that holds this frame
|
|
12
|
+
# @return [TwoCellAnchor]
|
|
13
|
+
attr_reader :anchor
|
|
14
|
+
|
|
15
|
+
# Creates a new GraphicFrame object
|
|
16
|
+
# @param [TwoCellAnchor] anchor
|
|
17
|
+
# @param [Class] chart_type
|
|
18
|
+
def initialize(anchor, chart_type, options)
|
|
19
|
+
DataTypeValidator.validate "Drawing.chart_type", Chart, chart_type
|
|
20
|
+
@anchor = anchor
|
|
21
|
+
@chart = chart_type.new(self, options)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# The relationship id for this graphic
|
|
25
|
+
# @return [String]
|
|
26
|
+
def rId
|
|
27
|
+
"rId#{@anchor.index+1}"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Serializes the graphic frame
|
|
31
|
+
# @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to.
|
|
32
|
+
# @return [String]
|
|
33
|
+
def to_xml(xml)
|
|
34
|
+
xml.graphicFrame {
|
|
35
|
+
xml.nvGraphicFramePr {
|
|
36
|
+
xml.cNvPr :id=>2, :name=>chart.title
|
|
37
|
+
xml.cNvGraphicFramePr
|
|
38
|
+
}
|
|
39
|
+
xml.xfrm {
|
|
40
|
+
xml[:a].off(:x=>0, :y=>0)
|
|
41
|
+
xml[:a].ext :cx=>0, :cy=>0
|
|
42
|
+
}
|
|
43
|
+
xml[:a].graphic {
|
|
44
|
+
xml.graphicData(:uri=>XML_NS_C) {
|
|
45
|
+
xml[:c].chart :'xmlns:c'=>XML_NS_C, :'xmlns:r'=>XML_NS_R, :'r:id'=>rId
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
module Axlsx
|
|
2
|
+
|
|
3
|
+
# The Line3DChart is a three dimentional line chart (who would have guessed?) that you can add to your worksheet.
|
|
4
|
+
# @example Creating a chart
|
|
5
|
+
# # This example creates a line in a single sheet.
|
|
6
|
+
# require "rubygems" # if that is your preferred way to manage gems!
|
|
7
|
+
# require "axlsx"
|
|
8
|
+
#
|
|
9
|
+
# p = Axlsx::Package.new
|
|
10
|
+
# ws = p.workbook.add_worksheet
|
|
11
|
+
# ws.add_row :values => ["This is a chart with no data in the sheet"]
|
|
12
|
+
#
|
|
13
|
+
# chart = ws.add_chart(Axlsx::Line3DChart, :start_at=> [0,1], :end_at=>[0,6], :title=>"Most Popular Pets")
|
|
14
|
+
# chart.add_series :data => [1, 9, 10], :labels => ["Slimy Reptiles", "Fuzzy Bunnies", "Rottweiler"]
|
|
15
|
+
#
|
|
16
|
+
# @see Worksheet#add_chart
|
|
17
|
+
# @see Worksheet#add_row
|
|
18
|
+
# @see Chart#add_series
|
|
19
|
+
# @see Series
|
|
20
|
+
# @see Package#serialize
|
|
21
|
+
class Line3DChart < Chart
|
|
22
|
+
|
|
23
|
+
# the category axis
|
|
24
|
+
# @return [CatAxis]
|
|
25
|
+
attr_reader :catAxis
|
|
26
|
+
|
|
27
|
+
# the category axis
|
|
28
|
+
# @return [ValAxis]
|
|
29
|
+
attr_reader :valAxis
|
|
30
|
+
|
|
31
|
+
# the category axis
|
|
32
|
+
# @return [Axis]
|
|
33
|
+
attr_reader :serAxis
|
|
34
|
+
|
|
35
|
+
# space between bar or column clusters, as a percentage of the bar or column width.
|
|
36
|
+
# @return [String]
|
|
37
|
+
attr_reader :gapDepth
|
|
38
|
+
|
|
39
|
+
#grouping for a column, line, or area chart.
|
|
40
|
+
# must be one of [:percentStacked, :clustered, :standard, :stacked]
|
|
41
|
+
# @return [Symbol]
|
|
42
|
+
attr_reader :grouping
|
|
43
|
+
|
|
44
|
+
# validation regex for gap amount percent
|
|
45
|
+
GAP_AMOUNT_PERCENT = /0*(([0-9])|([1-9][0-9])|([1-4][0-9][0-9])|500)%/
|
|
46
|
+
|
|
47
|
+
# Creates a new line chart object
|
|
48
|
+
# @param [GraphicFrame] frame The workbook that owns this chart.
|
|
49
|
+
# @option options [Cell, String] title
|
|
50
|
+
# @option options [Boolean] show_legend
|
|
51
|
+
# @option options [Symbol] grouping
|
|
52
|
+
# @option options [String] gapDepth
|
|
53
|
+
# @option options [Integer] rotX
|
|
54
|
+
# @option options [String] hPercent
|
|
55
|
+
# @option options [Integer] rotY
|
|
56
|
+
# @option options [String] depthPercent
|
|
57
|
+
# @option options [Boolean] rAngAx
|
|
58
|
+
# @option options [Integer] perspective
|
|
59
|
+
# @see Chart
|
|
60
|
+
# @see View3D
|
|
61
|
+
def initialize(frame, options={})
|
|
62
|
+
@gapDepth = nil
|
|
63
|
+
@grouping = :standard
|
|
64
|
+
@catAxId = rand(8 ** 8)
|
|
65
|
+
@valAxId = rand(8 ** 8)
|
|
66
|
+
@serAxId = rand(8 ** 8)
|
|
67
|
+
@catAxis = CatAxis.new(@catAxId, @valAxId)
|
|
68
|
+
@valAxis = ValAxis.new(@valAxId, @catAxId)
|
|
69
|
+
@serAxis = SerAxis.new(@serAxId, @valAxId)
|
|
70
|
+
super(frame, options)
|
|
71
|
+
@series_type = LineSeries
|
|
72
|
+
@view3D = View3D.new({:perspective=>30}.merge(options))
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# @see grouping
|
|
76
|
+
def grouping=(v)
|
|
77
|
+
RestrictionValidator.validate "Bar3DChart.grouping", [:percentStacked, :standard, :stacked], v
|
|
78
|
+
@grouping = v
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# @see gapDepth
|
|
82
|
+
def gapDepth=(v)
|
|
83
|
+
RegexValidator.validate "Bar3DChart.gapWidth", GAP_AMOUNT_PERCENT, v
|
|
84
|
+
@gapDepth=(v)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Serializes the bar chart
|
|
88
|
+
# @return [String]
|
|
89
|
+
def to_xml
|
|
90
|
+
super() do |xml|
|
|
91
|
+
xml.line3DChart {
|
|
92
|
+
xml.grouping :val=>grouping
|
|
93
|
+
xml.varyColors :val=>1
|
|
94
|
+
@series.each { |ser| ser.to_xml(xml) }
|
|
95
|
+
xml.dLbls {
|
|
96
|
+
xml.showLegendKey :val=>0
|
|
97
|
+
xml.showVal :val=>0
|
|
98
|
+
xml.showCatName :val=>0
|
|
99
|
+
xml.showSerName :val=>0
|
|
100
|
+
xml.showPercent :val=>0
|
|
101
|
+
xml.showBubbleSize :val=>0
|
|
102
|
+
}
|
|
103
|
+
xml.gapDepth :val=>@gapDepth unless @gapDepth.nil?
|
|
104
|
+
xml.axId :val=>@catAxId
|
|
105
|
+
xml.axId :val=>@valAxId
|
|
106
|
+
xml.axId :val=>@serAxId
|
|
107
|
+
}
|
|
108
|
+
@catAxis.to_xml(xml)
|
|
109
|
+
@valAxis.to_xml(xml)
|
|
110
|
+
@serAxis.to_xml(xml)
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
module Axlsx
|
|
2
|
+
# A LineSeries defines the title, data and labels for line charts
|
|
3
|
+
# @note The recommended way to manage series is to use Chart#add_series
|
|
4
|
+
# @see Worksheet#add_chart
|
|
5
|
+
# @see Chart#add_series
|
|
6
|
+
class LineSeries < Series
|
|
7
|
+
|
|
8
|
+
# The data for this series.
|
|
9
|
+
# @return [ValAxisData]
|
|
10
|
+
attr_reader :data
|
|
11
|
+
|
|
12
|
+
# The labels for this series.
|
|
13
|
+
# @return [CatAxisData]
|
|
14
|
+
attr_reader :labels
|
|
15
|
+
|
|
16
|
+
# Creates a new series
|
|
17
|
+
# @option options [Array, SimpleTypedList] data
|
|
18
|
+
# @option options [Array, SimpleTypedList] labels
|
|
19
|
+
# @param [Chart] chart
|
|
20
|
+
def initialize(chart, options={})
|
|
21
|
+
@labels, @data = nil, nil
|
|
22
|
+
super(chart, options)
|
|
23
|
+
@labels = CatAxisData.new(options[:labels]) unless options[:labels].nil?
|
|
24
|
+
@data = ValAxisData.new(options[:data]) unless options[:data].nil?
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Serializes the series
|
|
28
|
+
# @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to.
|
|
29
|
+
# @return [String]
|
|
30
|
+
def to_xml(xml)
|
|
31
|
+
super(xml) do |xml_inner|
|
|
32
|
+
@labels.to_xml(xml_inner) unless @labels.nil?
|
|
33
|
+
@data.to_xml(xml_inner) unless @data.nil?
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
# assigns the data for this series
|
|
40
|
+
def data=(v) DataTypeValidator.validate "Series.data", [SimpleTypedList], v; @data = v; end
|
|
41
|
+
|
|
42
|
+
# assigns the labels for this series
|
|
43
|
+
def labels=(v) DataTypeValidator.validate "Series.labels", [SimpleTypedList], v; @labels = v; end
|
|
44
|
+
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
module Axlsx
|
|
2
|
+
# The Marker class defines a point in the worksheet that drawing anchors attach to.
|
|
3
|
+
# @note The recommended way to manage markers is Worksheet#add_chart Markers are created for a two cell anchor based on the :start and :end options.
|
|
4
|
+
# @see Worksheet#add_chart
|
|
5
|
+
class Marker
|
|
6
|
+
|
|
7
|
+
# The column this marker anchors to
|
|
8
|
+
# @return [Integer]
|
|
9
|
+
attr_reader :col
|
|
10
|
+
|
|
11
|
+
# The offset distance from this marker's column
|
|
12
|
+
# @return [Integer]
|
|
13
|
+
attr_reader :colOff
|
|
14
|
+
|
|
15
|
+
# The row this marker anchors to
|
|
16
|
+
# @return [Integer]
|
|
17
|
+
attr_reader :row
|
|
18
|
+
|
|
19
|
+
# The offset distance from this marker's row
|
|
20
|
+
# @return [Integer]
|
|
21
|
+
attr_reader :rowOff
|
|
22
|
+
|
|
23
|
+
# Creates a new Marker object
|
|
24
|
+
# @option options [Integer] col
|
|
25
|
+
# @option options [Integer] colOff
|
|
26
|
+
# @option options [Integer] row
|
|
27
|
+
# @option options [Integer] rowOff
|
|
28
|
+
def initialize(options={})
|
|
29
|
+
@col, @colOff, @row, @rowOff = 0, 0, 0, 0
|
|
30
|
+
options.each do |o|
|
|
31
|
+
self.send("#{o[0]}=", o[1]) if self.respond_to? o[0]
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# @see col
|
|
36
|
+
def col=(v) Axlsx::validate_unsigned_int v; @col = v end
|
|
37
|
+
# @see colOff
|
|
38
|
+
def colOff=(v) Axlsx::validate_int v; @colOff = v end
|
|
39
|
+
# @see row
|
|
40
|
+
def row=(v) Axlsx::validate_unsigned_int v; @row = v end
|
|
41
|
+
# @see rowOff
|
|
42
|
+
def rowOff=(v) Axlsx::validate_int v; @rowOff = v end
|
|
43
|
+
|
|
44
|
+
# shortcut to set the column, row position for this marker
|
|
45
|
+
# @param col the column for the marker
|
|
46
|
+
# @param row the row of the marker
|
|
47
|
+
def coord(col, row)
|
|
48
|
+
self.col = col
|
|
49
|
+
self.row = row
|
|
50
|
+
end
|
|
51
|
+
# Serializes the marker
|
|
52
|
+
# @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to.
|
|
53
|
+
# @return [String]
|
|
54
|
+
def to_xml(xml)
|
|
55
|
+
[:col, :colOff, :row, :rowOff].each do |k|
|
|
56
|
+
xml.send(k.to_sym, self.send(k))
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
end
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
module Axlsx
|
|
2
|
+
# This class details a single cell anchor for drawings.
|
|
3
|
+
# @note The recommended way to manage drawings, images and charts is Worksheet#add_chart or Worksheet#add_image.
|
|
4
|
+
# @see Worksheet#add_chart
|
|
5
|
+
# @see Worksheet#add_image
|
|
6
|
+
class OneCellAnchor
|
|
7
|
+
|
|
8
|
+
# A marker that defines the from cell anchor. The default from column and row are 0 and 0 respectively
|
|
9
|
+
# @return [Marker]
|
|
10
|
+
attr_reader :from
|
|
11
|
+
|
|
12
|
+
# The object this anchor hosts
|
|
13
|
+
# @return [Pic]
|
|
14
|
+
attr_reader :object
|
|
15
|
+
|
|
16
|
+
# The drawing that holds this anchor
|
|
17
|
+
# @return [Drawing]
|
|
18
|
+
attr_reader :drawing
|
|
19
|
+
|
|
20
|
+
# the width of the graphic object in pixels.
|
|
21
|
+
# this is converted to EMU at a 92 ppi resolution
|
|
22
|
+
# @return [Integer]
|
|
23
|
+
attr_reader :width
|
|
24
|
+
|
|
25
|
+
# the height of the graphic object in pixels
|
|
26
|
+
# this is converted to EMU at a 92 ppi resolution
|
|
27
|
+
# @return [Integer]
|
|
28
|
+
attr_reader :height
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
# Creates a new OneCellAnchor object and an Pic associated with it.
|
|
32
|
+
# @param [Drawing] drawing
|
|
33
|
+
# @option options [Array] start_at the col, row to start at
|
|
34
|
+
# @option options [Integer] width
|
|
35
|
+
# @option options [Integer] height
|
|
36
|
+
# @option options [String] image_src the file location of the image you will render
|
|
37
|
+
# @option options [String] name the name attribute for the rendered image
|
|
38
|
+
# @option options [String] descr the description of the image rendered
|
|
39
|
+
def initialize(drawing, options={})
|
|
40
|
+
@drawing = drawing
|
|
41
|
+
@width = 0
|
|
42
|
+
@height = 0
|
|
43
|
+
drawing.anchors << self
|
|
44
|
+
@from = Marker.new
|
|
45
|
+
options.each do |o|
|
|
46
|
+
self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
|
|
47
|
+
end
|
|
48
|
+
@object = Pic.new(self, options)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# @see height
|
|
52
|
+
def height=(v) Axlsx::validate_unsigned_int(v); @height = v; end
|
|
53
|
+
|
|
54
|
+
# @see width
|
|
55
|
+
def width=(v) Axlsx::validate_unsigned_int(v); @width = v; end
|
|
56
|
+
|
|
57
|
+
# The index of this anchor in the drawing
|
|
58
|
+
# @return [Integer]
|
|
59
|
+
def index
|
|
60
|
+
@drawing.anchors.index(self)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Serializes the anchor
|
|
64
|
+
# @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to.
|
|
65
|
+
# @return [String]
|
|
66
|
+
def to_xml(xml)
|
|
67
|
+
xml[:xdr].oneCellAnchor {
|
|
68
|
+
xml.from {
|
|
69
|
+
from.to_xml(xml)
|
|
70
|
+
}
|
|
71
|
+
xml.ext ext
|
|
72
|
+
@object.to_xml(xml)
|
|
73
|
+
xml.clientData
|
|
74
|
+
}
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
private
|
|
78
|
+
|
|
79
|
+
# converts the pixel width and height to EMU units and returns a hash of
|
|
80
|
+
# !{:cx=>[Integer], :cy=>[Integer]
|
|
81
|
+
# @return [Hash]
|
|
82
|
+
def ext
|
|
83
|
+
cy = @height * 914400 / 96
|
|
84
|
+
cx = @width * 914400 / 96
|
|
85
|
+
{:cy=>cy, :cx=>cx}
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
end
|
|
89
|
+
end
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
module Axlsx
|
|
3
|
+
# a Pic object represents an image in your worksheet
|
|
4
|
+
# Worksheet#add_image is the recommended way to manage images in your sheets
|
|
5
|
+
# @see Worksheet#add_image
|
|
6
|
+
class Pic
|
|
7
|
+
|
|
8
|
+
# allowed file extenstions
|
|
9
|
+
ALLOWED_EXTENSIONS = ['gif', 'jpeg', 'png', 'jpg']
|
|
10
|
+
|
|
11
|
+
# The name to use for this picture
|
|
12
|
+
# @return [String]
|
|
13
|
+
attr_reader :name
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
# A description of the picture
|
|
17
|
+
# @return [String]
|
|
18
|
+
attr_reader :descr
|
|
19
|
+
|
|
20
|
+
# The path to the image you want to include
|
|
21
|
+
# Only local images are supported at this time and only jpg support
|
|
22
|
+
# @return [String]
|
|
23
|
+
attr_reader :image_src
|
|
24
|
+
|
|
25
|
+
# The anchor for this image
|
|
26
|
+
# @return [OneCellAnchor]
|
|
27
|
+
attr_reader :anchor
|
|
28
|
+
|
|
29
|
+
# The picture locking attributes for this picture
|
|
30
|
+
attr_reader :picture_locking
|
|
31
|
+
|
|
32
|
+
# Creates a new Pic(ture) object
|
|
33
|
+
# @param [Anchor] anchor the anchor that holds this image
|
|
34
|
+
# @option options [String] name
|
|
35
|
+
# @option options [String] descr
|
|
36
|
+
# @option options [String] image_src
|
|
37
|
+
# @option options [Array] start_at
|
|
38
|
+
# @option options [Intger] width
|
|
39
|
+
# @option options [Intger] height
|
|
40
|
+
def initialize(anchor, options={})
|
|
41
|
+
@anchor = anchor
|
|
42
|
+
@anchor.drawing.worksheet.workbook.images << self
|
|
43
|
+
options.each do |o|
|
|
44
|
+
self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
|
|
45
|
+
end
|
|
46
|
+
start_at(*options[:start_at]) if options[:start_at]
|
|
47
|
+
yield self if block_given?
|
|
48
|
+
@picture_locking = PictureLocking.new(options)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def image_src=(v)
|
|
52
|
+
Axlsx::validate_string(v)
|
|
53
|
+
RestrictionValidator.validate 'Pic.image_src', ALLOWED_EXTENSIONS, File.extname(v).delete('.')
|
|
54
|
+
raise ArgumentError, "File does not exist" unless File.exist?(v)
|
|
55
|
+
@image_src = v
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# @see name
|
|
59
|
+
def name=(v) Axlsx::validate_string(v); @name = v; end
|
|
60
|
+
|
|
61
|
+
# @see descr
|
|
62
|
+
def descr=(v) Axlsx::validate_string(v); @descr = v; end
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
# The file name of image_src without any path information
|
|
66
|
+
# @return [String]
|
|
67
|
+
def file_name
|
|
68
|
+
File.basename(image_src) unless image_src.nil?
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# returns the extension of image_src without the preceeding '.'
|
|
72
|
+
# @return [String]
|
|
73
|
+
def extname
|
|
74
|
+
File.extname(image_src).delete('.') unless image_src.nil?
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# The index of this image in the workbooks images collections
|
|
78
|
+
# @return [Index]
|
|
79
|
+
def index
|
|
80
|
+
@anchor.drawing.worksheet.workbook.images.index(self)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# The part name for this image used in serialization and relationship building
|
|
84
|
+
# @return [String]
|
|
85
|
+
def pn
|
|
86
|
+
"#{IMAGE_PN % [(index+1), extname]}"
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# providing access to the anchor's width attribute
|
|
90
|
+
# @param [Integer] v
|
|
91
|
+
# @see OneCellAnchor.width
|
|
92
|
+
def width
|
|
93
|
+
@anchor.width
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# @see width
|
|
97
|
+
def width=(v)
|
|
98
|
+
@anchor.width = v
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# providing access to update the anchor's height attribute
|
|
102
|
+
# @param [Integer] v
|
|
103
|
+
# @see OneCellAnchor.width
|
|
104
|
+
def height
|
|
105
|
+
@anchor.height
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# @see height
|
|
109
|
+
def height=(v)
|
|
110
|
+
@anchor.height = v
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# This is a short cut method to set the start anchor position
|
|
114
|
+
# If you need finer granularity in positioning use
|
|
115
|
+
# graphic_frame.anchor.from.colOff / rowOff
|
|
116
|
+
# @param [Integer] x The column
|
|
117
|
+
# @param [Integer] y The row
|
|
118
|
+
# @return [Marker]
|
|
119
|
+
def start_at(x, y)
|
|
120
|
+
@anchor.from.col = x
|
|
121
|
+
@anchor.from.row = y
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Serializes the picture
|
|
125
|
+
# @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to.
|
|
126
|
+
# @return [String]
|
|
127
|
+
def to_xml(xml)
|
|
128
|
+
xml.pic {
|
|
129
|
+
xml.nvPicPr {
|
|
130
|
+
xml.cNvPr :id=>"2", :name=>name, :descr=>descr
|
|
131
|
+
xml.cNvPicPr {
|
|
132
|
+
picture_locking.to_xml(xml)
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
xml.blipFill {
|
|
136
|
+
xml[:a].blip :'xmlns:r' => XML_NS_R, :'r:embed'=>"rId1"
|
|
137
|
+
xml[:a].stretch {
|
|
138
|
+
xml.fillRect
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
xml.spPr {
|
|
142
|
+
xml[:a].xfrm {
|
|
143
|
+
xml.off :x=>0, :y=>0
|
|
144
|
+
xml.ext :cx=>2336800, :cy=>2161540
|
|
145
|
+
}
|
|
146
|
+
xml[:a].prstGeom(:prst=>:rect) {
|
|
147
|
+
xml.avLst
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|