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
@@ -14,7 +14,7 @@ module Axlsx
14
14
  # @see Break
15
15
  def add_break(options)
16
16
  # force feed the excel default
17
- @list << Break.new(options.merge(:max => 16383, :man => true))
17
+ self << Break.new(options.merge(:max => 16383, :man => true))
18
18
  last
19
19
  end
20
20
 
@@ -25,7 +25,7 @@ module Axlsx
25
25
  # </rowBreaks>
26
26
  def to_xml_string(str='')
27
27
  return if empty?
28
- str << '<rowBreaks count="' << @list.size.to_s << '" manualBreakCount="' << @list.size.to_s << '">'
28
+ str << ('<rowBreaks count="' << self.size.to_s << '" manualBreakCount="' << self.size.to_s << '">')
29
29
  each { |brk| brk.to_xml_string(str) }
30
30
  str << '</rowBreaks>'
31
31
  end
@@ -95,9 +95,7 @@ module Axlsx
95
95
  # @param [String] str
96
96
  # @return [String]
97
97
  def to_xml_string(str = '')
98
- str << '<selection '
99
- serialized_attributes str
100
- str << '/>'
98
+ serialized_tag 'selection', str
101
99
  end
102
100
  end
103
101
  end
@@ -17,7 +17,9 @@ module Axlsx
17
17
  # @return [String]
18
18
  def to_xml_string(str = '')
19
19
  str << '<sheetData>'
20
- worksheet.rows.each_with_index{ |row, index| row.to_xml_string(index, str) }
20
+ worksheet.rows.each_with_index do |row, index|
21
+ row.to_xml_string(index, str)
22
+ end
21
23
  str << '</sheetData>'
22
24
  end
23
25
 
@@ -1,6 +1,6 @@
1
1
  module Axlsx
2
2
 
3
- # The SheetPr class manages serialization fo a worksheet's sheetPr element.
3
+ # The SheetPr class manages serialization of a worksheet's sheetPr element.
4
4
  class SheetPr
5
5
  include Axlsx::OptionsParser
6
6
  include Axlsx::Accessors
@@ -8,7 +8,7 @@ module Axlsx
8
8
 
9
9
  serializable_attributes :sync_horizontal,
10
10
  :sync_vertical,
11
- :transtion_evaluation,
11
+ :transition_evaluation,
12
12
  :transition_entry,
13
13
  :published,
14
14
  :filter_mode,
@@ -20,7 +20,7 @@ module Axlsx
20
20
  # waving magic show to set up the attriubte accessors
21
21
  boolean_attr_accessor :sync_horizontal,
22
22
  :sync_vertical,
23
- :transtion_evaluation,
23
+ :transition_evaluation,
24
24
  :transition_entry,
25
25
  :published,
26
26
  :filter_mode,
@@ -33,6 +33,7 @@ module Axlsx
33
33
  def initialize(worksheet, options={})
34
34
  raise ArgumentError, "you must provide a worksheet" unless worksheet.is_a?(Worksheet)
35
35
  @worksheet = worksheet
36
+ @outline_pr = nil
36
37
  parse_options options
37
38
  end
38
39
 
@@ -40,12 +41,18 @@ module Axlsx
40
41
  # @return [Worksheet]
41
42
  attr_reader :worksheet
42
43
 
44
+ # The tab color of the sheet.
45
+ # @return [Color]
46
+ attr_reader :tab_color
47
+
43
48
  # Serialize the object
44
49
  # @param [String] str serialized output will be appended to this object if provided.
45
50
  # @return [String]
46
51
  def to_xml_string(str = '')
47
52
  update_properties
48
53
  str << "<sheetPr #{serialized_attributes}>"
54
+ tab_color.to_xml_string(str, 'tabColor') if tab_color
55
+ outline_pr.to_xml_string(str) if @outline_pr
49
56
  page_setup_pr.to_xml_string(str)
50
57
  str << "</sheetPr>"
51
58
  end
@@ -55,6 +62,17 @@ module Axlsx
55
62
  def page_setup_pr
