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.
Files changed (77) hide show
  1. data/README.md +165 -134
  2. data/examples/example.rb +133 -153
  3. data/lib/axlsx/#cfb.xlsx# +0 -0
  4. data/lib/axlsx/content_type/content_type.rb +23 -0
  5. data/lib/axlsx/content_type/default.rb +37 -0
  6. data/lib/axlsx/content_type/override.rb +37 -0
  7. data/lib/axlsx/doc_props/app.rb +178 -0
  8. data/lib/axlsx/doc_props/core.rb +34 -0
  9. data/lib/axlsx/drawing/axis.rb +93 -0
  10. data/lib/axlsx/drawing/bar_3D_chart.rb +136 -0
  11. data/lib/axlsx/drawing/bar_series.rb +64 -0
  12. data/lib/axlsx/drawing/cat_axis.rb +63 -0
  13. data/lib/axlsx/drawing/cat_axis_data.rb +35 -0
  14. data/lib/axlsx/drawing/chart.rb +193 -0
  15. data/lib/axlsx/drawing/drawing.rb +137 -0
  16. data/lib/axlsx/drawing/graphic_frame.rb +52 -0
  17. data/lib/axlsx/drawing/line_3D_chart.rb +114 -0
  18. data/lib/axlsx/drawing/line_series.rb +46 -0
  19. data/lib/axlsx/drawing/marker.rb +61 -0
  20. data/lib/axlsx/drawing/one_cell_anchor.rb +89 -0
  21. data/lib/axlsx/drawing/pic.rb +153 -0
  22. data/lib/axlsx/drawing/picture_locking.rb +72 -0
  23. data/lib/axlsx/drawing/picture_locking.rb~ +36 -0
  24. data/lib/axlsx/drawing/pie_3D_chart.rb +41 -0
  25. data/lib/axlsx/drawing/pie_series.rb +56 -0
  26. data/lib/axlsx/drawing/scaling.rb +59 -0
  27. data/lib/axlsx/drawing/ser_axis.rb +45 -0
  28. data/lib/axlsx/drawing/series.rb +71 -0
  29. data/lib/axlsx/drawing/series_title.rb +22 -0
  30. data/lib/axlsx/drawing/title.rb +65 -0
  31. data/lib/axlsx/drawing/two_cell_anchor.rb +76 -0
  32. data/lib/axlsx/drawing/val_axis.rb +34 -0
  33. data/lib/axlsx/drawing/val_axis_data.rb +26 -0
  34. data/lib/axlsx/drawing/view_3D.rb +85 -0
  35. data/lib/axlsx/package.rb +223 -0
  36. data/lib/axlsx/rels/relationship.rb +44 -0
  37. data/lib/axlsx/rels/relationships.rb +25 -0
  38. data/lib/axlsx/stylesheet/border.rb +57 -0
  39. data/lib/axlsx/stylesheet/border_pr.rb +68 -0
  40. data/lib/axlsx/stylesheet/cell_alignment.rb +105 -0
  41. data/lib/axlsx/stylesheet/cell_protection.rb +36 -0
  42. data/lib/axlsx/stylesheet/cell_style.rb +65 -0
  43. data/lib/axlsx/stylesheet/color.rb +69 -0
  44. data/lib/axlsx/stylesheet/fill.rb +32 -0
  45. data/lib/axlsx/stylesheet/font.rb +139 -0
  46. data/lib/axlsx/stylesheet/gradient_fill.rb +76 -0
  47. data/lib/axlsx/stylesheet/gradient_stop.rb +33 -0
  48. data/lib/axlsx/stylesheet/num_fmt.rb +63 -0
  49. data/lib/axlsx/stylesheet/pattern_fill.rb +66 -0
  50. data/lib/axlsx/stylesheet/styles.rb +298 -0
  51. data/lib/axlsx/stylesheet/table_style.rb +47 -0
  52. data/lib/axlsx/stylesheet/table_style_element.rb +71 -0
  53. data/lib/axlsx/stylesheet/table_styles.rb +39 -0
  54. data/lib/axlsx/stylesheet/xf.rb +138 -0
  55. data/lib/axlsx/util/constants.rb +216 -0
  56. data/lib/axlsx/util/ms_off_crypto.rb +88 -0
  57. data/lib/axlsx/util/ms_off_crypto.rb~ +3 -0
  58. data/lib/axlsx/util/ms_offcrypto.rb~ +0 -0
  59. data/lib/axlsx/util/parser.rb +43 -0
  60. data/lib/axlsx/util/parser.rb~ +6 -0
  61. data/lib/axlsx/util/simple_typed_list.rb +160 -0
  62. data/lib/axlsx/util/validators.rb +132 -0
  63. data/lib/axlsx/version.rb +4 -0
  64. data/lib/axlsx/workbook/workbook.rb +161 -0
  65. data/lib/axlsx/workbook/worksheet/cell.rb +350 -0
  66. data/lib/axlsx/workbook/worksheet/row.rb +107 -0
  67. data/lib/axlsx/workbook/worksheet/worksheet.rb +335 -0
  68. data/lib/axlsx.rb +59 -0
  69. data/test/drawing/tc_axis.rb +1 -1
  70. data/test/drawing/tc_cat_axis.rb +1 -1
  71. data/test/drawing/tc_line_series.tc~ +34 -0
  72. data/test/drawing/tc_picture_locking.rb~ +77 -0
  73. data/test/tc_package.rb +10 -0
  74. data/test/workbook/worksheet/tc_cell.rb +15 -0
  75. data/test/workbook/worksheet/tc_worksheet.rb +22 -1
  76. metadata +117 -5
  77. 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