caxlsx 2.0.2 → 3.0.4

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 (210) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +125 -30
  3. data/README.md +65 -151
  4. data/Rakefile +9 -11
  5. data/examples/{image1.jpeg → assets/image1.jpeg} +0 -0
  6. data/examples/generate.rb +15 -0
  7. data/lib/axlsx.rb +35 -17
  8. data/lib/axlsx/content_type/abstract_content_type.rb +1 -1
  9. data/lib/axlsx/content_type/content_type.rb +1 -1
  10. data/lib/axlsx/doc_props/app.rb +1 -1
  11. data/lib/axlsx/doc_props/core.rb +5 -5
  12. data/lib/axlsx/drawing/area_chart.rb +99 -0
  13. data/lib/axlsx/drawing/area_series.rb +110 -0
  14. data/lib/axlsx/drawing/axes.rb +1 -1
  15. data/lib/axlsx/drawing/axis.rb +12 -9
  16. data/lib/axlsx/drawing/bar_3D_chart.rb +13 -13
  17. data/lib/axlsx/drawing/bar_chart.rb +143 -0
  18. data/lib/axlsx/drawing/bar_series.rb +12 -14
  19. data/lib/axlsx/drawing/bubble_chart.rb +59 -0
  20. data/lib/axlsx/drawing/bubble_series.rb +63 -0
  21. data/lib/axlsx/drawing/cat_axis.rb +5 -5
  22. data/lib/axlsx/drawing/chart.rb +52 -8
  23. data/lib/axlsx/drawing/d_lbls.rb +4 -4
  24. data/lib/axlsx/drawing/drawing.rb +6 -1
  25. data/lib/axlsx/drawing/graphic_frame.rb +3 -3
  26. data/lib/axlsx/drawing/hyperlink.rb +1 -3
  27. data/lib/axlsx/drawing/line_3D_chart.rb +2 -2
  28. data/lib/axlsx/drawing/line_chart.rb +10 -10
  29. data/lib/axlsx/drawing/line_series.rb +32 -3
  30. data/lib/axlsx/drawing/marker.rb +1 -1
  31. data/lib/axlsx/drawing/num_data.rb +4 -4
  32. data/lib/axlsx/drawing/num_data_source.rb +6 -6
  33. data/lib/axlsx/drawing/num_val.rb +3 -1
  34. data/lib/axlsx/drawing/one_cell_anchor.rb +3 -2
  35. data/lib/axlsx/drawing/pic.rb +25 -19
  36. data/lib/axlsx/drawing/picture_locking.rb +1 -3
  37. data/lib/axlsx/drawing/pie_3D_chart.rb +5 -6
  38. data/lib/axlsx/drawing/pie_series.rb +6 -6
  39. data/lib/axlsx/drawing/scaling.rb +6 -6
  40. data/lib/axlsx/drawing/scatter_chart.rb +10 -10
  41. data/lib/axlsx/drawing/scatter_series.rb +40 -7
  42. data/lib/axlsx/drawing/ser_axis.rb +2 -2
  43. data/lib/axlsx/drawing/series.rb +3 -3
  44. data/lib/axlsx/drawing/series_title.rb +4 -2
  45. data/lib/axlsx/drawing/str_data.rb +3 -3
  46. data/lib/axlsx/drawing/str_val.rb +3 -1
  47. data/lib/axlsx/drawing/title.rb +23 -4
  48. data/lib/axlsx/drawing/two_cell_anchor.rb +6 -1
  49. data/lib/axlsx/drawing/val_axis.rb +1 -1
  50. data/lib/axlsx/drawing/view_3D.rb +2 -2
  51. data/lib/axlsx/drawing/vml_drawing.rb +1 -1
  52. data/lib/axlsx/package.rb +58 -47
  53. data/lib/axlsx/rels/relationship.rb +27 -26
  54. data/lib/axlsx/rels/relationships.rb +7 -4
  55. data/lib/axlsx/stylesheet/border_pr.rb +2 -2
  56. data/lib/axlsx/stylesheet/cell_alignment.rb +1 -3
  57. data/lib/axlsx/stylesheet/cell_protection.rb +1 -3
  58. data/lib/axlsx/stylesheet/cell_style.rb +1 -3
  59. data/lib/axlsx/stylesheet/color.rb +1 -3
  60. data/lib/axlsx/stylesheet/font.rb +11 -3
  61. data/lib/axlsx/stylesheet/gradient_stop.rb +1 -1
  62. data/lib/axlsx/stylesheet/num_fmt.rb +10 -3
  63. data/lib/axlsx/stylesheet/pattern_fill.rb +1 -1
  64. data/lib/axlsx/stylesheet/styles.rb +7 -7
  65. data/lib/axlsx/stylesheet/table_style_element.rb +1 -3
  66. data/lib/axlsx/util/accessors.rb +6 -6
  67. data/lib/axlsx/util/constants.rb +108 -99
  68. data/lib/axlsx/util/mime_type_utils.rb +11 -0
  69. data/lib/axlsx/util/options_parser.rb +2 -1
  70. data/lib/axlsx/util/serialized_attributes.rb +16 -6
  71. data/lib/axlsx/util/simple_typed_list.rb +28 -52
  72. data/lib/axlsx/util/storage.rb +4 -4
  73. data/lib/axlsx/util/validators.rb +31 -19
  74. data/lib/axlsx/util/zip_command.rb +73 -0
  75. data/lib/axlsx/version.rb +1 -1
  76. data/lib/axlsx/workbook/defined_name.rb +11 -12
  77. data/lib/axlsx/workbook/defined_names.rb +2 -2
  78. data/lib/axlsx/workbook/shared_strings_table.rb +5 -5
  79. data/lib/axlsx/workbook/workbook.rb +36 -20
  80. data/lib/axlsx/workbook/workbook_view.rb +80 -0
  81. data/lib/axlsx/workbook/workbook_views.rb +22 -0
  82. data/lib/axlsx/workbook/worksheet/auto_filter/auto_filter.rb +2 -2
  83. data/lib/axlsx/workbook/worksheet/auto_filter/filters.rb +1 -3
  84. data/lib/axlsx/workbook/worksheet/break.rb +1 -3
  85. data/lib/axlsx/workbook/worksheet/cell.rb +164 -75
  86. data/lib/axlsx/workbook/worksheet/cell_serializer.rb +63 -43
  87. data/lib/axlsx/workbook/worksheet/cfvo.rb +1 -3
  88. data/lib/axlsx/workbook/worksheet/cfvos.rb +4 -1
  89. data/lib/axlsx/workbook/worksheet/col.rb +14 -13
  90. data/lib/axlsx/workbook/worksheet/col_breaks.rb +2 -2
  91. data/lib/axlsx/workbook/worksheet/cols.rb +5 -2
  92. data/lib/axlsx/workbook/worksheet/comment.rb +5 -6
  93. data/lib/axlsx/workbook/worksheet/comments.rb +9 -12
  94. data/lib/axlsx/workbook/worksheet/conditional_formatting.rb +1 -1
  95. data/lib/axlsx/workbook/worksheet/conditional_formatting_rule.rb +1 -1
  96. data/lib/axlsx/workbook/worksheet/data_bar.rb +4 -6
  97. data/lib/axlsx/workbook/worksheet/data_validation.rb +8 -6
  98. data/lib/axlsx/workbook/worksheet/dimension.rb +2 -2
  99. data/lib/axlsx/workbook/worksheet/header_footer.rb +6 -8
  100. data/lib/axlsx/workbook/worksheet/icon_set.rb +3 -5
  101. data/lib/axlsx/workbook/worksheet/merged_cells.rb +4 -2
  102. data/lib/axlsx/workbook/worksheet/outline_pr.rb +33 -0
  103. data/lib/axlsx/workbook/worksheet/page_margins.rb +1 -3
  104. data/lib/axlsx/workbook/worksheet/page_set_up_pr.rb +1 -1
  105. data/lib/axlsx/workbook/worksheet/page_setup.rb +21 -23
  106. data/lib/axlsx/workbook/worksheet/pane.rb +1 -3
  107. data/lib/axlsx/workbook/worksheet/pivot_table.rb +44 -28
  108. data/lib/axlsx/workbook/worksheet/pivot_table_cache_definition.rb +4 -4
  109. data/lib/axlsx/workbook/worksheet/print_options.rb +1 -3
  110. data/lib/axlsx/workbook/worksheet/protected_range.rb +1 -3
  111. data/lib/axlsx/workbook/worksheet/protected_ranges.rb +5 -2
  112. data/lib/axlsx/workbook/worksheet/rich_text.rb +55 -0
  113. data/lib/axlsx/workbook/worksheet/rich_text_run.rb +250 -0
  114. data/lib/axlsx/workbook/worksheet/row.rb +42 -52
  115. data/lib/axlsx/workbook/worksheet/row_breaks.rb +2 -2
  116. data/lib/axlsx/workbook/worksheet/selection.rb +1 -3
  117. data/lib/axlsx/workbook/worksheet/sheet_data.rb +3 -1
  118. data/lib/axlsx/workbook/worksheet/sheet_pr.rb +21 -3
  119. data/lib/axlsx/workbook/worksheet/sheet_protection.rb +1 -3
  120. data/lib/axlsx/workbook/worksheet/table.rb +6 -6
  121. data/lib/axlsx/workbook/worksheet/table_style_info.rb +1 -3
  122. data/lib/axlsx/workbook/worksheet/tables.rb +4 -1
  123. data/lib/axlsx/workbook/worksheet/worksheet.rb +76 -81
  124. data/lib/axlsx/workbook/worksheet/worksheet_drawing.rb +10 -10
  125. data/lib/axlsx/workbook/worksheet/worksheet_hyperlinks.rb +3 -3
  126. data/lib/caxlsx.rb +2 -0
  127. data/test/drawing/tc_area_chart.rb +39 -0
  128. data/test/drawing/tc_area_series.rb +71 -0
  129. data/test/drawing/tc_axis.rb +27 -0
  130. data/test/drawing/tc_bar_chart.rb +71 -0
  131. data/test/drawing/tc_bubble_chart.rb +44 -0
  132. data/test/drawing/tc_bubble_series.rb +21 -0
  133. data/test/drawing/tc_chart.rb +23 -10
  134. data/test/drawing/tc_data_source.rb +6 -0
  135. data/test/drawing/tc_drawing.rb +4 -4
  136. data/test/drawing/tc_hyperlink.rb +1 -1
  137. data/test/drawing/tc_line_chart.rb +5 -5
  138. data/test/drawing/tc_line_series.rb +47 -6
  139. data/test/drawing/tc_one_cell_anchor.rb +1 -1
  140. data/test/drawing/tc_pic.rb +11 -15
  141. data/test/drawing/tc_pie_series.rb +2 -1
  142. data/test/drawing/tc_scatter_series.rb +36 -1
  143. data/test/drawing/tc_series_title.rb +21 -0
  144. data/test/drawing/tc_str_val.rb +9 -0
  145. data/test/drawing/tc_title.rb +21 -0
  146. data/test/fixtures/image1.gif +0 -0
  147. data/test/fixtures/image1.jpeg +0 -0
  148. data/test/fixtures/image1.jpg +0 -0
  149. data/test/fixtures/image1.png +0 -0
  150. data/test/fixtures/image1_fake.jpg +0 -0
  151. data/test/rels/tc_relationship.rb +8 -0
  152. data/test/stylesheet/tc_font.rb +14 -2
  153. data/test/stylesheet/tc_styles.rb +29 -3
  154. data/test/tc_axlsx.rb +37 -0
  155. data/test/tc_helper.rb +2 -0
  156. data/test/tc_package.rb +50 -13
  157. data/test/util/tc_mime_type_utils.rb +13 -0
  158. data/test/util/tc_simple_typed_list.rb +2 -3
  159. data/test/util/tc_validators.rb +35 -11
  160. data/test/workbook/tc_defined_name.rb +12 -4
  161. data/test/workbook/tc_shared_strings_table.rb +16 -1
  162. data/test/workbook/tc_workbook.rb +38 -3
  163. data/test/workbook/tc_workbook_view.rb +50 -0
  164. data/test/workbook/worksheet/auto_filter/tc_filters.rb +1 -1
  165. data/test/workbook/worksheet/tc_break.rb +1 -1
  166. data/test/workbook/worksheet/tc_cell.rb +143 -9
  167. data/test/workbook/worksheet/tc_col.rb +18 -3
  168. data/test/workbook/worksheet/tc_conditional_formatting.rb +2 -2
  169. data/test/workbook/worksheet/tc_data_bar.rb +1 -1
  170. data/test/workbook/worksheet/tc_data_validation.rb +11 -11
  171. data/test/workbook/worksheet/tc_header_footer.rb +2 -2
  172. data/test/workbook/worksheet/tc_icon_set.rb +1 -1
  173. data/test/workbook/worksheet/tc_outline_pr.rb +19 -0
  174. data/test/workbook/worksheet/tc_page_setup.rb +3 -3
  175. data/test/workbook/worksheet/tc_pivot_table.rb +21 -6
  176. data/test/workbook/worksheet/tc_print_options.rb +1 -1
  177. data/test/workbook/worksheet/tc_rich_text.rb +44 -0
  178. data/test/workbook/worksheet/tc_rich_text_run.rb +173 -0
  179. data/test/workbook/worksheet/tc_row.rb +24 -2
  180. data/test/workbook/worksheet/tc_sheet_calc_pr.rb +1 -1
  181. data/test/workbook/worksheet/tc_sheet_format_pr.rb +4 -4
  182. data/test/workbook/worksheet/tc_sheet_pr.rb +26 -4
  183. data/test/workbook/worksheet/tc_sheet_protection.rb +5 -5
  184. data/test/workbook/worksheet/tc_sheet_view.rb +4 -4
  185. data/test/workbook/worksheet/tc_table.rb +2 -3
  186. data/test/workbook/worksheet/tc_worksheet.rb +123 -60
  187. metadata +180 -128
  188. data/examples/2010_comments.rb +0 -17
  189. data/examples/anchor_swapping.rb +0 -28
  190. data/examples/auto_filter.rb +0 -16
  191. data/examples/basic_charts.rb +0 -58
  192. data/examples/chart_colors.rb +0 -88
  193. data/examples/colored_links.rb +0 -59
  194. data/examples/conditional_formatting/example_conditional_formatting.rb +0 -74
  195. data/examples/conditional_formatting/getting_barred.rb +0 -37
  196. data/examples/conditional_formatting/hitting_the_high_notes.rb +0 -37
  197. data/examples/conditional_formatting/scaled_colors.rb +0 -39
  198. data/examples/conditional_formatting/stop_and_go.rb +0 -37
  199. data/examples/data_validation.rb +0 -50
  200. data/examples/example.rb +0 -777
  201. data/examples/extractive.rb +0 -45
  202. data/examples/ios_preview.rb +0 -14
  203. data/examples/page_setup.rb +0 -11
  204. data/examples/pivot_table.rb +0 -39
  205. data/examples/sheet_protection.rb +0 -10
  206. data/examples/skydrive/real_example.rb +0 -63
  207. data/examples/styles.rb +0 -66
  208. data/examples/underline.rb +0 -13
  209. data/examples/wrap_text.rb +0 -21
  210. data/lib/axlsx/util/parser.rb +0 -44