56
63
  @page_setup_pr ||= PageSetUpPr.new
57
64
  end
65
+
66
+ # The OutlinePr for this sheet pr object
67
+ # @return [OutlinePr]
68
+ def outline_pr
69
+ @outline_pr ||= OutlinePr.new
70
+ end
71
+
72
+ # @see tab_color
73
+ def tab_color=(v)
74
+ @tab_color ||= Color.new(:rgb => v)
75
+ end
58
76
 
59
77
  private
60
78
 
@@ -76,9 +76,7 @@ module Axlsx
76
76
  # @param [String] str
77
77
  # @return [String]
78
78
  def to_xml_string(str = '')
79
- str << '<sheetProtection '
80
- serialized_attributes str
81
- str << '/>'
79
+ serialized_tag('sheetProtection', str)
82
80
  end
83
81
 
84
82
  private
@@ -58,7 +58,7 @@ module Axlsx
58
58
  # @param [String, Cell] v
59
59
  # @return [Title]
60
60
  def name=(v)
61
- DataTypeValidator.validate "#{self.class}.name", [String], v
61
+ DataTypeValidator.validate :table_name, [String], v
62
62
  if v.is_a?(String)
63
63
  @name = v
64
64
  end
@@ -75,12 +75,12 @@ module Axlsx
75
75
  # @return [String]
76
76
  def to_xml_string(str = '')
77
77
  str << '<?xml version="1.0" encoding="UTF-8"?>'
78
- str << '<table xmlns="' << XML_NS << '" id="' << (index+1).to_s << '" name="' << @name << '" displayName="' << @name.gsub(/\s/,'_') << '" '
79
- str << 'ref="' << @ref << '" totalsRowShown="0">'
80
- str << '<autoFilter ref="' << @ref << '"/>'
81
- str << '<tableColumns count="' << header_cells.length.to_s << '">'
78
+ str << ('<table xmlns="' << XML_NS << '" id="' << (index+1).to_s << '" name="' << @name << '" displayName="' << @name.gsub(/\s/,'_') << '" ')
79
+ str << ('ref="' << @ref << '" totalsRowShown="0">')
80
+ str << ('<autoFilter ref="' << @ref << '"/>')
81
+ str << ('<tableColumns count="' << header_cells.length.to_s << '">')
82
82
  header_cells.each_with_index do |cell,index|
83
- str << '<tableColumn id ="' << (index+1).to_s << '" name="' << cell.value << '"/>'
83
+ str << ('<tableColumn id ="' << (index+1).to_s << '" name="' << cell.value << '"/>')
84
84
  end
85
85
  str << '</tableColumns>'
86
86
  table_style_info.to_xml_string(str)
@@ -43,9 +43,7 @@ module Axlsx
43
43
  # seralizes this object to an xml string
44
44
  # @param [String] str the string to contact this objects serialization to.
45
45
  def to_xml_string(str = '')
46
- str << '<tableStyleInfo '
47
- serialized_attributes str
48
- str << '/>'
46
+ serialized_tag('tableStyleInfo', str)
49
47
  end
50
48
  end
51
49
  end
@@ -20,10 +20,13 @@ module Axlsx
20
20
  map{ |table| Relationship.new(table, TABLE_R, "../#{table.pn}") }
21
21
  end
22
22
 
23
+ # renders the tables xml
24
+ # @param [String] str
25
+ # @return [String]
23
26
  def to_xml_string(str = "")
24
27
  return if empty?
25
28
  str << "<tableParts count='#{size}'>"
26
- @list.each { |table| str << "<tablePart r:id='#{table.rId}'/>" }
29
+ each { |table| str << "<tablePart r:id='#{table.rId}'/>" }
27
30
  str << '</tableParts>'
28
31
  end
29
32
  end
@@ -4,14 +4,7 @@ module Axlsx
4
4
  # The Worksheet class represents a worksheet in the workbook.
5
5
  class Worksheet
6
6
  include Axlsx::OptionsParser
