axlsx 1.1.4 → 1.1.5

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 (81) hide show
  1. data/README.md +10 -3
  2. data/Rakefile +7 -1
  3. data/examples/chart_colors.rb +1 -1
  4. data/examples/chart_colors.xlsx +0 -0
  5. data/examples/doc/_index.html +84 -0
  6. data/examples/doc/class_list.html +47 -0
  7. data/examples/doc/css/common.css +1 -0
  8. data/examples/doc/css/full_list.css +55 -0
  9. data/examples/doc/css/style.css +322 -0
  10. data/examples/doc/file_list.html +46 -0
  11. data/examples/doc/frames.html +13 -0
  12. data/examples/doc/index.html +84 -0
  13. data/examples/doc/js/app.js +205 -0
  14. data/examples/doc/js/full_list.js +173 -0
  15. data/examples/doc/js/jquery.js +16 -0
  16. data/examples/doc/method_list.html +46 -0
  17. data/examples/doc/top-level-namespace.html +95 -0
  18. data/examples/example.rb +12 -5
  19. data/examples/example.xlsx +0 -0
  20. data/examples/example_streamed.xlsx +0 -0
  21. data/examples/extractive.rb +3 -0
  22. data/lib/axlsx.rb +4 -4
  23. data/lib/axlsx/drawing/drawing.rb +7 -2
  24. data/lib/axlsx/drawing/graphic_frame.rb +2 -1
  25. data/lib/axlsx/drawing/num_data_source.rb +3 -0
  26. data/lib/axlsx/drawing/vml_drawing.rb +42 -0
  27. data/lib/axlsx/drawing/vml_drawing.rb~ +6 -0
  28. data/lib/axlsx/drawing/vml_shape.rb +128 -0
  29. data/lib/axlsx/drawing/vml_shape.rb~ +61 -0
  30. data/lib/axlsx/package.rb +24 -0
  31. data/lib/axlsx/rels/relationships.rb +0 -10
  32. data/lib/axlsx/stylesheet/gradient_fill.rb +1 -1
  33. data/lib/axlsx/util/constants.rb +24 -0
  34. data/lib/axlsx/util/validators.rb +32 -4
  35. data/lib/axlsx/version.rb +1 -1
  36. data/lib/axlsx/workbook/workbook.rb +21 -0
  37. data/lib/axlsx/workbook/worksheet/cell.rb +4 -2
  38. data/lib/axlsx/workbook/worksheet/comment.rb +107 -0
  39. data/lib/axlsx/workbook/worksheet/comment.rb~ +91 -0
  40. data/lib/axlsx/workbook/worksheet/comments.rb +77 -0
  41. data/lib/axlsx/workbook/worksheet/comments.rb~ +86 -0
  42. data/lib/axlsx/workbook/worksheet/page_setup.rb +90 -0
  43. data/lib/axlsx/workbook/worksheet/print_options.rb +63 -0
  44. data/lib/axlsx/workbook/worksheet/row.rb +2 -2
  45. data/lib/axlsx/workbook/worksheet/worksheet.rb +72 -9
  46. data/test/doc_props/tc_core.rb +3 -1
  47. data/test/drawing/tc_hyperlink.rb +4 -0
  48. data/test/drawing/tc_line_series.rb +6 -2
  49. data/test/drawing/tc_pie_series.rb +6 -1
  50. data/test/drawing/tc_vml_drawing.rb +25 -0
  51. data/{examples/#extractive.csv# → test/drawing/tc_vml_drawing.rb~} +0 -0
  52. data/test/drawing/tc_vml_shape.rb +100 -0
  53. data/test/rels/tc_relationship.rb +1 -0
  54. data/test/stylesheet/tc_gradient_fill.rb +8 -0
  55. data/test/stylesheet/tc_pattern_fill.rb +7 -1
  56. data/test/tc_helper.rb +1 -0
  57. data/test/tc_package.rb +16 -5
  58. data/test/util/tc_validators.rb +29 -0
  59. data/test/workbook/worksheet/tc_cell.rb +17 -0
  60. data/test/workbook/worksheet/tc_comment.rb +56 -0
  61. data/test/workbook/worksheet/tc_comments.rb +50 -0
  62. data/test/workbook/worksheet/tc_page_setup.rb +103 -0
  63. data/test/workbook/worksheet/tc_print_options.rb +72 -0
  64. data/test/workbook/worksheet/tc_row.rb +19 -13
  65. data/test/workbook/worksheet/tc_worksheet.rb +60 -7
  66. metadata +56 -24
  67. data/examples/#extractive.rb# +0 -45
  68. data/examples/chart_colors.rb~ +0 -0
  69. data/examples/colored_series_data.xlsx +0 -0
  70. data/examples/example.csv +0 -1000
  71. data/examples/extractive.csv +0 -1
  72. data/examples/extractive.csv~ +0 -1
  73. data/examples/extractive.rb~ +0 -3
  74. data/examples/extractive.xlsx +0 -0
  75. data/examples/no-use_autowidth.xlsx +0 -0
  76. data/examples/shared_strings_example.xlsx +0 -0
  77. data/examples/stack.rb +0 -21
  78. data/examples/stack.rb~ +0 -27
  79. data/examples/stack.xlsx +0 -0
  80. data/examples/~$chart_colors.xlsx +0 -0
  81. data/examples/~$extractive.xlsx +0 -0
@@ -0,0 +1,61 @@
1
+ module Axlsx
2
+ class VmlShape
3
+
4
+ attr_reader :row
5
+
6
+ attr_reader :column
7
+
8
+ attr_reader :left_column
9
+ attr_reader :left_offset
10
+ attr_reader :top_row
11
+ attr_reader :top_offset
12
+ attr_reader :right_column
13
+ attr_reader :right_offset
14
+ attr_reader :bottom_row
15
+ attr_reader :bottom_offset
16
+
17
+ def initialize(comment, options={})
18
+ @row = @column = 0
19
+ @left_column = 0
20
+ @left_offset = 15
21
+ @top_row = 0
22
+ @top_offset = 2
23
+ @right_column = 0
24
+ @right_offset = 50
25
+ @bottom_row = 0
26
+ @bottom_offset = 5
27
+ options.each do |o|
28
+ self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
29
+ end
30
+
31
+
32
+ end
33
+
34
+ def xml_to_string(str ='') str << <<SHAME_ON_YOU
35
+
36
+ <v:shape id="_x0000_s#{@comments.worksheet.index+1}07#{index+1}" type="#_x0000_t202"
37
+ style='position:absolute;margin-left:104pt;margin-top:2pt;width:800px;height:27pt;z-index:1;mso-wrap-style:tight'
38
+ fillcolor="#ffffa1 [80]" o:insetmode="auto">
39
+ <v:fill color2="#ffffa1 [80]"/>
40
+ <v:shadow on="t" obscured="t"/>
41
+ <v:path o:connecttype="none"/>
42
+ <v:textbox style='mso-fit-text-with-word-wrap:t'>
43
+ <div style='text-align:left'></div>
44
+ </v:textbox>
45
+
46
+ <x:ClientData ObjectType="Note">
47
+ <x:MoveWithCells/>
48
+ <x:SizeWithCells/>
49
+ # LeftColumn, LeftOffset, TopRow, TopOffset, RightColumn, RightOffset, BottomRow, BottomOffset.
50
+ <x:Anchor>#{comment.comments.worksheet[comment.ref].index + 1}, 15, #{comment.comments.worksheet[comment.ref].row.index}, 2, #{comment.comments.worksheet[comment.ref].index + 5}, 50, #{comment.comments.worksheet[comment.ref].row.index + 5}, 5</x:Anchor>
51
+ <x:AutoFill>False</x:AutoFill>
52
+ <x:Row>#{comment.comments.worksheet[comment.ref].row.index}</x:Row>
53
+ <x:Column>#{comment.comments.worksheet[comment.ref].index}</x:Column>
54
+ <x:Visible/>
55
+ </x:ClientData>
56
+ </v:shape>
57
+ SHAME_ON_YOU
58
+
59
+ end
60
+ end
61
+ end
@@ -180,15 +180,24 @@ module Axlsx
180
180
  {:entry => CONTENT_TYPES_PN, :doc => content_types.to_xml_string, :schema => CONTENT_TYPES_XSD},
181
181
  {:entry => WORKBOOK_PN, :doc => workbook.to_xml_string, :schema => SML_XSD}
182
182
  ]