@@ -6,7 +6,7 @@ module Axlsx
6
6
  include Axlsx::OptionsParser
7
7
 
8
8
  # creates a new Scaling object
9
- # @option options [Integer, Fixnum] logBase
9
+ # @option options [Integer] logBase
10
10
  # @option options [Symbol] orientation
11
11
  # @option options [Float] max
12
12
  # @option options [Float] min
@@ -35,7 +35,7 @@ module Axlsx
35
35
  attr_reader :min
36
36
 
37
37
  # @see logBase
38
- def logBase=(v) DataTypeValidator.validate "Scaling.logBase", [Integer, Fixnum], v, lambda { |arg| arg >= 2 && arg <= 1000}; @logBase = v; end
38
+ def logBase=(v) DataTypeValidator.validate "Scaling.logBase", [Integer], v, lambda { |arg| arg >= 2 && arg <= 1000}; @logBase = v; end
39
39
  # @see orientation
40
40
  def orientation=(v) RestrictionValidator.validate "Scaling.orientation", [:minMax, :maxMin], v; @orientation = v; end
41
41
  # @see max
@@ -49,10 +49,10 @@ module Axlsx
49
49
  # @return [String]
50
50
  def to_xml_string(str = '')
51
51
  str << '<c:scaling>'
52
- str << '<c:logBase val="' << @logBase.to_s << '"/>' unless @logBase.nil?
53
- str << '<c:orientation val="' << @orientation.to_s << '"/>' unless @orientation.nil?
54
- str << '<c:min val="' << @min.to_s << '"/>' unless @min.nil?
55
- str << '<c:max val="' << @max.to_s << '"/>' unless @max.nil?
52
+ str << ('<c:logBase val="' << @logBase.to_s << '"/>') unless @logBase.nil?
53
+ str << ('<c:orientation val="' << @orientation.to_s << '"/>') unless @orientation.nil?
54
+ str << ('<c:min val="' << @min.to_s << '"/>') unless @min.nil?
55
+ str << ('<c:max val="' << @max.to_s << '"/>') unless @max.nil?
56
56
  str << '</c:scaling>'