7
-
8
- # definition of characters which are less than the maximum width of 0-9 in the default font for use in String#count.
9
- # This is used for autowidth calculations
10
- # @return [String]
11
- def self.thin_chars
12
- # removed 'e' and 'y' from this list - as a GUESS
13
- @thin_chars ||= "^.acfijklrstxzFIJL()-"
14
- end
7
+ include Axlsx::SerializedAttributes
15
8
 
16
9
  # Creates a new worksheet.
17
10
  # @note the recommended way to manage worksheets is Workbook#add_worksheet
@@ -24,12 +17,15 @@ module Axlsx
24
17
  def initialize(wb, options={})
25
18
  self.workbook = wb
26
19
  @sheet_protection = nil
27
-
28
20
  initialize_page_options(options)
29
21
  parse_options options
30
22
  @workbook.worksheets << self
23
+ @sheet_id = index + 1
24
+ yield self if block_given?
31
25
  end
32
26
 
27
+ serializable_attributes :sheet_id, :state
28
+
33
29
  # Initalizes page margin, setup and print options
34
30
  # @param [Hash] options Options passed in from the initializer
35
31
  def initialize_page_options(options)
@@ -44,7 +40,23 @@ module Axlsx
44
40
  # The name of the worksheet
45
41
  # @return [String]
46
42
  def name
47
- @name ||= "Sheet" + (index+1).to_s
43
+ @name ||= "Sheet" + (index+1).to_s
44
+ end
45
+
46
+ # Specifies the visible state of this sheet. Allowed states are
47
+ # :visible, :hidden or :very_hidden. The default value is :visible.
48
+ #
49
+ # Worksheets in the :hidden state can be shown using the sheet formatting properties in excel.
50
+ # :very_hidden sheets should be inaccessible to end users.
51
+ # @param [Symbol] sheet_state The visible state for this sheet.
52
+ def state=(sheet_state)
53
+ RestrictionValidator.validate :worksheet_state, [:visible, :hidden, :very_hidden], sheet_state
54
+ @state = sheet_state
55
+ end
56
+
57
+ # The visibility of this sheet
58
+ def state
59
+ @state ||= :visible
48
60
  end
49
61
 
50
62
  # The sheet calculation properties
@@ -76,7 +88,7 @@ module Axlsx
76
88
  # @see [SheetFormatPr]
77
89
  def sheet_format_pr
78
90
  @sheet_format_pr ||= SheetFormatPr.new
79
- yeild @sheet_format_pr if block_given?
91
+ yield @sheet_format_pr if block_given?
80
92
  @sheet_format_pr
81
93
  end
82
94
 
@@ -129,7 +141,7 @@ module Axlsx
129
141
  # @return [SimpleTypedList]
130
142
  # @see Worksheet#add_row
131
143
  def rows
132
- @rows ||= SimpleTypedList.new Row
144
+ @rows ||= SimpleTypedList.new Row
133
145
  end
134
146
 
135
147
  # returns the sheet data as columns
@@ -137,12 +149,12 @@ module Axlsx
137
149
  # cell at a specific index. The block will be called with the row and column
138
150
  # index in the missing cell was found.
139
151
  # @example
140
- # cols { |row_index, column_index| p "warn - row #{row_index} is does not have a cell at #{column_index}
152
+ # cols { |row_index, column_index| puts "warn - row #{row_index} does not have a cell at #{column_index}" }
141
153
  def cols(&block)
142
154
  @rows.transpose(&block)
143
155
  end
144
156
 
145
- # An range that excel will apply an auto-filter to "A1:B3"
157
+ # A range that excel will apply an auto-filter to "A1:B3"
146
158
  # This will turn filtering on for the cells in the range.
147
159
  # The first row is considered the header, while subsequent rows are considered to be data.
148
160
  # @return String
@@ -249,7 +261,7 @@ module Axlsx
249
261
  @header_footer
250
262
  end
251
263
 
252
- # convinience method to access all cells in this worksheet
264
+ # convenience method to access all cells in this worksheet
253
265
  # @return [Array] cells
254
266
  def cells
