axlsx 2.0.1 → 2.1.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +6 -3
- data/Rakefile +9 -10
- data/examples/IMAGE1UP.JPEG +0 -0
- data/examples/auto_filter.rb +10 -1
- data/examples/conditional_formatting/example_conditional_formatting.rb +3 -3
- data/examples/example.rb +72 -4
- data/examples/merge_cells.rb +17 -0
- data/examples/no_grid_with_borders.rb +18 -0
- data/examples/pivot_test.rb +63 -0
- data/examples/split.rb +16 -0
- data/lib/axlsx.rb +30 -16
- data/lib/axlsx/content_type/abstract_content_type.rb +1 -1
- data/lib/axlsx/content_type/content_type.rb +1 -1
- data/lib/axlsx/doc_props/app.rb +1 -1
- data/lib/axlsx/doc_props/core.rb +5 -5
- data/lib/axlsx/drawing/axes.rb +1 -1
- data/lib/axlsx/drawing/axis.rb +12 -9
- data/lib/axlsx/drawing/bar_3D_chart.rb +13 -13
- data/lib/axlsx/drawing/bar_series.rb +9 -9
- data/lib/axlsx/drawing/bubble_chart.rb +59 -0
- data/lib/axlsx/drawing/bubble_series.rb +63 -0
- data/lib/axlsx/drawing/cat_axis.rb +5 -5
- data/lib/axlsx/drawing/chart.rb +44 -7
- data/lib/axlsx/drawing/drawing.rb +3 -1
- data/lib/axlsx/drawing/graphic_frame.rb +3 -3
- data/lib/axlsx/drawing/hyperlink.rb +1 -3
- data/lib/axlsx/drawing/line_3D_chart.rb +2 -2
- data/lib/axlsx/drawing/line_chart.rb +10 -10
- data/lib/axlsx/drawing/line_series.rb +14 -2
- data/lib/axlsx/drawing/marker.rb +1 -1
- data/lib/axlsx/drawing/num_data.rb +4 -4
- data/lib/axlsx/drawing/num_data_source.rb +6 -6
- data/lib/axlsx/drawing/num_val.rb +1 -1
- data/lib/axlsx/drawing/one_cell_anchor.rb +1 -1
- data/lib/axlsx/drawing/pic.rb +2 -3
- data/lib/axlsx/drawing/picture_locking.rb +1 -3
- data/lib/axlsx/drawing/pie_3D_chart.rb +5 -6
- data/lib/axlsx/drawing/pie_series.rb +6 -6
- data/lib/axlsx/drawing/scaling.rb +4 -4
- data/lib/axlsx/drawing/scatter_chart.rb +10 -10
- data/lib/axlsx/drawing/scatter_series.rb +26 -7
- data/lib/axlsx/drawing/ser_axis.rb +2 -2
- data/lib/axlsx/drawing/series.rb +3 -3
- data/lib/axlsx/drawing/series_title.rb +2 -2
- data/lib/axlsx/drawing/str_data.rb +3 -3
- data/lib/axlsx/drawing/str_val.rb +1 -1
- data/lib/axlsx/drawing/title.rb +3 -3
- data/lib/axlsx/drawing/val_axis.rb +1 -1
- data/lib/axlsx/drawing/vml_drawing.rb +1 -1
- data/lib/axlsx/package.rb +39 -28
- data/lib/axlsx/rels/relationship.rb +1 -1
- data/lib/axlsx/rels/relationships.rb +2 -2
- data/lib/axlsx/stylesheet/border_pr.rb +2 -2
- data/lib/axlsx/stylesheet/cell_alignment.rb +1 -3
- data/lib/axlsx/stylesheet/cell_protection.rb +1 -3
- data/lib/axlsx/stylesheet/cell_style.rb +1 -3
- data/lib/axlsx/stylesheet/color.rb +1 -3
- data/lib/axlsx/stylesheet/font.rb +1 -1
- data/lib/axlsx/stylesheet/gradient_stop.rb +1 -1
- data/lib/axlsx/stylesheet/num_fmt.rb +1 -3
- data/lib/axlsx/stylesheet/pattern_fill.rb +1 -1
- data/lib/axlsx/stylesheet/styles.rb +6 -6
- data/lib/axlsx/stylesheet/table_style_element.rb +1 -3
- data/lib/axlsx/util/accessors.rb +6 -6
- data/lib/axlsx/util/constants.rb +106 -101
- data/lib/axlsx/util/options_parser.rb +2 -1
- data/lib/axlsx/util/parser.rb +4 -4
- data/lib/axlsx/util/serialized_attributes.rb +16 -6
- data/lib/axlsx/util/simple_typed_list.rb +28 -52
- data/lib/axlsx/util/storage.rb +4 -4
- data/lib/axlsx/util/string.rb +7 -0
- data/lib/axlsx/util/validators.rb +20 -13
- data/lib/axlsx/version.rb +1 -1
- data/lib/axlsx/workbook/defined_name.rb +11 -12
- data/lib/axlsx/workbook/defined_names.rb +2 -2
- data/lib/axlsx/workbook/shared_strings_table.rb +5 -5
- data/lib/axlsx/workbook/workbook.rb +19 -12
- data/lib/axlsx/workbook/workbook_view.rb +78 -0
- data/lib/axlsx/workbook/workbook_views.rb +22 -0
- data/lib/axlsx/workbook/worksheet/auto_filter/auto_filter.rb +2 -2
- data/lib/axlsx/workbook/worksheet/auto_filter/filters.rb +1 -3
- data/lib/axlsx/workbook/worksheet/break.rb +1 -3
- data/lib/axlsx/workbook/worksheet/cell.rb +128 -73
- data/lib/axlsx/workbook/worksheet/cell_serializer.rb +50 -40
- data/lib/axlsx/workbook/worksheet/cfvo.rb +1 -3
- data/lib/axlsx/workbook/worksheet/cfvos.rb +1 -1
- data/lib/axlsx/workbook/worksheet/col.rb +7 -10
- data/lib/axlsx/workbook/worksheet/col_breaks.rb +2 -2
- data/lib/axlsx/workbook/worksheet/comment.rb +5 -6
- data/lib/axlsx/workbook/worksheet/comments.rb +9 -12
- data/lib/axlsx/workbook/worksheet/conditional_formatting.rb +1 -1
- data/lib/axlsx/workbook/worksheet/conditional_formatting_rule.rb +1 -1
- data/lib/axlsx/workbook/worksheet/data_bar.rb +4 -6
- data/lib/axlsx/workbook/worksheet/data_validation.rb +6 -4
- data/lib/axlsx/workbook/worksheet/dimension.rb +2 -2
- data/lib/axlsx/workbook/worksheet/header_footer.rb +6 -8
- data/lib/axlsx/workbook/worksheet/icon_set.rb +3 -5
- data/lib/axlsx/workbook/worksheet/merged_cells.rb +2 -2
- data/lib/axlsx/workbook/worksheet/page_margins.rb +1 -3
- data/lib/axlsx/workbook/worksheet/page_set_up_pr.rb +1 -1
- data/lib/axlsx/workbook/worksheet/page_setup.rb +21 -23
- data/lib/axlsx/workbook/worksheet/pane.rb +1 -3
- data/lib/axlsx/workbook/worksheet/pivot_table.rb +17 -24
- data/lib/axlsx/workbook/worksheet/pivot_table_cache_definition.rb +4 -4
- data/lib/axlsx/workbook/worksheet/print_options.rb +1 -3
- data/lib/axlsx/workbook/worksheet/protected_range.rb +1 -3
- data/lib/axlsx/workbook/worksheet/protected_ranges.rb +1 -1
- data/lib/axlsx/workbook/worksheet/rich_text.rb +35 -0
- data/lib/axlsx/workbook/worksheet/rich_text_run.rb +254 -0
- data/lib/axlsx/workbook/worksheet/row.rb +33 -51
- data/lib/axlsx/workbook/worksheet/row_breaks.rb +2 -2
- data/lib/axlsx/workbook/worksheet/selection.rb +1 -3
- data/lib/axlsx/workbook/worksheet/sheet_data.rb +3 -1
- data/lib/axlsx/workbook/worksheet/sheet_protection.rb +1 -3
- data/lib/axlsx/workbook/worksheet/table.rb +6 -6
- data/lib/axlsx/workbook/worksheet/table_style_info.rb +1 -3
- data/lib/axlsx/workbook/worksheet/tables.rb +1 -1
- data/lib/axlsx/workbook/worksheet/worksheet.rb +59 -30
- data/lib/axlsx/workbook/worksheet/worksheet_hyperlinks.rb +3 -3
- data/test/drawing/tc_axis.rb +27 -0
- data/test/drawing/tc_bubble_chart.rb +44 -0
- data/test/drawing/tc_bubble_series.rb +21 -0
- data/test/drawing/tc_data_source.rb +6 -0
- data/test/drawing/tc_line_chart.rb +5 -5
- data/test/drawing/tc_line_series.rb +10 -2
- data/test/drawing/tc_pic.rb +4 -0
- data/test/drawing/tc_scatter_series.rb +25 -1
- data/test/tc_helper.rb +1 -1
- data/test/tc_package.rb +7 -1
- data/test/util/tc_simple_typed_list.rb +1 -2
- data/test/workbook/tc_defined_name.rb +12 -4
- data/test/workbook/tc_workbook.rb +16 -2
- data/test/workbook/tc_workbook_view.rb +50 -0
- data/test/workbook/worksheet/auto_filter/tc_filters.rb +1 -1
- data/test/workbook/worksheet/tc_break.rb +1 -1
- data/test/workbook/worksheet/tc_cell.rb +30 -4
- data/test/workbook/worksheet/tc_col.rb +2 -2
- data/test/workbook/worksheet/tc_conditional_formatting.rb +2 -2
- data/test/workbook/worksheet/tc_data_bar.rb +1 -1
- data/test/workbook/worksheet/tc_data_validation.rb +11 -11
- data/test/workbook/worksheet/tc_header_footer.rb +2 -2
- data/test/workbook/worksheet/tc_icon_set.rb +1 -1
- data/test/workbook/worksheet/tc_page_setup.rb +3 -3
- data/test/workbook/worksheet/tc_print_options.rb +1 -1
- data/test/workbook/worksheet/tc_rich_text.rb +44 -0
- data/test/workbook/worksheet/tc_rich_text_run.rb +172 -0
- data/test/workbook/worksheet/tc_row.rb +2 -2
- data/test/workbook/worksheet/tc_sheet_calc_pr.rb +1 -1
- data/test/workbook/worksheet/tc_sheet_format_pr.rb +4 -4
- data/test/workbook/worksheet/tc_sheet_protection.rb +5 -5
- data/test/workbook/worksheet/tc_sheet_view.rb +4 -4
- data/test/workbook/worksheet/tc_worksheet.rb +49 -10
- metadata +81 -55
- data/test/axlsx.qcachegrind +0 -2226
@@ -11,8 +11,8 @@ module Axlsx
|
|
11
11
|
# @param [String] str
|
12
12
|
# @return [String]
|
13
13
|
def to_xml_string(str = '')
|
14
|
-
return if
|
15
|
-
str <<
|
14
|
+
return if empty?
|
15
|
+
str << '<definedNames>'
|
16
16
|
each { |defined_name| defined_name.to_xml_string(str) }
|
17
17
|
str << '</definedNames>'
|
18
18
|
end
|
@@ -38,7 +38,7 @@ module Axlsx
|
|
38
38
|
@xml_space = xml_space
|
39
39
|
@unique_cells = {}
|
40
40
|
@shared_xml_string = ""
|
41
|
-
shareable_cells = cells.flatten.select{ |cell| cell.plain_string? }
|
41
|
+
shareable_cells = cells.flatten.select{ |cell| cell.plain_string? || cell.contains_rich_text? }
|
42
42
|
@count = shareable_cells.size
|
43
43
|
resolve(shareable_cells)
|
44
44
|
end
|
@@ -47,10 +47,10 @@ module Axlsx
|
|
47
47
|
# @param [String] str
|
48
48
|
# @return [String]
|
49
49
|
def to_xml_string(str='')
|
50
|
-
|
51
|
-
str << '
|
52
|
-
str << '
|
53
|
-
str =
|
50
|
+
Axlsx::sanitize(@shared_xml_string)
|
51
|
+
str << ('<?xml version="1.0" encoding="UTF-8"?><sst xmlns="' << XML_NS << '"')
|
52
|
+
str << (' count="' << @count.to_s << '" uniqueCount="' << unique_count.to_s << '"')
|
53
|
+
str << (' xml:space="' << xml_space.to_s << '">' << @shared_xml_string << '</sst>')
|
54
54
|
end
|
55
55
|
|
56
56
|
private
|
@@ -5,6 +5,8 @@ require 'axlsx/workbook/worksheet/auto_filter/auto_filter.rb'
|
|
5
5
|
require 'axlsx/workbook/worksheet/date_time_converter.rb'
|
6
6
|
require 'axlsx/workbook/worksheet/protected_range.rb'
|
7
7
|
require 'axlsx/workbook/worksheet/protected_ranges.rb'
|
8
|
+
require 'axlsx/workbook/worksheet/rich_text_run'
|
9
|
+
require 'axlsx/workbook/worksheet/rich_text'
|
8
10
|
require 'axlsx/workbook/worksheet/cell_serializer.rb'
|
9
11
|
require 'axlsx/workbook/worksheet/cell.rb'
|
10
12
|
require 'axlsx/workbook/worksheet/page_margins.rb'
|
@@ -37,7 +39,8 @@ require 'axlsx/workbook/worksheet/worksheet_hyperlinks'
|
|
37
39
|
require 'axlsx/workbook/worksheet/break'
|
38
40
|
require 'axlsx/workbook/worksheet/row_breaks'
|
39
41
|
require 'axlsx/workbook/worksheet/col_breaks'
|
40
|
-
|
42
|
+
require 'axlsx/workbook/workbook_view'
|
43
|
+
require 'axlsx/workbook/workbook_views'
|
41
44
|
|
42
45
|
|
43
46
|
require 'axlsx/workbook/worksheet/worksheet.rb'
|
@@ -139,6 +142,10 @@ require 'axlsx/workbook/worksheet/selection.rb'
|
|
139
142
|
# @return [SimpleTypedList]
|
140
143
|
attr_reader :pivot_tables
|
141
144
|
|
145
|
+
# A collection of views for this workbook
|
146
|
+
def views
|
147
|
+
@views ||= WorkbookViews.new
|
148
|
+
end
|
142
149
|
|
143
150
|
# A collection of defined names for this workbook
|
144
151
|
# @note The recommended way to manage defined names is Workbook#add_defined_name
|
@@ -263,6 +270,10 @@ require 'axlsx/workbook/worksheet/selection.rb'
|
|
263
270
|
worksheet
|
264
271
|
end
|
265
272
|
|
273
|
+
def add_view(options={})
|
274
|
+
views << WorkbookView.new(options)
|
275
|
+
end
|
276
|
+
|
266
277
|
# Adds a defined name to this workbook
|
267
278
|
# @return [DefinedName]
|
268
279
|
# @param [String] formula @see DefinedName
|
@@ -283,7 +294,7 @@ require 'axlsx/workbook/worksheet/selection.rb'
|
|
283
294
|
end
|
284
295
|
r << Relationship.new(self, STYLES_R, STYLES_PN)
|
285
296
|
if use_shared_strings
|
286
|
-
r << Relationship.new(self, SHARED_STRINGS_R,
|
297
|
+
r << Relationship.new(self, SHARED_STRINGS_R, SHARED_STRINGS_PN)
|
287
298
|
end
|
288
299
|
r
|
289
300
|
end
|
@@ -327,23 +338,19 @@ require 'axlsx/workbook/worksheet/selection.rb'
|
|
327
338
|
# @param [String] str
|
328
339
|
# @return [String]
|
329
340
|
def to_xml_string(str='')
|
330
|
-
add_worksheet unless worksheets.size > 0
|
341
|
+
add_worksheet(name: 'Sheet1') unless worksheets.size > 0
|
331
342
|
str << '<?xml version="1.0" encoding="UTF-8"?>'
|
332
|
-
str << '<workbook xmlns="' << XML_NS << '" xmlns:r="' << XML_NS_R << '">'
|
333
|
-
str << '<workbookPr date1904="' << @@date1904.to_s << '"/>'
|
343
|
+
str << ('<workbook xmlns="' << XML_NS << '" xmlns:r="' << XML_NS_R << '">')
|
344
|
+
str << ('<workbookPr date1904="' << @@date1904.to_s << '"/>')
|
345
|
+
views.to_xml_string(str)
|
334
346
|
str << '<sheets>'
|
335
|
-
|
336
|
-
str << '<sheet name="' << sheet.name << '" sheetId="' << (index+1).to_s << '" r:id="' << sheet.rId << '"/>'
|
337
|
-
if defined_name = sheet.auto_filter.defined_name
|
338
|
-
add_defined_name defined_name, :name => '_xlnm._FilterDatabase', :local_sheet_id => index, :hidden => 1
|
339
|
-
end
|
340
|
-
end
|
347
|
+
worksheets.each { |sheet| sheet.to_sheet_node_xml_string(str) }
|
341
348
|
str << '</sheets>'
|
342
349
|
defined_names.to_xml_string(str)
|
343
350
|
unless pivot_tables.empty?
|
344
351
|
str << '<pivotCaches>'
|
345
352
|
pivot_tables.each do |pivot_table|
|
346
|
-
str << '<pivotCache cacheId="' << pivot_table.cache_definition.cache_id.to_s << '" r:id="' << pivot_table.cache_definition.rId << '"/>'
|
353
|
+
str << ('<pivotCache cacheId="' << pivot_table.cache_definition.cache_id.to_s << '" r:id="' << pivot_table.cache_definition.rId << '"/>')
|
347
354
|
end
|
348
355
|
str << '</pivotCaches>'
|
349
356
|
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# <xsd:complexType name="CT_BookView">
|
2
|
+
# <xsd:sequence>
|
3
|
+
# <xsd:element name="extLst" type="CT_ExtensionList" minOccurs="0" maxOccurs="1"/>
|
4
|
+
# </xsd:sequence>
|
5
|
+
# <xsd:attribute name="visibility" type="ST_Visibility" use="optional" default="visible"/>
|
6
|
+
# <xsd:attribute name="minimized" type="xsd:boolean" use="optional" default="false"/>
|
7
|
+
# <xsd:attribute name="showHorizontalScroll" type="xsd:boolean" use="optional" default="true"/>
|
8
|
+
# <xsd:attribute name="showVerticalScroll" type="xsd:boolean" use="optional" default="true"/>
|
9
|
+
# <xsd:attribute name="showSheetTabs" type="xsd:boolean" use="optional" default="true"/>
|
10
|
+
# <xsd:attribute name="xWindow" type="xsd:int" use="optional"/>
|
11
|
+
# <xsd:attribute name="yWindow" type="xsd:int" use="optional"/>
|
12
|
+
# <xsd:attribute name="windowWidth" type="xsd:unsignedInt" use="optional"/>
|
13
|
+
# <xsd:attribute name="windowHeight" type="xsd:unsignedInt" use="optional"/>
|
14
|
+
# <xsd:attribute name="tabRatio" type="xsd:unsignedInt" use="optional" default="600"/>
|
15
|
+
# <xsd:attribute name="firstSheet" type="xsd:unsignedInt" use="optional" default="0"/>
|
16
|
+
# <xsd:attribute name="activeTab" type="xsd:unsignedInt" use="optional" default="0"/>
|
17
|
+
# <xsd:attribute name="autoFilterDateGrouping" type="xsd:boolean" use="optional"
|
18
|
+
# default="true"/>
|
19
|
+
# </xsd:complexType>
|
20
|
+
|
21
|
+
module Axlsx
|
22
|
+
|
23
|
+
# A BookView defines the display properties for a workbook.
|
24
|
+
# Units for window widths and other dimensions are expressed in twips.
|
25
|
+
# Twip measurements are portable between different display resolutions.
|
26
|
+
# The formula is (screen pixels) * (20 * 72) / (logical device dpi),
|
27
|
+
# where the logical device dpi can be different for x and y coordinates.
|
28
|
+
class WorkbookView
|
29
|
+
|
30
|
+
include Axlsx::SerializedAttributes
|
31
|
+
include Axlsx::OptionsParser
|
32
|
+
include Axlsx::Accessors
|
33
|
+
|
34
|
+
|
35
|
+
# Creates a new BookView object
|
36
|
+
# @params [Hash] options A hash of key/value pairs that will be mapped to this instances attributes.
|
37
|
+
# @option [Symbol] visibility Specifies visible state of the workbook window. The default value for this attribute is :visible.
|
38
|
+
# @option [Boolean] minimized Specifies a boolean value that indicates whether the workbook window is minimized.
|
39
|
+
# @option [Boolean] show_horizontal_scroll Specifies a boolean value that indicates whether to display the horizontal scroll bar in the user interface.
|
40
|
+
# @option [Boolean] show_vertical_scroll Specifies a boolean value that indicates whether to display the vertical scroll bar.
|
41
|
+
# @option [Boolean] show_sheet_tabs Specifies a boolean value that indicates whether to display the sheet tabs in the user interface.
|
42
|
+
# @option [Integer] tab_ratio Specifies ratio between the workbook tabs bar and the horizontal scroll bar.
|
43
|
+
# @option [Integer] first_sheet Specifies the index to the first sheet in this book view.
|
44
|
+
# @option [Integer] active_tab Specifies an unsignedInt that contains the index to the active sheet in this book view.
|
45
|
+
# @option [Integer] x_window Specifies the X coordinate for the upper left corner of the workbook window. The unit of measurement for this value is twips.
|
46
|
+
# @option [Integer] y_window Specifies the Y coordinate for the upper left corner of the workbook window. The unit of measurement for this value is twips.
|
47
|
+
# @option [Integer] window_width Specifies the width of the workbook window. The unit of measurement for this value is twips.
|
48
|
+
# @option [Integer] window_height Specifies the height of the workbook window. The unit of measurement for this value is twips.
|
49
|
+
# @option [Boolean] auto_filter_date_grouping Specifies a boolean value that indicates whether to group dates when presenting the user with filtering options in the user interface.
|
50
|
+
def initialize(options={})
|
51
|
+
parse_options options
|
52
|
+
yield self if block_given?
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
unsigned_int_attr_accessor :x_window, :y_window, :window_width, :window_height,
|
57
|
+
:tab_ratio, :first_sheet, :active_tab
|
58
|
+
|
59
|
+
validated_attr_accessor [:visibility], :validate_view_visibility
|
60
|
+
|
61
|
+
serializable_attributes :visibility, :minimized,
|
62
|
+
:show_horizontal_scroll, :show_vertical_scroll,
|
63
|
+
:show_sheet_tabs, :tab_ratio, :first_sheet, :active_tab,
|
64
|
+
:x_window, :y_window, :window_width, :window_height,
|
65
|
+
:auto_filter_date_grouping
|
66
|
+
|
67
|
+
boolean_attr_accessor :minimized, :show_horizontal_scroll, :show_vertical_scroll,
|
68
|
+
:show_sheet_tabs, :auto_filter_date_grouping
|
69
|
+
|
70
|
+
|
71
|
+
|
72
|
+
def to_xml_string(str = '')
|
73
|
+
str << '<workbookView '
|
74
|
+
serialized_attributes str
|
75
|
+
str << '></workbookView>'
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Axlsx
|
2
|
+
# a simple types list of BookView objects
|
3
|
+
class WorkbookViews < SimpleTypedList
|
4
|
+
|
5
|
+
# creates the book views object
|
6
|
+
def initialize
|
7
|
+
super WorkbookView
|
8
|
+
end
|
9
|
+
|
10
|
+
# Serialize to xml
|
11
|
+
# @param [String] str
|
12
|
+
# @return [String]
|
13
|
+
def to_xml_string(str = '')
|
14
|
+
return if empty?
|
15
|
+
str << "<bookViews>"
|
16
|
+
each { |view| view.to_xml_string(str) }
|
17
|
+
str << '</bookViews>'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
|
@@ -47,8 +47,8 @@ module Axlsx
|
|
47
47
|
columns.last
|
48
48
|
end
|
49
49
|
|
50
|
-
# actually performs the filtering of rows who's cells do not
|
51
|
-
# match the filter.
|
50
|
+
# actually performs the filtering of rows who's cells do not
|
51
|
+
# match the filter.
|
52
52
|
def apply
|
53
53
|
first_cell, last_cell = range.split(':')
|
54
54
|
start_point = Axlsx::name_to_indices(first_cell)
|
@@ -237,9 +237,7 @@ include Axlsx::SerializedAttributes
|
|
237
237
|
# Serialize the object to xml
|
238
238
|
# @param [String] str The string object this serialization will be concatenated to.
|
239
239
|
def to_xml_string(str = '')
|
240
|
-
|
241
|
-
serialized_attributes str
|
242
|
-
str << '/>'
|
240
|
+
serialized_tag('dateGroupItem', str)
|
243
241
|
end
|
244
242
|
end
|
245
243
|
end
|
@@ -30,17 +30,24 @@ module Axlsx
|
|
30
30
|
# @option options [String] color an 8 letter rgb specification
|
31
31
|
# @option options [Number] formula_value The value to cache for a formula cell.
|
32
32
|
# @option options [Symbol] scheme must be one of :none, major, :minor
|
33
|
-
def initialize(row, value=
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
33
|
+
def initialize(row, value = nil, options = {})
|
34
|
+
@row = row
|
35
|
+
# Do not use instance vars if not needed to use less RAM
|
36
|
+
# And do not call parse_options on frequently used options
|
37
|
+
# to get less GC cycles
|
38
|
+
type = options.delete(:type) || cell_type_from_value(value)
|
39
|
+
self.type = type unless type == :string
|
40
|
+
|
41
|
+
|
42
|
+
val = options.delete(:style)
|
43
|
+
self.style = val unless val.nil? || val == 0
|
44
|
+
val = options.delete(:formula_value)
|
45
|
+
self.formula_value = val unless val.nil?
|
46
|
+
|
47
|
+
parse_options(options)
|
48
|
+
|
49
|
+
self.value = value
|
50
|
+
value.cell = self if contains_rich_text?
|
44
51
|
end
|
45
52
|
|
46
53
|
# this is the cached value for formula cells. If you want the values to render in iOS/Mac OSX preview
|
@@ -53,15 +60,20 @@ module Axlsx
|
|
53
60
|
# needs to define bla=(v) and bla methods on the class that hook into a
|
54
61
|
# set_attr method that kicks the suplied validator and updates the instance_variable
|
55
62
|
# for the key
|
56
|
-
INLINE_STYLES = [
|
57
|
-
|
58
|
-
|
59
|
-
|
63
|
+
INLINE_STYLES = [:value, :type, :font_name, :charset,
|
64
|
+
:family, :b, :i, :strike, :outline,
|
65
|
+
:shadow, :condense, :extend, :u,
|
66
|
+
:vertAlign, :sz, :color, :scheme].freeze
|
67
|
+
|
68
|
+
CELL_TYPES = [:date, :time, :float, :integer, :richtext,
|
69
|
+
:string, :boolean, :iso_8601].freeze
|
60
70
|
|
61
71
|
# The index of the cellXfs item to be applied to this cell.
|
62
72
|
# @return [Integer]
|
63
73
|
# @see Axlsx::Styles
|
64
|
-
|
74
|
+
def style
|
75
|
+
defined?(@style) ? @style : 0
|
76
|
+
end
|
65
77
|
|
66
78
|
# The row this cell belongs to.
|
67
79
|
# @return [Row]
|
@@ -78,18 +90,21 @@ module Axlsx
|
|
78
90
|
# :string to :integer or :float, type conversions always return 0 or 0.0
|
79
91
|
# :string, :integer, or :float to :time conversions always return the original value as a string and set the cells type to :string.
|
80
92
|
# No support is currently implemented for parsing time strings.
|
81
|
-
|
93
|
+
def type
|
94
|
+
defined?(@type) ? @type : :string
|
95
|
+
end
|
96
|
+
|
82
97
|
# @see type
|
83
98
|
def type=(v)
|
84
|
-
RestrictionValidator.validate
|
85
|
-
@type=v
|
86
|
-
self.value = @value unless @value.nil?
|
99
|
+
RestrictionValidator.validate :cell_type, CELL_TYPES, v
|
100
|
+
@type = v
|
101
|
+
self.value = @value unless !defined?(@value) || @value.nil?
|
87
102
|
end
|
88
103
|
|
89
|
-
|
90
104
|
# The value of this cell.
|
91
105
|
# @return [String, Integer, Float, Time, Boolean] casted value based on cell's type attribute.
|
92
106
|
attr_reader :value
|
107
|
+
|
93
108
|
# @see value
|
94
109
|
def value=(v)
|
95
110
|
#TODO: consider doing value based type determination first?
|
@@ -99,16 +114,20 @@ module Axlsx
|
|
99
114
|
# Indicates that the cell has one or more of the custom cell styles applied.
|
100
115
|
# @return [Boolean]
|
101
116
|
def is_text_run?
|
102
|
-
@is_text_run
|
117
|
+
defined?(@is_text_run) && @is_text_run && !contains_rich_text?
|
118
|
+
end
|
119
|
+
|
120
|
+
def contains_rich_text?
|
121
|
+
type == :richtext
|
103
122
|
end
|
104
|
-
|
123
|
+
|
105
124
|
# Indicates if the cell is good for shared string table
|
106
125
|
def plain_string?
|
107
|
-
|
126
|
+
type == :string && # String typed
|
108
127
|
!is_text_run? && # No inline styles
|
109
128
|
!@value.nil? && # Not nil
|
110
129
|
!@value.empty? && # Not empty
|
111
|
-
!@value.start_with?(
|
130
|
+
!@value.start_with?(?=) # Not a formula
|
112
131
|
end
|
113
132
|
|
114
133
|
# The inline font_name property for the cell
|
@@ -231,7 +250,7 @@ module Axlsx
|
|
231
250
|
attr_reader :vertAlign
|
232
251
|
# @see vertAlign
|
233
252
|
def vertAlign=(v)
|
234
|
-
RestrictionValidator.validate
|
253
|
+
RestrictionValidator.validate :cell_vertAlign, [:baseline, :subscript, :superscript], v
|
235
254
|
set_run_style nil, :vertAlign, v
|
236
255
|
end
|
237
256
|
|
@@ -241,7 +260,7 @@ module Axlsx
|
|
241
260
|
attr_reader :scheme
|
242
261
|
# @see scheme
|
243
262
|
def scheme=(v)
|
244
|
-
RestrictionValidator.validate
|
263
|
+
RestrictionValidator.validate :cell_scheme, [:none, :major, :minor], v
|
245
264
|
set_run_style nil, :scheme, v
|
246
265
|
end
|
247
266
|
|
@@ -251,14 +270,14 @@ module Axlsx
|
|
251
270
|
|
252
271
|
# @return [Integer] The index of the cell in the containing row.
|
253
272
|
def index
|
254
|
-
@row.
|
273
|
+
@row.index(self)
|
255
274
|
end
|
256
275
|
|
257
276
|
# @return [String] The alpha(column)numeric(row) reference for this sell.
|
258
277
|
# @example Relative Cell Reference
|
259
278
|
# ws.rows.first.cells.first.r #=> "A1"
|
260
279
|
def r
|
261
|
-
Axlsx::cell_r index, @row.
|
280
|
+
Axlsx::cell_r index, @row.row_index
|
262
281
|
end
|
263
282
|
|
264
283
|
# @return [String] The absolute alpha(column)numeric(row) reference for this sell.
|
@@ -272,26 +291,26 @@ module Axlsx
|
|
272
291
|
# @raise [ArgumentError] Invalid cellXfs id if the value provided is not within cellXfs items range.
|
273
292
|
def style=(v)
|
274
293
|
Axlsx::validate_unsigned_int(v)
|
275
|
-
count =
|
294
|
+
count = styles.cellXfs.size
|
276
295
|
raise ArgumentError, "Invalid cellXfs id" unless v < count
|
277
296
|
@style = v
|
278
297
|
end
|
279
298
|
|
280
|
-
# @return [Array] of x/y coordinates in the
|
299
|
+
# @return [Array] of x/y coordinates in the sheet for this cell.
|
281
300
|
def pos
|
282
|
-
[index, row.
|
301
|
+
[index, row.row_index]
|
283
302
|
end
|
284
303
|
|
285
304
|
# Merges all the cells in a range created between this cell and the cell or string name for a cell provided
|
286
305
|
# @see worksheet.merge_cells
|
287
306
|
# @param [Cell, String] target The last cell, or str ref for the cell in the merge range
|
288
307
|
def merge(target)
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
self.row.worksheet.merge_cells "#{
|
308
|
+
start, stop = if target.is_a?(String)
|
309
|
+
[self.r, target]
|
310
|
+
elsif(target.is_a?(Cell))
|
311
|
+
Axlsx.sort_cells([self, target]).map { |c| c.r }
|
312
|
+
end
|
313
|
+
self.row.worksheet.merge_cells "#{start}:#{stop}" unless stop.nil?
|
295
314
|
end
|
296
315
|
|
297
316
|
# Serializes the cell
|
@@ -304,17 +323,11 @@ module Axlsx
|
|
304
323
|
end
|
305
324
|
|
306
325
|
def is_formula?
|
307
|
-
|
326
|
+
type == :string && @value.to_s.start_with?(?=)
|
308
327
|
end
|
309
328
|
|
310
|
-
|
311
|
-
|
312
|
-
# - different fonts have different mdw and char widths
|
313
|
-
def autowidth
|
314
|
-
return if is_formula? || value == nil
|
315
|
-
mdw = 1.78 #This is the widest width of 0..9 in arial@10px)
|
316
|
-
font_scale = (font_size/10.0).to_f
|
317
|
-
((value.to_s.count(Worksheet.thin_chars) * mdw + 5) / mdw * 256) / 256.0 * font_scale
|
329
|
+
def is_array_formula?
|
330
|
+
type == :string && @value.to_s.start_with?('{=') && @value.to_s.end_with?('}')
|
318
331
|
end
|
319
332
|
|
320
333
|
# returns the absolute or relative string style reference for
|
@@ -326,21 +339,69 @@ module Axlsx
|
|
326
339
|
absolute ? r_abs : r
|
327
340
|
end
|
328
341
|
|
342
|
+
# Creates a defined name in the workbook for this cell.
|
343
|
+
def name=(label)
|
344
|
+
row.worksheet.workbook.add_defined_name "#{row.worksheet.name}!#{r_abs}", name: label
|
345
|
+
@name = label
|
346
|
+
end
|
347
|
+
|
348
|
+
# returns the name of the cell
|
349
|
+
attr_reader :name
|
350
|
+
|
351
|
+
def autowidth
|
352
|
+
return if is_formula? || value.nil?
|
353
|
+
if contains_rich_text?
|
354
|
+
string_width('', font_size) + value.autowidth
|
355
|
+
elsif styles.cellXfs[style].alignment && styles.cellXfs[style].alignment.wrap_text
|
356
|
+
max_width = 0
|
357
|
+
value.to_s.split(/\r?\n/).each do |line|
|
358
|
+
width = string_width(line, font_size)
|
359
|
+
max_width = width if width > max_width
|
360
|
+
end
|
361
|
+
max_width
|
362
|
+
else
|
363
|
+
string_width(value, font_size)
|
364
|
+
end
|
365
|
+
end
|
366
|
+
|
367
|
+
# Returns the sanatized value
|
368
|
+
# TODO find a better way to do this as it accounts for 30% of
|
369
|
+
# processing time in benchmarking...
|
370
|
+
def clean_value
|
371
|
+
if type == :string && !Axlsx::trust_input
|
372
|
+
Axlsx::sanitize(::CGI.escapeHTML(@value.to_s))
|
373
|
+
else
|
374
|
+
@value.to_s
|
375
|
+
end
|
376
|
+
end
|
377
|
+
|
329
378
|
private
|
379
|
+
|
380
|
+
def styles
|
381
|
+
row.worksheet.styles
|
382
|
+
end
|
383
|
+
|
384
|
+
# Returns the width of a string according to the current style
|
385
|
+
# This is still not perfect...
|
386
|
+
# - scaling is not linear as font sizes increase
|
387
|
+
def string_width(string, font_size)
|
388
|
+
font_scale = font_size / 10.0
|
389
|
+
(string.to_s.count(Worksheet::THIN_CHARS) + 3.0) * (font_size/10.0)
|
390
|
+
end
|
330
391
|
|
331
392
|
# we scale the font size if bold style is applied to either the style font or
|
332
393
|
# the cell itself. Yes, it is a bit of a hack, but it is much better than using
|
333
394
|
# imagemagick and loading metrics for every character.
|
334
395
|
def font_size
|
335
|
-
|
336
|
-
|
337
|
-
|
396
|
+
return sz if sz
|
397
|
+
font = styles.fonts[styles.cellXfs[style].fontId] || styles.fonts[0]
|
398
|
+
(font.b || (defined?(@b) && @b)) ? (font.sz * 1.5) : font.sz
|
338
399
|
end
|
339
400
|
|
340
401
|
# Utility method for setting inline style attributes
|
341
|
-
def set_run_style(
|
342
|
-
return unless INLINE_STYLES.include?(attr.
|
343
|
-
Axlsx.send(validator, value) unless validator
|
402
|
+
def set_run_style(validator, attr, value)
|
403
|
+
return unless INLINE_STYLES.include?(attr.to_sym)
|
404
|
+
Axlsx.send(validator, value) unless validator.nil?
|
344
405
|
self.instance_variable_set :"@#{attr.to_s}", value
|
345
406
|
@is_text_run = true
|
346
407
|
end
|
@@ -351,9 +412,6 @@ module Axlsx
|
|
351
412
|
@ssti = v
|
352
413
|
end
|
353
414
|
|
354
|
-
# assigns the owning row for this cell.
|
355
|
-
def row=(v) @row=v end
|
356
|
-
|
357
415
|
# Determines the cell type based on the cell value.
|
358
416
|
# @note This is only used when a cell is created but no :type option is specified, the following rules apply:
|
359
417
|
# 1. If the value is an instance of Date, the type is set to :date
|
@@ -369,15 +427,14 @@ module Axlsx
|
|
369
427
|
:time
|
370
428
|
elsif v.is_a?(TrueClass) || v.is_a?(FalseClass)
|
371
429
|
:boolean
|
372
|
-
elsif v.to_s =~
|
430
|
+
elsif v.to_s =~ Axlsx::NUMERIC_REGEX
|
373
431
|
:integer
|
374
|
-
elsif v.to_s =~
|
432
|
+
elsif v.to_s =~ Axlsx::FLOAT_REGEX
|
375
433
|
:float
|
376
|
-
|
377
|
-
# T(2[0-3]|[0-1][0-9]):([0-5][0-9]):([0-5][0-9])(\.[0-9]+)?
|
378
|
-
# (Z|[+-](?:2[0-3]|[0-1][0-9]):[0-5][0-9])?\Z
|
379
|
-
elsif v.to_s =~/\A(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[0-1]|0[1-9]|[1-2][0-9])T(2[0-3]|[0-1][0-9]):([0-5][0-9]):([0-5][0-9])(\.[0-9]+)?(Z|[+-](?:2[0-3]|[0-1][0-9]):[0-5][0-9])?\Z/
|
434
|
+
elsif v.to_s =~ Axlsx::ISO_8601_REGEX
|
380
435
|
:iso_8601
|
436
|
+
elsif v.is_a? RichText
|
437
|
+
:richtext
|
381
438
|
else
|
382
439
|
:string
|
383
440
|
end
|
@@ -388,27 +445,25 @@ module Axlsx
|
|
388
445
|
# About Time - Time in OOXML is *different* from what you might expect. The history as to why is interesting, but you can safely assume that if you are generating docs on a mac, you will want to specify Workbook.1904 as true when using time typed values.
|
389
446
|
# @see Axlsx#date1904
|
390
447
|
def cast_value(v)
|
391
|
-
return
|
392
|
-
|
448
|
+
return v if v.is_a?(RichText) || v.nil?
|
449
|
+
case type
|
450
|
+
when :date
|
393
451
|
self.style = STYLE_DATE if self.style == 0
|
394
452
|
v
|
395
|
-
|
453
|
+
when :time
|
396
454
|
self.style = STYLE_DATE if self.style == 0
|
397
455
|
v.respond_to?(:to_time) ? v.to_time : v
|
398
|
-
|
456
|
+
when :float
|
399
457
|
v.to_f
|
400
|
-
|
458
|
+
when :integer
|
401
459
|
v.to_i
|
402
|
-
|
460
|
+
when :boolean
|
403
461
|
v ? 1 : 0
|
404
|
-
|
462
|
+
when :iso_8601
|
405
463
|
#consumer is responsible for ensuring the iso_8601 format when specifying this type
|
406
464
|
v
|
407
465
|
else
|
408
|
-
|
409
|
-
# TODO find a better way to do this as it accounts for 30% of
|
410
|
-
# processing time in benchmarking...
|
411
|
-
Axlsx::trust_input ? v.to_s : ::CGI.escapeHTML(v.to_s)
|
466
|
+
v.to_s
|
412
467
|
end
|
413
468
|
end
|
414
469
|
|