57
57
  end
58
58
 
@@ -25,7 +25,7 @@ module Axlsx
25
25
  # the y value axis
26
26
  # @return [ValAxis]
27
27
  def y_val_axis
28
- axes[:x_val_axis]
28
+ axes[:y_val_axis]
29
29
  end
30
30
  alias :yValAxis :y_val_axis
31
31
 
@@ -51,15 +51,15 @@ module Axlsx
51
51
  # @param [String] str
52
52
  # @return [String]
53
53
  def to_xml_string(str = '')
54
- super(str) do |str_inner|
55
- str_inner << '<c:scatterChart>'
56
- str_inner << '<c:scatterStyle val="' << scatter_style.to_s << '"/>'
57
- str_inner << '<c:varyColors val="' << vary_colors.to_s << '"/>'
58
- @series.each { |ser| ser.to_xml_string(str_inner) }
59
- d_lbls.to_xml_string(str_inner) if @d_lbls
60
- axes.to_xml_string(str_inner, :ids => true)
61
- str_inner << '</c:scatterChart>'
62
- axes.to_xml_string(str_inner)
54
+ super(str) do
55
+ str << '<c:scatterChart>'
56
+ str << ('<c:scatterStyle val="' << scatter_style.to_s << '"/>')
57
+ str << ('<c:varyColors val="' << vary_colors.to_s << '"/>')
58
+ @series.each { |ser| ser.to_xml_string(str) }
59
+ d_lbls.to_xml_string(str) if @d_lbls
60
+ axes.to_xml_string(str, :ids => true)
61
+ str << '</c:scatterChart>'
62
+ axes.to_xml_string(str)
63
63
  end
