axlsx 1.2.0 → 2.0.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.
- checksums.yaml +7 -0
- data/.yardopts +3 -2
- data/.yardopts_guide +19 -0
- data/CHANGELOG.md +64 -1
- data/README.md +105 -87
- data/Rakefile +0 -5
- data/examples/2010_comments.rb +17 -0
- data/examples/anchor_swapping.rb +28 -0
- data/examples/auto_filter.rb +16 -0
- data/examples/basic_charts.rb +4 -0
- data/examples/colored_links.rb +59 -0
- data/examples/conditional_formatting/example_conditional_formatting.rb +4 -2
- data/examples/example.rb +569 -258
- data/examples/ios_preview.rb +14 -0
- data/examples/page_setup.rb +11 -0
- data/examples/pivot_table.rb +39 -0
- data/examples/skydrive/real_example.rb +8 -8
- data/examples/styles.rb +66 -0
- data/examples/underline.rb +13 -0
- data/examples/wrap_text.rb +21 -0
- data/lib/axlsx/content_type/abstract_content_type.rb +32 -0
- data/lib/axlsx/content_type/content_type.rb +1 -1
- data/lib/axlsx/content_type/default.rb +6 -37
- data/lib/axlsx/content_type/override.rb +6 -38
- data/lib/axlsx/doc_props/app.rb +10 -7
- data/lib/axlsx/doc_props/core.rb +6 -1
- data/lib/axlsx/drawing/axes.rb +61 -0
- data/lib/axlsx/drawing/axis.rb +20 -17
- data/lib/axlsx/drawing/bar_3D_chart.rb +31 -22
- data/lib/axlsx/drawing/cat_axis.rb +2 -10
- data/lib/axlsx/drawing/chart.rb +33 -6
- data/lib/axlsx/drawing/d_lbls.rb +21 -31
- data/lib/axlsx/drawing/drawing.rb +11 -17
- data/lib/axlsx/drawing/graphic_frame.rb +3 -3
- data/lib/axlsx/drawing/hyperlink.rb +42 -36
- data/lib/axlsx/drawing/line_3D_chart.rb +28 -70
- data/lib/axlsx/drawing/line_chart.rb +99 -0
- data/lib/axlsx/drawing/line_series.rb +20 -2
- data/lib/axlsx/drawing/marker.rb +38 -18
- data/lib/axlsx/drawing/num_data.rb +6 -6
- data/lib/axlsx/drawing/num_data_source.rb +17 -16
- data/lib/axlsx/drawing/one_cell_anchor.rb +28 -21
- data/lib/axlsx/drawing/pic.rb +43 -45
- data/lib/axlsx/drawing/picture_locking.rb +12 -44
- data/lib/axlsx/drawing/pie_3D_chart.rb +2 -1
- data/lib/axlsx/drawing/scaling.rb +13 -13
- data/lib/axlsx/drawing/scatter_chart.rb +32 -21
- data/lib/axlsx/drawing/ser_axis.rb +15 -16
- data/lib/axlsx/drawing/series.rb +3 -6
- data/lib/axlsx/drawing/str_data.rb +3 -3
- data/lib/axlsx/drawing/str_val.rb +7 -8
- data/lib/axlsx/drawing/two_cell_anchor.rb +7 -27
- data/lib/axlsx/drawing/val_axis.rb +14 -13
- data/lib/axlsx/drawing/view_3D.rb +52 -38
- data/lib/axlsx/drawing/vml_shape.rb +20 -79
- data/lib/axlsx/package.rb +58 -28
- data/lib/axlsx/rels/relationship.rb +75 -9
- data/lib/axlsx/rels/relationships.rb +8 -1
- data/lib/axlsx/stylesheet/border.rb +29 -20
- data/lib/axlsx/stylesheet/border_pr.rb +5 -4
- data/lib/axlsx/stylesheet/cell_alignment.rb +55 -29
- data/lib/axlsx/stylesheet/cell_protection.rb +7 -4
- data/lib/axlsx/stylesheet/cell_style.rb +19 -14
- data/lib/axlsx/stylesheet/color.rb +20 -17
- data/lib/axlsx/stylesheet/dxf.rb +4 -4
- data/lib/axlsx/stylesheet/font.rb +22 -22
- data/lib/axlsx/stylesheet/gradient_fill.rb +45 -21
- data/lib/axlsx/stylesheet/num_fmt.rb +23 -14
- data/lib/axlsx/stylesheet/pattern_fill.rb +12 -21
- data/lib/axlsx/stylesheet/styles.rb +37 -22
- data/lib/axlsx/stylesheet/table_style.rb +17 -16
- data/lib/axlsx/stylesheet/table_style_element.rb +15 -11
- data/lib/axlsx/stylesheet/table_styles.rb +14 -11
- data/lib/axlsx/stylesheet/xf.rb +28 -26
- data/lib/axlsx/util/accessors.rb +64 -0
- data/lib/axlsx/util/constants.rb +127 -6
- data/lib/axlsx/util/options_parser.rb +15 -0
- data/lib/axlsx/util/serialized_attributes.rb +79 -0
- data/lib/axlsx/util/simple_typed_list.rb +50 -15
- data/lib/axlsx/util/validators.rb +51 -16
- data/lib/axlsx/version.rb +2 -2
- data/lib/axlsx/workbook/defined_name.rb +14 -59
- data/lib/axlsx/workbook/shared_strings_table.rb +13 -4
- data/lib/axlsx/workbook/workbook.rb +85 -6
- data/lib/axlsx/workbook/worksheet/auto_filter/auto_filter.rb +77 -0
- data/lib/axlsx/workbook/worksheet/auto_filter/filter_column.rb +94 -0
- data/lib/axlsx/workbook/worksheet/auto_filter/filters.rb +246 -0
- data/lib/axlsx/workbook/worksheet/break.rb +37 -0
- data/lib/axlsx/workbook/worksheet/cell.rb +109 -107
- data/lib/axlsx/workbook/worksheet/cell_serializer.rb +144 -0
- data/lib/axlsx/workbook/worksheet/cfvo.rb +15 -15
- data/lib/axlsx/workbook/worksheet/cfvos.rb +15 -0
- data/lib/axlsx/workbook/worksheet/col.rb +43 -29
- data/lib/axlsx/workbook/worksheet/col_breaks.rb +35 -0
- data/lib/axlsx/workbook/worksheet/color_scale.rb +62 -28
- data/lib/axlsx/workbook/worksheet/comment.rb +28 -37
- data/lib/axlsx/workbook/worksheet/comments.rb +3 -3
- data/lib/axlsx/workbook/worksheet/conditional_formatting.rb +11 -11
- data/lib/axlsx/workbook/worksheet/conditional_formatting_rule.rb +31 -27
- data/lib/axlsx/workbook/worksheet/data_bar.rb +75 -41
- data/lib/axlsx/workbook/worksheet/data_validation.rb +61 -62
- data/lib/axlsx/workbook/worksheet/date_time_converter.rb +6 -5
- data/lib/axlsx/workbook/worksheet/dimension.rb +0 -1
- data/lib/axlsx/workbook/worksheet/header_footer.rb +54 -0
- data/lib/axlsx/workbook/worksheet/icon_set.rb +20 -20
- data/lib/axlsx/workbook/worksheet/page_margins.rb +21 -19
- data/lib/axlsx/workbook/worksheet/page_set_up_pr.rb +44 -0
- data/lib/axlsx/workbook/worksheet/page_setup.rb +152 -23
- data/lib/axlsx/workbook/worksheet/pane.rb +48 -51
- data/lib/axlsx/workbook/worksheet/pivot_table.rb +273 -0
- data/lib/axlsx/workbook/worksheet/pivot_table_cache_definition.rb +66 -0
- data/lib/axlsx/workbook/worksheet/pivot_tables.rb +24 -0
- data/lib/axlsx/workbook/worksheet/print_options.rb +8 -30
- data/lib/axlsx/workbook/worksheet/protected_range.rb +16 -13
- data/lib/axlsx/workbook/worksheet/row.rb +59 -83
- data/lib/axlsx/workbook/worksheet/row_breaks.rb +33 -0
- data/lib/axlsx/workbook/worksheet/selection.rb +30 -38
- data/lib/axlsx/workbook/worksheet/sheet_calc_pr.rb +29 -0
- data/lib/axlsx/workbook/worksheet/sheet_format_pr.rb +60 -0
- data/lib/axlsx/workbook/worksheet/sheet_pr.rb +49 -4
- data/lib/axlsx/workbook/worksheet/sheet_protection.rb +51 -155
- data/lib/axlsx/workbook/worksheet/sheet_view.rb +68 -234
- data/lib/axlsx/workbook/worksheet/table.rb +25 -19
- data/lib/axlsx/workbook/worksheet/table_style_info.rb +51 -0
- data/lib/axlsx/workbook/worksheet/tables.rb +1 -1
- data/lib/axlsx/workbook/worksheet/worksheet.rb +174 -35
- data/lib/axlsx/workbook/worksheet/worksheet_comments.rb +6 -5
- data/lib/axlsx/workbook/worksheet/worksheet_drawing.rb +4 -10
- data/lib/axlsx/workbook/worksheet/worksheet_hyperlink.rb +74 -0
- data/lib/axlsx/workbook/worksheet/worksheet_hyperlinks.rb +38 -0
- data/lib/axlsx.rb +55 -5
- data/lib/schema/sml.xsd +4 -0
- data/test/axlsx.qcachegrind +2226 -0
- data/test/benchmark.rb +2 -3
- data/test/content_type/tc_default.rb +0 -11
- data/test/content_type/tc_override.rb +0 -13
- data/test/doc_props/tc_core.rb +7 -0
- data/test/drawing/tc_axes.rb +8 -0
- data/test/drawing/tc_axis.rb +15 -17
- data/test/drawing/tc_bar_3D_chart.rb +6 -0
- data/test/drawing/tc_cat_axis.rb +9 -9
- data/test/drawing/tc_chart.rb +20 -0
- data/test/drawing/tc_d_lbls.rb +14 -4
- data/test/drawing/tc_drawing.rb +0 -5
- data/test/drawing/tc_graphic_frame.rb +5 -3
- data/test/drawing/tc_hyperlink.rb +0 -4
- data/test/drawing/tc_line_chart.rb +39 -0
- data/test/drawing/tc_line_series.rb +8 -2
- data/test/drawing/tc_pic.rb +14 -3
- data/test/drawing/tc_ser_axis.rb +13 -12
- data/test/drawing/tc_two_cell_anchor.rb +3 -3
- data/test/drawing/tc_val_axis.rb +6 -6
- data/test/drawing/tc_vml_shape.rb +9 -3
- data/test/profile.rb +11 -21
- data/test/rels/tc_relationship.rb +32 -9
- data/test/rels/tc_relationships.rb +12 -1
- data/test/stylesheet/tc_color.rb +6 -0
- data/test/stylesheet/tc_styles.rb +15 -2
- data/test/tc_axlsx.rb +35 -2
- data/test/tc_helper.rb +7 -1
- data/test/tc_package.rb +44 -5
- data/test/util/tc_serialized_attributes.rb +19 -0
- data/test/util/tc_validators.rb +26 -1
- data/test/workbook/tc_defined_name.rb +2 -2
- data/test/workbook/tc_shared_strings_table.rb +6 -0
- data/test/workbook/tc_workbook.rb +38 -1
- data/test/workbook/worksheet/auto_filter/tc_auto_filter.rb +38 -0
- data/test/workbook/worksheet/auto_filter/tc_filter_column.rb +76 -0
- data/test/workbook/worksheet/auto_filter/tc_filters.rb +50 -0
- data/test/workbook/worksheet/tc_break.rb +49 -0
- data/test/workbook/worksheet/tc_cell.rb +40 -6
- data/test/workbook/worksheet/tc_col.rb +11 -1
- data/test/workbook/worksheet/tc_color_scale.rb +31 -2
- data/test/workbook/worksheet/tc_comment.rb +21 -6
- data/test/workbook/worksheet/tc_comments.rb +2 -2
- data/test/workbook/worksheet/tc_conditional_formatting.rb +7 -0
- data/test/workbook/worksheet/tc_data_bar.rb +7 -0
- data/test/workbook/worksheet/tc_date_time_converter.rb +3 -11
- data/test/workbook/worksheet/tc_header_footer.rb +151 -0
- data/test/workbook/worksheet/tc_page_set_up_pr.rb +15 -0
- data/test/workbook/worksheet/tc_page_setup.rb +6 -1
- data/test/workbook/worksheet/tc_pane.rb +5 -45
- data/test/workbook/worksheet/tc_pivot_table.rb +120 -0
- data/test/workbook/worksheet/tc_pivot_table_cache_definition.rb +54 -0
- data/test/workbook/worksheet/tc_row.rb +4 -4
- data/test/workbook/worksheet/tc_selection.rb +9 -48
- data/test/workbook/worksheet/tc_sheet_calc_pr.rb +18 -0
- data/test/workbook/worksheet/tc_sheet_format_pr.rb +88 -0
- data/test/workbook/worksheet/tc_sheet_pr.rb +27 -0
- data/test/workbook/worksheet/tc_sheet_view.rb +39 -39
- data/test/workbook/worksheet/{table/tc_table.rb → tc_table.rb} +8 -3
- data/test/workbook/worksheet/tc_table_style_info.rb +53 -0
- data/test/workbook/worksheet/tc_worksheet.rb +131 -16
- data/test/workbook/worksheet/tc_worksheet_hyperlink.rb +55 -0
- metadata +97 -64
- data/examples/example.xlsx +0 -0
- data/examples/example_streamed.xlsx +0 -0
- data/examples/extractive.pdf +0 -0
- data/examples/image1.gif +0 -0
- data/examples/image1.jpg +0 -0
- data/examples/image1.png +0 -0
- data/examples/no-use_autowidth.xlsx +0 -0
- data/examples/sample.png +0 -0
- data/examples/scraping_html.rb +0 -91
- data/examples/shared_strings_example.xlsx +0 -0
- data/examples/sheet_view.rb +0 -34
- data/examples/two_cell_anchor_image.rb +0 -11
- data/lib/axlsx/workbook/worksheet/auto_filter.rb +0 -34
|
@@ -0,0 +1,273 @@
|
|
|
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
|
+
parse_options options
|
|
29
|
+
yield self if block_given?
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# The reference to the table data
|
|
33
|
+
# @return [String]
|
|
34
|
+
attr_reader :ref
|
|
35
|
+
|
|
36
|
+
# The name of the table.
|
|
37
|
+
# @return [String]
|
|
38
|
+
attr_reader :name
|
|
39
|
+
|
|
40
|
+
# The name of the sheet.
|
|
41
|
+
# @return [String]
|
|
42
|
+
attr_reader :sheet
|
|
43
|
+
|
|
44
|
+
# The sheet used as data source for the pivot table
|
|
45
|
+
# @return [Worksheet]
|
|
46
|
+
attr_writer :data_sheet
|
|
47
|
+
|
|
48
|
+
# @see #data_sheet
|
|
49
|
+
def data_sheet
|
|
50
|
+
@data_sheet || @sheet
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# The range where the data for this pivot table lives.
|
|
54
|
+
# @return [String]
|
|
55
|
+
attr_reader :range
|
|
56
|
+
|
|
57
|
+
# (see #range)
|
|
58
|
+
def range=(v)
|
|
59
|
+
DataTypeValidator.validate "#{self.class}.range", [String], v
|
|
60
|
+
if v.is_a?(String)
|
|
61
|
+
@range = v
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# The rows
|
|
66
|
+
# @return [Array]
|
|
67
|
+
attr_reader :rows
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
# (see #rows)
|
|
71
|
+
def rows=(v)
|
|
72
|
+
DataTypeValidator.validate "#{self.class}.rows", [Array], v
|
|
73
|
+
v.each do |ref|
|
|
74
|
+
DataTypeValidator.validate "#{self.class}.rows[]", [String], ref
|
|
75
|
+
end
|
|
76
|
+
@rows = v
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# The columns
|
|
80
|
+
# @return [Array]
|
|
81
|
+
attr_reader :columns
|
|
82
|
+
|
|
83
|
+
# (see #columns)
|
|
84
|
+
def columns=(v)
|
|
85
|
+
DataTypeValidator.validate "#{self.class}.columns", [Array], v
|
|
86
|
+
v.each do |ref|
|
|
87
|
+
DataTypeValidator.validate "#{self.class}.columns[]", [String], ref
|
|
88
|
+
end
|
|
89
|
+
@columns = v
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# The data
|
|
93
|
+
# @return [Array]
|
|
94
|
+
attr_reader :data
|
|
95
|
+
|
|
96
|
+
# (see #data)
|
|
97
|
+
def data=(v)
|
|
98
|
+
DataTypeValidator.validate "#{self.class}.data", [Array], v
|
|
99
|
+
@data = []
|
|
100
|
+
v.each do |data_field|
|
|
101
|
+
if data_field.is_a? String
|
|
102
|
+
data_field = {:ref => data_field}
|
|
103
|
+
end
|
|
104
|
+
data_field.values.each do |value|
|
|
105
|
+
DataTypeValidator.validate "#{self.class}.data[]", [String], value
|
|
106
|
+
end
|
|
107
|
+
@data << data_field
|
|
108
|
+
end
|
|
109
|
+
@data
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# The pages
|
|
113
|
+
# @return [String]
|
|
114
|
+
attr_reader :pages
|
|
115
|
+
|
|
116
|
+
# (see #pages)
|
|
117
|
+
def pages=(v)
|
|
118
|
+
DataTypeValidator.validate "#{self.class}.pages", [Array], v
|
|
119
|
+
v.each do |ref|
|
|
120
|
+
DataTypeValidator.validate "#{self.class}.pages[]", [String], ref
|
|
121
|
+
end
|
|
122
|
+
@pages = v
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# The index of this chart in the workbooks charts collection
|
|
126
|
+
# @return [Integer]
|
|
127
|
+
def index
|
|
128
|
+
@sheet.workbook.pivot_tables.index(self)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# The part name for this table
|
|
132
|
+
# @return [String]
|
|
133
|
+
def pn
|
|
134
|
+
"#{PIVOT_TABLE_PN % (index+1)}"
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# The relationship part name of this pivot table
|
|
138
|
+
# @return [String]
|
|
139
|
+
def rels_pn
|
|
140
|
+
"#{PIVOT_TABLE_RELS_PN % (index+1)}"
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# The cache_definition for this pivot table
|
|
144
|
+
# @return [PivotTableCacheDefinition]
|
|
145
|
+
def cache_definition
|
|
146
|
+
@cache_definition ||= PivotTableCacheDefinition.new(self)
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# The relationships for this pivot table.
|
|
150
|
+
# @return [Relationships]
|
|
151
|
+
def relationships
|
|
152
|
+
r = Relationships.new
|
|
153
|
+
r << Relationship.new(cache_definition, PIVOT_TABLE_CACHE_DEFINITION_R, "../#{cache_definition.pn}")
|
|
154
|
+
r
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# Serializes the object
|
|
158
|
+
# @param [String] str
|
|
159
|
+
# @return [String]
|
|
160
|
+
def to_xml_string(str = '')
|
|
161
|
+
str << '<?xml version="1.0" encoding="UTF-8"?>'
|
|
162
|
+
str << '<pivotTableDefinition xmlns="' << XML_NS << '" name="' << name << '" cacheId="' << cache_definition.cache_id.to_s << '" 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">'
|
|
163
|
+
str << '<location firstDataCol="1" firstDataRow="1" firstHeaderRow="1" ref="' << ref << '"/>'
|
|
164
|
+
str << '<pivotFields count="' << header_cells_count.to_s << '">'
|
|
165
|
+
header_cell_values.each do |cell_value|
|
|
166
|
+
str << pivot_field_for(cell_value)
|
|
167
|
+
end
|
|
168
|
+
str << '</pivotFields>'
|
|
169
|
+
if rows.empty?
|
|
170
|
+
str << '<rowFields count="1"><field x="-2"/></rowFields>'
|
|
171
|
+
str << '<rowItems count="2"><i><x/></i> <i i="1"><x v="1"/></i></rowItems>'
|
|
172
|
+
else
|
|
173
|
+
str << '<rowFields count="' << rows.size.to_s << '">'
|
|
174
|
+
rows.each do |row_value|
|
|
175
|
+
str << '<field x="' << header_index_of(row_value).to_s << '"/>'
|
|
176
|
+
end
|
|
177
|
+
str << '</rowFields>'
|
|
178
|
+
str << '<rowItems count="' << rows.size.to_s << '">'
|
|
179
|
+
rows.size.times do |i|
|
|
180
|
+
str << '<i/>'
|
|
181
|
+
end
|
|
182
|
+
str << '</rowItems>'
|
|
183
|
+
end
|
|
184
|
+
if columns.empty?
|
|
185
|
+
str << '<colItems count="1"><i/></colItems>'
|
|
186
|
+
else
|
|
187
|
+
str << '<colFields count="' << columns.size.to_s << '">'
|
|
188
|
+
columns.each do |column_value|
|
|
189
|
+
str << '<field x="' << header_index_of(column_value).to_s << '"/>'
|
|
190
|
+
end
|
|
191
|
+
str << '</colFields>'
|
|
192
|
+
end
|
|
193
|
+
unless pages.empty?
|
|
194
|
+
str << '<pageFields count="' << pages.size.to_s << '">'
|
|
195
|
+
pages.each do |page_value|
|
|
196
|
+
str << '<pageField fld="' << header_index_of(page_value).to_s << '"/>'
|
|
197
|
+
end
|
|
198
|
+
str << '</pageFields>'
|
|
199
|
+
end
|
|
200
|
+
unless data.empty?
|
|
201
|
+
str << "<dataFields count=\"#{data.size}\">"
|
|
202
|
+
data.each do |datum_value|
|
|
203
|
+
str << "<dataField name='#{@subtotal} of #{datum_value[:ref]}' fld='#{header_index_of(datum_value[:ref])}' baseField='0' baseItem='0'"
|
|
204
|
+
str << " subtotal='#{datum_value[:subtotal]}' " if datum_value[:subtotal]
|
|
205
|
+
str << "/>"
|
|
206
|
+
end
|
|
207
|
+
str << '</dataFields>'
|
|
208
|
+
end
|
|
209
|
+
str << '</pivotTableDefinition>'
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
# References for header cells
|
|
213
|
+
# @return [Array]
|
|
214
|
+
def header_cell_refs
|
|
215
|
+
Axlsx::range_to_a(header_range).first
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
# The header cells for the pivot table
|
|
219
|
+
# @return [Array]
|
|
220
|
+
def header_cells
|
|
221
|
+
data_sheet[header_range]
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
# The values in the header cells collection
|
|
225
|
+
# @return [Array]
|
|
226
|
+
def header_cell_values
|
|
227
|
+
header_cells.map(&:value)
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
# The number of cells in the header_cells collection
|
|
231
|
+
# @return [Integer]
|
|
232
|
+
def header_cells_count
|
|
233
|
+
header_cells.count
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
# The index of a given value in the header cells
|
|
237
|
+
# @return [Integer]
|
|
238
|
+
def header_index_of(value)
|
|
239
|
+
header_cell_values.index(value)
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
private
|
|
243
|
+
|
|
244
|
+
def pivot_field_for(cell_ref)
|
|
245
|
+
if rows.include? cell_ref
|
|
246
|
+
'<pivotField axis="axisRow" compact="0" outline="0" subtotalTop="0" showAll="0" includeNewItemsInFilter="1">' <<
|
|
247
|
+
'<items count="1"><item t="default"/></items>' <<
|
|
248
|
+
'</pivotField>'
|
|
249
|
+
elsif columns.include? cell_ref
|
|
250
|
+
'<pivotField axis="axisCol" compact="0" outline="0" subtotalTop="0" showAll="0" includeNewItemsInFilter="1">' <<
|
|
251
|
+
'<items count="1"><item t="default"/></items>' <<
|
|
252
|
+
'</pivotField>'
|
|
253
|
+
elsif pages.include? cell_ref
|
|
254
|
+
'<pivotField axis="axisCol" compact="0" outline="0" subtotalTop="0" showAll="0" includeNewItemsInFilter="1">' <<
|
|
255
|
+
'<items count="1"><item t="default"/></items>' <<
|
|
256
|
+
'</pivotField>'
|
|
257
|
+
elsif data_refs.include? cell_ref
|
|
258
|
+
'<pivotField dataField="1" compact="0" outline="0" subtotalTop="0" showAll="0" includeNewItemsInFilter="1">' <<
|
|
259
|
+
'</pivotField>'
|
|
260
|
+
else
|
|
261
|
+
'<pivotField compact="0" outline="0" subtotalTop="0" showAll="0" includeNewItemsInFilter="1">' <<
|
|
262
|
+
'</pivotField>'
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
def data_refs
|
|
266
|
+
data.map { |hash| hash[:ref] }
|
|
267
|
+
end
|
|
268
|
+
def header_range
|
|
269
|
+
range.gsub(/^(\w+?)(\d+)\:(\w+?)\d+$/, '\1\2:\3\2')
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
end
|
|
273
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
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 PivotTableCacheDefinition
|
|
7
|
+
|
|
8
|
+
include Axlsx::OptionsParser
|
|
9
|
+
|
|
10
|
+
# Creates a new PivotTable object
|
|
11
|
+
# @param [String] pivot_table The pivot table this cache definition is in
|
|
12
|
+
def initialize(pivot_table)
|
|
13
|
+
@pivot_table = pivot_table
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# # The reference to the pivot table data
|
|
17
|
+
# # @return [PivotTable]
|
|
18
|
+
attr_reader :pivot_table
|
|
19
|
+
|
|
20
|
+
# The index of this chart in the workbooks charts collection
|
|
21
|
+
# @return [Integer]
|
|
22
|
+
def index
|
|
23
|
+
pivot_table.sheet.workbook.pivot_tables.index(pivot_table)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# The part name for this table
|
|
27
|
+
# @return [String]
|
|
28
|
+
def pn
|
|
29
|
+
"#{PIVOT_TABLE_CACHE_DEFINITION_PN % (index+1)}"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# The identifier for this cache
|
|
33
|
+
# @return [Integer]
|
|
34
|
+
def cache_id
|
|
35
|
+
index + 1
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# The relationship id for this pivot table cache definition.
|
|
39
|
+
# @see Relationship#Id
|
|
40
|
+
# @return [String]
|
|
41
|
+
def rId
|
|
42
|
+
pivot_table.relationships.for(self).Id
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Serializes the object
|
|
46
|
+
# @param [String] str
|
|
47
|
+
# @return [String]
|
|
48
|
+
def to_xml_string(str = '')
|
|
49
|
+
str << '<?xml version="1.0" encoding="UTF-8"?>'
|
|
50
|
+
str << '<pivotCacheDefinition xmlns="' << XML_NS << '" xmlns:r="' << XML_NS_R << '" invalid="1" refreshOnLoad="1" recordCount="0">'
|
|
51
|
+
str << '<cacheSource type="worksheet">'
|
|
52
|
+
str << '<worksheetSource ref="' << pivot_table.range << '" sheet="' << pivot_table.data_sheet.name << '"/>'
|
|
53
|
+
str << '</cacheSource>'
|
|
54
|
+
str << '<cacheFields count="' << pivot_table.header_cells_count.to_s << '">'
|
|
55
|
+
pivot_table.header_cells.each do |cell|
|
|
56
|
+
str << '<cacheField name="' << cell.value << '" numFmtId="0">'
|
|
57
|
+
str << '<sharedItems count="0">'
|
|
58
|
+
str << '</sharedItems>'
|
|
59
|
+
str << '</cacheField>'
|
|
60
|
+
end
|
|
61
|
+
str << '</cacheFields>'
|
|
62
|
+
str << '</pivotCacheDefinition>'
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module Axlsx
|
|
2
|
+
|
|
3
|
+
# A simple, self serializing class for storing pivot tables
|
|
4
|
+
class PivotTables < SimpleTypedList
|
|
5
|
+
|
|
6
|
+
# creates a new Tables object
|
|
7
|
+
def initialize(worksheet)
|
|
8
|
+
raise ArgumentError, "you must provide a worksheet" unless worksheet.is_a?(Worksheet)
|
|
9
|
+
super PivotTable
|
|
10
|
+
@worksheet = worksheet
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# The worksheet that owns this collection of pivot tables
|
|
14
|
+
# @return [Worksheet]
|
|
15
|
+
attr_reader :worksheet
|
|
16
|
+
|
|
17
|
+
# returns the relationships required by this collection
|
|
18
|
+
def relationships
|
|
19
|
+
return [] if empty?
|
|
20
|
+
map{ |pivot_table| Relationship.new(pivot_table, PIVOT_TABLE_R, "../#{pivot_table.pn}") }
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
end
|
|
@@ -6,22 +6,9 @@ module Axlsx
|
|
|
6
6
|
# @see Worksheet#initialize
|
|
7
7
|
class PrintOptions
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
# Whether row and column headings should be printed.
|
|
14
|
-
# @return [Boolean]
|
|
15
|
-
attr_reader :headings
|
|
16
|
-
|
|
17
|
-
# Whether the content should be centered horizontally on the page.
|
|
18
|
-
# @return [Boolean]
|
|
19
|
-
attr_reader :horizontal_centered
|
|
20
|
-
|
|
21
|
-
# Whether the content should be centered vertically on the page.
|
|
22
|
-
# @return [Boolean]
|
|
23
|
-
attr_reader :vertical_centered
|
|
24
|
-
|
|
9
|
+
include Axlsx::OptionsParser
|
|
10
|
+
include Axlsx::SerializedAttributes
|
|
11
|
+
include Axlsx::Accessors
|
|
25
12
|
# Creates a new PrintOptions object
|
|
26
13
|
# @option options [Boolean] grid_lines Whether grid lines should be printed
|
|
27
14
|
# @option options [Boolean] headings Whether row and column headings should be printed
|
|
@@ -32,31 +19,22 @@ module Axlsx
|
|
|
32
19
|
set(options)
|
|
33
20
|
end
|
|
34
21
|
|
|
22
|
+
serializable_attributes :grid_lines, :headings, :horizontal_centered, :vertical_centered
|
|
23
|
+
boolean_attr_accessor :grid_lines, :headings, :horizontal_centered, :vertical_centered
|
|
24
|
+
|
|
35
25
|
# Set some or all options at once.
|
|
36
26
|
# @param [Hash] options The options to set (possible keys are :grid_lines, :headings, :horizontal_centered, and :vertical_centered).
|
|
37
27
|
def set(options)
|
|
38
|
-
options
|
|
39
|
-
send("#{k}=", v) if respond_to? "#{k}="
|
|
40
|
-
end
|
|
28
|
+
parse_options options
|
|
41
29
|
end
|
|
42
30
|
|
|
43
|
-
# @see grid_lines
|
|
44
|
-
def grid_lines=(v); Axlsx::validate_boolean(v); @grid_lines = v; end
|
|
45
|
-
# @see headings
|
|
46
|
-
def headings=(v); Axlsx::validate_boolean(v); @headings = v; end
|
|
47
|
-
# @see horizontal_centered
|
|
48
|
-
def horizontal_centered=(v); Axlsx::validate_boolean(v); @horizontal_centered = v; end
|
|
49
|
-
# @see vertical_centered
|
|
50
|
-
def vertical_centered=(v); Axlsx::validate_boolean(v); @vertical_centered = v; end
|
|
51
|
-
|
|
52
31
|
# Serializes the page options element.
|
|
53
32
|
# @note As all attributes default to "false" according to the xml schema definition, the generated xml includes only those attributes that are set to true.
|
|
54
33
|
# @param [String] str
|
|
55
34
|
# @return [String]
|
|
56
35
|
def to_xml_string(str = '')
|
|
57
36
|
str << '<printOptions '
|
|
58
|
-
|
|
59
|
-
str << instance_values.select{ |k,v| v == true }.map{ |k,v| k.gsub(/_(.)/){ $1.upcase } << %{="#{v}"} }.join(' ')
|
|
37
|
+
serialized_attributes str
|
|
60
38
|
str << '/>'
|
|
61
39
|
end
|
|
62
40
|
end
|
|
@@ -4,6 +4,18 @@ module Axlsx
|
|
|
4
4
|
# @see Worksheet#protect_range
|
|
5
5
|
class ProtectedRange
|
|
6
6
|
|
|
7
|
+
include Axlsx::OptionsParser
|
|
8
|
+
include Axlsx::SerializedAttributes
|
|
9
|
+
|
|
10
|
+
# Initializes a new protected range object
|
|
11
|
+
# @option [String] sqref The cell range reference to protect. This can be an absolute or a relateve range however, it only applies to the current sheet.
|
|
12
|
+
# @option [String] name An optional name for the protected name.
|
|
13
|
+
def initialize(options={})
|
|
14
|
+
parse_options options
|
|
15
|
+
yield self if block_given?
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
serializable_attributes :sqref, :name
|
|
7
19
|
# The reference for the protected range
|
|
8
20
|
# @return [String]
|
|
9
21
|
attr_reader :sqref
|
|
@@ -12,16 +24,6 @@ module Axlsx
|
|
|
12
24
|
# @return [String]
|
|
13
25
|
attr_reader :name
|
|
14
26
|
|
|
15
|
-
# Initializes a new protected range object
|
|
16
|
-
# @option [String] sqref The cell range reference to protect. This can be an absolute or a relateve range however, it only applies to the current sheet.
|
|
17
|
-
# @option [String] name An optional name for the protected name.
|
|
18
|
-
def initialize(options={})
|
|
19
|
-
options.each do |o|
|
|
20
|
-
self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
|
|
21
|
-
end
|
|
22
|
-
yield self if block_given?
|
|
23
|
-
end
|
|
24
|
-
|
|
25
27
|
# @see sqref
|
|
26
28
|
def sqref=(v)
|
|
27
29
|
Axlsx.validate_string(v)
|
|
@@ -33,14 +35,15 @@ module Axlsx
|
|
|
33
35
|
Axlsx.validate_string(v)
|
|
34
36
|
@name = v
|
|
35
37
|
end
|
|
36
|
-
|
|
38
|
+
|
|
37
39
|
# serializes the proteted range
|
|
38
40
|
# @param [String] str if this string object is provided we append
|
|
39
41
|
# our output to that object. Use this - it helps limit the number of
|
|
40
42
|
# objects created during serialization
|
|
41
43
|
def to_xml_string(str="")
|
|
42
|
-
|
|
43
|
-
str
|
|
44
|
+
str << '<protectedRange '
|
|
45
|
+
serialized_attributes str
|
|
46
|
+
str << '/>'
|
|
44
47
|
end
|
|
45
48
|
end
|
|
46
49
|
end
|
|
@@ -5,59 +5,14 @@ module Axlsx
|
|
|
5
5
|
# @see Worksheet#add_row
|
|
6
6
|
class Row
|
|
7
7
|
|
|
8
|
+
include SerializedAttributes
|
|
9
|
+
include Accessors
|
|
8
10
|
# No support is provided for the following attributes
|
|
9
11
|
# spans
|
|
10
12
|
# thickTop
|
|
11
13
|
# thickBottom
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
# A list of serilizable attributes.
|
|
15
|
-
# @note height(ht) and customHeight are manages separately for now. Have a look at Row#height
|
|
16
|
-
SERIALIZABLE_ATTRIBUTES = [:hidden, :outlineLevel, :collapsed, :s, :customFormat, :ph]
|
|
17
|
-
|
|
18
|
-
# The worksheet this row belongs to
|
|
19
|
-
# @return [Worksheet]
|
|
20
|
-
attr_reader :worksheet
|
|
21
|
-
|
|
22
|
-
# The cells this row holds
|
|
23
|
-
# @return [SimpleTypedList]
|
|
24
|
-
attr_reader :cells
|
|
25
|
-
|
|
26
|
-
# Row height measured in point size. There is no margin padding on row height.
|
|
27
|
-
# @return [Float]
|
|
28
|
-
attr_reader :height
|
|
29
|
-
|
|
30
|
-
# Flag indicating if the outlining of row.
|
|
31
|
-
# @return [Boolean]
|
|
32
|
-
attr_reader :collapsed
|
|
33
|
-
|
|
34
|
-
# Flag indicating if the the row is hidden.
|
|
35
|
-
# @return [Boolean]
|
|
36
|
-
attr_reader :hidden
|
|
37
|
-
|
|
38
|
-
# Outlining level of the row, when outlining is on
|
|
39
|
-
# @return [Integer]
|
|
40
|
-
attr_reader :outlineLevel
|
|
41
|
-
|
|
42
|
-
# The style applied ot the row. This affects the entire row.
|
|
43
|
-
# @return [Integer]
|
|
44
|
-
attr_reader :s
|
|
45
|
-
|
|
46
|
-
# indicates that a style has been applied directly to the row via Row#s
|
|
47
|
-
# @return [Boolean]
|
|
48
|
-
attr_reader :customFormat
|
|
49
|
-
|
|
50
|
-
# indicates if the row should show phonetic
|
|
51
|
-
# @return [Boolean]
|
|
52
|
-
attr_reader :ph
|
|
53
|
-
|
|
54
|
-
# NOTE removing this from the api as it is actually incorrect.
|
|
55
|
-
# having a method to style a row's cells is fine, but it is not an attribute on the row.
|
|
56
|
-
# The proper attribute is ':s'
|
|
57
|
-
# attr_reader style
|
|
58
|
-
#
|
|
59
|
-
|
|
60
|
-
# Creates a new row. New Cell objects are created based on the values, types and style options.
|
|
15
|
+
# Creates a new row. New Cell objects are created based on the values, types and style options.
|
|
61
16
|
# A new cell is created for each item in the values array. style and types options are applied as follows:
|
|
62
17
|
# If the types option is defined and is a symbol it is applied to all the cells created.
|
|
63
18
|
# If the types option is an array, cell types are applied by index for each cell
|
|
@@ -73,7 +28,7 @@ module Axlsx
|
|
|
73
28
|
# @see Row#array_to_cells
|
|
74
29
|
# @see Cell
|
|
75
30
|
def initialize(worksheet, values=[], options={})
|
|
76
|
-
@
|
|
31
|
+
@ht = nil
|
|
77
32
|
self.worksheet = worksheet
|
|
78
33
|
@cells = SimpleTypedList.new Cell
|
|
79
34
|
@worksheet.rows << self
|
|
@@ -81,29 +36,48 @@ module Axlsx
|
|
|
81
36
|
array_to_cells(values, options)
|
|
82
37
|
end
|
|
83
38
|
|
|
84
|
-
#
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
39
|
+
# A list of serializable attributes.
|
|
40
|
+
serializable_attributes :hidden, :outline_level, :collapsed, :custom_format, :s, :ph, :custom_height, :ht
|
|
41
|
+
|
|
42
|
+
# Boolean row attribute accessors
|
|
43
|
+
boolean_attr_accessor :hidden, :collapsed, :custom_format, :ph, :custom_height
|
|
89
44
|
|
|
90
|
-
#
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
45
|
+
# The worksheet this row belongs to
|
|
46
|
+
# @return [Worksheet]
|
|
47
|
+
attr_reader :worksheet
|
|
48
|
+
|
|
49
|
+
# The cells this row holds
|
|
50
|
+
# @return [SimpleTypedList]
|
|
51
|
+
attr_reader :cells
|
|
52
|
+
|
|
53
|
+
# Row height measured in point size. There is no margin padding on row height.
|
|
54
|
+
# @return [Float]
|
|
55
|
+
def height
|
|
56
|
+
@ht
|
|
94
57
|
end
|
|
95
|
-
|
|
96
|
-
#
|
|
97
|
-
|
|
58
|
+
|
|
59
|
+
# Outlining level of the row, when outlining is on
|
|
60
|
+
# @return [Integer]
|
|
61
|
+
attr_reader :outline_level
|
|
62
|
+
alias :outlineLevel :outline_level
|
|
63
|
+
|
|
64
|
+
# The style applied ot the row. This affects the entire row.
|
|
65
|
+
# @return [Integer]
|
|
66
|
+
attr_reader :s
|
|
98
67
|
|
|
99
68
|
# @see Row#s
|
|
100
|
-
def s=(v)
|
|
69
|
+
def s=(v)
|
|
70
|
+
Axlsx.validate_unsigned_numeric(v)
|
|
71
|
+
@custom_format = true
|
|
72
|
+
@s = v
|
|
73
|
+
end
|
|
101
74
|
|
|
102
75
|
# @see Row#outline
|
|
103
|
-
def
|
|
76
|
+
def outline_level=(v)
|
|
104
77
|
Axlsx.validate_unsigned_numeric(v)
|
|
105
|
-
@
|
|
78
|
+
@outline_level = v
|
|
106
79
|
end
|
|
80
|
+
alias :outlineLevel= :outline_level=
|
|
107
81
|
|
|
108
82
|
# The index of this row in the worksheet
|
|
109
83
|
# @return [Integer]
|
|
@@ -116,21 +90,14 @@ module Axlsx
|
|
|
116
90
|
# @param [String] str The string this rows xml will be appended to.
|
|
117
91
|
# @return [String]
|
|
118
92
|
def to_xml_string(r_index, str = '')
|
|
119
|
-
str << '<row
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
end
|
|
123
|
-
if custom_height?
|
|
124
|
-
str << 'customHeight="1" ht="' << height.to_s << '">'
|
|
125
|
-
else
|
|
126
|
-
str << '>'
|
|
127
|
-
end
|
|
93
|
+
str << '<row '
|
|
94
|
+
serialized_attributes(str, { :r => r_index + 1 })
|
|
95
|
+
str << '>'
|
|
128
96
|
@cells.each_with_index { |cell, c_index| cell.to_xml_string(r_index, c_index, str) }
|
|
129
97
|
str << '</row>'
|
|
130
|
-
str
|
|
131
98
|
end
|
|
132
99
|
|
|
133
|
-
# Adds a
|
|
100
|
+
# Adds a single sell to the row based on the data provided and updates the worksheet's autofit data.
|
|
134
101
|
# @return [Cell]
|
|
135
102
|
def add_cell(value="", options={})
|
|
136
103
|
c = Cell.new(self, value, options)
|
|
@@ -154,13 +121,13 @@ module Axlsx
|
|
|
154
121
|
end
|
|
155
122
|
|
|
156
123
|
# @see height
|
|
157
|
-
def height=(v)
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
@
|
|
124
|
+
def height=(v)
|
|
125
|
+
Axlsx::validate_unsigned_numeric(v)
|
|
126
|
+
unless v.nil?
|
|
127
|
+
@ht = v
|
|
128
|
+
@custom_height = true
|
|
129
|
+
end
|
|
130
|
+
@ht
|
|
164
131
|
end
|
|
165
132
|
|
|
166
133
|
private
|
|
@@ -180,15 +147,24 @@ module Axlsx
|
|
|
180
147
|
def array_to_cells(values, options={})
|
|
181
148
|
values = values
|
|
182
149
|
DataTypeValidator.validate 'Row.array_to_cells', Array, values
|
|
183
|
-
types, style = options.delete(:types), options.delete(:style)
|
|
150
|
+
types, style, formula_values = options.delete(:types), options.delete(:style), options.delete(:formula_values)
|
|
184
151
|
values.each_with_index do |value, index|
|
|
152
|
+
|
|
153
|
+
#WTF IS THIS PAP?
|
|
185
154
|
cell_style = style.is_a?(Array) ? style[index] : style
|
|
186
155
|
options[:style] = cell_style if cell_style
|
|
156
|
+
|
|
187
157
|
cell_type = types.is_a?(Array)? types[index] : types
|
|
188
158
|
options[:type] = cell_type if cell_type
|
|
159
|
+
|
|
160
|
+
formula_value = formula_values[index] if formula_values.is_a?(Array)
|
|
161
|
+
options[:formula_value] = formula_value if formula_value
|
|
162
|
+
|
|
189
163
|
Cell.new(self, value, options)
|
|
164
|
+
|
|
190
165
|
options.delete(:style)
|
|
191
166
|
options.delete(:type)
|
|
167
|
+
options.delete(:formula_value)
|
|
192
168
|
end
|
|
193
169
|
end
|
|
194
170
|
end
|