183
+
183
184
  workbook.drawings.each do |drawing|
184
185
  @parts << {:entry => "xl/#{drawing.rels_pn}", :doc => drawing.relationships.to_xml_string, :schema => RELS_XSD}
185
186
  @parts << {:entry => "xl/#{drawing.pn}", :doc => drawing.to_xml_string, :schema => DRAWING_XSD}
186
187
  end
187
188
 
189
+
188
190
  workbook.tables.each do |table|
189
191
  @parts << {:entry => "xl/#{table.pn}", :doc => table.to_xml_string, :schema => SML_XSD}
190
192
  end
191
193
 
194
+ workbook.comments.each do|comment|
195
+ if comment.size > 0
196
+ @parts << { :entry => "xl/#{comment.pn}", :doc => comment.to_xml_string, :schema => SML_XSD }
197
+ @parts << { :entry => "xl/#{comment.vml_drawing.pn}", :doc => comment.vml_drawing.to_xml_string, :schema => nil }
198
+ end
199
+ end
200
+
192
201
  workbook.charts.each do |chart|
193
202
  @parts << {:entry => "xl/#{chart.pn}", :doc => chart.to_xml_string, :schema => DRAWING_XSD}
194
203
  end
@@ -229,18 +238,33 @@ module Axlsx
229
238
  # @private