64
64
  str
65
65
  end
@@ -21,9 +21,25 @@ module Axlsx
21
21
  # @return [String]
22
22
  attr_reader :color
23
23
 
24
+ # @return [String]
25
+ attr_reader :ln_width
26
+
27
+ # Line smoothing between data points
28
+ # @return [Boolean]
29
+ attr_reader :smooth
30
+
24
31
  # Creates a new ScatterSeries
25
32
  def initialize(chart, options={})
26
33
  @xData, @yData = nil
34
+ if options[:smooth].nil?
35
+ # If caller hasn't specified smoothing or not, turn smoothing on or off based on scatter style
36
+ @smooth = [:smooth, :smoothMarker].include?(chart.scatter_style)
37
+ else
38
+ # Set smoothing according to the option provided
39
+ Axlsx::validate_boolean(options[:smooth])
40
+ @smooth = options[:smooth]
41
+ end
42
+ @ln_width = options[:ln_width] unless options[:ln_width].nil?
27
43
  super(chart, options)
28
44
  @xData = AxDataSource.new(:tag_name => :xVal, :data => options[:xData]) unless options[:xData].nil?
29
45
  @yData = NumDataSource.new({:tag_name => :yVal, :data => options[:yData]}) unless options[:yData].nil?
@@ -34,30 +50,47 @@ module Axlsx
34
50
  @color = v
35
51
  end
36
52
 
53
+ # @see smooth
54
+ def smooth=(v)
55
+ Axlsx::validate_boolean(v)
56
+ @smooth = v
57
+ end
58
+
59
+ # @see ln_width
60
+ def ln_width=(v)
61
+ @ln_width = v
62
+ end
63
+
37
64
  # Serializes the object
38
65
  # @param [String] str
39
66
  # @return [String]
40
67
  def to_xml_string(str = '')
41
- super(str) do |inner_str|
68
+ super(str) do
42
69
  # needs to override the super color here to push in ln/and something else!
43
70
  if color
44
71
  str << '<c:spPr><a:solidFill>'
45
- str << '<a:srgbClr val="' << color << '"/>'
72
+ str << ('<a:srgbClr val="' << color << '"/>')
46
73
  str << '</a:solidFill>'
47
74
  str << '<a:ln><a:solidFill>'
48
- str << '<a:srgbClr val="' << color << '"/></a:solidFill></a:ln>'
75
+ str << ('<a:srgbClr val="' << color << '"/></a:solidFill></a:ln>')
49
76
  str << '</c:spPr>'
50
77
  str << '<c:marker>'
51
78
  str << '<c:spPr><a:solidFill>'
52
- str << '<a:srgbClr val="' << color << '"/>'
79
+ str << ('<a:srgbClr val="' << color << '"/>')
53
80
  str << '</a:solidFill>'
54
81
  str << '<a:ln><a:solidFill>'
55
- str << '<a:srgbClr val="' << color << '"/></a:solidFill></a:ln>'
82
+ str << ('<a:srgbClr val="' << color << '"/></a:solidFill></a:ln>')
56
83
  str << '</c:spPr>'
57
84
  str << '</c:marker>'
58
85
  end
59
- @xData.to_xml_string(inner_str) unless @xData.nil?
60
- @yData.to_xml_string(inner_str) unless @yData.nil?
86
+ if ln_width
87
+ str << '<c:spPr>'
88
+ str << '<a:ln w="' << ln_width.to_s << '"/>'
89
+ str << '</c:spPr>'
90
+ end
91
+ @xData.to_xml_string(str) unless @xData.nil?
92
+ @yData.to_xml_string(str) unless @yData.nil?
93
+ str << ('<c:smooth val="' << ((smooth) ? '1' : '0') << '"/>')
61
94
  end
62
95
  str
63
96
  end
@@ -35,8 +35,8 @@ module Axlsx
35
35
  def to_xml_string(str = '')
36
36
  str << '<c:serAx>'
37
37
  super(str)
