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.
- data/.yardopts +5 -2
- data/CHANGELOG.md +78 -0
- data/LICENSE +1 -1
- data/README.md +132 -331
- data/Rakefile +17 -5
- data/examples/basic_charts.rb +54 -0
- data/examples/chart_colors.rb +88 -0
- data/examples/conditional_formatting/example_conditional_formatting.rb +72 -0
- data/examples/conditional_formatting/getting_barred.rb +37 -0
- data/examples/conditional_formatting/hitting_the_high_notes.rb +37 -0
- data/examples/conditional_formatting/scaled_colors.rb +39 -0
- data/examples/conditional_formatting/stop_and_go.rb +37 -0
- data/examples/data_validation.rb +50 -0
- data/examples/example.rb +300 -152
- data/examples/example.xlsx +0 -0
- data/examples/example_streamed.xlsx +0 -0
- data/examples/extractive.pdf +0 -0
- data/examples/extractive.rb +45 -0
- data/examples/no-use_autowidth.xlsx +0 -0
- data/examples/sample.png +0 -0
- data/examples/scraping_html.rb +91 -0
- data/examples/shared_strings_example.xlsx +0 -0
- data/examples/sheet_protection.rb +10 -0
- data/examples/sheet_view.rb +34 -0
- data/examples/skydrive/real_example.rb +63 -0
- data/examples/two_cell_anchor_image.rb +11 -0
- data/lib/axlsx/content_type/content_type.rb +2 -0
- data/lib/axlsx/content_type/default.rb +30 -15
- data/lib/axlsx/content_type/override.rb +29 -14
- data/lib/axlsx/doc_props/app.rb +161 -104
- data/lib/axlsx/doc_props/core.rb +9 -5
- data/lib/axlsx/drawing/ax_data_source.rb +26 -0
- data/lib/axlsx/drawing/axis.rb +106 -35
- data/lib/axlsx/drawing/bar_3D_chart.rb +49 -45
- data/lib/axlsx/drawing/bar_series.rb +25 -7
- data/lib/axlsx/drawing/cat_axis.rb +50 -22
- data/lib/axlsx/drawing/chart.rb +69 -56
- data/lib/axlsx/drawing/d_lbls.rb +100 -0
- data/lib/axlsx/drawing/drawing.rb +28 -12
- data/lib/axlsx/drawing/graphic_frame.rb +2 -1
- data/lib/axlsx/drawing/line_3D_chart.rb +3 -10
- data/lib/axlsx/drawing/line_series.rb +20 -4
- data/lib/axlsx/drawing/num_data.rb +52 -0
- data/lib/axlsx/drawing/num_data_source.rb +61 -0
- data/lib/axlsx/drawing/num_val.rb +32 -0
- data/lib/axlsx/drawing/pic.rb +44 -4
- data/lib/axlsx/drawing/pie_3D_chart.rb +10 -7
- data/lib/axlsx/drawing/pie_series.rb +18 -4
- data/lib/axlsx/drawing/scatter_chart.rb +12 -18
- data/lib/axlsx/drawing/scatter_series.rb +28 -2
- data/lib/axlsx/drawing/ser_axis.rb +1 -1
- data/lib/axlsx/drawing/series.rb +1 -1
- data/lib/axlsx/drawing/str_data.rb +42 -0
- data/lib/axlsx/drawing/str_val.rb +33 -0
- data/lib/axlsx/drawing/title.rb +21 -9
- data/lib/axlsx/drawing/two_cell_anchor.rb +46 -9
- data/lib/axlsx/drawing/view_3D.rb +44 -31
- data/lib/axlsx/drawing/vml_drawing.rb +42 -0
- data/lib/axlsx/drawing/vml_shape.rb +125 -0
- data/lib/axlsx/package.rb +44 -16
- data/lib/axlsx/rels/relationship.rb +3 -3
- data/lib/axlsx/rels/relationships.rb +1 -11
- data/lib/axlsx/stylesheet/color.rb +0 -1
- data/lib/axlsx/stylesheet/dxf.rb +79 -0
- data/lib/axlsx/stylesheet/font.rb +2 -1
- data/lib/axlsx/stylesheet/gradient_fill.rb +1 -1
- data/lib/axlsx/stylesheet/styles.rb +143 -50
- data/lib/axlsx/stylesheet/table_style.rb +3 -3
- data/lib/axlsx/stylesheet/xf.rb +2 -0
- data/lib/axlsx/util/constants.rb +36 -0
- data/lib/axlsx/util/simple_typed_list.rb +15 -21
- data/lib/axlsx/util/validators.rb +122 -5
- data/lib/axlsx/version.rb +2 -7
- data/lib/axlsx/workbook/defined_name.rb +174 -0
- data/lib/axlsx/workbook/defined_names.rb +21 -0
- data/lib/axlsx/workbook/shared_strings_table.rb +12 -13
- data/lib/axlsx/workbook/workbook.rb +71 -13
- data/lib/axlsx/workbook/worksheet/auto_filter.rb +34 -0
- data/lib/axlsx/workbook/worksheet/cell.rb +45 -36
- data/lib/axlsx/workbook/worksheet/cfvo.rb +62 -0
- data/lib/axlsx/workbook/worksheet/col.rb +17 -1
- data/lib/axlsx/workbook/worksheet/color_scale.rb +76 -0
- data/lib/axlsx/workbook/worksheet/cols.rb +20 -0
- data/lib/axlsx/workbook/worksheet/comment.rb +101 -0
- data/lib/axlsx/workbook/worksheet/comments.rb +85 -0
- data/lib/axlsx/workbook/worksheet/conditional_formatting.rb +82 -0
- data/lib/axlsx/workbook/worksheet/conditional_formatting_rule.rb +216 -0
- data/lib/axlsx/workbook/worksheet/conditional_formattings.rb +25 -0
- data/lib/axlsx/workbook/worksheet/data_bar.rb +97 -0
- data/lib/axlsx/workbook/worksheet/data_validation.rb +245 -0
- data/lib/axlsx/workbook/worksheet/data_validations.rb +28 -0
- data/lib/axlsx/workbook/worksheet/dimension.rb +65 -0
- data/lib/axlsx/workbook/worksheet/icon_set.rb +83 -0
- data/lib/axlsx/workbook/worksheet/merged_cells.rb +35 -0
- data/lib/axlsx/workbook/worksheet/page_setup.rb +113 -0
- data/lib/axlsx/workbook/worksheet/pane.rb +144 -0
- data/lib/axlsx/workbook/worksheet/print_options.rb +63 -0
- data/lib/axlsx/workbook/worksheet/protected_range.rb +46 -0
- data/lib/axlsx/workbook/worksheet/protected_ranges.rb +34 -0
- data/lib/axlsx/workbook/worksheet/row.rb +69 -12
- data/lib/axlsx/workbook/worksheet/selection.rb +111 -0
- data/lib/axlsx/workbook/worksheet/sheet_data.rb +25 -0
- data/lib/axlsx/workbook/worksheet/sheet_pr.rb +24 -0
- data/lib/axlsx/workbook/worksheet/sheet_protection.rb +224 -0
- data/lib/axlsx/workbook/worksheet/sheet_view.rb +379 -0
- data/lib/axlsx/workbook/worksheet/table.rb +3 -3
- data/lib/axlsx/workbook/worksheet/tables.rb +31 -0
- data/lib/axlsx/workbook/worksheet/worksheet.rb +379 -233
- data/lib/axlsx/workbook/worksheet/worksheet_comments.rb +57 -0
- data/lib/axlsx/workbook/worksheet/worksheet_drawing.rb +64 -0
- data/lib/axlsx.rb +31 -16
- data/test/benchmark.rb +30 -38
- data/test/content_type/tc_content_type.rb +1 -6
- data/test/doc_props/tc_app.rb +31 -1
- data/test/doc_props/tc_core.rb +3 -1
- data/test/drawing/tc_axis.rb +46 -3
- data/test/drawing/tc_bar_3D_chart.rb +12 -12
- data/test/drawing/tc_bar_series.rb +17 -13
- data/test/drawing/tc_cat_axis.rb +3 -3
- data/test/drawing/tc_cat_axis_data.rb +23 -13
- data/test/drawing/tc_chart.rb +29 -11
- data/test/drawing/tc_d_lbls.rb +47 -0
- data/test/drawing/tc_data_source.rb +17 -0
- data/test/drawing/tc_drawing.rb +11 -5
- data/test/drawing/tc_hyperlink.rb +4 -5
- data/test/drawing/tc_line_series.rb +9 -11
- data/test/drawing/tc_named_axis_data.rb +27 -0
- data/test/drawing/tc_num_data.rb +31 -0
- data/test/drawing/tc_num_val.rb +29 -0
- data/test/drawing/tc_pic.rb +22 -2
- data/test/drawing/tc_pie_3D_chart.rb +4 -8
- data/test/drawing/tc_pie_series.rb +11 -13
- data/test/drawing/tc_scatter_chart.rb +6 -1
- data/test/drawing/tc_scatter_series.rb +6 -5
- data/test/drawing/tc_series.rb +1 -1
- data/test/drawing/tc_str_data.rb +18 -0
- data/test/drawing/tc_str_val.rb +21 -0
- data/test/drawing/tc_title.rb +16 -0
- data/test/drawing/tc_two_cell_anchor.rb +2 -3
- data/test/drawing/tc_view_3D.rb +18 -18
- data/test/drawing/tc_vml_drawing.rb +25 -0
- data/test/drawing/tc_vml_shape.rb +100 -0
- data/test/profile.rb +2 -1
- data/test/rels/tc_relationship.rb +1 -0
- data/test/stylesheet/tc_dxf.rb +81 -0
- data/test/stylesheet/tc_gradient_fill.rb +8 -0
- data/test/stylesheet/tc_pattern_fill.rb +7 -1
- data/test/stylesheet/tc_styles.rb +163 -3
- data/test/stylesheet/tc_table_style.rb +8 -0
- data/test/stylesheet/tc_table_style_element.rb +10 -1
- data/test/tc_helper.rb +1 -0
- data/test/tc_package.rb +93 -17
- data/test/util/tc_simple_typed_list.rb +13 -0
- data/test/util/tc_validators.rb +95 -9
- data/test/workbook/tc_defined_name.rb +41 -0
- data/test/workbook/tc_workbook.rb +5 -3
- data/test/workbook/worksheet/table/tc_table.rb +3 -11
- data/test/workbook/worksheet/tc_cell.rb +52 -18
- data/test/workbook/worksheet/tc_cfvo.rb +31 -0
- data/test/workbook/worksheet/tc_col.rb +9 -0
- data/test/workbook/worksheet/tc_color_scale.rb +29 -0
- data/test/workbook/worksheet/tc_comment.rb +57 -0
- data/test/workbook/worksheet/tc_comments.rb +57 -0
- data/test/workbook/worksheet/tc_conditional_formatting.rb +217 -0
- data/test/workbook/worksheet/tc_data_bar.rb +39 -0
- data/test/workbook/worksheet/tc_data_validation.rb +265 -0
- data/test/workbook/worksheet/tc_date_time_converter.rb +11 -5
- data/test/workbook/worksheet/tc_icon_set.rb +45 -0
- data/test/workbook/worksheet/tc_page_setup.rb +138 -0
- data/test/workbook/worksheet/tc_pane.rb +94 -0
- data/test/workbook/worksheet/tc_print_options.rb +72 -0
- data/test/workbook/worksheet/tc_protected_range.rb +17 -0
- data/test/workbook/worksheet/tc_row.rb +44 -13
- data/test/workbook/worksheet/tc_selection.rb +94 -0
- data/test/workbook/worksheet/tc_sheet_protection.rb +117 -0
- data/test/workbook/worksheet/tc_sheet_view.rb +214 -0
- data/test/workbook/worksheet/tc_worksheet.rb +147 -50
- metadata +216 -148
- data/examples/example.csv +0 -1000
- data/examples/example.rb~ +0 -112
- data/lib/axlsx/drawing/cat_axis_data.rb +0 -34
- data/lib/axlsx/drawing/hlink_click.rb~ +0 -0
- data/lib/axlsx/drawing/hyperlink.rb~ +0 -64
- data/lib/axlsx/drawing/named_axis_data.rb +0 -36
- data/lib/axlsx/drawing/picture_locking.rb~ +0 -36
- data/lib/axlsx/drawing/val_axis_data.rb +0 -27
- data/lib/axlsx/stylesheet/#num_fmt.rb# +0 -69
- data/lib/axlsx/util/cbf.rb +0 -333
- data/lib/axlsx/util/cfb.rb~ +0 -201
- data/lib/axlsx/util/ms_off_crypto.rb +0 -189
- data/lib/axlsx/util/ms_off_crypto.rb~ +0 -3
- data/lib/axlsx/util/ms_offcrypto.rb~ +0 -0
- data/lib/axlsx/util/parser.rb~ +0 -6
- data/lib/axlsx/util/storage.rb~ +0 -0
- data/lib/axlsx/workbook/shared_strings_table.rb~ +0 -69
- data/lib/axlsx/workbook/worksheet/col.rb~ +0 -0
- data/lib/axlsx/workbook/worksheet/shared_strings_table.rb~ +0 -0
- data/lib/axlsx/workbook/worksheet/table.rb~ +0 -97
- data/lib/schema/dc.xsd~ +0 -118
- data/lib/schema/dcterms.xsd~ +0 -331
- data/lib/schema/opc-coreProperties.xsd~ +0 -50
- data/test/#benchmark.txt# +0 -7
- data/test/#tc_helper.rb# +0 -3
- data/test/benchmark.rb~ +0 -0
- data/test/benchmark.txt +0 -6
- data/test/benchmark.txt~ +0 -6
- data/test/drawing/tc_val_axis_data.rb +0 -17
- data/test/example.csv +0 -1000
- data/test/example.xlsx +0 -0
- data/test/example_streamed.xlsx +0 -0
- data/test/tc_axlsx.rb~ +0 -0
- data/test/tc_helper.rb~ +0 -3
- data/test/workbook/worksheet/table/tc_table.rb~ +0 -72
- data/test/workbook/worksheet/tc_col.rb~ +0 -10
|
@@ -3,22 +3,6 @@ require 'cgi'
|
|
|
3
3
|
module Axlsx
|
|
4
4
|
# A cell in a worksheet.
|
|
5
5
|
# Cell stores inforamation requried to serialize a single worksheet cell to xml. You must provde the Row that the cell belongs to and the cells value. The data type will automatically be determed if you do not specify the :type option. The default style will be applied if you do not supply the :style option. Changing the cell's type will recast the value to the type specified. Altering the cell's value via the property accessor will also automatically cast the provided value to the cell's type.
|
|
6
|
-
# @example Manually creating and manipulating Cell objects
|
|
7
|
-
# ws = Workbook.new.add_worksheet
|
|
8
|
-
# # This is the simple, and recommended way to create cells. Data types will automatically be determined for you.
|
|
9
|
-
# ws.add_row :values => [1,"fish",Time.now]
|
|
10
|
-
#
|
|
11
|
-
# # but you can also do this
|
|
12
|
-
# r = ws.add_row
|
|
13
|
-
# r.add_cell 1
|
|
14
|
-
#
|
|
15
|
-
# # or even this
|
|
16
|
-
# r = ws.add_row
|
|
17
|
-
# c = Cell.new row, 1, :value=>integer
|
|
18
|
-
#
|
|
19
|
-
# # cells can also be accessed via Row#cells. The example here changes the cells type, which will automatically updated the value from 1 to 1.0
|
|
20
|
-
# r.cells.last.type = :float
|
|
21
|
-
#
|
|
22
6
|
# @note The recommended way to generate cells is via Worksheet#add_row
|
|
23
7
|
#
|
|
24
8
|
# @see Worksheet#add_row
|
|
@@ -74,13 +58,20 @@ module Axlsx
|
|
|
74
58
|
@value = cast_value(v)
|
|
75
59
|
end
|
|
76
60
|
|
|
77
|
-
|
|
78
61
|
# Indicates that the cell has one or more of the custom cell styles applied.
|
|
79
62
|
# @return [Boolean]
|
|
80
63
|
def is_text_run?
|
|
81
64
|
@is_text_run ||= false
|
|
82
65
|
end
|
|
83
66
|
|
|
67
|
+
# Indicates if the cell is good for shared string table
|
|
68
|
+
def plain_string?
|
|
69
|
+
@type == :string && # String typed
|
|
70
|
+
!is_text_run? && # No inline styles
|
|
71
|
+
!@value.nil? && # Not nil
|
|
72
|
+
!@value.empty? && # Not empty
|
|
73
|
+
!@value.start_with?('=') # Not a formula
|
|
74
|
+
end
|
|
84
75
|
|
|
85
76
|
# The inline font_name property for the cell
|
|
86
77
|
# @return [String]
|
|
@@ -151,10 +142,10 @@ module Axlsx
|
|
|
151
142
|
# The inline color property for the cell
|
|
152
143
|
# @return [Color]
|
|
153
144
|
attr_reader :color
|
|
154
|
-
# @param [String] The 8 character representation for an rgb color #FFFFFFFF"
|
|
145
|
+
# @param [String] v The 8 character representation for an rgb color #FFFFFFFF"
|
|
155
146
|
def color=(v)
|
|
156
147
|
@color = v.is_a?(Color) ? v : Color.new(:rgb=>v)
|
|
157
|
-
@
|
|
148
|
+
@is_text_run = true
|
|
158
149
|
end
|
|
159
150
|
|
|
160
151
|
# The inline sz property for the cell
|
|
@@ -204,7 +195,7 @@ module Axlsx
|
|
|
204
195
|
# @option options [Symbol] scheme must be one of :none, major, :minor
|
|
205
196
|
def initialize(row, value="", options={})
|
|
206
197
|
self.row=row
|
|
207
|
-
@font_name = @charset = @family = @b = @i = @strike = @outline = @shadow = nil
|
|
198
|
+
@value = @font_name = @charset = @family = @b = @i = @strike = @outline = @shadow = nil
|
|
208
199
|
@condense = @u = @vertAlign = @sz = @color = @scheme = @extend = @ssti = nil
|
|
209
200
|
@styles = row.worksheet.workbook.styles
|
|
210
201
|
@row.cells << self
|
|
@@ -220,15 +211,6 @@ module Axlsx
|
|
|
220
211
|
# @return [Integer]
|
|
221
212
|
attr_reader :ssti
|
|
222
213
|
|
|
223
|
-
# equality comparison to test value, type and inline style attributes
|
|
224
|
-
# this is how we work out if the cell needs to be added or already exists in the shared strings table
|
|
225
|
-
def shareable_hash
|
|
226
|
-
self_hash = {}
|
|
227
|
-
INLINE_STYLES.each { |style| self_hash[style] = self.instance_variable_get("@" + style) }
|
|
228
|
-
self_hash['color'] = self_hash['color'].instance_values if self_hash['color']
|
|
229
|
-
self_hash
|
|
230
|
-
end
|
|
231
|
-
|
|
232
214
|
# @return [Integer] The index of the cell in the containing row.
|
|
233
215
|
def index
|
|
234
216
|
@row.cells.index(self)
|
|
@@ -237,9 +219,8 @@ module Axlsx
|
|
|
237
219
|
# @return [String] The alpha(column)numeric(row) reference for this sell.
|
|
238
220
|
# @example Relative Cell Reference
|
|
239
221
|
# ws.rows.first.cells.first.r #=> "A1"
|
|
240
|
-
# @note this will be discontinued in 1.1.0 - prefer Axlsx.cell_r
|
|
241
222
|
def r
|
|
242
|
-
|
|
223
|
+
Axlsx::cell_r index, @row.index
|
|
243
224
|
end
|
|
244
225
|
|
|
245
226
|
# @return [String] The absolute alpha(column)numeric(row) reference for this sell.
|
|
@@ -280,9 +261,8 @@ module Axlsx
|
|
|
280
261
|
# @return [String]
|
|
281
262
|
def run_xml_string(str = '')
|
|
282
263
|
if is_text_run?
|
|
283
|
-
data =
|
|
264
|
+
data = instance_values.reject{|key, value| value == nil || key == 'value' || key == 'type' }
|
|
284
265
|
keys = data.keys & INLINE_STYLES
|
|
285
|
-
keys.delete ['value', 'type']
|
|
286
266
|
str << "<r><rPr>"
|
|
287
267
|
keys.each do |key|
|
|
288
268
|
case key
|
|
@@ -291,7 +271,7 @@ module Axlsx
|
|
|
291
271
|
when 'color'
|
|
292
272
|
str << data[key].to_xml_string
|
|
293
273
|
else
|
|
294
|
-
"<" << key.to_s << " val='" << data[key].to_s << "'/>"
|
|
274
|
+
str << "<" << key.to_s << " val='" << data[key].to_s << "'/>"
|
|
295
275
|
end
|
|
296
276
|
end
|
|
297
277
|
str << "</rPr>" << "<t>" << value.to_s << "</t></r>"
|
|
@@ -307,13 +287,15 @@ module Axlsx
|
|
|
307
287
|
# @param [String] str The string index the cell content will be appended to. Defaults to empty string.
|
|
308
288
|
# @return [String] xml text for the cell
|
|
309
289
|
def to_xml_string(r_index, c_index, str = '')
|
|
310
|
-
return str if @value.nil?
|
|
311
290
|
str << '<c r="' << Axlsx::cell_r(c_index, r_index) << '" s="' << @style.to_s << '" '
|
|
291
|
+
return str << '/>' if @value.nil?
|
|
292
|
+
|
|
312
293
|
case @type
|
|
294
|
+
|
|
313
295
|
when :string
|
|
314
296
|
#parse formula
|
|
315
297
|
if @value.start_with?('=')
|
|
316
|
-
str << 't="str"><f>' << @value.to_s.
|
|
298
|
+
str << 't="str"><f>' << @value.to_s.sub('=', '') << '</f>'
|
|
317
299
|
else
|
|
318
300
|
#parse shared
|
|
319
301
|
if @ssti
|
|
@@ -335,8 +317,35 @@ module Axlsx
|
|
|
335
317
|
str << '</c>'
|
|
336
318
|
end
|
|
337
319
|
|
|
320
|
+
def is_formula?
|
|
321
|
+
@type == :string && @value.to_s.start_with?('=')
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
# This is still not perfect...
|
|
325
|
+
# - scaling is not linear as font sizes increst
|
|
326
|
+
# - different fonts have different mdw and char widths
|
|
327
|
+
def autowidth
|
|
328
|
+
return if is_formula? || value == nil
|
|
329
|
+
mdw = 1.78 #This is the widest width of 0..9 in arial@10px)
|
|
330
|
+
font_scale = (font_size/10.0).to_f
|
|
331
|
+
((value.to_s.count(Worksheet.thin_chars) * mdw + 5) / mdw * 256) / 256.0 * font_scale
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
# returns the absolute or relative string style reference for
|
|
335
|
+
# this cell.
|
|
336
|
+
# @param [Boolean] absolute -when false a relative reference will be
|
|
337
|
+
# returned.
|
|
338
|
+
# @return [String]
|
|
339
|
+
def reference(absolute=true)
|
|
340
|
+
absolute ? r_abs : r
|
|
341
|
+
end
|
|
342
|
+
|
|
338
343
|
private
|
|
339
344
|
|
|
345
|
+
def font_size
|
|
346
|
+
sz || @styles.fonts[@styles.cellXfs[style].fontId].sz
|
|
347
|
+
end
|
|
348
|
+
|
|
340
349
|
# Utility method for setting inline style attributes
|
|
341
350
|
def set_run_style( validator, attr, value)
|
|
342
351
|
return unless INLINE_STYLES.include?(attr.to_s)
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
module Axlsx
|
|
2
|
+
# Conditional Format Value Object
|
|
3
|
+
# Describes the values of the interpolation points in a gradient scale. This object is used by ColorScale, DataBar and IconSet classes
|
|
4
|
+
#
|
|
5
|
+
# @note The recommended way to manage these rules is via Worksheet#add_conditional_formatting
|
|
6
|
+
# @see Worksheet#add_conditional_formatting
|
|
7
|
+
# @see ConditionalFormattingRule#initialize
|
|
8
|
+
#
|
|
9
|
+
class Cfvo
|
|
10
|
+
|
|
11
|
+
# Type (ST_CfvoType)
|
|
12
|
+
# The type of this conditional formatting value object. options are num, percent, max, min, formula and percentile
|
|
13
|
+
# @return [Symbol]
|
|
14
|
+
attr_reader :type
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# Type (xsd:boolean)
|
|
18
|
+
# For icon sets, determines whether this threshold value uses the greater than or equal to operator. 0 indicates 'greater than' is used instead of 'greater than or equal to'.
|
|
19
|
+
# The default value is true
|
|
20
|
+
# @return [Boolean]
|
|
21
|
+
attr_reader :gte
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
# Type (ST_Xstring)
|
|
25
|
+
# The value of the conditional formatting object
|
|
26
|
+
# This library will accept any value so long as it supports to_s
|
|
27
|
+
attr_reader :val
|
|
28
|
+
|
|
29
|
+
# Creates a new Cfvo object
|
|
30
|
+
# @option options [Symbol] type The type of conditional formatting value object
|
|
31
|
+
# @option options [Boolean] gte threshold value usage indicator
|
|
32
|
+
# @option options [String] val The value of the conditional formatting object
|
|
33
|
+
def initialize(options={})
|
|
34
|
+
@gte = true
|
|
35
|
+
options.each do |o|
|
|
36
|
+
self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# @see type
|
|
41
|
+
def type=(v); Axlsx::validate_conditional_formatting_value_object_type(v); @type = v end
|
|
42
|
+
|
|
43
|
+
# @see gte
|
|
44
|
+
def gte=(v); Axlsx::validate_boolean(v); @gte = v end
|
|
45
|
+
|
|
46
|
+
# @see val
|
|
47
|
+
def val=(v)
|
|
48
|
+
raise ArgumentError, "#{v.inspect} must respond to to_s" unless v.respond_to?(:to_s)
|
|
49
|
+
@val = v.to_s
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# serialize the Csvo object
|
|
53
|
+
# @param [String] str
|
|
54
|
+
# @return [String]
|
|
55
|
+
def to_xml_string(str = '')
|
|
56
|
+
str << '<cfvo '
|
|
57
|
+
str << instance_values.map { |key, value| '' << key << '="' << value.to_s << '"' }.join(' ')
|
|
58
|
+
str << ' />'
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -60,7 +60,8 @@ module Axlsx
|
|
|
60
60
|
|
|
61
61
|
# @see Col#outline
|
|
62
62
|
def outlineLevel=(v)
|
|
63
|
-
Axlsx.
|
|
63
|
+
Axlsx.validate_unsigned_numeric(v)
|
|
64
|
+
raise ArgumentError, 'outlineLevel must be between 0 and 7' unless 0 <= v && v <= 7
|
|
64
65
|
@outlineLevel = v
|
|
65
66
|
end
|
|
66
67
|
|
|
@@ -101,6 +102,21 @@ module Axlsx
|
|
|
101
102
|
self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
|
|
102
103
|
end
|
|
103
104
|
end
|
|
105
|
+
|
|
106
|
+
# updates the width for this col based on the cells autowidth and
|
|
107
|
+
# an optionally specified fixed width
|
|
108
|
+
# @param [Cell] cell The cell to use in updating this col's width
|
|
109
|
+
# @param [Integer] fixed_width If this is specified the width is set
|
|
110
|
+
# to this value and the cell's attributes are ignored.
|
|
111
|
+
# @param [Boolean] use_autowidth If this is false, the cell's
|
|
112
|
+
# autowidth value will be ignored.
|
|
113
|
+
def update_width(cell, fixed_width=nil, use_autowidth=true)
|
|
114
|
+
if fixed_width.is_a? Numeric
|
|
115
|
+
self.width = fixed_width
|
|
116
|
+
elsif use_autowidth
|
|
117
|
+
self.width = [width || 0, cell.autowidth || 0].max
|
|
118
|
+
end
|
|
119
|
+
end
|
|
104
120
|
|
|
105
121
|
# Serialize this columns data to an xml string
|
|
106
122
|
# @param [String] str
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
module Axlsx
|
|
2
|
+
# Conditional Format Rule color scale object
|
|
3
|
+
# Describes a gradated color scale in this conditional formatting rule.
|
|
4
|
+
|
|
5
|
+
# @note The recommended way to manage these rules is via Worksheet#add_conditional_formatting
|
|
6
|
+
# @see Worksheet#add_conditional_formatting
|
|
7
|
+
# @see ConditionalFormattingRule#initialize
|
|
8
|
+
class ColorScale
|
|
9
|
+
|
|
10
|
+
# A simple typed list of cfvos
|
|
11
|
+
# @return [SimpleTypedList]
|
|
12
|
+
# @see Cfvo
|
|
13
|
+
attr_reader :value_objects
|
|
14
|
+
|
|
15
|
+
# A simple types list of colors
|
|
16
|
+
# @return [SimpleTypedList]
|
|
17
|
+
# @see Color
|
|
18
|
+
attr_reader :colors
|
|
19
|
+
|
|
20
|
+
# creates a new ColorScale object.
|
|
21
|
+
# This method will yield it self so you can alter the properites of the defauls conditional formating value object (cfvo and colors
|
|
22
|
+
# Two value objects and two colors are created on initialization and cannot be deleted.
|
|
23
|
+
# @see Cfvo
|
|
24
|
+
# @see Color
|
|
25
|
+
def initialize
|
|
26
|
+
initialize_value_objects
|
|
27
|
+
initialize_colors
|
|
28
|
+
yield self if block_given?
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# adds a new cfvo / color pair to the color scale and returns a hash containing
|
|
32
|
+
# a reference to the newly created cfvo and color objects so you can alter the default properties.
|
|
33
|
+
# @return [Hash] a hash with :cfvo and :color keys referencing the newly added objects.
|
|
34
|
+
def add(options={})
|
|
35
|
+
@value_objects << Cfvo.new(:type => options[:type] || :min, :val => options[:val] || 0)
|
|
36
|
+
@colors << Color.new(:rgb => options[:color] || "FF000000")
|
|
37
|
+
{:cfvo => @value_objects.last, :color => @colors.last}
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
# removes the cfvo and color pair at the index specified.
|
|
42
|
+
# @param [Integer] index The index of the cfvo and color object to delete
|
|
43
|
+
# @note you cannot remove the first two cfvo and color pairs
|
|
44
|
+
def delete_at(index=2)
|
|
45
|
+
@value_objects.delete_at index
|
|
46
|
+
@colors.delete_at index
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Serialize this color_scale object data to an xml string
|
|
50
|
+
# @param [String] str
|
|
51
|
+
# @return [String]
|
|
52
|
+
def to_xml_string(str = '')
|
|
53
|
+
str << '<colorScale>'
|
|
54
|
+
@value_objects.each { |cfvo| cfvo.to_xml_string(str) }
|
|
55
|
+
@colors.each { |color| color.to_xml_string(str) }
|
|
56
|
+
str << '</colorScale>'
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
private
|
|
60
|
+
|
|
61
|
+
# creates the initial cfvo objects
|
|
62
|
+
def initialize_value_objects
|
|
63
|
+
@value_objects = SimpleTypedList.new Cfvo
|
|
64
|
+
@value_objects.concat [Cfvo.new(:type => :min, :val => 0), Cfvo.new(:type => :max, :val => 0)]
|
|
65
|
+
@value_objects.lock
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# creates the initial color objects
|
|
69
|
+
def initialize_colors
|
|
70
|
+
@colors = SimpleTypedList.new Color
|
|
71
|
+
@colors.concat [Color.new(:rgb => "FFFF0000"), Color.new(:rgb => "FF0000FF")]
|
|
72
|
+
@colors.lock
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module Axlsx
|
|
2
|
+
|
|
3
|
+
# The cols class manages the col object used to manage column widths.
|
|
4
|
+
# This is where the magic happens with autowidth
|
|
5
|
+
class Cols < SimpleTypedList
|
|
6
|
+
|
|
7
|
+
def initialize(worksheet)
|
|
8
|
+
raise ArgumentError, "you must provide a worksheet" unless worksheet.is_a?(Worksheet)
|
|
9
|
+
super Col
|
|
10
|
+
@worksheet = worksheet
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def to_xml_string(str = '')
|
|
14
|
+
return if empty?
|
|
15
|
+
str << '<cols>'
|
|
16
|
+
each { |item| item.to_xml_string(str) }
|
|
17
|
+
str << '</cols>'
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
module Axlsx
|
|
2
|
+
|
|
3
|
+
# A comment is the text data for a comment
|
|
4
|
+
class Comment
|
|
5
|
+
|
|
6
|
+
# The text to render
|
|
7
|
+
# @return [String]
|
|
8
|
+
attr_reader :text
|
|
9
|
+
|
|
10
|
+
# The author of this comment
|
|
11
|
+
# @see Comments
|
|
12
|
+
# @return [String]
|
|
13
|
+
attr_reader :author
|
|
14
|
+
|
|
15
|
+
# The owning Comments object
|
|
16
|
+
# @return [Comments]
|
|
17
|
+
attr_reader :comments
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
# The string based cell position reference (e.g. 'A1') that determines the positioning of this comment
|
|
21
|
+
# @return [String]
|
|
22
|
+
attr_reader :ref
|
|
23
|
+
|
|
24
|
+
# TODO
|
|
25
|
+
# r (Rich Text Run)
|
|
26
|
+
# rPh (Phonetic Text Run)
|
|
27
|
+
# phoneticPr (Phonetic Properties)
|
|
28
|
+
|
|
29
|
+
def initialize(comments, options={})
|
|
30
|
+
raise ArgumentError, "A comment needs a parent comments object" unless comments.is_a?(Comments)
|
|
31
|
+
@comments = comments
|
|
32
|
+
options.each do |o|
|
|
33
|
+
self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
|
|
34
|
+
end
|
|
35
|
+
yield self if block_given?
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# The vml shape that will render this comment
|
|
39
|
+
# @return [VmlShape]
|
|
40
|
+
def vml_shape
|
|
41
|
+
@vml_shape ||= initialize_vml_shape
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
#
|
|
45
|
+
# The index of this author in a unique sorted list of all authors in
|
|
46
|
+
# the comment.
|
|
47
|
+
# @return [Integer]
|
|
48
|
+
def author_index
|
|
49
|
+
@comments.authors.index(author)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# @see ref
|
|
53
|
+
def ref=(v)
|
|
54
|
+
Axlsx::DataTypeValidator.validate "Comment.ref", [String, Cell], v
|
|
55
|
+
@ref = v if v.is_a?(String)
|
|
56
|
+
@ref = v.r if v.is_a?(Cell)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# @see text
|
|
60
|
+
def text=(v)
|
|
61
|
+
Axlsx::validate_string(v)
|
|
62
|
+
@text = v
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# @see author
|
|
66
|
+
def author=(v)
|
|
67
|
+
@author = v
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# serialize the object
|
|
71
|
+
# @param [String] str
|
|
72
|
+
# @return [String]
|
|
73
|
+
def to_xml_string(str = "")
|
|
74
|
+
author = @comments.authors[author_index]
|
|
75
|
+
str << '<comment ref="' << ref << '" authorId="' << author_index.to_s << '">'
|
|
76
|
+
str << '<text><r>'
|
|
77
|
+
str << '<rPr> <b/><color indexed="81"/></rPr>'
|
|
78
|
+
str << '<t>' << author.to_s << ':
|
|
79
|
+
</t></r>'
|
|
80
|
+
str << '<r>'
|
|
81
|
+
str << '<rPr><color indexed="81"/></rPr>'
|
|
82
|
+
str << '<t>' << text << '</t></r></text>'
|
|
83
|
+
str << '</comment>'
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
private
|
|
87
|
+
|
|
88
|
+
# initialize the vml shape based on this comment's ref/position in the worksheet.
|
|
89
|
+
# by default, all columns are 5 columns wide and 5 rows high
|
|
90
|
+
def initialize_vml_shape
|
|
91
|
+
pos = Axlsx::name_to_indices(ref)
|
|
92
|
+
@vml_shape = VmlShape.new(:row => pos[1], :column => pos[0]) do |vml|
|
|
93
|
+
vml.left_column = vml.column
|
|
94
|
+
vml.right_column = vml.column + 2
|
|
95
|
+
vml.top_row = vml.row
|
|
96
|
+
vml.bottom_row = vml.row + 4
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
end
|
|
101
|
+
end
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
module Axlsx
|
|
3
|
+
|
|
4
|
+
# Comments is a collection of Comment objects for a worksheet
|
|
5
|
+
class Comments < SimpleTypedList
|
|
6
|
+
|
|
7
|
+
# the vml_drawing that holds the shapes for comments
|
|
8
|
+
# @return [VmlDrawing]
|
|
9
|
+
attr_reader :vml_drawing
|
|
10
|
+
|
|
11
|
+
# The worksheet that these comments belong to
|
|
12
|
+
# @return [Worksheet]
|
|
13
|
+
attr_reader :worksheet
|
|
14
|
+
|
|
15
|
+
# The index of this collection in the workbook. Effectively the index of the worksheet.
|
|
16
|
+
# @return [Integer]
|
|
17
|
+
def index
|
|
18
|
+
@worksheet.index
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# The part name for this object
|
|
22
|
+
# @return [String]
|
|
23
|
+
def pn
|
|
24
|
+
"#{COMMENT_PN % (index+1)}"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Creates a new Comments object
|
|
28
|
+
# @param [Worksheet] worksheet The sheet that these comments belong to.
|
|
29
|
+
def initialize(worksheet)
|
|
30
|
+
raise ArgumentError, "you must provide a worksheet" unless worksheet.is_a?(Worksheet)
|
|
31
|
+
super(Comment)
|
|
32
|
+
@worksheet = worksheet
|
|
33
|
+
@vml_drawing = VmlDrawing.new(self)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Adds a new comment to the worksheet that owns these comments.
|
|
37
|
+
# @note the author, text and ref options are required
|
|
38
|
+
# @option options [String] author The name of the author for this comment
|
|
39
|
+
# @option options [String] text The text for this comment
|
|
40
|
+
# @option options [Stirng|Cell] ref The cell that this comment is attached to.
|
|
41
|
+
def add_comment(options={})
|
|
42
|
+
raise ArgumentError, "Comment require an author" unless options[:author]
|
|
43
|
+
raise ArgumentError, "Comment requires text" unless options[:text]
|
|
44
|
+
raise ArgumentError, "Comment requires ref" unless options[:ref]
|
|
45
|
+
@list << Comment.new(self, options)
|
|
46
|
+
yield @list.last if block_given?
|
|
47
|
+
@list.last
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# A sorted list of the unique authors in the contained comments
|
|
51
|
+
# @return [Array]
|
|
52
|
+
def authors
|
|
53
|
+
@list.map { |comment| comment.author.to_s }.uniq.sort
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# The relationships required by this object
|
|
57
|
+
# @return [Array]
|
|
58
|
+
def relationships
|
|
59
|
+
[Relationship.new(VML_DRAWING_R, "../#{vml_drawing.pn}"),
|
|
60
|
+
Relationship.new(COMMENT_R, "../#{pn}"),
|
|
61
|
+
Relationship.new(COMMENT_R_NULL, "NULL")]
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# serialize the object
|
|
65
|
+
# @param [String] str
|
|
66
|
+
# @return [String]
|
|
67
|
+
def to_xml_string(str="")
|
|
68
|
+
str << '<?xml version="1.0" encoding="UTF-8"?>'
|
|
69
|
+
str << '<comments xmlns="' << XML_NS << '">'
|
|
70
|
+
str << '<authors>'
|
|
71
|
+
authors.each do |author|
|
|
72
|
+
str << '<author>' << author.to_s << '</author>'
|
|
73
|
+
end
|
|
74
|
+
str << '</authors>'
|
|
75
|
+
str << '<commentList>'
|
|
76
|
+
@list.each do |comment|
|
|
77
|
+
comment.to_xml_string str
|
|
78
|
+
end
|
|
79
|
+
str << '</commentList></comments>'
|
|
80
|
+
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
module Axlsx
|
|
2
|
+
# Conditional formatting allows styling of ranges based on functions
|
|
3
|
+
#
|
|
4
|
+
# @note The recommended way to manage conditional formatting is via Worksheet#add_conditional_formatting
|
|
5
|
+
# @see Worksheet#add_conditional_formatting
|
|
6
|
+
# @see ConditionalFormattingRule
|
|
7
|
+
class ConditionalFormatting
|
|
8
|
+
|
|
9
|
+
# Range over which the formatting is applied, in "A1:B2" format
|
|
10
|
+
# @return [String]
|
|
11
|
+
attr_reader :sqref
|
|
12
|
+
|
|
13
|
+
# Rules to apply the formatting to. Can be either a hash of
|
|
14
|
+
# options to create a {ConditionalFormattingRule}, an array of hashes
|
|
15
|
+
# for multiple ConditionalFormattingRules, or an array of already
|
|
16
|
+
# created ConditionalFormattingRules.
|
|
17
|
+
# @see ConditionalFormattingRule#initialize
|
|
18
|
+
# @return [Array]
|
|
19
|
+
attr_reader :rules
|
|
20
|
+
|
|
21
|
+
# Creates a new {ConditionalFormatting} object
|
|
22
|
+
# @option options [Array] rules The rules to apply
|
|
23
|
+
# @option options [String] sqref The range to apply the rules to
|
|
24
|
+
def initialize(options={})
|
|
25
|
+
@rules = []
|
|
26
|
+
options.each do |o|
|
|
27
|
+
self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}="
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Add Conditional Formatting Rules to this object. Rules can either
|
|
32
|
+
# be already created {ConditionalFormattingRule} elements or
|
|
33
|
+
# hashes of options for automatic creation. If rules is a hash
|
|
34
|
+
# instead of an array, assume only one rule being added.
|
|
35
|
+
#
|
|
36
|
+
# @example This would apply formatting "1" to cells > 20, and formatting "2" to cells < 1
|
|
37
|
+
# conditional_formatting.add_rules [
|
|
38
|
+
# { :type => :cellIs, :operator => :greaterThan, :formula => "20", :dxfId => 1, :priority=> 1 },
|
|
39
|
+
# { :type => :cellIs, :operator => :lessThan, :formula => "10", :dxfId => 2, :priority=> 2 } ]
|
|
40
|
+
#
|
|
41
|
+
# @param [Array|Hash] rules the rules to apply, can be just one in hash form
|
|
42
|
+
# @see ConditionalFormattingRule#initialize
|
|
43
|
+
def add_rules(rules)
|
|
44
|
+
rules = [rules] if rules.is_a? Hash
|
|
45
|
+
rules.each do |rule|
|
|
46
|
+
add_rule rule
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Add a ConditionalFormattingRule. If a hash of options is passed
|
|
51
|
+
# in create a rule on the fly.
|
|
52
|
+
# @param [ConditionalFormattingRule|Hash] rule A rule to use, or the options necessary to create one.
|
|
53
|
+
# @see ConditionalFormattingRule#initialize
|
|
54
|
+
def add_rule(rule)
|
|
55
|
+
if rule.is_a? Axlsx::ConditionalFormattingRule
|
|
56
|
+
@rules << rule
|
|
57
|
+
elsif rule.is_a? Hash
|
|
58
|
+
@rules << ConditionalFormattingRule.new(rule)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# @see rules
|
|
63
|
+
def rules=(v); @rules = v end
|
|
64
|
+
# @see sqref
|
|
65
|
+
def sqref=(v); Axlsx::validate_string(v); @sqref = v end
|
|
66
|
+
|
|
67
|
+
# Serializes the conditional formatting element
|
|
68
|
+
# @example Conditional Formatting XML looks like:
|
|
69
|
+
# <conditionalFormatting sqref="E3:E9">
|
|
70
|
+
# <cfRule type="cellIs" dxfId="0" priority="1" operator="greaterThan">
|
|
71
|
+
# <formula>0.5</formula>
|
|
72
|
+
# </cfRule>
|
|
73
|
+
# </conditionalFormatting>
|
|
74
|
+
# @param [String] str
|
|
75
|
+
# @return [String]
|
|
76
|
+
def to_xml_string(str = '')
|
|
77
|
+
str << '<conditionalFormatting sqref="' << sqref << '">'
|
|
78
|
+
str << rules.collect{ |rule| rule.to_xml_string }.join(' ')
|
|
79
|
+
str << '</conditionalFormatting>'
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|