caxlsx 2.0.2 → 3.0.4

Sign up to get free protection for your applications and to get access to all the features.
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
-