38
- str << '<c:tickLblSkip val="' << @tick_lbl_skip.to_s << '"/>' unless @tick_lbl_skip.nil?
39
- str << '<c:tickMarkSkip val="' << @tick_mark_skip.to_s << '"/>' unless @tick_mark_skip.nil?
38
+ str << ('<c:tickLblSkip val="' << @tick_lbl_skip.to_s << '"/>') unless @tick_lbl_skip.nil?
39
+ str << ('<c:tickMarkSkip val="' << @tick_mark_skip.to_s << '"/>') unless @tick_mark_skip.nil?
40
40
  str << '</c:serAx>'
41
41
  end
42
42
  end
@@ -59,10 +59,10 @@ module Axlsx
59
59
  # @return [String]
60
60
  def to_xml_string(str = '')
61
61
  str << '<c:ser>'
62
- str << '<c:idx val="' << index.to_s << '"/>'
63
- str << '<c:order val="' << (order || index).to_s << '"/>'
62
+ str << ('<c:idx val="' << index.to_s << '"/>')
63
+ str << ('<c:order val="' << (order || index).to_s << '"/>')
64
64
  title.to_xml_string(str) unless title.nil?
65
- yield str if block_given?
65
+ yield if block_given?
66
66
  str << '</c:ser>'
67
67
  end
68
68
  end
@@ -7,13 +7,15 @@ module Axlsx
7
7
  # @param [String] str
8
8
  # @return [String]
9
9
  def to_xml_string(str = '')
10
+ clean_value = Axlsx::trust_input ? @text.to_s : ::CGI.escapeHTML(Axlsx::sanitize(@text.to_s))
11
+
10
12
  str << '<c:tx>'
11
13
  str << '<c:strRef>'
12
- str << '<c:f>' << Axlsx::cell_range([@cell]) << '</c:f>'
14
+ str << ('<c:f>' << Axlsx::cell_range([@cell]) << '</c:f>')
13
15
  str << '<c:strCache>'
14
16
  str << '<c:ptCount val="1"/>'
15
17
  str << '<c:pt idx="0">'
16
- str << '<c:v>' << @text << '</c:v>'
18
+ str << ('<c:v>' << clean_value << '</c:v>')
17
19
  str << '</c:pt>'
18
20
  str << '</c:strCache>'
19
21
  str << '</c:strRef>'
@@ -29,12 +29,12 @@ module Axlsx
29
29
 
30
30
  # serialize the object
31
31
  def to_xml_string(str = "")
32
- str << '<c:' << @tag_name.to_s << '>'
33
- str << '<c:ptCount val="' << @pt.size.to_s << '"/>'
32
+ str << ('<c:' << @tag_name.to_s << '>')
33
+ str << ('<c:ptCount val="' << @pt.size.to_s << '"/>')
34
34
  @pt.each_with_index do |value, index|
35
35
  value.to_xml_string index, str
36
36
  end
37
- str << '</c:' << @tag_name.to_s << '>'
37
+ str << ('</c:' << @tag_name.to_s << '>')
38
38
  end
39
39
 
40
40
  end
@@ -26,7 +26,9 @@ module Axlsx
26
26
  # serialize the object
27
27
  def to_xml_string(idx, str = "")
28
28
  Axlsx::validate_unsigned_int(idx)
29
- str << '<c:pt idx="' << idx.to_s << '"><c:v>' << v.to_s << '</c:v></c:pt>'
29
+ if !v.to_s.empty?
30
+ str << ('<c:pt idx="' << idx.to_s << '"><c:v>' << ::CGI.escapeHTML(v.to_s) << '</c:v></c:pt>')
31
+ end
30
32
  end
31
33
  end
32
34
  end
@@ -7,15 +7,24 @@ module Axlsx
7
7
  # @return [String]
8
8
  attr_reader :text
9
9
 
10
+ # Text size property
11
+ # @return [String]
12
+ attr_reader :text_size
13
+
10
14
  # The cell that holds the text for the title. Setting this property will automatically update the text attribute.
11
15
  # @return [Cell]
12
16
  attr_reader :cell
13
17
 
14
18
  # Creates a new Title object
15
19
  # @param [String, Cell] title The cell or string to be used for the chart's title
16
- def initialize(title="")
20
+ def initialize(title="", title_size="")
17
21
  self.cell = title if title.is_a?(Cell)
18
22
  self.text = title.to_s unless title.is_a?(Cell)
23
+ if title_size.to_s.empty?
24
+ self.text_size = "1600"
25
+ else
26
+ self.text_size = title_size.to_s
27
+ end
19
28
  end
20
29
 
21
30
  # @see text
@@ -26,6 +35,14 @@ module Axlsx
26
35
  v
27
36
  end
28
37
 
38
+ # @see text_size
39
+ def text_size=(v)
40
+ DataTypeValidator.validate 'Title.text_size', String, v
41
+ @text_size = v
42
+ @cell = nil
43
+ v
44
+ end
45
+
29
46
  # @see cell
30
47
  def cell=(v)
31
48
  DataTypeValidator.validate 'Title.text', Cell, v
@@ -45,14 +62,15 @@ module Axlsx
45
62
  def to_xml_string(str = '')
46
63
  str << '<c:title>'
47
64
  unless @text.empty?
65
+ clean_value = Axlsx::trust_input ? @text.to_s : ::CGI.escapeHTML(Axlsx::sanitize(@text.to_s))
48
66
  str << '<c:tx>'
49
67
  if @cell.is_a?(Cell)
50
68
  str << '<c:strRef>'
51
- str << '<c:f>' << Axlsx::cell_range([@cell]) << '</c:f>'
69
+ str << ('<c:f>' << Axlsx::cell_range([@cell]) << '</c:f>')
52
70
  str << '<c:strCache>'
53
71
  str << '<c:ptCount val="1"/>'
54
72
  str << '<c:pt idx="0">'
