caxlsx 3.2.0 → 3.4.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 (301) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +9 -9
  3. data/.yardopts_guide +18 -18
  4. data/CHANGELOG.md +394 -354
  5. data/LICENSE +21 -21
  6. data/README.md +184 -168
  7. data/Rakefile +28 -29
  8. data/examples/generate.rb +15 -15
  9. data/lib/axlsx/content_type/abstract_content_type.rb +29 -32
  10. data/lib/axlsx/content_type/content_type.rb +22 -26
  11. data/lib/axlsx/content_type/default.rb +21 -25
  12. data/lib/axlsx/content_type/override.rb +21 -25
  13. data/lib/axlsx/doc_props/app.rb +230 -235
  14. data/lib/axlsx/doc_props/core.rb +34 -39
  15. data/lib/axlsx/drawing/area_chart.rb +96 -99
  16. data/lib/axlsx/drawing/area_series.rb +107 -110
  17. data/lib/axlsx/drawing/ax_data_source.rb +21 -26
  18. data/lib/axlsx/drawing/axes.rb +60 -61
  19. data/lib/axlsx/drawing/axis.rb +185 -190
  20. data/lib/axlsx/drawing/bar_3D_chart.rb +145 -148
  21. data/lib/axlsx/drawing/bar_chart.rb +135 -138
  22. data/lib/axlsx/drawing/bar_series.rb +91 -97
  23. data/lib/axlsx/drawing/bubble_chart.rb +56 -59
  24. data/lib/axlsx/drawing/bubble_series.rb +60 -63
  25. data/lib/axlsx/drawing/cat_axis.rb +80 -85
  26. data/lib/axlsx/drawing/chart.rb +294 -276
  27. data/lib/axlsx/drawing/d_lbls.rb +92 -90
  28. data/lib/axlsx/drawing/drawing.rb +163 -167
  29. data/lib/axlsx/drawing/graphic_frame.rb +51 -54
  30. data/lib/axlsx/drawing/hyperlink.rb +97 -100
  31. data/lib/axlsx/drawing/line_3D_chart.rb +64 -68
  32. data/lib/axlsx/drawing/line_chart.rb +96 -99
  33. data/lib/axlsx/drawing/line_series.rb +107 -110
  34. data/lib/axlsx/drawing/marker.rb +80 -84
  35. data/lib/axlsx/drawing/num_data.rb +47 -52
  36. data/lib/axlsx/drawing/num_data_source.rb +58 -62
  37. data/lib/axlsx/drawing/num_val.rb +31 -34
  38. data/lib/axlsx/drawing/one_cell_anchor.rb +97 -99
  39. data/lib/axlsx/drawing/pic.rb +244 -211
  40. data/lib/axlsx/drawing/picture_locking.rb +39 -42
  41. data/lib/axlsx/drawing/pie_3D_chart.rb +42 -47
  42. data/lib/axlsx/drawing/pie_series.rb +69 -74
  43. data/lib/axlsx/drawing/scaling.rb +57 -60
  44. data/lib/axlsx/drawing/scatter_chart.rb +71 -74
  45. data/lib/axlsx/drawing/scatter_series.rb +126 -129
  46. data/lib/axlsx/drawing/ser_axis.rb +41 -45
  47. data/lib/axlsx/drawing/series.rb +67 -69
  48. data/lib/axlsx/drawing/series_title.rb +23 -25
  49. data/lib/axlsx/drawing/str_data.rb +37 -42
  50. data/lib/axlsx/drawing/str_val.rb +31 -34
  51. data/lib/axlsx/drawing/title.rb +104 -97
  52. data/lib/axlsx/drawing/two_cell_anchor.rb +95 -97
  53. data/lib/axlsx/drawing/val_axis.rb +34 -37
  54. data/lib/axlsx/drawing/view_3D.rb +115 -115
  55. data/lib/axlsx/drawing/vml_drawing.rb +39 -42
  56. data/lib/axlsx/drawing/vml_shape.rb +63 -66
  57. data/lib/axlsx/package.rb +397 -388
  58. data/lib/axlsx/rels/relationship.rb +127 -130
  59. data/lib/axlsx/rels/relationships.rb +29 -32
  60. data/lib/axlsx/stylesheet/border.rb +70 -73
  61. data/lib/axlsx/stylesheet/border_pr.rb +69 -71
  62. data/lib/axlsx/stylesheet/cell_alignment.rb +124 -132
  63. data/lib/axlsx/stylesheet/cell_protection.rb +38 -41
  64. data/lib/axlsx/stylesheet/cell_style.rb +68 -72
  65. data/lib/axlsx/stylesheet/color.rb +77 -76
  66. data/lib/axlsx/stylesheet/dxf.rb +75 -79
  67. data/lib/axlsx/stylesheet/fill.rb +31 -35
  68. data/lib/axlsx/stylesheet/font.rb +157 -156
  69. data/lib/axlsx/stylesheet/gradient_fill.rb +101 -103
  70. data/lib/axlsx/stylesheet/gradient_stop.rb +36 -37
  71. data/lib/axlsx/stylesheet/num_fmt.rb +83 -86
  72. data/lib/axlsx/stylesheet/pattern_fill.rb +71 -73
  73. data/lib/axlsx/stylesheet/styles.rb +543 -494
  74. data/lib/axlsx/stylesheet/table_style.rb +51 -54
  75. data/lib/axlsx/stylesheet/table_style_element.rb +74 -77
  76. data/lib/axlsx/stylesheet/table_styles.rb +42 -46
  77. data/lib/axlsx/stylesheet/xf.rb +144 -147
  78. data/lib/axlsx/util/accessors.rb +62 -64
  79. data/lib/axlsx/util/constants.rb +414 -410
  80. data/lib/axlsx/util/mime_type_utils.rb +24 -11
  81. data/lib/axlsx/util/options_parser.rb +15 -16
  82. data/lib/axlsx/util/serialized_attributes.rb +88 -89
  83. data/lib/axlsx/util/simple_typed_list.rb +180 -179
  84. data/lib/axlsx/util/storage.rb +142 -146
  85. data/lib/axlsx/util/validators.rb +315 -312
  86. data/lib/axlsx/util/zip_command.rb +71 -73
  87. data/lib/axlsx/version.rb +4 -5
  88. data/lib/axlsx/workbook/defined_name.rb +129 -128
  89. data/lib/axlsx/workbook/defined_names.rb +20 -21
  90. data/lib/axlsx/workbook/shared_strings_table.rb +74 -77
  91. data/lib/axlsx/workbook/workbook.rb +430 -395
  92. data/lib/axlsx/workbook/workbook_view.rb +75 -80
  93. data/lib/axlsx/workbook/workbook_views.rb +20 -22
  94. data/lib/axlsx/workbook/worksheet/auto_filter/auto_filter.rb +78 -77
  95. data/lib/axlsx/workbook/worksheet/auto_filter/filter_column.rb +94 -94
  96. data/lib/axlsx/workbook/worksheet/auto_filter/filters.rb +243 -244
  97. data/lib/axlsx/workbook/worksheet/border_creator.rb +79 -0
  98. data/lib/axlsx/workbook/worksheet/break.rb +32 -35
  99. data/lib/axlsx/workbook/worksheet/cell.rb +552 -506
  100. data/lib/axlsx/workbook/worksheet/cell_serializer.rb +164 -164
  101. data/lib/axlsx/workbook/worksheet/cfvo.rb +60 -60
  102. data/lib/axlsx/workbook/worksheet/cfvos.rb +16 -18
  103. data/lib/axlsx/workbook/worksheet/col.rb +142 -145
  104. data/lib/axlsx/workbook/worksheet/col_breaks.rb +34 -35
  105. data/lib/axlsx/workbook/worksheet/color_scale.rb +108 -110
  106. data/lib/axlsx/workbook/worksheet/cols.rb +23 -23
  107. data/lib/axlsx/workbook/worksheet/comment.rb +90 -91
  108. data/lib/axlsx/workbook/worksheet/comments.rb +78 -82
  109. data/lib/axlsx/workbook/worksheet/conditional_formatting.rb +81 -82
  110. data/lib/axlsx/workbook/worksheet/conditional_formatting_rule.rb +216 -220
  111. data/lib/axlsx/workbook/worksheet/conditional_formattings.rb +23 -25
  112. data/lib/axlsx/workbook/worksheet/data_bar.rb +127 -129
  113. data/lib/axlsx/workbook/worksheet/data_validation.rb +266 -246
  114. data/lib/axlsx/workbook/worksheet/data_validations.rb +25 -28
  115. data/lib/axlsx/workbook/worksheet/date_time_converter.rb +28 -30
  116. data/lib/axlsx/workbook/worksheet/dimension.rb +65 -64
  117. data/lib/axlsx/workbook/worksheet/header_footer.rb +51 -52
  118. data/lib/axlsx/workbook/worksheet/icon_set.rb +80 -81
  119. data/lib/axlsx/workbook/worksheet/merged_cells.rb +37 -37
  120. data/lib/axlsx/workbook/worksheet/outline_pr.rb +32 -33
  121. data/lib/axlsx/workbook/worksheet/page_margins.rb +97 -97
  122. data/lib/axlsx/workbook/worksheet/page_set_up_pr.rb +42 -44
  123. data/lib/axlsx/workbook/worksheet/page_setup.rb +237 -240
  124. data/lib/axlsx/workbook/worksheet/pane.rb +138 -139
  125. data/lib/axlsx/workbook/worksheet/pivot_table.rb +332 -296
  126. data/lib/axlsx/workbook/worksheet/pivot_table_cache_definition.rb +63 -66
  127. data/lib/axlsx/workbook/worksheet/pivot_tables.rb +23 -24
  128. data/lib/axlsx/workbook/worksheet/print_options.rb +38 -39
  129. data/lib/axlsx/workbook/worksheet/protected_range.rb +46 -47
  130. data/lib/axlsx/workbook/worksheet/protected_ranges.rb +37 -37
  131. data/lib/axlsx/workbook/worksheet/rich_text.rb +53 -55
  132. data/lib/axlsx/workbook/worksheet/rich_text_run.rb +266 -250
  133. data/lib/axlsx/workbook/worksheet/row.rb +173 -164
  134. data/lib/axlsx/workbook/worksheet/row_breaks.rb +32 -33
  135. data/lib/axlsx/workbook/worksheet/selection.rb +99 -101
  136. data/lib/axlsx/workbook/worksheet/sheet_calc_pr.rb +28 -29
  137. data/lib/axlsx/workbook/worksheet/sheet_data.rb +25 -27
  138. data/lib/axlsx/workbook/worksheet/sheet_format_pr.rb +18 -18
  139. data/lib/axlsx/workbook/worksheet/sheet_pr.rb +87 -87
  140. data/lib/axlsx/workbook/worksheet/sheet_protection.rb +117 -118
  141. data/lib/axlsx/workbook/worksheet/sheet_view.rb +206 -213
  142. data/lib/axlsx/workbook/worksheet/table.rb +100 -102
  143. data/lib/axlsx/workbook/worksheet/table_style_info.rb +48 -49
  144. data/lib/axlsx/workbook/worksheet/tables.rb +34 -34
  145. data/lib/axlsx/workbook/worksheet/worksheet.rb +857 -786
  146. data/lib/axlsx/workbook/worksheet/worksheet_comments.rb +58 -58
  147. data/lib/axlsx/workbook/worksheet/worksheet_drawing.rb +59 -58
  148. data/lib/axlsx/workbook/worksheet/worksheet_hyperlink.rb +73 -74
  149. data/lib/axlsx/workbook/worksheet/worksheet_hyperlinks.rb +38 -38
  150. data/lib/axlsx.rb +218 -185
  151. data/lib/caxlsx.rb +1 -2
  152. data/lib/schema/dc.xsd +118 -118
  153. data/lib/schema/dcmitype.xsd +51 -51
  154. data/lib/schema/dcterms.xsd +331 -331
  155. data/lib/schema/dml-chartDrawing.xsd +146 -146
  156. data/lib/schema/dml-compatibility.xsd +14 -14
  157. data/lib/schema/dml-lockedCanvas.xsd +11 -11
  158. data/lib/schema/dml-main.xsd +3048 -3048
  159. data/lib/schema/dml-picture.xsd +23 -23
  160. data/lib/schema/dml-spreadsheetDrawing.xsd +185 -185
  161. data/lib/schema/dml-wordprocessingDrawing.xsd +185 -185
  162. data/lib/schema/shared-additionalCharacteristics.xsd +28 -28
  163. data/lib/schema/shared-bibliography.xsd +144 -144
  164. data/lib/schema/shared-commonSimpleTypes.xsd +166 -166
  165. data/lib/schema/shared-customXmlDataProperties.xsd +25 -25
  166. data/lib/schema/shared-customXmlSchemaProperties.xsd +18 -18
  167. data/lib/schema/shared-documentPropertiesCustom.xsd +59 -59
  168. data/lib/schema/shared-documentPropertiesExtended.xsd +56 -56
  169. data/lib/schema/shared-documentPropertiesVariantTypes.xsd +195 -195
  170. data/lib/schema/shared-relationshipReference.xsd +25 -25
  171. data/lib/schema/vml-main.xsd +569 -569
  172. data/lib/schema/vml-officeDrawing.xsd +509 -509
  173. data/lib/schema/vml-presentationDrawing.xsd +12 -12
  174. data/lib/schema/vml-spreadsheetDrawing.xsd +108 -108
  175. data/lib/schema/vml-wordprocessingDrawing.xsd +96 -96
  176. data/lib/schema/xml.xsd +116 -116
  177. metadata +5 -252
  178. data/test/benchmark.rb +0 -72
  179. data/test/content_type/tc_content_type.rb +0 -76
  180. data/test/content_type/tc_default.rb +0 -16
  181. data/test/content_type/tc_override.rb +0 -14
  182. data/test/doc_props/tc_app.rb +0 -43
  183. data/test/doc_props/tc_core.rb +0 -42
  184. data/test/drawing/tc_area_chart.rb +0 -39
  185. data/test/drawing/tc_area_series.rb +0 -71
  186. data/test/drawing/tc_axes.rb +0 -8
  187. data/test/drawing/tc_axis.rb +0 -112
  188. data/test/drawing/tc_bar_3D_chart.rb +0 -86
  189. data/test/drawing/tc_bar_chart.rb +0 -86
  190. data/test/drawing/tc_bar_series.rb +0 -46
  191. data/test/drawing/tc_bubble_chart.rb +0 -44
  192. data/test/drawing/tc_bubble_series.rb +0 -21
  193. data/test/drawing/tc_cat_axis.rb +0 -31
  194. data/test/drawing/tc_cat_axis_data.rb +0 -27
  195. data/test/drawing/tc_chart.rb +0 -123
  196. data/test/drawing/tc_d_lbls.rb +0 -57
  197. data/test/drawing/tc_data_source.rb +0 -23
  198. data/test/drawing/tc_drawing.rb +0 -80
  199. data/test/drawing/tc_graphic_frame.rb +0 -27
  200. data/test/drawing/tc_hyperlink.rb +0 -64
  201. data/test/drawing/tc_line_3d_chart.rb +0 -47
  202. data/test/drawing/tc_line_chart.rb +0 -39
  203. data/test/drawing/tc_line_series.rb +0 -71
  204. data/test/drawing/tc_marker.rb +0 -44
  205. data/test/drawing/tc_named_axis_data.rb +0 -27
  206. data/test/drawing/tc_num_data.rb +0 -31
  207. data/test/drawing/tc_num_val.rb +0 -29
  208. data/test/drawing/tc_one_cell_anchor.rb +0 -66
  209. data/test/drawing/tc_pic.rb +0 -103
  210. data/test/drawing/tc_picture_locking.rb +0 -72
  211. data/test/drawing/tc_pie_3D_chart.rb +0 -28
  212. data/test/drawing/tc_pie_series.rb +0 -33
  213. data/test/drawing/tc_scaling.rb +0 -36
  214. data/test/drawing/tc_scatter_chart.rb +0 -48
  215. data/test/drawing/tc_scatter_series.rb +0 -74
  216. data/test/drawing/tc_ser_axis.rb +0 -31
  217. data/test/drawing/tc_series.rb +0 -23
  218. data/test/drawing/tc_series_title.rb +0 -54
  219. data/test/drawing/tc_str_data.rb +0 -18
  220. data/test/drawing/tc_str_val.rb +0 -30
  221. data/test/drawing/tc_title.rb +0 -70
  222. data/test/drawing/tc_two_cell_anchor.rb +0 -36
  223. data/test/drawing/tc_val_axis.rb +0 -24
  224. data/test/drawing/tc_view_3D.rb +0 -54
  225. data/test/drawing/tc_vml_drawing.rb +0 -25
  226. data/test/drawing/tc_vml_shape.rb +0 -106
  227. data/test/fixtures/image1.gif +0 -0
  228. data/test/fixtures/image1.jpeg +0 -0
  229. data/test/fixtures/image1.jpg +0 -0
  230. data/test/fixtures/image1.png +0 -0
  231. data/test/fixtures/image1_fake.jpg +0 -0
  232. data/test/profile.rb +0 -24
  233. data/test/rels/tc_relationship.rb +0 -52
  234. data/test/rels/tc_relationships.rb +0 -37
  235. data/test/stylesheet/tc_border.rb +0 -37
  236. data/test/stylesheet/tc_border_pr.rb +0 -32
  237. data/test/stylesheet/tc_cell_alignment.rb +0 -81
  238. data/test/stylesheet/tc_cell_protection.rb +0 -29
  239. data/test/stylesheet/tc_cell_style.rb +0 -57
  240. data/test/stylesheet/tc_color.rb +0 -43
  241. data/test/stylesheet/tc_dxf.rb +0 -81
  242. data/test/stylesheet/tc_fill.rb +0 -18
  243. data/test/stylesheet/tc_font.rb +0 -133
  244. data/test/stylesheet/tc_gradient_fill.rb +0 -72
  245. data/test/stylesheet/tc_gradient_stop.rb +0 -31
  246. data/test/stylesheet/tc_num_fmt.rb +0 -30
  247. data/test/stylesheet/tc_pattern_fill.rb +0 -43
  248. data/test/stylesheet/tc_styles.rb +0 -309
  249. data/test/stylesheet/tc_table_style.rb +0 -44
  250. data/test/stylesheet/tc_table_style_element.rb +0 -45
  251. data/test/stylesheet/tc_table_styles.rb +0 -29
  252. data/test/stylesheet/tc_xf.rb +0 -120
  253. data/test/tc_axlsx.rb +0 -109
  254. data/test/tc_helper.rb +0 -10
  255. data/test/tc_package.rb +0 -317
  256. data/test/util/tc_mime_type_utils.rb +0 -13
  257. data/test/util/tc_serialized_attributes.rb +0 -19
  258. data/test/util/tc_simple_typed_list.rb +0 -77
  259. data/test/util/tc_validators.rb +0 -210
  260. data/test/workbook/tc_defined_name.rb +0 -49
  261. data/test/workbook/tc_shared_strings_table.rb +0 -59
  262. data/test/workbook/tc_workbook.rb +0 -165
  263. data/test/workbook/tc_workbook_view.rb +0 -50
  264. data/test/workbook/worksheet/auto_filter/tc_auto_filter.rb +0 -38
  265. data/test/workbook/worksheet/auto_filter/tc_filter_column.rb +0 -76
  266. data/test/workbook/worksheet/auto_filter/tc_filters.rb +0 -50
  267. data/test/workbook/worksheet/tc_break.rb +0 -49
  268. data/test/workbook/worksheet/tc_cell.rb +0 -465
  269. data/test/workbook/worksheet/tc_cfvo.rb +0 -31
  270. data/test/workbook/worksheet/tc_col.rb +0 -93
  271. data/test/workbook/worksheet/tc_color_scale.rb +0 -58
  272. data/test/workbook/worksheet/tc_comment.rb +0 -72
  273. data/test/workbook/worksheet/tc_comments.rb +0 -57
  274. data/test/workbook/worksheet/tc_conditional_formatting.rb +0 -224
  275. data/test/workbook/worksheet/tc_data_bar.rb +0 -46
  276. data/test/workbook/worksheet/tc_data_validation.rb +0 -265
  277. data/test/workbook/worksheet/tc_date_time_converter.rb +0 -124
  278. data/test/workbook/worksheet/tc_header_footer.rb +0 -151
  279. data/test/workbook/worksheet/tc_icon_set.rb +0 -45
  280. data/test/workbook/worksheet/tc_outline_pr.rb +0 -19
  281. data/test/workbook/worksheet/tc_page_margins.rb +0 -97
  282. data/test/workbook/worksheet/tc_page_set_up_pr.rb +0 -15
  283. data/test/workbook/worksheet/tc_page_setup.rb +0 -143
  284. data/test/workbook/worksheet/tc_pane.rb +0 -54
  285. data/test/workbook/worksheet/tc_pivot_table.rb +0 -180
  286. data/test/workbook/worksheet/tc_pivot_table_cache_definition.rb +0 -62
  287. data/test/workbook/worksheet/tc_print_options.rb +0 -72
  288. data/test/workbook/worksheet/tc_protected_range.rb +0 -17
  289. data/test/workbook/worksheet/tc_rich_text.rb +0 -44
  290. data/test/workbook/worksheet/tc_rich_text_run.rb +0 -173
  291. data/test/workbook/worksheet/tc_row.rb +0 -160
  292. data/test/workbook/worksheet/tc_selection.rb +0 -55
  293. data/test/workbook/worksheet/tc_sheet_calc_pr.rb +0 -18
  294. data/test/workbook/worksheet/tc_sheet_format_pr.rb +0 -88
  295. data/test/workbook/worksheet/tc_sheet_pr.rb +0 -49
  296. data/test/workbook/worksheet/tc_sheet_protection.rb +0 -117
  297. data/test/workbook/worksheet/tc_sheet_view.rb +0 -214
  298. data/test/workbook/worksheet/tc_table.rb +0 -77
  299. data/test/workbook/worksheet/tc_table_style_info.rb +0 -53
  300. data/test/workbook/worksheet/tc_worksheet.rb +0 -632
  301. data/test/workbook/worksheet/tc_worksheet_hyperlink.rb +0 -55