230
239
  def content_types
231
240
  c_types = base_content_types
241
+
232
242
  workbook.drawings.each do |drawing|
233
243
  c_types << Axlsx::Override.new(:PartName => "/xl/#{drawing.pn}",
234
244
  :ContentType => DRAWING_CT)
235
245
  end
246
+
236
247
  workbook.charts.each do |chart|
237
248
  c_types << Axlsx::Override.new(:PartName => "/xl/#{chart.pn}",
238
249
  :ContentType => CHART_CT)
239
250
  end
251
+
240
252
  workbook.tables.each do |table|
241
253
  c_types << Axlsx::Override.new(:PartName => "/xl/#{table.pn}",
242
254
  :ContentType => TABLE_CT)
243
255
  end
256
+
257
+ workbook.comments.each do |comment|
258
+ if comment.size > 0
259
+ c_types << Axlsx::Override.new(:PartName => "/xl/#{comment.pn}",
260
+ :ContentType => COMMENT_CT)
261
+ end
262
+ end
263
+
264
+ if workbook.comments.size > 0
265
+ c_types << Axlsx::Default.new(:Extension => "vml", :ContentType => VML_DRAWING_CT)
266
+ end
267
+
244
268
  workbook.worksheets.each do |sheet|
245
269
  c_types << Axlsx::Override.new(:PartName => "/xl/#{sheet.pn}",
246
270
  :ContentType => WORKSHEET_CT)
@@ -17,16 +17,6 @@ require 'axlsx/rels/relationship.rb'
17
17
  each_with_index { |rel, index| rel.to_xml_string(index+1, str) }
18
18
  str << '</Relationships>'
19
19
  end
20
- # Serializes the relationships document.
21
- # @return [String]
22
- def to_xml()
23
- builder = Nokogiri::XML::Builder.new(:encoding => ENCODING) do |xml|
24
- xml.Relationships(:xmlns => Axlsx::RELS_R) {
25
- each_with_index { |rel, index| rel.to_xml(xml, "rId#{index+1}") }
26
- }
27
- end
28
- builder.to_xml(:save_with => 0)
29
- end
30
20
 
31
21
  end
32
22
  end
@@ -68,7 +68,7 @@ module Axlsx
68
68
  # @param [String] str
69
69
  # @return [String]