55
- str << '<c:v>' << @text << '</c:v>'
73
+ str << ('<c:v>' << clean_value << '</c:v>')
56
74
  str << '</c:pt>'
57
75
  str << '</c:strCache>'
58
76
  str << '</c:strRef>'
@@ -62,7 +80,8 @@ module Axlsx
62
80
  str << '<a:lstStyle/>'
63
81
  str << '<a:p>'
64
82
  str << '<a:r>'
65
- str << '<a:t>' << @text.to_s << '</a:t>'
83
+ str << ('<a:rPr sz="' << @text_size.to_s << '"/>')
84
+ str << ('<a:t>' << clean_value << '</a:t>')
66
85
  str << '</a:r>'
67
86
  str << '</a:p>'
68
87
  str << '</c:rich>'
@@ -37,11 +37,16 @@ module Axlsx
37
37
  drawing.anchors << self
38
38
  @from, @to = Marker.new, Marker.new(:col => 5, :row=>10)
39
39
  parse_options options
40
+
41
+ # bit of a hack to work around the fact that the coords for start at and end at
42
+ # are passed in as an array when specified in intialization options - however
43
+ start_at(*options[:start_at]) if options[:start_at]
44
+ end_at(*options[:end_at]) if options[:end_at]
40
45
  end
41
46
 
42
47
  # sets the col, row attributes for the from marker.
43
48
  # @note The recommended way to set the start position for graphical
44
- # objects is directly thru the object.
49
+ # objects is directly thru the object.
45
50
  # @see Chart#start_at
46
51
  def start_at(x, y=nil)
47
52
  from.coord x, y
@@ -29,7 +29,7 @@ module Axlsx
29
29
  def to_xml_string(str = '')
30
30
  str << '<c:valAx>'
31
31
  super(str)
32
- str << '<c:crossBetween val="' << @cross_between.to_s << '"/>'
32
+ str << ('<c:crossBetween val="' << @cross_between.to_s << '"/>')
33
33
  str << '</c:valAx>'
34
34
  end
35
35
 
@@ -86,12 +86,12 @@ module Axlsx
86
86
  alias :rAngAx= :r_ang_ax=
87
87
 
88
88
  # @see perspective
89
- def perspective=(v)
89
+ def perspective=(v)
90
90
  RangeValidator.validate "View3D.perspective", 0, 240, v
91
91
  @perspective = v
92
92
  end
93
93
 
94
- # DataTypeValidator.validate "#{self.class}.perspective", [Integer, Fixnum], v, lambda {|arg| arg >= 0 && arg <= 240 }; @perspective = v; end
94
+ # DataTypeValidator.validate "#{self.class}.perspective", [Integer], v, lambda {|arg| arg >= 0 && arg <= 240 }; @perspective = v; end
95
95
 
96
96
  # Serializes the object
97
97
  # @param [String] str
@@ -20,7 +20,7 @@ module Axlsx
20
20
  # @param [String] str
21
21
  # @return [String]
22
22
  def to_xml_string(str = '')
23
- str = <<BAD_PROGRAMMER
23
+ str << <<BAD_PROGRAMMER
24
24
  <xml xmlns:v="urn:schemas-microsoft-com:vml"
25
25
  xmlns:o="urn:schemas-microsoft-com:office:office"
26
26
  xmlns:x="urn:schemas-microsoft-com:office:excel">
@@ -1,7 +1,7 @@
1
- # encoding: UTF-8
1
+ # encoding: utf-8
2
2
  module Axlsx
3
3
  # Package is responsible for managing all the bits and peices that Open Office XML requires to make a valid
4
- # xlsx document including valdation and serialization.
4
+ # xlsx document including validation and serialization.
5
5
  class Package
6
6
  include Axlsx::OptionsParser
7
7
 
@@ -22,7 +22,7 @@ module Axlsx
22
22
  # @example Package.new :author => 'you!', :workbook => Workbook.new
23
23
  def initialize(options={})
24
24
  @workbook = nil
25
- @core, @app = Core.new, App.new
25
+ @core, @app = Core.new, App.new
26
26
  @core.creator = options[:author] || @core.creator
27
27
  @core.created = options[:created_at]
28
28
  parse_options options
@@ -68,20 +68,16 @@ module Axlsx
68
68
  @workbook
69
69
  end
70
70
 
71
- #def self.parse(input, confirm_valid = false)
72
- # p = Package.new
73
- # z = Zip::File.open(input)
74
- # p.workbook = Workbook.parse z.get_entry(WORKBOOK_PN)
75
- # p
76
- #end
77
-
78
71
  # @see workbook
79
- def workbook=(workbook) DataTypeValidator.validate "Package.workbook", Workbook, workbook; @workbook = workbook; end
72
+ def workbook=(workbook) DataTypeValidator.validate :Package_workbook, Workbook, workbook; @workbook = workbook; end
80
73
 
81
74
  # Serialize your workbook to disk as an xlsx document.
82
75
  #
83
76
  # @param [String] output The name of the file you want to serialize your package to
84
77
  # @param [Boolean] confirm_valid Validate the package prior to serialization.
78
+ # @param [String, nil] zip_command When `nil`, `#serialize` with RubyZip to
79
+ # zip the XLSX file contents. When a String, the provided zip command (e.g.,
80
+ # "zip") is used to zip the file contents (may be faster for large files)
85
81
  # @return [Boolean] False if confirm_valid and validation errors exist. True if the package was serialized
86
82
  # @note A tremendous amount of effort has gone into ensuring that you cannot create invalid xlsx documents.
87
83
  # confirm_valid should be used in the rare case that you cannot open the serialized file.
@@ -95,16 +91,28 @@ module Axlsx
95
91
  # # ......add cool stuff to your workbook......
96
92
  # p.serialize("example.xlsx")
97
93
  #