255
267
  rows.flatten
@@ -290,50 +302,6 @@ module Axlsx
290
302
  @sheet_pr ||= SheetPr.new self
291
303
  end
292
304
 
293
- # Indicates if gridlines should be shown in the sheet.
294
- # This is true by default.
295
- # @return [Boolean]
296
- # @deprecated Use SheetView#show_grid_lines= instead.
297
- def show_gridlines=(v)
298
- warn('axlsx::DEPRECIATED: Worksheet#show_gridlines= has been depreciated. This value can be set over SheetView#show_grid_lines=.')
299
- Axlsx::validate_boolean v
300
- sheet_view.show_grid_lines = v
301
- end
302
-
303
- # @see selected
304
- # @return [Boolean]
305
- # @deprecated Use SheetView#tab_selected= instead.
306
- def selected=(v)
307
- warn('axlsx::DEPRECIATED: Worksheet#selected= has been depreciated. This value can be set over SheetView#tab_selected=.')
308
- Axlsx::validate_boolean v
309
- sheet_view.tab_selected = v
310
- end
311
-
312
- # Indicates if the worksheet should show gridlines or not
313
- # @return Boolean
314
- # @deprecated Use SheetView#show_grid_lines instead.
315
- def show_gridlines
316
- warn('axlsx::DEPRECIATED: Worksheet#show_gridlines has been depreciated. This value can get over SheetView#show_grid_lines.')
317
- sheet_view.show_grid_lines
318
- end
319
-
320
- # Indicates if the worksheet is selected in the workbook
321
- # It is possible to have more than one worksheet selected, however it might cause issues
322
- # in some older versions of excel when using copy and paste.
323
- # @return Boolean
324
- # @deprecated Use SheetView#tab_selected instead.
325
- def selected
326
- warn('axlsx::DEPRECIATED: Worksheet#selected has been depreciated. This value can get over SheetView#tab_selected.')
327
- sheet_view.tab_selected
328
- end
329
-
330
- # (see #fit_to_page)
331
- # @return [Boolean]
332
- def fit_to_page=(v)
333
- warn('axlsx::DEPRECIATED: Worksheet#fit_to_page has been depreciated. This value will automatically be set for you when you use PageSetup#fit_to.')
334
- fit_to_page?
335
- end
336
-
337
305
  # The name of the worksheet
338
306
  # The name of a worksheet must be unique in the workbook, and must not exceed 31 characters
339
307
  # @param [String] name
@@ -346,7 +314,7 @@ module Axlsx
346
314
  # @param [String] v
347
315
  # @see auto_filter
348
316
  def auto_filter=(v)
349
- DataTypeValidator.validate "Worksheet.auto_filter", String, v
317
+ DataTypeValidator.validate :worksheet_auto_filter, String, v
350
318
  auto_filter.range = v
351
319
  end
352
320
 
@@ -419,6 +387,12 @@ module Axlsx
419
387
  # @example - use << alias
420
388
  # ws << [3, 4, 5], :types => [nil, :float]
421
389
  #
390
+ # @example - specify whether a row should escape formulas or not
391
+ # ws.add_row ['=IF(2+2=4,4,5)', 2, 3], :escape_formulas=>true
392
+ #
393
+ # @example - specify whether a certain cells in a row should escape formulas or not
394
+ # ws.add_row ['=IF(2+2=4,4,5)', '=IF(13+13=4,4,5)'], :escape_formulas=>[true, false]
395
+ #
422
396
  # @see Worksheet#column_widths
423
397
  # @return [Row]
424
398
  # @option options [Array] values
@@ -426,11 +400,15 @@ module Axlsx
426
400
  # @option options [Array, Integer] style
427
401
  # @option options [Array] widths each member of the widths array will affect how auto_fit behavies.
428
402
  # @option options [Float] height the row's height (in points)
403
+ # @option options [Array, Boolean] escape_formulas - Whether to treat a value starting with an equal
404
+ # sign as formula (default) or as simple string.
405
+ # Allowing user generated data to be interpreted as formulas can be dangerous
406
+ # (see https://www.owasp.org/index.php/CSV_Injection for details).
429
407
  def add_row(values=[], options={})