@@ -1,296 +1,332 @@
1
- # encoding: UTF-8
2
- module Axlsx
3
- # Table
4
- # @note Worksheet#add_pivot_table is the recommended way to create tables for your worksheets.
5
- # @see README for examples
6
- class PivotTable
7
-
8
- include Axlsx::OptionsParser
9
-
10
- # Creates a new PivotTable object
11
- # @param [String] ref The reference to where the pivot table lives like 'G4:L17'.
12
- # @param [String] range The reference to the pivot table data like 'A1:D31'.
13
- # @param [Worksheet] sheet The sheet containing the table data.
14
- # @option options [Cell, String] name
15
- # @option options [TableStyle] style
16
- def initialize(ref, range, sheet, options={})
17
- @ref = ref
18
- self.range = range
19
- @sheet = sheet
20
- @sheet.workbook.pivot_tables << self
21
- @name = "PivotTable#{index+1}"
22
- @data_sheet = nil
23
- @rows = []
24
- @columns = []
25
- @data = []
26
- @pages = []
27
- @subtotal = nil
28
- @no_subtotals_on_headers = []
29
- @style_info = {}
30
- parse_options options
31
- yield self if block_given?
32
- end
33
-
34
- # Defines the headers in which subtotals are not to be included
35
- # @return[Array]
36
- attr_accessor :no_subtotals_on_headers
37
-
38
- # Style info for the pivot table
39
- # @return[Hash]
40
- attr_accessor :style_info
41
-
42
- # The reference to the table data
43
- # @return [String]
44
- attr_reader :ref
45
-
46
- # The name of the table.
47
- # @return [String]
48
- attr_reader :name
49
-
50
- # The name of the sheet.
51
- # @return [String]
52
- attr_reader :sheet
53
-
54
- # The sheet used as data source for the pivot table
55
- # @return [Worksheet]
56
- attr_writer :data_sheet
57
-
58
- # @see #data_sheet
59
- def data_sheet
60
- @data_sheet || @sheet
61
- end
62
-
63
- # The range where the data for this pivot table lives.
64
- # @return [String]
65
- attr_reader :range
66
-
67
- # (see #range)
68
- def range=(v)
69
- DataTypeValidator.validate "#{self.class}.range", [String], v
70
- if v.is_a?(String)
71
- @range = v
72
- end
73
- end
74
-
75
- # The rows
76
- # @return [Array]
77
- attr_reader :rows
78
-
79
-
80
- # (see #rows)
81
- def rows=(v)
82
- DataTypeValidator.validate "#{self.class}.rows", [Array], v
83
- v.each do |ref|
84
- DataTypeValidator.validate "#{self.class}.rows[]", [String], ref
85
- end
86
- @rows = v
87
- end
88
-
89
- # The columns
90
- # @return [Array]
91
- attr_reader :columns
92
-
93
- # (see #columns)
94
- def columns=(v)
95
- DataTypeValidator.validate "#{self.class}.columns", [Array], v
96
- v.each do |ref|
97
- DataTypeValidator.validate "#{self.class}.columns[]", [String], ref
98
- end
99
- @columns = v
100
- end
101
-
102
- # The data
103
- # @return [Array]
104
- attr_reader :data
105
-
106
- # (see #data)
107
- def data=(v)
108
- DataTypeValidator.validate "#{self.class}.data", [Array], v
109
- @data = []
110
- v.each do |data_field|
111
- if data_field.is_a? String
112
- data_field = {:ref => data_field}
113
- end
114
- data_field.each do |key, value|
115
- if key == :num_fmt
116
- DataTypeValidator.validate "#{self.class}.data[]", [Integer], value
117
- else
118
- DataTypeValidator.validate "#{self.class}.data[]", [String], value
119
- end
120
- end
121
- @data << data_field
122
- end
123
- @data
124
- end
125
-
126
- # The pages
127
- # @return [String]
128
- attr_reader :pages
129
-
130
- # (see #pages)
131
- def pages=(v)
132
- DataTypeValidator.validate "#{self.class}.pages", [Array], v
133
- v.each do |ref|
134
- DataTypeValidator.validate "#{self.class}.pages[]", [String], ref
135
- end
136
- @pages = v
137
- end
138
-
139
- # The index of this chart in the workbooks charts collection
140
- # @return [Integer]
141
- def index
142
- @sheet.workbook.pivot_tables.index(self)
143
- end
144
-
145
- # The part name for this table
146
- # @return [String]
147
- def pn
148
- "#{PIVOT_TABLE_PN % (index+1)}"
149
- end
150
-
151
- # The relationship part name of this pivot table
152
- # @return [String]
153
- def rels_pn
154
- "#{PIVOT_TABLE_RELS_PN % (index+1)}"
155
- end
156
-
157
- # The cache_definition for this pivot table
158
- # @return [PivotTableCacheDefinition]
159
- def cache_definition
160
- @cache_definition ||= PivotTableCacheDefinition.new(self)
161
- end
162
-
163
- # The relationships for this pivot table.
164
- # @return [Relationships]
165
- def relationships
166
- r = Relationships.new
167
- r << Relationship.new(cache_definition, PIVOT_TABLE_CACHE_DEFINITION_R, "../#{cache_definition.pn}")
168
- r
169
- end
170
-
171
- # Serializes the object
172
- # @param [String] str
173
- # @return [String]
174
- def to_xml_string(str = '')
175
- str << '<?xml version="1.0" encoding="UTF-8"?>'
176
-
177
- str << ('<pivotTableDefinition xmlns="' << XML_NS << '" name="' << name << '" cacheId="' << cache_definition.cache_id.to_s << '"' << (data.size <= 1 ? ' dataOnRows="1"' : '') << ' applyNumberFormats="0" applyBorderFormats="0" applyFontFormats="0" applyPatternFormats="0" applyAlignmentFormats="0" applyWidthHeightFormats="1" dataCaption="Data" showMultipleLabel="0" showMemberPropertyTips="0" useAutoFormatting="1" indent="0" compact="0" compactData="0" gridDropZones="1" multipleFieldFilters="0">')
178
-
179
- str << ('<location firstDataCol="1" firstDataRow="1" firstHeaderRow="1" ref="' << ref << '"/>')
180
- str << ('<pivotFields count="' << header_cells_count.to_s << '">')
181
- header_cell_values.each do |cell_value|
182
- str << pivot_field_for(cell_value, !no_subtotals_on_headers.include?(cell_value))
183
- end
184
- str << '</pivotFields>'
185
- if rows.empty?
186
- str << '<rowFields count="1"><field x="-2"/></rowFields>'
187
- str << '<rowItems count="2"><i><x/></i> <i i="1"><x v="1"/></i></rowItems>'
188
- else
189
- str << ('<rowFields count="' << rows.size.to_s << '">')
190
- rows.each do |row_value|
191
- str << ('<field x="' << header_index_of(row_value).to_s << '"/>')
192
- end
193
- str << '</rowFields>'
194
- str << ('<rowItems count="' << rows.size.to_s << '">')
195
- rows.size.times do |i|
196
- str << '<i/>'
197
- end
198
- str << '</rowItems>'
199
- end
200
- if columns.empty? && data.size <= 1
201
- str << '<colItems count="1"><i/></colItems>'
202
- else
203
- str << ('<colFields count="' << columns.size.to_s << '">')
204
- columns.each do |column_value|
205
- str << ('<field x="' << header_index_of(column_value).to_s << '"/>')
206
- end
207
- str << '</colFields>'
208
- end
209
- unless pages.empty?
210
- str << ('<pageFields count="' << pages.size.to_s << '">')
211
- pages.each do |page_value|
212
- str << ('<pageField fld="' << header_index_of(page_value).to_s << '"/>')
213
- end
214
- str << '</pageFields>'
215
- end
216
- unless data.empty?
217
- str << "<dataFields count=\"#{data.size}\">"
218
- data.each do |datum_value|
219
- # The correct name prefix in ["Sum","Average", etc...]
220
- str << "<dataField name='#{(datum_value[:subtotal]||'')} of #{datum_value[:ref]}' fld='#{header_index_of(datum_value[:ref])}' baseField='0' baseItem='0'"
221
- str << " numFmtId='#{datum_value[:num_fmt]}'" if datum_value[:num_fmt]
222
- str << " subtotal='#{datum_value[:subtotal]}' " if datum_value[:subtotal]
223
- str << "/>"
224
- end
225
- str << '</dataFields>'
226
- end
227
- # custom pivot table style
228
- unless style_info.empty?
229
- str << '<pivotTableStyleInfo'
230
- style_info.each do |k,v|
231
- str << ' ' << k.to_s << '="' << v.to_s << '"'
232
- end
233
- str << ' />'
234
- end
235
- str << '</pivotTableDefinition>'
236
- end
237
-
238
- # References for header cells
239
- # @return [Array]
240
- def header_cell_refs
241
- Axlsx::range_to_a(header_range).first
242
- end
243
-
244
- # The header cells for the pivot table
245
- # @return [Array]
246
- def header_cells
247
- data_sheet[header_range]
248
- end
249
-
250
- # The values in the header cells collection
251
- # @return [Array]
252
- def header_cell_values
253
- header_cells.map(&:value)
254
- end
255
-
256
- # The number of cells in the header_cells collection
257
- # @return [Integer]
258
- def header_cells_count
259
- header_cells.count
260
- end
261
-
262
- # The index of a given value in the header cells
263
- # @return [Integer]
264
- def header_index_of(value)
265
- header_cell_values.index(value)
266
- end
267
-
268
- private
269
-
270
- def pivot_field_for(cell_ref, subtotal=true)
271
- if rows.include? cell_ref
272
- if subtotal
273
- '<pivotField axis="axisRow" compact="0" outline="0" subtotalTop="0" showAll="0" includeNewItemsInFilter="1"><items count="1"><item t="default"/></items></pivotField>'
274
- else
275
- '<pivotField axis="axisRow" compact="0" outline="0" subtotalTop="0" showAll="0" includeNewItemsInFilter="1" defaultSubtotal="0"></pivotField>'
276
- end
277
- elsif columns.include? cell_ref
278
- '<pivotField axis="axisCol" compact="0" outline="0" subtotalTop="0" showAll="0" includeNewItemsInFilter="1"><items count="1"><item t="default"/></items></pivotField>'
279
- elsif pages.include? cell_ref
280
- '<pivotField axis="axisPage" compact="0" outline="0" subtotalTop="0" showAll="0" includeNewItemsInFilter="1"><items count="1"><item t="default"/></items></pivotField>'
281
- elsif data_refs.include? cell_ref
282
- '<pivotField dataField="1" compact="0" outline="0" subtotalTop="0" showAll="0" includeNewItemsInFilter="1"></pivotField>'
283
- else
284
- '<pivotField compact="0" outline="0" subtotalTop="0" showAll="0" includeNewItemsInFilter="1"></pivotField>'
285
- end
286
- end
287
-
288
- def data_refs
289
- data.map { |hash| hash[:ref] }
290
- end
291
-
292
- def header_range
293
- range.gsub(/^(\w+?)(\d+)\:(\w+?)\d+$/, '\1\2:\3\2')
294
- end
295
- end
296
- end
1
+ module Axlsx
2
+ # Table
3
+ # @note Worksheet#add_pivot_table is the recommended way to create tables for your worksheets.
4
+ # @see README for examples
5
+ class PivotTable
6
+ include Axlsx::OptionsParser
7
+
8
+ # Creates a new PivotTable object
9
+ # @param [String] ref The reference to where the pivot table lives like 'G4:L17'.
10
+ # @param [String] range The reference to the pivot table data like 'A1:D31'.
11
+ # @param [Worksheet] sheet The sheet containing the table data.
12
+ # @option options [Cell, String] name
13
+ # @option options [TableStyle] style
14
+ def initialize(ref, range, sheet, options = {})
15
+ @ref = ref
16
+ self.range = range
17
+ @sheet = sheet
18
+ @sheet.workbook.pivot_tables << self
19
+ @name = "PivotTable#{index + 1}"
20
+ @data_sheet = nil
21
+ @rows = []
22
+ @columns = []
23
+ @data = []
24
+ @pages = []
25
+ @subtotal = nil
26
+ @no_subtotals_on_headers = []
27
+ @sort_on_headers = {}
28
+ @style_info = {}
29
+ parse_options options
30
+ yield self if block_given?
31
+ end
32
+
33
+ # Defines the headers in which subtotals are not to be included.
34
+ # @return [Array]
35
+ attr_accessor :no_subtotals_on_headers
36
+
37
+ # Defines the headers in which sort is applied.
38
+ # Can be an array of headers to sort ascending by default, or a hash for specific control
39
+ # (with headers as keys, `:ascending` or `:descending` as values).
40
+ #
41
+ # Examples: `["year", "month"]` or `{"year" => :descending, "month" => :descending}`
42
+ # @return [Hash]
43
+ attr_reader :sort_on_headers
44
+
45
+ # (see #sort_on_headers)
46
+ def sort_on_headers=(headers)
47
+ headers ||= {}
48
+ headers = Hash[*headers.map { |h| [h, :ascending] }.flatten] if headers.is_a?(Array)
49
+ @sort_on_headers = headers
50
+ end
51
+
52
+ # Style info for the pivot table
53
+ # @return [Hash]
54
+ attr_accessor :style_info
55
+
56
+ # The reference to the table data
57
+ # @return [String]
58
+ attr_reader :ref
59
+
60
+ # The name of the table.
61
+ # @return [String]
62
+ attr_reader :name
63
+
64
+ # The name of the sheet.
65
+ # @return [String]
66
+ attr_reader :sheet
67
+
68
+ # The sheet used as data source for the pivot table
69
+ # @return [Worksheet]
70
+ attr_writer :data_sheet
71
+
72
+ # @see #data_sheet
73
+ def data_sheet
74
+ @data_sheet || @sheet
75
+ end
76
+
77
+ # The range where the data for this pivot table lives.
78
+ # @return [String]
79
+ attr_reader :range
80
+
81
+ # (see #range)
82
+ def range=(v)
83
+ DataTypeValidator.validate "#{self.class}.range", [String], v
84
+ if v.is_a?(String)
85
+ @range = v
86
+ end
87
+ end
88
+
89
+ # The rows
90
+ # @return [Array]
91
+ attr_reader :rows
92
+
93
+ # (see #rows)
94
+ def rows=(v)
95
+ DataTypeValidator.validate "#{self.class}.rows", [Array], v
96
+ v.each do |ref|
97
+ DataTypeValidator.validate "#{self.class}.rows[]", [String], ref
98
+ end
99
+ @rows = v
100
+ end
101
+
102
+ # The columns
103
+ # @return [Array]
104
+ attr_reader :columns
105
+
106
+ # (see #columns)
107
+ def columns=(v)
108
+ DataTypeValidator.validate "#{self.class}.columns", [Array], v
109
+ v.each do |ref|
110
+ DataTypeValidator.validate "#{self.class}.columns[]", [String], ref
111
+ end
112
+ @columns = v
113
+ end
114
+
115
+ # The data
116
+ # @return [Array]
117
+ attr_reader :data
118
+
119
+ # (see #data)
120
+ def data=(v)
121
+ DataTypeValidator.validate "#{self.class}.data", [Array], v
122
+ @data = []
123
+ v.each do |data_field|
124
+ if data_field.is_a? String
125
+ data_field = { :ref => data_field }
126
+ end
127
+ data_field.each do |key, value|
128
+ if key == :num_fmt
129
+ DataTypeValidator.validate "#{self.class}.data[]", [Integer], value
130
+ else
131
+ DataTypeValidator.validate "#{self.class}.data[]", [String], value
132
+ end
133
+ end
134
+ @data << data_field
135
+ end
136
+ @data
137
+ end
138
+
139
+ # The pages
140
+ # @return [String]
141
+ attr_reader :pages
142
+
143
+ # (see #pages)
144
+ def pages=(v)
145
+ DataTypeValidator.validate "#{self.class}.pages", [Array], v
146
+ v.each do |ref|
147
+ DataTypeValidator.validate "#{self.class}.pages[]", [String], ref
148
+ end
149
+ @pages = v
150
+ end
151
+
152
+ # The index of this chart in the workbooks charts collection
153
+ # @return [Integer]
154
+ def index
155
+ @sheet.workbook.pivot_tables.index(self)
156
+ end
157
+
158
+ # The part name for this table
159
+ # @return [String]
160
+ def pn
161
+ "#{PIVOT_TABLE_PN % (index + 1)}"
162
+ end
163
+
164
+ # The relationship part name of this pivot table
165
+ # @return [String]
166
+ def rels_pn
167
+ "#{PIVOT_TABLE_RELS_PN % (index + 1)}"
168
+ end
169
+
170
+ # The cache_definition for this pivot table
171
+ # @return [PivotTableCacheDefinition]
172
+ def cache_definition
173
+ @cache_definition ||= PivotTableCacheDefinition.new(self)
174
+ end
175
+
176
+ # The relationships for this pivot table.
177
+ # @return [Relationships]
178
+ def relationships
179
+ r = Relationships.new
180
+ r << Relationship.new(cache_definition, PIVOT_TABLE_CACHE_DEFINITION_R, "../#{cache_definition.pn}")
181
+ r
182
+ end
183
+
184
+ # Serializes the object
185
+ # @param [String] str
186
+ # @return [String]
187
+ def to_xml_string(str = '')
188
+ str << '<?xml version="1.0" encoding="UTF-8"?>'
189
+
190
+ str << ('<pivotTableDefinition xmlns="' << XML_NS << '" name="' << name << '" cacheId="' << cache_definition.cache_id.to_s << '"' << (data.size <= 1 ? ' dataOnRows="1"' : '') << ' applyNumberFormats="0" applyBorderFormats="0" applyFontFormats="0" applyPatternFormats="0" applyAlignmentFormats="0" applyWidthHeightFormats="1" dataCaption="Data" showMultipleLabel="0" showMemberPropertyTips="0" useAutoFormatting="1" indent="0" compact="0" compactData="0" gridDropZones="1" multipleFieldFilters="0">')
191
+
192
+ str << ('<location firstDataCol="1" firstDataRow="1" firstHeaderRow="1" ref="' << ref << '"/>')
193
+ str << ('<pivotFields count="' << header_cells_count.to_s << '">')
194
+
195
+ header_cell_values.each do |cell_value|
196
+ subtotal = !no_subtotals_on_headers.include?(cell_value)
197
+ sorttype = sort_on_headers[cell_value]
198
+ str << pivot_field_for(cell_value, subtotal, sorttype)
199
+ end
200
+
201
+ str << '</pivotFields>'
202
+ if rows.empty?
203
+ str << '<rowFields count="1"><field x="-2"/></rowFields>'
204
+ str << '<rowItems count="2"><i><x/></i> <i i="1"><x v="1"/></i></rowItems>'
205
+ else
206
+ str << ('<rowFields count="' << rows.size.to_s << '">')
207
+ rows.each do |row_value|
208
+ str << ('<field x="' << header_index_of(row_value).to_s << '"/>')
209
+ end
210
+ str << '</rowFields>'
211
+ str << ('<rowItems count="' << rows.size.to_s << '">')
212
+ rows.size.times do |i|
213
+ str << '<i/>'
214
+ end
215
+ str << '</rowItems>'
216
+ end
217
+ if columns.empty?
218
+ if data.size > 1
219
+ str << '<colFields count="1"><field x="-2"/></colFields>'
220
+ str << "<colItems count=\"#{data.size}\">"
221
+ str << '<i><x/></i>'
222
+ data[1..-1].each_with_index do |datum_value, i|
223
+ str << "<i i=\"#{i + 1}\"><x v=\"#{i + 1}\"/></i>"
224
+ end
225
+ str << '</colItems>'
226
+ else
227
+ str << '<colItems count="1"><i/></colItems>'
228
+ end
229
+ else
230
+ str << ('<colFields count="' << columns.size.to_s << '">')
231
+ columns.each do |column_value|
232
+ str << ('<field x="' << header_index_of(column_value).to_s << '"/>')
233
+ end
234
+ str << '</colFields>'
235
+ end
236
+ unless pages.empty?
237
+ str << ('<pageFields count="' << pages.size.to_s << '">')
238
+ pages.each do |page_value|
239
+ str << ('<pageField fld="' << header_index_of(page_value).to_s << '"/>')
240
+ end
241
+ str << '</pageFields>'
242
+ end
243
+ unless data.empty?
244
+ str << "<dataFields count=\"#{data.size}\">"
245
+ data.each do |datum_value|
246
+ # The correct name prefix in ["Sum","Average", etc...]
247
+ str << "<dataField name='#{(datum_value[:subtotal] || '')} of #{datum_value[:ref]}' fld='#{header_index_of(datum_value[:ref])}' baseField='0' baseItem='0'"
248
+ str << " numFmtId='#{datum_value[:num_fmt]}'" if datum_value[:num_fmt]
249
+ str << " subtotal='#{datum_value[:subtotal]}' " if datum_value[:subtotal]
250
+ str << "/>"
251
+ end
252
+ str << '</dataFields>'
253
+ end
254
+ # custom pivot table style
255
+ unless style_info.empty?
256
+ str << '<pivotTableStyleInfo'
257
+ style_info.each do |k, v|
258
+ str << ' ' << k.to_s << '="' << v.to_s << '"'
259
+ end
260
+ str << ' />'
261
+ end
262
+ str << '</pivotTableDefinition>'
263
+ end
264
+
265
+ # References for header cells
266
+ # @return [Array]
267
+ def header_cell_refs
268
+ Axlsx::range_to_a(header_range).first
269
+ end
270
+
271
+ # The header cells for the pivot table
272
+ # @return [Array]
273
+ def header_cells
274
+ data_sheet[header_range]
275
+ end
276
+
277
+ # The values in the header cells collection
278
+ # @return [Array]
279
+ def header_cell_values
280
+ header_cells.map(&:value)
281
+ end
282
+
283
+ # The number of cells in the header_cells collection
284
+ # @return [Integer]
285
+ def header_cells_count
286
+ header_cells.count
287
+ end
288
+
289
+ # The index of a given value in the header cells
290
+ # @return [Integer]
291
+ def header_index_of(value)
292
+ header_cell_values.index(value)
293
+ end
294
+
295
+ private
296
+
297
+ def pivot_field_for(cell_ref, subtotal, sorttype)
298
+ attributes = %w[compact="0" outline="0" subtotalTop="0" showAll="0" includeNewItemsInFilter="1"]
299
+ items_tag = '<items count="1"><item t="default"/></items>'
300
+ include_items_tag = false
301
+
302
+ if rows.include? cell_ref
303
+ attributes << 'axis="axisRow"'
304
+ attributes << "sortType=\"#{sorttype == :descending ? 'descending' : 'ascending'}\"" if sorttype
305
+ if subtotal
306
+ include_items_tag = true
307
+ else
308
+ attributes << 'defaultSubtotal="0"'
309
+ end
310
+ elsif columns.include? cell_ref
311
+ attributes << 'axis="axisCol"'
312
+ attributes << "sortType=\"#{sorttype == :descending ? 'descending' : 'ascending'}\"" if sorttype
313
+ include_items_tag = true
314
+ elsif pages.include? cell_ref
315
+ attributes << 'axis="axisPage"'
316
+ include_items_tag = true
317
+ elsif data_refs.include? cell_ref
318
+ attributes << 'dataField="1"'
319
+ end
320
+
321
+ "<pivotField #{attributes.join(' ')}>#{include_items_tag ? items_tag : nil}</pivotField>"
322
+ end
323
+
324
+ def data_refs
325
+ data.map { |hash| hash[:ref] }
326
+ end
327
+
328
+ def header_range
329
+ range.gsub(/^(\w+?)(\d+)\:(\w+?)\d+$/, '\1\2:\3\2')
330
+ end
331
+ end
332
+ end