94
+ # # Serialize to a file, using a system zip binary
95
+ # p.serialize("example.xlsx", false, zip_command: "zip")
96
+ # p.serialize("example.xlsx", false, zip_command: "/path/to/zip")
97
+ # p.serialize("example.xlsx", false, zip_command: "zip -1")
98
+ #
98
99
  # # Serialize to a stream
99
100
  # s = p.to_stream()
100
101
  # File.open('example_streamed.xlsx', 'w') { |f| f.write(s.read) }
101
- def serialize(output, confirm_valid=false)
102
+ def serialize(output, confirm_valid=false, zip_command: nil)
102
103
  return false unless !confirm_valid || self.validate.empty?
103
- Relationship.clear_cached_instances
104
- Zip::OutputStream.open(output) do |zip|
104
+ zip_provider = if zip_command
105
+ ZipCommand.new(zip_command)
106
+ else
107
+ Zip::OutputStream
108
+ end
109
+ Relationship.initialize_ids_cache
110
+ zip_provider.open(output) do |zip|
105
111
  write_parts(zip)
106
112
  end
107
113
  true
114
+ ensure
115
+ Relationship.clear_ids_cache
108
116
  end
109
117
 
110
118
 
@@ -113,11 +121,13 @@ module Axlsx
113
121
  # @return [StringIO|Boolean] False if confirm_valid and validation errors exist. rewound string IO if not.
114
122
  def to_stream(confirm_valid=false)
115
123
  return false unless !confirm_valid || self.validate.empty?
116
- Relationship.clear_cached_instances
124
+ Relationship.initialize_ids_cache
117
125
  zip = write_parts(Zip::OutputStream.new(StringIO.new, true))
118
126
  stream = zip.close_buffer
119
127
  stream.rewind
120
128
  stream
129
+ ensure
130
+ Relationship.clear_ids_cache
121
131
  end
122
132
 
123
133
  # Encrypt the package into a CFB using the password provided
@@ -135,7 +145,7 @@ module Axlsx
135
145
  # dcterms and xml namespaces. Those remote schema are included in this gem, and the original files have been altered to
136
146
  # refer to the local versions.
137
147
  #
138
- # If by chance you are able to creat a package that does not validate it indicates that the internal
148
+ # If by chance you are able to create a package that does not validate it indicates that the internal
139
149
  # validation is not robust enough and needs to be improved. Please report your errors to the gem author.
140
150
  # @see http://www.ecma-international.org/publications/standards/Ecma-376.htm
141
151
  # @example
@@ -146,7 +156,9 @@ module Axlsx
146
156
  def validate
147
157
  errors = []
148
158
  parts.each do |part|
149
- errors.concat validate_single_doc(part[:schema], part[:doc]) unless part[:schema].nil?
159
+ unless part[:schema].nil?
160
+ errors.concat validate_single_doc(part[:schema], part[:doc].to_xml_string)
161
+ end
150
162
  end
151
163
  errors
152
164
  end
@@ -154,20 +166,18 @@ module Axlsx
154
166
  private
155
167
 
156
168
  # Writes the package parts to a zip archive.
157
- # @param [Zip::OutputStream] zip
158
- # @return [Zip::OutputStream]
169
+ # @param [Zip::OutputStream, ZipCommand] zip
170
+ # @return [Zip::OutputStream, ZipCommand]
159
171
  def write_parts(zip)
160
172
  p = parts
161
173
  p.each do |part|
162
174
  unless part[:doc].nil?
163
175
  zip.put_next_entry(zip_entry_for_part(part))
164
- entry = ['1.9.2', '1.9.3'].include?(RUBY_VERSION) ? part[:doc].force_encoding('BINARY') : part[:doc]
165
- zip.puts(entry)
176
+ part[:doc].to_xml_string(zip)
166
177
  end
167
178
  unless part[:path].nil?
168
179
  zip.put_next_entry(zip_entry_for_part(part))
169
- # binread for 1.9.3
170
- zip.write IO.respond_to?(:binread) ? IO.binread(part[:path]) : IO.read(part[:path])
180
+ zip.write IO.read(part[:path], mode: "rb")
171
181
  end
172
182
  end
173
183
  zip
@@ -194,40 +204,40 @@ module Axlsx
194
204
  # @private
195
205
  def parts
196
206
  parts = [
197
- {:entry => RELS_PN, :doc => relationships.to_xml_string, :schema => RELS_XSD},
198
- {:entry => "xl/#{STYLES_PN}", :doc => workbook.styles.to_xml_string, :schema => SML_XSD},
199
- {:entry => CORE_PN, :doc => @core.to_xml_string, :schema => CORE_XSD},
200
- {:entry => APP_PN, :doc => @app.to_xml_string, :schema => APP_XSD},
201
- {:entry => WORKBOOK_RELS_PN, :doc => workbook.relationships.to_xml_string, :schema => RELS_XSD},
202
- {:entry => CONTENT_TYPES_PN, :doc => content_types.to_xml_string, :schema => CONTENT_TYPES_XSD},
203
- {:entry => WORKBOOK_PN, :doc => workbook.to_xml_string, :schema => SML_XSD}
207
+ {:entry => RELS_PN, :doc => relationships, :schema => RELS_XSD},
208
+ {:entry => "xl/#{STYLES_PN}", :doc => workbook.styles, :schema => SML_XSD},
209
+ {:entry => CORE_PN, :doc => @core, :schema => CORE_XSD},
210
+ {:entry => APP_PN, :doc => @app, :schema => APP_XSD},
211
+ {:entry => WORKBOOK_RELS_PN, :doc => workbook.relationships, :schema => RELS_XSD},
212
+ {:entry => CONTENT_TYPES_PN, :doc => content_types, :schema => CONTENT_TYPES_XSD},
213
+ {:entry => WORKBOOK_PN, :doc => workbook, :schema => SML_XSD}
204
214
  ]
