axlsx 1.1.0 → 1.2.0

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 (214) hide show
  1. data/.yardopts +5 -2
  2. data/CHANGELOG.md +78 -0
  3. data/LICENSE +1 -1
  4. data/README.md +132 -331
  5. data/Rakefile +17 -5
  6. data/examples/basic_charts.rb +54 -0
  7. data/examples/chart_colors.rb +88 -0
  8. data/examples/conditional_formatting/example_conditional_formatting.rb +72 -0
  9. data/examples/conditional_formatting/getting_barred.rb +37 -0
  10. data/examples/conditional_formatting/hitting_the_high_notes.rb +37 -0
  11. data/examples/conditional_formatting/scaled_colors.rb +39 -0
  12. data/examples/conditional_formatting/stop_and_go.rb +37 -0
  13. data/examples/data_validation.rb +50 -0
  14. data/examples/example.rb +300 -152
  15. data/examples/example.xlsx +0 -0
  16. data/examples/example_streamed.xlsx +0 -0
  17. data/examples/extractive.pdf +0 -0
  18. data/examples/extractive.rb +45 -0
  19. data/examples/no-use_autowidth.xlsx +0 -0
  20. data/examples/sample.png +0 -0
  21. data/examples/scraping_html.rb +91 -0
  22. data/examples/shared_strings_example.xlsx +0 -0
  23. data/examples/sheet_protection.rb +10 -0
  24. data/examples/sheet_view.rb +34 -0
  25. data/examples/skydrive/real_example.rb +63 -0
  26. data/examples/two_cell_anchor_image.rb +11 -0
  27. data/lib/axlsx/content_type/content_type.rb +2 -0
  28. data/lib/axlsx/content_type/default.rb +30 -15
  29. data/lib/axlsx/content_type/override.rb +29 -14
  30. data/lib/axlsx/doc_props/app.rb +161 -104
  31. data/lib/axlsx/doc_props/core.rb +9 -5
  32. data/lib/axlsx/drawing/ax_data_source.rb +26 -0
  33. data/lib/axlsx/drawing/axis.rb +106 -35
  34. data/lib/axlsx/drawing/bar_3D_chart.rb +49 -45
  35. data/lib/axlsx/drawing/bar_series.rb +25 -7
  36. data/lib/axlsx/drawing/cat_axis.rb +50 -22
  37. data/lib/axlsx/drawing/chart.rb +69 -56
  38. data/lib/axlsx/drawing/d_lbls.rb +100 -0
  39. data/lib/axlsx/drawing/drawing.rb +28 -12
  40. data/lib/axlsx/drawing/graphic_frame.rb +2 -1
  41. data/lib/axlsx/drawing/line_3D_chart.rb +3 -10
  42. data/lib/axlsx/drawing/line_series.rb +20 -4
  43. data/lib/axlsx/drawing/num_data.rb +52 -0
  44. data/lib/axlsx/drawing/num_data_source.rb +61 -0
  45. data/lib/axlsx/drawing/num_val.rb +32 -0
  46. data/lib/axlsx/drawing/pic.rb +44 -4
  47. data/lib/axlsx/drawing/pie_3D_chart.rb +10 -7
  48. data/lib/axlsx/drawing/pie_series.rb +18 -4
  49. data/lib/axlsx/drawing/scatter_chart.rb +12 -18
  50. data/lib/axlsx/drawing/scatter_series.rb +28 -2
  51. data/lib/axlsx/drawing/ser_axis.rb +1 -1
  52. data/lib/axlsx/drawing/series.rb +1 -1
  53. data/lib/axlsx/drawing/str_data.rb +42 -0
  54. data/lib/axlsx/drawing/str_val.rb +33 -0
  55. data/lib/axlsx/drawing/title.rb +21 -9
  56. data/lib/axlsx/drawing/two_cell_anchor.rb +46 -9
  57. data/lib/axlsx/drawing/view_3D.rb +44 -31
  58. data/lib/axlsx/drawing/vml_drawing.rb +42 -0
  59. data/lib/axlsx/drawing/vml_shape.rb +125 -0
  60. data/lib/axlsx/package.rb +44 -16
  61. data/lib/axlsx/rels/relationship.rb +3 -3
  62. data/lib/axlsx/rels/relationships.rb +1 -11
  63. data/lib/axlsx/stylesheet/color.rb +0 -1
  64. data/lib/axlsx/stylesheet/dxf.rb +79 -0
  65. data/lib/axlsx/stylesheet/font.rb +2 -1
  66. data/lib/axlsx/stylesheet/gradient_fill.rb +1 -1
  67. data/lib/axlsx/stylesheet/styles.rb +143 -50
  68. data/lib/axlsx/stylesheet/table_style.rb +3 -3
  69. data/lib/axlsx/stylesheet/xf.rb +2 -0
  70. data/lib/axlsx/util/constants.rb +36 -0
  71. data/lib/axlsx/util/simple_typed_list.rb +15 -21
  72. data/lib/axlsx/util/validators.rb +122 -5
  73. data/lib/axlsx/version.rb +2 -7
  74. data/lib/axlsx/workbook/defined_name.rb +174 -0
  75. data/lib/axlsx/workbook/defined_names.rb +21 -0
  76. data/lib/axlsx/workbook/shared_strings_table.rb +12 -13
  77. data/lib/axlsx/workbook/workbook.rb +71 -13
  78. data/lib/axlsx/workbook/worksheet/auto_filter.rb +34 -0
  79. data/lib/axlsx/workbook/worksheet/cell.rb +45 -36
  80. data/lib/axlsx/workbook/worksheet/cfvo.rb +62 -0
  81. data/lib/axlsx/workbook/worksheet/col.rb +17 -1
  82. data/lib/axlsx/workbook/worksheet/color_scale.rb +76 -0
  83. data/lib/axlsx/workbook/worksheet/cols.rb +20 -0
  84. data/lib/axlsx/workbook/worksheet/comment.rb +101 -0
  85. data/lib/axlsx/workbook/worksheet/comments.rb +85 -0
  86. data/lib/axlsx/workbook/worksheet/conditional_formatting.rb +82 -0
  87. data/lib/axlsx/workbook/worksheet/conditional_formatting_rule.rb +216 -0
  88. data/lib/axlsx/workbook/worksheet/conditional_formattings.rb +25 -0
  89. data/lib/axlsx/workbook/worksheet/data_bar.rb +97 -0
  90. data/lib/axlsx/workbook/worksheet/data_validation.rb +245 -0
  91. data/lib/axlsx/workbook/worksheet/data_validations.rb +28 -0
  92. data/lib/axlsx/workbook/worksheet/dimension.rb +65 -0
  93. data/lib/axlsx/workbook/worksheet/icon_set.rb +83 -0
  94. data/lib/axlsx/workbook/worksheet/merged_cells.rb +35 -0
  95. data/lib/axlsx/workbook/worksheet/page_setup.rb +113 -0
  96. data/lib/axlsx/workbook/worksheet/pane.rb +144 -0
  97. data/lib/axlsx/workbook/worksheet/print_options.rb +63 -0
  98. data/lib/axlsx/workbook/worksheet/protected_range.rb +46 -0
  99. data/lib/axlsx/workbook/worksheet/protected_ranges.rb +34 -0
  100. data/lib/axlsx/workbook/worksheet/row.rb +69 -12
  101. data/lib/axlsx/workbook/worksheet/selection.rb +111 -0
  102. data/lib/axlsx/workbook/worksheet/sheet_data.rb +25 -0
  103. data/lib/axlsx/workbook/worksheet/sheet_pr.rb +24 -0
  104. data/lib/axlsx/workbook/worksheet/sheet_protection.rb +224 -0
  105. data/lib/axlsx/workbook/worksheet/sheet_view.rb +379 -0
  106. data/lib/axlsx/workbook/worksheet/table.rb +3 -3
  107. data/lib/axlsx/workbook/worksheet/tables.rb +31 -0
  108. data/lib/axlsx/workbook/worksheet/worksheet.rb +379 -233
  109. data/lib/axlsx/workbook/worksheet/worksheet_comments.rb +57 -0
  110. data/lib/axlsx/workbook/worksheet/worksheet_drawing.rb +64 -0
  111. data/lib/axlsx.rb +31 -16
  112. data/test/benchmark.rb +30 -38
  113. data/test/content_type/tc_content_type.rb +1 -6
  114. data/test/doc_props/tc_app.rb +31 -1
  115. data/test/doc_props/tc_core.rb +3 -1
  116. data/test/drawing/tc_axis.rb +46 -3
  117. data/test/drawing/tc_bar_3D_chart.rb +12 -12
  118. data/test/drawing/tc_bar_series.rb +17 -13
  119. data/test/drawing/tc_cat_axis.rb +3 -3
  120. data/test/drawing/tc_cat_axis_data.rb +23 -13
  121. data/test/drawing/tc_chart.rb +29 -11
  122. data/test/drawing/tc_d_lbls.rb +47 -0
  123. data/test/drawing/tc_data_source.rb +17 -0
  124. data/test/drawing/tc_drawing.rb +11 -5
  125. data/test/drawing/tc_hyperlink.rb +4 -5
  126. data/test/drawing/tc_line_series.rb +9 -11
  127. data/test/drawing/tc_named_axis_data.rb +27 -0
  128. data/test/drawing/tc_num_data.rb +31 -0
  129. data/test/drawing/tc_num_val.rb +29 -0
  130. data/test/drawing/tc_pic.rb +22 -2
  131. data/test/drawing/tc_pie_3D_chart.rb +4 -8
  132. data/test/drawing/tc_pie_series.rb +11 -13
  133. data/test/drawing/tc_scatter_chart.rb +6 -1
  134. data/test/drawing/tc_scatter_series.rb +6 -5
  135. data/test/drawing/tc_series.rb +1 -1
  136. data/test/drawing/tc_str_data.rb +18 -0
  137. data/test/drawing/tc_str_val.rb +21 -0
  138. data/test/drawing/tc_title.rb +16 -0
  139. data/test/drawing/tc_two_cell_anchor.rb +2 -3
  140. data/test/drawing/tc_view_3D.rb +18 -18
  141. data/test/drawing/tc_vml_drawing.rb +25 -0
  142. data/test/drawing/tc_vml_shape.rb +100 -0
  143. data/test/profile.rb +2 -1
  144. data/test/rels/tc_relationship.rb +1 -0
  145. data/test/stylesheet/tc_dxf.rb +81 -0
  146. data/test/stylesheet/tc_gradient_fill.rb +8 -0
  147. data/test/stylesheet/tc_pattern_fill.rb +7 -1
  148. data/test/stylesheet/tc_styles.rb +163 -3
  149. data/test/stylesheet/tc_table_style.rb +8 -0
  150. data/test/stylesheet/tc_table_style_element.rb +10 -1
  151. data/test/tc_helper.rb +1 -0
  152. data/test/tc_package.rb +93 -17
  153. data/test/util/tc_simple_typed_list.rb +13 -0
  154. data/test/util/tc_validators.rb +95 -9
  155. data/test/workbook/tc_defined_name.rb +41 -0
  156. data/test/workbook/tc_workbook.rb +5 -3
  157. data/test/workbook/worksheet/table/tc_table.rb +3 -11
  158. data/test/workbook/worksheet/tc_cell.rb +52 -18
  159. data/test/workbook/worksheet/tc_cfvo.rb +31 -0
  160. data/test/workbook/worksheet/tc_col.rb +9 -0
  161. data/test/workbook/worksheet/tc_color_scale.rb +29 -0
  162. data/test/workbook/worksheet/tc_comment.rb +57 -0
  163. data/test/workbook/worksheet/tc_comments.rb +57 -0
  164. data/test/workbook/worksheet/tc_conditional_formatting.rb +217 -0
  165. data/test/workbook/worksheet/tc_data_bar.rb +39 -0
  166. data/test/workbook/worksheet/tc_data_validation.rb +265 -0
  167. data/test/workbook/worksheet/tc_date_time_converter.rb +11 -5
  168. data/test/workbook/worksheet/tc_icon_set.rb +45 -0
  169. data/test/workbook/worksheet/tc_page_setup.rb +138 -0
  170. data/test/workbook/worksheet/tc_pane.rb +94 -0
  171. data/test/workbook/worksheet/tc_print_options.rb +72 -0
  172. data/test/workbook/worksheet/tc_protected_range.rb +17 -0
  173. data/test/workbook/worksheet/tc_row.rb +44 -13
  174. data/test/workbook/worksheet/tc_selection.rb +94 -0
  175. data/test/workbook/worksheet/tc_sheet_protection.rb +117 -0
  176. data/test/workbook/worksheet/tc_sheet_view.rb +214 -0
  177. data/test/workbook/worksheet/tc_worksheet.rb +147 -50
  178. metadata +216 -148
  179. data/examples/example.csv +0 -1000
  180. data/examples/example.rb~ +0 -112
  181. data/lib/axlsx/drawing/cat_axis_data.rb +0 -34
  182. data/lib/axlsx/drawing/hlink_click.rb~ +0 -0
  183. data/lib/axlsx/drawing/hyperlink.rb~ +0 -64
  184. data/lib/axlsx/drawing/named_axis_data.rb +0 -36
  185. data/lib/axlsx/drawing/picture_locking.rb~ +0 -36
  186. data/lib/axlsx/drawing/val_axis_data.rb +0 -27
  187. data/lib/axlsx/stylesheet/#num_fmt.rb# +0 -69
  188. data/lib/axlsx/util/cbf.rb +0 -333
  189. data/lib/axlsx/util/cfb.rb~ +0 -201
  190. data/lib/axlsx/util/ms_off_crypto.rb +0 -189
  191. data/lib/axlsx/util/ms_off_crypto.rb~ +0 -3
  192. data/lib/axlsx/util/ms_offcrypto.rb~ +0 -0
  193. data/lib/axlsx/util/parser.rb~ +0 -6
  194. data/lib/axlsx/util/storage.rb~ +0 -0
  195. data/lib/axlsx/workbook/shared_strings_table.rb~ +0 -69
  196. data/lib/axlsx/workbook/worksheet/col.rb~ +0 -0
  197. data/lib/axlsx/workbook/worksheet/shared_strings_table.rb~ +0 -0
  198. data/lib/axlsx/workbook/worksheet/table.rb~ +0 -97
  199. data/lib/schema/dc.xsd~ +0 -118
  200. data/lib/schema/dcterms.xsd~ +0 -331
  201. data/lib/schema/opc-coreProperties.xsd~ +0 -50
  202. data/test/#benchmark.txt# +0 -7
  203. data/test/#tc_helper.rb# +0 -3
  204. data/test/benchmark.rb~ +0 -0
  205. data/test/benchmark.txt +0 -6
  206. data/test/benchmark.txt~ +0 -6
  207. data/test/drawing/tc_val_axis_data.rb +0 -17
  208. data/test/example.csv +0 -1000
  209. data/test/example.xlsx +0 -0
  210. data/test/example_streamed.xlsx +0 -0
  211. data/test/tc_axlsx.rb~ +0 -0
  212. data/test/tc_helper.rb~ +0 -3
  213. data/test/workbook/worksheet/table/tc_table.rb~ +0 -72
  214. data/test/workbook/worksheet/tc_col.rb~ +0 -10