70
70
  def to_xml_string(str = '')
71
- str << '<gradientFill'
71
+ str << '<gradientFill '
72
72
  h = self.instance_values.reject { |k,v| k.to_sym == :stop }
73
73
  str << h.map { |key, value| '' << key.to_s << '="' << value.to_s << '"' }.join(' ')
74
74
  str << '>'
@@ -79,6 +79,18 @@ module Axlsx
79
79
  # image rels namespace
80
80
  HYPERLINK_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink"
81
81
 
82
+ # comment rels namespace
83
+ COMMENT_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments"
84
+
85
+ # comment relation for nil target
86
+ COMMENT_R_NULL = "http://purl.oclc.org/ooxml/officeDocument/relationships/comments"
87
+
88
+ #vml drawing relation namespace
89
+ VML_DRAWING_R = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing'
90
+
91
+ # VML Drawing content type
92
+ VML_DRAWING_CT = "application/vnd.openxmlformats-officedocument.vmlDrawing"
93
+
82
94
  # table content type
83
95
  TABLE_CT = "application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml"
84
96
 
@@ -109,6 +121,9 @@ module Axlsx
109
121
  # chart content type
110
122
  CHART_CT = "application/vnd.openxmlformats-officedocument.drawingml.chart+xml"
111
123
 
124
+ # comments content type
125
+ COMMENT_CT = "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml"
126
+
112
127
  # jpeg content type
113
128
  JPEG_CT = "image/jpeg"
114
129
 
@@ -172,6 +187,9 @@ module Axlsx
172
187
  # drawing rels part
173
188
  DRAWING_RELS_PN = "drawings/_rels/drawing%d.xml.rels"
174
189
 
190
+ # vml drawing part
191
+ VML_DRAWING_PN = "drawings/vmlDrawing%d.vml"
192
+
175
193
  # drawing part
176
194
  TABLE_PN = "tables/table%d.xml"
177
195
 
@@ -181,6 +199,9 @@ module Axlsx
181
199
  # chart part
182
200
  IMAGE_PN = "media/image%d.%s"
183
201
 
202
+ # comment part
203
+ COMMENT_PN = "comments%d.xml"
204
+
184
205
  # location of schema files for validation
185
206
  SCHEMA_BASE = File.dirname(__FILE__)+'/../../schema/'
186
207
 
@@ -240,4 +261,7 @@ module Axlsx
240
261
 
241
262
  # error message for invalid angles
242
263
  ERR_ANGLE = "Angles must be a value between -90 and 90. You provided: %s"
264
+
265
+ # error message for non 'integerish' value
266
+ ERR_INTEGERISH = "You value must be, or be castable via to_i, an Integer. You provided %s"
243
267
  end
@@ -45,8 +45,20 @@ module Axlsx
45
45
  true
46
46
  end
47
47
 
48
+
49
+ # Requires that the value can be converted to an integer
50
+ # @para, [Any] v the value to validate
51
+ # @raise [ArgumentError] raised if the value cannot be converted to an integer
52
+ def self.validate_integerish(v)
53
+ raise ArgumentError, (ERR_INTEGERISH % v.inspect) unless (v.respond_to?(:to_i) && v.to_i.is_a?(Integer))
54
+ end
55
+
56
+ # Requires that the value is between -54000000 and 54000000
57
+ # @param [Any] v The value validated
58
+ # @raise [ArgumentError] raised if the value cannot be converted to an integer between the allowed angle values for chart label rotation.
59
+ # @return [Boolean] true if the data is valid
48
60
  def self.validate_angle(v)
49
- raise ArgumentError, (ERR_ANGLE % v.inspect) unless (v >= -5400000 && v <= 5400000)
61
+ raise ArgumentError, (ERR_ANGLE % v.inspect) unless (v.to_i >= -5400000 && v.to_i <= 5400000)
50
62
  end
51
63
  # Requires that the value is a Fixnum or Integer and is greater or equal to 0
52
64
  # @param [Any] v The value validated
@@ -90,6 +102,22 @@ module Axlsx
90
102
  DataTypeValidator.validate :float, Float, v