430
- Row.new(self, values, options)
431
- update_column_info @rows.last.cells, options.delete(:widths) || []
432
- yield @rows.last if block_given?
433
- @rows.last
408
+ row = Row.new(self, values, options)
409
+ update_column_info row, options.delete(:widths)
410
+ yield row if block_given?
411
+ row
434
412
  end
435
413
 
436
414
  alias :<< :add_row
@@ -522,7 +500,7 @@ module Axlsx
522
500
  # @example
523
501
  # ws.add_page_break("A4")
524
502
  def add_page_break(cell)
525
- DataTypeValidator.validate "Worksheet#add_page_break cell", [String, Cell], cell
503
+ DataTypeValidator.validate :worksheet_page_break, [String, Cell], cell
526
504
  column_index, row_index = if cell.is_a?(String)
527
505
  Axlsx.name_to_indices(cell)
528
506
  else
@@ -535,12 +513,12 @@ module Axlsx
535
513
  end
536
514
 
537
515
  # This is a helper method that Lets you specify a fixed width for multiple columns in a worksheet in one go.
538
- # Axlsx is sparse, so if you have not set data for a column, you cannot set the width.
516
+ # Note that you must call column_widths AFTER adding data, otherwise the width will not be set successfully.
539
517
  # Setting a fixed column width to nil will revert the behaviour back to calculating the width for you on the next call to add_row.
540
518
  # @example This would set the first and third column widhts but leave the second column in autofit state.
541
519
  # ws.column_widths 7.2, nil, 3
542
520
  # @note For updating only a single column it is probably easier to just set the width of the ws.column_info[col_index].width directly
543
- # @param [Integer|Float|Fixnum|nil] widths
521
+ # @param [Integer|Float|nil] widths
544
522
  def column_widths(*widths)
545
523
  widths.each_with_index do |value, index|
546
524
  next if value == nil
@@ -559,7 +537,7 @@ module Axlsx
559
537
  # @see README.md for an example
560
538
  def col_style(index, style, options={})
561
539
  offset = options.delete(:row_offset) || 0
562
- cells = @rows[(offset..-1)].map { |row| row.cells[index] }.flatten.compact
540
+ cells = @rows[(offset..-1)].map { |row| row[index] }.flatten.compact
563
541
  cells.each { |cell| cell.style = style }
564
542
  end
565
543
 
@@ -577,18 +555,27 @@ module Axlsx
577
555
  cells.each { |cell| cell.style = style }
578
556
  end
579
557
 
558
+ # Returns a sheet node serialization for this sheet in the workbook.
559
+ def to_sheet_node_xml_string(str='')
560
+ add_autofilter_defined_name_to_workbook
561
+ str << '<sheet '
562
+ serialized_attributes str
563
+ str << ('name="' << name << '" ')
564
+ str << ('r:id="' << rId << '"></sheet>')
565
+ end
566
+
580
567
  # Serializes the worksheet object to an xml string
581
568
  # This intentionally does not use nokogiri for performance reasons
582
569
  # @return [String]
583
- def to_xml_string
570
+ def to_xml_string str=''
571
+ add_autofilter_defined_name_to_workbook
584
572
  auto_filter.apply if auto_filter.range
585
- str = '<?xml version="1.0" encoding="UTF-8"?>'
573
+ str << '<?xml version="1.0" encoding="UTF-8"?>'
586
574
  str << worksheet_node
587
575
  serializable_parts.each do |item|
588
576
  item.to_xml_string(str) if item
589
577
  end
590
578
  str << '</worksheet>'
591
- Axlsx::sanitize(str)
592
579
  end
593
580
 
594
581
  # The worksheet relationships. This is managed automatically by the worksheet
@@ -606,7 +593,7 @@ module Axlsx
606
593
  # Returns the cell or cells defined using excel style A1:B3 references.