@@ -0,0 +1,111 @@
1
+ # encoding: UTF-8
2
+ module Axlsx
3
+ # Selection options for worksheet panes.
4
+ #
5
+ # @note The recommended way to manage the selection pane options is via SheetView#add_selection
6
+ # @see SheetView#add_selection
7
+ class Selection
8
+
9
+ # Active Cell Location
10
+ # Location of the active cell.
11
+ # @see type
12
+ # @return [String]
13
+ # default nil
14
+ attr_reader :active_cell
15
+
16
+
17
+ # Active Cell Index
18
+ # 0-based index of the range reference (in the array of references listed in sqref)
19
+ # containing the active cell. Only used when the selection in sqref is not contiguous.
20
+ # Therefore, this value needs to be aware of the order in which the range references are
21
+ # written in sqref.
22
+ # When this value is out of range then activeCell can be used.
23
+ # @see type
24
+ # @return [Integer]
25
+ # default nil
26
+ attr_reader :active_cell_id
27
+
28
+
29
+ # Pane
30
+ # The pane to which this selection belongs.
31
+ # Options are
32
+ # * bottom_left: Bottom left pane, when both vertical and horizontal
33
+ # splits are applied. This value is also used when only
34
+ # a horizontal split has been applied, dividing the pane
35
+ # into upper and lower regions. In that case, this value
36
+ # specifies the bottom pane.
37
+ # * bottom_right: Bottom right pane, when both vertical and horizontal
38
+ # splits are applied.
39
+ # * top_left: Top left pane, when both vertical and horizontal splits
40
+ # are applied. This value is also used when only a horizontal
41
+ # split has been applied, dividing the pane into upper and lower
42
+ # regions. In that case, this value specifies the top pane.
43
+ # This value is also used when only a vertical split has
44
+ # been applied, dividing the pane into right and left
45
+ # regions. In that case, this value specifies the left pane
46
+ # * top_right: Top right pane, when both vertical and horizontal
47
+ # splits are applied. This value is also used when only
48
+ # a vertical split has been applied, dividing the pane
49
+ # into right and left regions. In that case, this value
50
+ # specifies the right pane.
51
+ # @see type
52
+ # @return [Symbol]
53
+ # default nil
54
+ attr_reader :pane
55
+
56
+
57
+ # Sequence of References
58
+ # Range of the selection. Can be non-contiguous set of ranges.
59
+ # @see type
60
+ # @return [String]
61
+ # default nil
62
+ attr_reader :sqref
63
+
64
+
65
+ # Creates a new {Selection} object
66
+ # @option options [Cell, String] active_cell Active Cell Location
67
+ # @option options [Integer] active_cell_id Active Cell Index
68
+ # @option options [Symbol] pane Pane
69
+ # @option options [String] sqref Sequence of References
70
+ def initialize(options={})
71
+ #defaults
72
+ @active_cell = @active_cell_id = @pane = @sqref = nil
73
+
74
+ # write options to instance variables
75
+ options.each do |o|
76
+ self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
77
+ end
78
+ end
79
+
80
+
81
+ # @see active_cell
82
+ def active_cell=(v)
83
+ cell = (v.class == Axlsx::Cell ? v.r_abs : v)
84
+ Axlsx::validate_string(cell)
85
+ @active_cell = cell
86
+ end
87
+
88
+
89
+ # @see active_cell_id
90
+ def active_cell_id=(v); Axlsx::validate_unsigned_int(v); @active_cell_id = v end
91
+
92
+
93
+ # @see pane
94
+ def pane=(v); Axlsx::validate_pane_type(v); @pane = v end
95
+
96
+
97
+ # @see sqref
98
+ def sqref=(v); Axlsx::validate_string(v); @sqref = v end
99
+
100
+
101
+ # Serializes the data validation
102
+ # @param [String] str
103
+ # @return [String]
104
+ def to_xml_string(str = '')
105
+ str << '<selection '
106
+ str << instance_values.map { |key, value| '' << key.gsub(/_(.)/){ $1.upcase } <<
107
+ %{="#{[:pane].include?(key.to_sym) ? value.to_s.gsub(/_(.)/){ $1.upcase } : value}"} unless value.nil? }.join(' ')
108
+ str << '/>'
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,25 @@
1
+ module Axlsx
2
+
3
+ # This class manages the serialization of rows for worksheets
4
+ class SheetData
5
+
6
+ # Creates a new SheetData object
7
+ # @param [Worksheet] worksheet The worksheet that owns this sheet data.
8
+ def initialize(worksheet)
9
+ raise ArgumentError, "you must provide a worksheet" unless worksheet.is_a?(Worksheet)
10
+ @worksheet = worksheet
11
+ end
12
+
13
+ attr_reader :worksheet
14
+
15
+ # Serialize the sheet data
16
+ # @param [String] str the string this objects serializaton will be concacted to.
17
+ # @return [String]
18
+ def to_xml_string(str = '')
19
+ str << '<sheetData>'
20
+ worksheet.rows.each_with_index{ |row, index| row.to_xml_string(index, str) }
21
+ str << '</sheetData>'
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,24 @@
1
+ module Axlsx
2
+
3
+ # The SheetPr class manages serialization fo a worksheet's sheetPr element.
4
+ # Only fit_to_page is implemented
5
+ class SheetPr
6
+
7
+ # Creates a new SheetPr object
8
+ # @param [Worksheet] worksheet The worksheet that owns this SheetPr object
9
+ def initialize(worksheet)
10
+ raise ArgumentError, "you must provide a worksheet" unless worksheet.is_a?(Worksheet)
11
+ @worksheet = worksheet
12
+ end
13
+
14
+ attr_reader :worksheet
15
+
16
+ # Serialize the object
17
+ # @param [String] str serialized output will be appended to this object if provided.
18
+ # @return [String]
19
+ def to_xml_string(str = '')
20
+ return unless worksheet.fit_to_page?
21
+ str << "<sheetPr><pageSetUpPr fitToPage=\"%s\"></pageSetUpPr></sheetPr>" % worksheet.fit_to_page?
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,224 @@
1
+ # encoding: UTF-8
2
+ module Axlsx
3
+
4
+ # The SheetProtection object manages worksheet protection options per sheet.
5
+ class SheetProtection
6
+
7
+ # If 1 or true then AutoFilters should not be allowed to operate when the sheet is protected.
8
+ # If 0 or false then AutoFilters should be allowed to operate when the sheet is protected.
9
+ # @return [Boolean]
10
+ # default true
11
+ attr_reader :auto_filter
12
+
13
+ # If 1 or true then deleting columns should not be allowed when the sheet is protected.
14
+ # If 0 or false then deleting columns should be allowed when the sheet is protected.
15
+ # @return [Boolean]
16
+ # default true
17
+ attr_reader :delete_columns
18
+
19
+ # If 1 or true then deleting rows should not be allowed when the sheet is protected.
20
+ # If 0 or false then deleting rows should be allowed when the sheet is protected.
21
+ # @return [Boolean]
22
+ # default true
23
+ attr_reader :delete_rows
24
+
25
+ # If 1 or true then formatting cells should not be allowed when the sheet is protected.
26
+ # If 0 or false then formatting cells should be allowed when the sheet is protected.
27
+ # @return [Boolean]
28
+ # default true
29
+ attr_reader :format_cells
30
+
31
+ # If 1 or true then formatting columns should not be allowed when the sheet is protected.
32
+ # If 0 or false then formatting columns should be allowed when the sheet is protected.
33
+ # @return [Boolean]
34
+ # default true
35
+ attr_reader :format_columns
36
+
37
+ # If 1 or true then formatting rows should not be allowed when the sheet is protected.
38
+ # If 0 or false then formatting rows should be allowed when the sheet is protected.
39
+ # @return [Boolean]
40
+ # default true
41
+ attr_reader :format_rows
42
+
43
+ # If 1 or true then inserting columns should not be allowed when the sheet is protected.
44
+ # If 0 or false then inserting columns should be allowed when the sheet is protected.
45
+ # @return [Boolean]
46
+ # default true
47
+ attr_reader :insert_columns
48
+
49
+ # If 1 or true then inserting hyperlinks should not be allowed when the sheet is protected.
50
+ # If 0 or false then inserting hyperlinks should be allowed when the sheet is protected.
51
+ # @return [Boolean]
52
+ # default true
53
+ attr_reader :insert_hyperlinks
54
+
55
+ # If 1 or true then inserting rows should not be allowed when the sheet is protected.
56
+ # If 0 or false then inserting rows should be allowed when the sheet is protected.
57
+ # @return [Boolean]
58
+ # default true
59
+ attr_reader :insert_rows
60
+
61
+ # If 1 or true then editing of objects should not be allowed when the sheet is protected.
62
+ # If 0 or false then objects are allowed to be edited when the sheet is protected.
63
+ # @return [Boolean]
64
+ # default false
65
+ attr_reader :objects
66
+
67
+ # If 1 or true then PivotTables should not be allowed to operate when the sheet is protected.
68
+ # If 0 or false then PivotTables should be allowed to operate when the sheet is protected.
69
+ # @return [Boolean]
70
+ # default true
71
+ attr_reader :pivot_tables
72
+
73
+ # Specifies the salt which was prepended to the user-supplied password before it was hashed using the hashing algorithm
74
+ # @return [String]
75
+ attr_reader :salt_value
76
+
77
+ # If 1 or true then Scenarios should not be edited when the sheet is protected.
78
+ # If 0 or false then Scenarios are allowed to be edited when the sheet is protected.
79
+ # @return [Boolean]
80
+ # default false
81
+ attr_reader :scenarios
82
+
83
+ # If 1 or true then selection of locked cells should not be allowed when the sheet is protected.
84
+ # If 0 or false then selection of locked cells should be allowed when the sheet is protected.
85
+ # @return [Boolean]
86
+ # default false
87
+ attr_reader :select_locked_cells
88
+
89
+ # If 1 or true then selection of unlocked cells should not be allowed when the sheet is protected.
90
+ # If 0 or false then selection of unlocked cells should be allowed when the sheet is protected.
91
+ # @return [Boolean]
92
+ # default false
93
+ attr_reader :select_unlocked_cells
94
+
95
+ # If 1 or true then the sheet is protected.
96
+ # If 0 or false then the sheet is not protected.
97
+ # @return [Boolean]
98
+ # default true
99
+ attr_reader :sheet
100
+
101
+ # If 1 or true then sorting should not be allowed when the sheet is protected.
102
+ # If 0 or false then sorting should be allowed when the sheet is protected.
103
+ # @return [Boolean]
104
+ # default true
105
+ attr_reader :sort
106
+
107
+ # Password hash
108
+ # @return [String]
109
+ # default nil
110
+ attr_reader :password
111
+
112
+ # Creates a new SheetProtection instance
113
+ # @option options [Boolean] sheet @see SheetProtection#sheet
114
+ # @option options [Boolean] objects @see SheetProtection#objects
115
+ # @option options [Boolean] scenarios @see SheetProtection#scenarios
116
+ # @option options [Boolean] format_cells @see SheetProtection#objects
117
+ # @option options [Boolean] format_columns @see SheetProtection#format_columns
118
+ # @option options [Boolean] format_rows @see SheetProtection#format_rows
119
+ # @option options [Boolean] insert_columns @see SheetProtection#insert_columns
120
+ # @option options [Boolean] insert_rows @see SheetProtection#insert_rows
121
+ # @option options [Boolean] insert_hyperlinks @see SheetProtection#insert_hyperlinks
122
+ # @option options [Boolean] delete_columns @see SheetProtection#delete_columns
123
+ # @option options [Boolean] delete_rows @see SheetProtection#delete_rows
124
+ # @option options [Boolean] select_locked_cells @see SheetProtection#select_locked_cells
125
+ # @option options [Boolean] sort @see SheetProtection#sort
126
+ # @option options [Boolean] auto_filter @see SheetProtection#auto_filter
127
+ # @option options [Boolean] pivot_tables @see SheetProtection#pivot_tables
128
+ # @option options [Boolean] select_unlocked_cells @see SheetProtection#select_unlocked_cells
129
+ # @option options [String] password. The password required for unlocking. @see SheetProtection#password=
130
+ # @option options [Boolean] objects @see SheetProtection#objects
131
+ def initialize(options={})
132
+ @objects = @scenarios = @select_locked_cells = @select_unlocked_cells = false
133
+ @sheet = @format_cells = @format_rows = @format_columns = @insert_columns = @insert_rows = @insert_hyperlinks = @delete_columns = @delete_rows = @sort = @auto_filter = @pivot_tables = true
134
+ @password = nil
135
+
136
+ options.each do |o|
137
+ self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
138
+ end
139
+ end
140
+
141
+
142
+ # create validating setters for boolean values
143
+ # @return [Boolean]
144
+ [:sheet, :objects, :scenarios, :select_locked_cells, :sort,
145
+ :select_unlocked_cells, :format_cells, :format_rows, :format_columns,
146
+ :insert_columns, :insert_rows, :insert_hyperlinks, :delete_columns,
147
+ :delete_rows, :auto_filter, :pivot_tables].each do |f_name|
148
+ define_method "#{f_name.to_s}=".to_sym do |v|
149
+ Axlsx::validate_boolean(v)
150
+ instance_variable_set "@#{f_name.to_s}".to_sym, v
151
+ end
152
+ end
153
+
154
+ # This block is intended to implement the salt_value, hash_value and spin count as per the ECMA-376 standard.
155
+ # However, it does not seem to actually work in EXCEL - instead they are using their old retro algorithm shown below
156
+ # defined in the transitional portion of the speck. I am leaving this code in in the hope that someday Ill be able to
157
+ # figure out why it does not work, and if Excel even supports it.
158
+ # def propper_password=(v)
159
+ # @algorithm_name = v == nil ? nil : 'SHA-1'
160
+ # @salt_value = @spin_count = @hash_value = v if v == nil
161
+ # return if v == nil
162
+ # require 'digest/sha1'
163
+ # @spin_count = 10000
164
+ # @salt_value = Digest::SHA1.hexdigest(rand(36**8).to_s(36))
165
+ # @spin_count.times do |count|
166
+ # @hash_value = Digest::SHA1.hexdigest((@hash_value ||= (@salt_value + v.to_s)) + Array(count).pack('V'))
167
+ # end
168
+ # end
169
+
170
+
171
+
172
+ # encodes password for protection locking
173
+ def password=(v)
174
+ return if v == nil
175
+ @password = create_password_hash(v)
176
+ end
177
+
178
+ # Serialize the object
179
+ # @param [String] str
180
+ # @return [String]
181
+ def to_xml_string(str = '')
182
+ str << '<sheetProtection '
183
+ str << instance_values.map{ |k,v| k.gsub(/_(.)/){ $1.upcase } << %{="#{v.to_s}"} }.join(' ')
184
+ str << '/>'
185
+ end
186
+
187
+ private
188
+ # Creates a password hash for a given password
189
+ # @return [String]
190
+ def create_password_hash(password)
191
+ encoded_password = encode_password(password)
192
+
193
+ password_as_hex = [encoded_password].pack("v")
194
+ password_as_string = password_as_hex.unpack("H*").first.upcase
195
+
196
+ password_as_string[2..3] + password_as_string[0..1]
197
+ end
198
+
199
+
200
+ # Encodes a given password
201
+ # Based on the algorithm provided by Daniel Rentz of OpenOffice.
202
+ # http://www.openoffice.org/sc/excelfileformat.pdf, Revision 1.42, page 115 (21.05.2012)
203
+ # @return [String]
204
+ def encode_password(password)
205
+ i = 0
206
+ chars = password.split(//)
207
+ count = chars.size
208
+
209
+ chars.collect! do |char|
210
+ i += 1
211
+ char = char.unpack('c')[0] << i #ord << i
212
+ low_15 = char & 0x7fff
213
+ high_15 = char & 0x7fff << 15
214
+ high_15 = high_15 >> 15
215
+ char = low_15 | high_15
216
+ end
217
+
218
+ encoded_password = 0x0000
219
+ chars.each { |c| encoded_password ^= c }
220
+ encoded_password ^= count
221
+ encoded_password ^= 0xCE4B
222
+ end
223
+ end
224
+ end