91
103
  end
92
104
 
105
+ # Requires that the value is a string containing a positive decimal number followed by one of the following units:
106
+ # "mm", "cm", "in", "pt", "pc", "pi"
107
+ def self.validate_number_with_unit(v)
108
+ RegexValidator.validate "number_with_unit", /\A[0-9]+(\.[0-9]+)?(mm|cm|in|pt|pc|pi)\Z/, v
109
+ end
110
+
111
+ # Requires that the value is an integer ranging from 10 to 400.
112
+ def self.validate_page_scale(v)
113
+ DataTypeValidator.validate "page_scale", [Fixnum, Integer], v, lambda { |arg| arg >= 10 && arg <= 400 }
114
+ end
115
+
116
+ # Requires that the value is one of :default, :landscape, or :portrait.
117
+ def self.validate_page_orientation(v)
118
+ RestrictionValidator.validate "page_orientation", [:default, :landscape, :portrait], v
119
+ end
120
+
93
121
  # Requires that the value is valid pattern type.
94
122
  # valid pattern types must be one of :none, :solid, :mediumGray, :darkGray, :lightGray, :darkHorizontal, :darkVertical, :darkDown,
95
123
  # :darkUp, :darkGrid, :darkTrellis, :lightHorizontal, :lightVertical, :lightDown, :lightUp, :lightGrid, :lightTrellis, :gray125, or :gray0625.
@@ -169,17 +197,17 @@ module Axlsx
169
197
  end
170
198
 
171
199
  # Requires that the value is a valid content_type
172
- # TABLE_CT, WORKBOOK_CT, APP_CT, RELS_CT, STYLES_CT, XML_CT, WORKSHEET_CT, SHARED_STRINGS_CT, CORE_CT, CHART_CT, DRAWING_CT are allowed
200
+ # TABLE_CT, WORKBOOK_CT, APP_CT, RELS_CT, STYLES_CT, XML_CT, WORKSHEET_CT, SHARED_STRINGS_CT, CORE_CT, CHART_CT, DRAWING_CT, COMMENT_CT are allowed
173
201
  # @param [Any] v The value validated
174
202
  def self.validate_content_type(v)
175
- RestrictionValidator.validate :content_type, [TABLE_CT, WORKBOOK_CT, APP_CT, RELS_CT, STYLES_CT, XML_CT, WORKSHEET_CT, SHARED_STRINGS_CT, CORE_CT, CHART_CT, JPEG_CT, GIF_CT, PNG_CT, DRAWING_CT], v
203
+ RestrictionValidator.validate :content_type, [TABLE_CT, WORKBOOK_CT, APP_CT, RELS_CT, STYLES_CT, XML_CT, WORKSHEET_CT, SHARED_STRINGS_CT, CORE_CT, CHART_CT, JPEG_CT, GIF_CT, PNG_CT, DRAWING_CT, COMMENT_CT, VML_DRAWING_CT], v
176
204
  end
177
205
 
178
206
  # Requires that the value is a valid relationship_type
179
207
  # XML_NS_R, TABLE_R, WORKBOOK_R, WORKSHEET_R, APP_R, RELS_R, CORE_R, STYLES_R, CHART_R, DRAWING_R, IMAGE_R, HYPERLINK_R, SHARED_STRINGS_R are allowed
180
208
  # @param [Any] v The value validated
181
209
  def self.validate_relationship_type(v)
182
- RestrictionValidator.validate :relationship_type, [XML_NS_R, TABLE_R, WORKBOOK_R, WORKSHEET_R, APP_R, RELS_R, CORE_R, STYLES_R, CHART_R, DRAWING_R, IMAGE_R, HYPERLINK_R, SHARED_STRINGS_R], v
210
+ RestrictionValidator.validate :relationship_type, [XML_NS_R, TABLE_R, WORKBOOK_R, WORKSHEET_R, APP_R, RELS_R, CORE_R, STYLES_R, CHART_R, DRAWING_R, IMAGE_R, HYPERLINK_R, SHARED_STRINGS_R, COMMENT_R, VML_DRAWING_R, COMMENT_R_NULL], v
183
211
  end