205
215
 
206
216
  workbook.drawings.each do |drawing|
207
- parts << {:entry => "xl/#{drawing.rels_pn}", :doc => drawing.relationships.to_xml_string, :schema => RELS_XSD}
208
- parts << {:entry => "xl/#{drawing.pn}", :doc => drawing.to_xml_string, :schema => DRAWING_XSD}
217
+ parts << {:entry => "xl/#{drawing.rels_pn}", :doc => drawing.relationships, :schema => RELS_XSD}
218
+ parts << {:entry => "xl/#{drawing.pn}", :doc => drawing, :schema => DRAWING_XSD}
209
219
  end
210
220
 
211
221
 
212
222
  workbook.tables.each do |table|
213
- parts << {:entry => "xl/#{table.pn}", :doc => table.to_xml_string, :schema => SML_XSD}
223
+ parts << {:entry => "xl/#{table.pn}", :doc => table, :schema => SML_XSD}
214
224
  end
215
225
  workbook.pivot_tables.each do |pivot_table|
216
226
  cache_definition = pivot_table.cache_definition
217
- parts << {:entry => "xl/#{pivot_table.rels_pn}", :doc => pivot_table.relationships.to_xml_string, :schema => RELS_XSD}
218
- parts << {:entry => "xl/#{pivot_table.pn}", :doc => pivot_table.to_xml_string} #, :schema => SML_XSD}
219
- parts << {:entry => "xl/#{cache_definition.pn}", :doc => cache_definition.to_xml_string} #, :schema => SML_XSD}
227
+ parts << {:entry => "xl/#{pivot_table.rels_pn}", :doc => pivot_table.relationships, :schema => RELS_XSD}
228
+ parts << {:entry => "xl/#{pivot_table.pn}", :doc => pivot_table} #, :schema => SML_XSD}
229
+ parts << {:entry => "xl/#{cache_definition.pn}", :doc => cache_definition} #, :schema => SML_XSD}
220
230
  end
221
231
 
222
232
  workbook.comments.each do|comment|
223
233
  if comment.size > 0
224
- parts << { :entry => "xl/#{comment.pn}", :doc => comment.to_xml_string, :schema => SML_XSD }
225
- parts << { :entry => "xl/#{comment.vml_drawing.pn}", :doc => comment.vml_drawing.to_xml_string, :schema => nil }
234
+ parts << { :entry => "xl/#{comment.pn}", :doc => comment, :schema => SML_XSD }
235
+ parts << { :entry => "xl/#{comment.vml_drawing.pn}", :doc => comment.vml_drawing, :schema => nil }
226
236
  end
227
237
  end
228
238
 
229
239
  workbook.charts.each do |chart|
230
- parts << {:entry => "xl/#{chart.pn}", :doc => chart.to_xml_string, :schema => DRAWING_XSD}
240
+ parts << {:entry => "xl/#{chart.pn}", :doc => chart, :schema => DRAWING_XSD}
231
241
  end
232
242
 
233
243
  workbook.images.each do |image|
@@ -235,14 +245,16 @@ module Axlsx
235
245
  end
236
246
 
237
247
  if use_shared_strings
238
- parts << {:entry => "xl/#{SHARED_STRINGS_PN}", :doc => workbook.shared_strings.to_xml_string, :schema => SML_XSD}
248
+ parts << {:entry => "xl/#{SHARED_STRINGS_PN}", :doc => workbook.shared_strings, :schema => SML_XSD}
239
249
  end
240
250
 
241
251
  workbook.worksheets.each do |sheet|
242
- parts << {:entry => "xl/#{sheet.rels_pn}", :doc => sheet.relationships.to_xml_string, :schema => RELS_XSD}
243
- parts << {:entry => "xl/#{sheet.pn}", :doc => sheet.to_xml_string, :schema => SML_XSD}
252
+ parts << {:entry => "xl/#{sheet.rels_pn}", :doc => sheet.relationships, :schema => RELS_XSD}
253
+ parts << {:entry => "xl/#{sheet.pn}", :doc => sheet, :schema => SML_XSD}
244
254
  end
245
- parts
255
+
256
+ # Sort parts for correct MIME detection
257
+ parts.sort_by { |part| part[:entry] }
246
258
  end
247
259
 
248
260
  # Performs xsd validation for a signle document
@@ -303,7 +315,7 @@ module Axlsx
303
315
  c_types << Axlsx::Override.new(:PartName => "/xl/#{sheet.pn}",
304
316
  :ContentType => WORKSHEET_CT)
305
317
  end
306
- exts = workbook.images.map { |image| image.extname }
318
+ exts = workbook.images.map { |image| image.extname.downcase }
307
319
  exts.uniq.each do |ext|
308
320
  ct = if ['jpeg', 'jpg'].include?(ext)
309
321
  JPEG_CT
@@ -326,8 +338,8 @@ module Axlsx
326
338
  # @private
327
339
  def base_content_types
328
340
  c_types = ContentType.new()
329
- c_types << Default.new(:ContentType => RELS_CT, :Extension => RELS_EX)
330
- c_types << Default.new(:Extension => XML_EX, :ContentType => XML_CT)
341
+ c_types << Default.new(:ContentType => RELS_CT, :Extension => RELS_EX)
342
+ c_types << Default.new(:Extension => XML_EX, :ContentType => XML_CT)
331
343
  c_types << Override.new(:PartName => "/#{APP_PN}", :ContentType => APP_CT)
332
344
  c_types << Override.new(:PartName => "/#{CORE_PN}", :ContentType => CORE_CT)
333
345
  c_types << Override.new(:PartName => "/xl/#{STYLES_PN}", :ContentType => STYLES_CT)
@@ -349,4 +361,3 @@ module Axlsx
349
361
  end
350
362
  end
351
363
  end
352
-