607
594
  # @param [String|Integer] cell_def the string defining the cell or range of cells, or the rownumber
608
595
  # @return [Cell, Array]
609
- def [] (cell_def)
596
+ def [](cell_def)
610
597
  return rows[cell_def] if cell_def.is_a?(Integer)
611
598
  parts = cell_def.split(':').map{ |part| name_to_cell part }
612
599
  if parts.size == 1
@@ -622,7 +609,7 @@ module Axlsx
622
609
  def name_to_cell(name)
623
610
  col_index, row_index = *Axlsx::name_to_indices(name)
624
611
  r = rows[row_index]
625
- r.cells[col_index] if r
612
+ r[col_index] if r
626
613
  end
627
614
 
628
615
  # shortcut method to access styles direclty from the worksheet
@@ -675,8 +662,10 @@ module Axlsx
675
662
  end
676
663
 
677
664
  def validate_sheet_name(name)
678
- DataTypeValidator.validate "Worksheet.name", String, name
679
- raise ArgumentError, (ERR_SHEET_NAME_TOO_LONG % name) if name.size > 31
665
+ DataTypeValidator.validate :worksheet_name, String, name
666
+ # ignore first character (BOM) after encoding to utf16 because Excel does so, too.
667
+ character_length = name.encode("utf-16")[1..-1].encode("utf-16").bytesize / 2
668
+ raise ArgumentError, (ERR_SHEET_NAME_TOO_LONG % name) if character_length > 31
680
669
  raise ArgumentError, (ERR_SHEET_NAME_CHARACTER_FORBIDDEN % name) if '[]*/\?:'.chars.any? { |char| name.include? char }
681
670
  name = Axlsx::coder.encode(name)
682
671
  sheet_names = @workbook.worksheets.reject { |s| s == self }.map { |s| s.name }
@@ -695,8 +684,8 @@ module Axlsx
695
684
  def range(*cell_def)
696
685
  first, last = cell_def
697
686
  cells = []
698
- rows[(first.row.index..last.row.index)].each do |r|
699
- r.cells[(first.index..last.index)].each do |c|
687
+ rows[(first.row.row_index..last.row.row_index)].each do |r|
688
+ r[(first.index..last.index)].each do |c|
700
689
  cells << c
701
690
  end
702
691
  end
@@ -734,7 +723,7 @@ module Axlsx
734
723
  # Helper method for parsingout the root node for worksheet
735
724
  # @return [String]
736
725
  def worksheet_node
737
- "<worksheet xmlns=\"%s\" xmlns:r=\"%s\" xml:space=\"#{xml_space}\">" % [XML_NS, XML_NS_R]
726
+ "<worksheet xmlns=\"#{XML_NS}\" xmlns:r=\"#{XML_NS_R}\" xml:space=\"#{xml_space}\">"
738
727
  end
739
728
 
740
729
  def sheet_data
@@ -753,11 +742,12 @@ module Axlsx
753
742
 
754
743
  def workbook=(v) DataTypeValidator.validate "Worksheet.workbook", Workbook, v; @workbook = v; end
755
744
 
756
- def update_column_info(cells, widths=[])
745
+ def update_column_info(cells, widths=nil)
757
746
  cells.each_with_index do |cell, index|
747
+ width = widths ? widths[index] : nil
758
748
  col = find_or_create_column_info(index)
759
- next if widths[index] == :ignore
760
- col.update_width(cell, widths[index], workbook.use_autowidth)
749
+ next if width == :ignore
750
+ col.update_width(cell, width, workbook.use_autowidth)
761
751
  end
762
752
  end
763
753
 
@@ -765,5 +755,10 @@ module Axlsx
765
755
  column_info[index] ||= Col.new(index + 1, index + 1)
766
756
  end
767
757
 
758
+ def add_autofilter_defined_name_to_workbook
759
+ return if !auto_filter.range
760
+ workbook.add_defined_name auto_filter.defined_name, name: '_xlnm._FilterDatabase', local_sheet_id: index, hidden: 1
761
+ end
762
+
768
763
  end
769
764
  end