184
212
 
185
213
  # Requires that the value is a valid table element type
@@ -5,6 +5,6 @@ module Axlsx
5
5
  # When using bunle exec rake and referencing the gem on github or locally
6
6
  # it will use the gemspec, which preloads this constant for the gem's version.
7
7
  # We check to make sure that it has not already been loaded
8
- VERSION="1.1.4" unless defined? Axlsx::VERSION
8
+ VERSION="1.1.5" unless defined? Axlsx::VERSION
9
9
 
10
10
  end
@@ -4,6 +4,8 @@ module Axlsx
4
4
  require 'axlsx/workbook/worksheet/date_time_converter.rb'
5
5
  require 'axlsx/workbook/worksheet/cell.rb'
6
6
  require 'axlsx/workbook/worksheet/page_margins.rb'
7
+ require 'axlsx/workbook/worksheet/page_setup.rb'
8
+ require 'axlsx/workbook/worksheet/print_options.rb'
7
9
  require 'axlsx/workbook/worksheet/cfvo.rb'
8
10
  require 'axlsx/workbook/worksheet/color_scale.rb'
9
11
  require 'axlsx/workbook/worksheet/data_bar.rb'
@@ -12,6 +14,8 @@ require 'axlsx/workbook/worksheet/conditional_formatting.rb'
12
14
  require 'axlsx/workbook/worksheet/conditional_formatting_rule.rb'
13
15
  require 'axlsx/workbook/worksheet/row.rb'
14
16
  require 'axlsx/workbook/worksheet/col.rb'
17
+ require 'axlsx/workbook/worksheet/comments.rb'
18
+ require 'axlsx/workbook/worksheet/comment.rb'
15
19
  require 'axlsx/workbook/worksheet/worksheet.rb'
16
20
  require 'axlsx/workbook/shared_strings_table.rb'
17
21
  require 'axlsx/workbook/worksheet/table.rb'
@@ -82,6 +86,9 @@ require 'axlsx/workbook/worksheet/table.rb'
82
86
  # @return [SimpleTypedList]
83
87
  attr_reader :drawings
84
88
 
89
+ # pretty sure this two are always empty and can be removed.
90
+
91
+
85
92
  # A colllection of tables associated with this workbook
86
93
  # @note The recommended way to manage drawings is Worksheet#add_table
87
94
  # @see Worksheet#add_table
@@ -90,6 +97,15 @@ require 'axlsx/workbook/worksheet/table.rb'
90
97
  attr_reader :tables
91
98
 
92
99
 
100
+ # A colllection of comments associated with this workbook
101
+ # @note The recommended way to manage comments is Worksheet#add_comment
102
+ # @see Worksheet#add_comment
103
+ # @see Comment
104
+ # @return [Comments]
105
+ def comments
106
+ self.worksheets.map { |ws| ws.comments }.compact
107
+ end
108
+
93
109
  # The styles associated with this workbook
94
110
  # @note The recommended way to manage styles is Styles#add_style
95
111
  # @see Style#add_style
@@ -123,7 +139,12 @@ require 'axlsx/workbook/worksheet/table.rb'
123
139
  @drawings = SimpleTypedList.new Drawing
124
140
  @charts = SimpleTypedList.new Chart
125
141
  @images = SimpleTypedList.new Pic
142
+
143
+ # Are these even used????? Check package serialization parts
126
144
  @tables = SimpleTypedList.new Table
145
+ @comments = SimpleTypedList.new Comments
146
+
147
+
127
148
  @use_autowidth = true
128
149
 
129
150
  self.date1904= !options[:date1904].nil? && options[:date1904]
@@ -288,13 +288,15 @@ module Axlsx
288
288
  # @param [String] str The string index the cell content will be appended to. Defaults to empty string.
289
289
  # @return [String] xml text for the cell
290
290
  def to_xml_string(r_index, c_index, str = '')
291
- return str if @value.nil?
292
291
  str << '<c r="' << Axlsx::cell_r(c_index, r_index) << '" s="' << @style.to_s << '" '
292
+ return str << '/>' if @value.nil?
293
+
293
294
  case @type
295
+
294
296
  when :string
295
297
  #parse formula
296
298
  if @value.start_with?('=')
297
- str << 't="str"><f>' << @value.to_s.gsub('=', '') << '</f>'
299
+ str << 't="str"><f>' << @value.to_s.sub('=', '') << '</f>'
298
300
  else
299
301
  #parse shared
300
302
  if @ssti
@@ -0,0 +1,107 @@
1
+ module Axlsx
2
+
3
+ # A comment is the text data for a comment
4
+ class Comment
5
+
6
+ # The text to render
7
+ # @return [String]
8
+ attr_reader :text
9
+
10
+ # The author of this comment
11
+ # @see Comments
12
+ # @return [String]
13
+ attr_reader :author
14
+
15
+ # The owning Comments object
16
+ # @return [Comments]
17
+ attr_reader :comments
18
+
19
+
20
+ # The string based cell position reference (e.g. 'A1') that determines the positioning of this comment
21
+ # @return [String]
22
+ attr_reader :ref
23
+
24
+ # TODO
25
+ # r (Rich Text Run)
26
+ # rPh (Phonetic Text Run)
27
+ # phoneticPr (Phonetic Properties)
28
+
29
+ def initialize(comments, options={})
30
+ raise ArgumentError, "A comment needs a parent comments object" unless comments.is_a?(Comments)
31
+ @comments = comments
32
+ options.each do |o|
33
+ self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
34
+ end
35
+ yield self if block_given?
36
+ end
37
+
38
+ # The vml shape that will render this comment
39
+ # @return [VmlShape]
40
+ def vml_shape
41
+ @vml_shape ||= initialize_vml_shape
42
+ end
43
+
44
+ # The index of this comment
45
+ # @return [Integer]
46
+ def index
47
+ @comments.index(self)
48
+ end
49
+
50
+ #
51
+ # The index of this author in a unique sorted list of all authors in
52
+ # the comment.
53
+ # @return [Integer]
54
+ def author_index
55
+ @comments.authors.index(author)
56
+ end
57
+
58
+ # @see ref
59
+ def ref=(v)
60
+ Axlsx::DataTypeValidator.validate "Comment.ref", [String, Cell], v
61
+ @ref = v if v.is_a?(String)
62
+ @ref = v.r if v.is_a?(Cell)
63
+ end
64
+
65
+ # @see text
66
+ def text=(v)
67
+ Axlsx::validate_string(v)
68
+ @text = v
69
+ end
70
+
71
+ # @see author
72
+ def author=(v)
73
+ @author = v
74
+ end
75
+
76
+ # serialize the object
77
+ # @param [String] str
78
+ # @return [String]
79
+ def to_xml_string(str = "")
80
+ author = @comments.authors[author_index]
81
+ str << '<comment ref="' << ref << '" authorId="' << author_index.to_s << '">'
82
+ str << '<text><r>'
83
+ str << '<rPr> <b/><color indexed="81"/></rPr>'
84
+ str << '<t>' << author.to_s << ':
85
+ </t></r>'
86
+ str << '<r>'
87
+ str << '<rPr><color indexed="81"/></rPr>'
88
+ str << '<t>' << text << '</t></r></text>'
89
+ str << '</comment>'
90
+ end
91
+
92
+ private
93
+
94
+ # initialize the vml shape based on this comment's ref/position in the worksheet.
95
+ # by default, all columns are 5 columns wide and 5 rows high
96
+ def initialize_vml_shape
97
+ pos = Axlsx::name_to_indices(ref)
98
+ @vml_shape = VmlShape.new(:row => pos[1], :column => pos[0]) do |vml|
99
+ vml.left_column = vml.row + 1
100
+ vml.right_column = vml.column + 4
101
+ vml.top_row = vml.row
102
+ vml.bottom_row = vml.row + 4
103
+ end
104
+ end
105
+
106
+ end
107
+ end