caxlsx 4.0.0 → 4.4.1
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 +4 -4
- data/CHANGELOG.md +48 -12
- data/README.md +18 -9
- data/Rakefile +2 -9
- data/examples/generate.rb +3 -1
- data/lib/axlsx/content_type/abstract_content_type.rb +6 -3
- data/lib/axlsx/content_type/content_type.rb +4 -4
- data/lib/axlsx/content_type/default.rb +4 -1
- data/lib/axlsx/content_type/override.rb +4 -1
- data/lib/axlsx/doc_props/app.rb +91 -24
- data/lib/axlsx/drawing/area_chart.rb +3 -3
- data/lib/axlsx/drawing/area_series.rb +10 -4
- data/lib/axlsx/drawing/ax_data_source.rb +1 -1
- data/lib/axlsx/drawing/axes.rb +1 -1
- data/lib/axlsx/drawing/axis.rb +25 -7
- data/lib/axlsx/drawing/bar_3D_chart.rb +14 -4
- data/lib/axlsx/drawing/bar_chart.rb +14 -4
- data/lib/axlsx/drawing/bar_series.rb +14 -5
- data/lib/axlsx/drawing/bubble_chart.rb +2 -2
- data/lib/axlsx/drawing/bubble_series.rb +2 -2
- data/lib/axlsx/drawing/cat_axis.rb +23 -8
- data/lib/axlsx/drawing/chart.rb +33 -8
- data/lib/axlsx/drawing/d_lbls.rb +9 -8
- data/lib/axlsx/drawing/drawing.rb +50 -49
- data/lib/axlsx/drawing/hyperlink.rb +13 -4
- data/lib/axlsx/drawing/line_3D_chart.rb +3 -3
- data/lib/axlsx/drawing/line_chart.rb +3 -3
- data/lib/axlsx/drawing/line_series.rb +10 -4
- data/lib/axlsx/drawing/marker.rb +19 -4
- data/lib/axlsx/drawing/num_val.rb +1 -1
- data/lib/axlsx/drawing/one_cell_anchor.rb +8 -2
- data/lib/axlsx/drawing/pic.rb +17 -8
- data/lib/axlsx/drawing/pie_3D_chart.rb +3 -3
- data/lib/axlsx/drawing/pie_chart.rb +36 -0
- data/lib/axlsx/drawing/pie_series.rb +18 -6
- data/lib/axlsx/drawing/scaling.rb +18 -4
- data/lib/axlsx/drawing/scatter_chart.rb +2 -2
- data/lib/axlsx/drawing/scatter_series.rb +2 -2
- data/lib/axlsx/drawing/ser_axis.rb +11 -5
- data/lib/axlsx/drawing/series.rb +8 -2
- data/lib/axlsx/drawing/two_cell_anchor.rb +1 -1
- data/lib/axlsx/drawing/val_axis.rb +2 -2
- data/lib/axlsx/drawing/view_3D.rb +8 -2
- data/lib/axlsx/drawing/vml_shape.rb +1 -1
- data/lib/axlsx/package.rb +54 -21
- data/lib/axlsx/rels/relationship.rb +15 -5
- data/lib/axlsx/rels/relationships.rb +3 -3
- data/lib/axlsx/stylesheet/border.rb +12 -3
- data/lib/axlsx/stylesheet/border_pr.rb +16 -4
- data/lib/axlsx/stylesheet/cell_alignment.rb +39 -10
- data/lib/axlsx/stylesheet/cell_protection.rb +9 -2
- data/lib/axlsx/stylesheet/cell_style.rb +30 -7
- data/lib/axlsx/stylesheet/color.rb +10 -4
- data/lib/axlsx/stylesheet/dxf.rb +29 -6
- data/lib/axlsx/stylesheet/fill.rb +4 -1
- data/lib/axlsx/stylesheet/font.rb +59 -13
- data/lib/axlsx/stylesheet/gradient_fill.rb +9 -3
- data/lib/axlsx/stylesheet/gradient_stop.rb +9 -2
- data/lib/axlsx/stylesheet/num_fmt.rb +8 -2
- data/lib/axlsx/stylesheet/pattern_fill.rb +15 -3
- data/lib/axlsx/stylesheet/styles.rb +84 -43
- data/lib/axlsx/stylesheet/table_style.rb +15 -4
- data/lib/axlsx/stylesheet/table_style_element.rb +12 -3
- data/lib/axlsx/stylesheet/table_styles.rb +10 -3
- data/lib/axlsx/stylesheet/theme.rb +163 -0
- data/lib/axlsx/stylesheet/xf.rb +70 -16
- data/lib/axlsx/util/accessors.rb +9 -7
- data/lib/axlsx/util/buffered_zip_output_stream.rb +6 -2
- data/lib/axlsx/util/constants.rb +14 -2
- data/lib/axlsx/util/mime_type_utils.rb +72 -13
- data/lib/axlsx/util/serialized_attributes.rb +2 -2
- data/lib/axlsx/util/simple_typed_list.rb +26 -14
- data/lib/axlsx/util/storage.rb +4 -4
- data/lib/axlsx/util/uri_utils.rb +70 -0
- data/lib/axlsx/util/validators.rb +6 -6
- data/lib/axlsx/version.rb +1 -1
- data/lib/axlsx/workbook/defined_name.rb +2 -1
- data/lib/axlsx/workbook/defined_names.rb +1 -1
- data/lib/axlsx/workbook/shared_strings_table.rb +3 -3
- data/lib/axlsx/workbook/workbook.rb +87 -67
- data/lib/axlsx/workbook/workbook_view.rb +1 -1
- data/lib/axlsx/workbook/workbook_views.rb +1 -1
- data/lib/axlsx/workbook/worksheet/auto_filter/auto_filter.rb +4 -4
- data/lib/axlsx/workbook/worksheet/auto_filter/filter_column.rb +5 -3
- data/lib/axlsx/workbook/worksheet/auto_filter/filters.rb +4 -4
- data/lib/axlsx/workbook/worksheet/auto_filter/sort_condition.rb +1 -1
- data/lib/axlsx/workbook/worksheet/auto_filter/sort_state.rb +2 -2
- data/lib/axlsx/workbook/worksheet/border_creator.rb +4 -4
- data/lib/axlsx/workbook/worksheet/cell.rb +40 -20
- data/lib/axlsx/workbook/worksheet/cell_serializer.rb +1 -1
- data/lib/axlsx/workbook/worksheet/cfvo.rb +8 -2
- data/lib/axlsx/workbook/worksheet/col.rb +23 -9
- data/lib/axlsx/workbook/worksheet/col_breaks.rb +1 -1
- data/lib/axlsx/workbook/worksheet/cols.rb +1 -1
- data/lib/axlsx/workbook/worksheet/comment.rb +2 -2
- data/lib/axlsx/workbook/worksheet/comments.rb +1 -1
- data/lib/axlsx/workbook/worksheet/conditional_formatting.rb +9 -3
- data/lib/axlsx/workbook/worksheet/conditional_formatting_rule.rb +70 -15
- data/lib/axlsx/workbook/worksheet/conditional_formattings.rb +3 -3
- data/lib/axlsx/workbook/worksheet/data_validation.rb +53 -14
- data/lib/axlsx/workbook/worksheet/data_validations.rb +3 -3
- data/lib/axlsx/workbook/worksheet/date_time_converter.rb +2 -2
- data/lib/axlsx/workbook/worksheet/dimension.rb +1 -1
- data/lib/axlsx/workbook/worksheet/header_footer.rb +1 -1
- data/lib/axlsx/workbook/worksheet/icon_set.rb +17 -5
- data/lib/axlsx/workbook/worksheet/merged_cells.rb +1 -1
- data/lib/axlsx/workbook/worksheet/outline_pr.rb +1 -1
- data/lib/axlsx/workbook/worksheet/page_margins.rb +30 -7
- data/lib/axlsx/workbook/worksheet/page_set_up_pr.rb +1 -2
- data/lib/axlsx/workbook/worksheet/page_setup.rb +32 -9
- data/lib/axlsx/workbook/worksheet/pane.rb +9 -2
- data/lib/axlsx/workbook/worksheet/pivot_table.rb +30 -6
- data/lib/axlsx/workbook/worksheet/pivot_tables.rb +1 -1
- data/lib/axlsx/workbook/worksheet/print_options.rb +1 -0
- data/lib/axlsx/workbook/worksheet/protected_ranges.rb +1 -1
- data/lib/axlsx/workbook/worksheet/rich_text_run.rb +31 -11
- data/lib/axlsx/workbook/worksheet/row.rb +5 -2
- data/lib/axlsx/workbook/worksheet/row_breaks.rb +1 -1
- data/lib/axlsx/workbook/worksheet/selection.rb +8 -2
- data/lib/axlsx/workbook/worksheet/sheet_calc_pr.rb +1 -0
- data/lib/axlsx/workbook/worksheet/sheet_pr.rb +1 -1
- data/lib/axlsx/workbook/worksheet/sheet_protection.rb +1 -1
- data/lib/axlsx/workbook/worksheet/sheet_view.rb +30 -9
- data/lib/axlsx/workbook/worksheet/table_style_info.rb +3 -2
- data/lib/axlsx/workbook/worksheet/tables.rb +1 -1
- data/lib/axlsx/workbook/worksheet/worksheet.rb +28 -14
- data/lib/axlsx/workbook/worksheet/worksheet_comments.rb +4 -4
- data/lib/axlsx/workbook/worksheet/worksheet_drawing.rb +1 -1
- data/lib/axlsx/workbook/worksheet/worksheet_hyperlink.rb +3 -2
- data/lib/axlsx/workbook/worksheet/worksheet_hyperlinks.rb +2 -2
- data/lib/axlsx.rb +46 -30
- data/lib/caxlsx.rb +1 -1
- metadata +13 -52
|
@@ -9,6 +9,10 @@ module Axlsx
|
|
|
9
9
|
# The 4_096 was chosen somewhat arbitrary, however, it was difficult to see any obvious improvement with larger
|
|
10
10
|
# buffer sizes.
|
|
11
11
|
BUFFER_SIZE = 4_096
|
|
12
|
+
# The suppress_extra_fields method was introduced in rubyzip 3.2
|
|
13
|
+
# Between rubyzip 3.0 and 3.2, it automatically writes zip64 support to the xlsx files
|
|
14
|
+
# See: https://github.com/caxlsx/caxlsx/issues/481
|
|
15
|
+
SUPPRESS_ZIP64 = Zip::OutputStream.method(:open).parameters.any? { |_, key| key == :suppress_extra_fields } ? { suppress_extra_fields: :zip64 } : {}
|
|
12
16
|
|
|
13
17
|
def initialize(zos)
|
|
14
18
|
@zos = zos
|
|
@@ -19,7 +23,7 @@ module Axlsx
|
|
|
19
23
|
#
|
|
20
24
|
# The directory and its contents are removed at the end of the block.
|
|
21
25
|
def self.open(file_name, encrypter = nil)
|
|
22
|
-
Zip::OutputStream.open(file_name, encrypter) do |zos|
|
|
26
|
+
Zip::OutputStream.open(file_name, encrypter: encrypter, **SUPPRESS_ZIP64) do |zos|
|
|
23
27
|
bzos = new(zos)
|
|
24
28
|
yield(bzos)
|
|
25
29
|
ensure
|
|
@@ -28,7 +32,7 @@ module Axlsx
|
|
|
28
32
|
end
|
|
29
33
|
|
|
30
34
|
def self.write_buffer(io = ::StringIO.new, encrypter = nil)
|
|
31
|
-
Zip::OutputStream.write_buffer(io, encrypter) do |zos|
|
|
35
|
+
Zip::OutputStream.write_buffer(io, encrypter: encrypter, **SUPPRESS_ZIP64) do |zos|
|
|
32
36
|
bzos = new(zos)
|
|
33
37
|
yield(bzos)
|
|
34
38
|
ensure
|
data/lib/axlsx/util/constants.rb
CHANGED
|
@@ -79,6 +79,9 @@ module Axlsx
|
|
|
79
79
|
# shared strings namespace
|
|
80
80
|
SHARED_STRINGS_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings"
|
|
81
81
|
|
|
82
|
+
# theme rels namespace
|
|
83
|
+
THEME_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme"
|
|
84
|
+
|
|
82
85
|
# drawing rels namespace
|
|
83
86
|
DRAWING_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing"
|
|
84
87
|
|
|
@@ -133,6 +136,9 @@ module Axlsx
|
|
|
133
136
|
# shared strings content type
|
|
134
137
|
SHARED_STRINGS_CT = "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml"
|
|
135
138
|
|
|
139
|
+
# theme content type
|
|
140
|
+
THEME_CT = "application/vnd.openxmlformats-officedocument.theme+xml"
|
|
141
|
+
|
|
136
142
|
# core content type
|
|
137
143
|
CORE_CT = "application/vnd.openxmlformats-package.core-properties+xml"
|
|
138
144
|
|
|
@@ -187,6 +193,9 @@ module Axlsx
|
|
|
187
193
|
# shared_strings part
|
|
188
194
|
SHARED_STRINGS_PN = "sharedStrings.xml"
|
|
189
195
|
|
|
196
|
+
# theme part
|
|
197
|
+
THEME_PN = "theme/theme1.xml"
|
|
198
|
+
|
|
190
199
|
# app part
|
|
191
200
|
APP_PN = "docProps/app.xml"
|
|
192
201
|
|
|
@@ -259,7 +268,10 @@ module Axlsx
|
|
|
259
268
|
# drawing validation schema
|
|
260
269
|
DRAWING_XSD = "#{SCHEMA_BASE}dml-spreadsheetDrawing.xsd"
|
|
261
270
|
|
|
262
|
-
#
|
|
271
|
+
# theme validation schema
|
|
272
|
+
THEME_XSD = "#{SCHEMA_BASE}dml-main.xsd"
|
|
273
|
+
|
|
274
|
+
# number format id for percentage formatting using the default formatting id.
|
|
263
275
|
NUM_FMT_PERCENT = 9
|
|
264
276
|
|
|
265
277
|
# number format id for date format like 2011/11/13
|
|
@@ -404,7 +416,7 @@ module Axlsx
|
|
|
404
416
|
CONTROL_CHARS = pattern.freeze
|
|
405
417
|
|
|
406
418
|
# ISO 8601 date recognition
|
|
407
|
-
ISO_8601_REGEX = /\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]+)
|
|
419
|
+
ISO_8601_REGEX = /\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/.freeze
|
|
408
420
|
|
|
409
421
|
# FLOAT recognition
|
|
410
422
|
SAFE_FLOAT_REGEX = /\A[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]{1,2})?\Z/.freeze
|
|
@@ -1,22 +1,81 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'open-uri'
|
|
4
|
-
|
|
5
3
|
module Axlsx
|
|
6
4
|
# This module defines some utils related with mime type detection
|
|
7
5
|
module MimeTypeUtils
|
|
8
|
-
#
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
6
|
+
# Extension to MIME type mapping for Windows fallback
|
|
7
|
+
EXTENSION_FALLBACKS = {
|
|
8
|
+
'.jpg' => 'image/jpeg',
|
|
9
|
+
'.jpeg' => 'image/jpeg',
|
|
10
|
+
'.png' => 'image/png',
|
|
11
|
+
'.gif' => 'image/gif'
|
|
12
|
+
}.freeze
|
|
13
|
+
|
|
14
|
+
class << self
|
|
15
|
+
# Detect a file mime type
|
|
16
|
+
# @param [String] v File path
|
|
17
|
+
# @return [String] File mime type
|
|
18
|
+
def get_mime_type(v)
|
|
19
|
+
mime_type = Marcel::MimeType.for(Pathname.new(v))
|
|
20
|
+
|
|
21
|
+
# Windows fallback: Marcel sometimes returns application/octet-stream for valid image files
|
|
22
|
+
if mime_type == 'application/octet-stream' && windows_platform?
|
|
23
|
+
extension = File.extname(v).downcase
|
|
24
|
+
# Verify it's actually an image by checking the file header
|
|
25
|
+
if EXTENSION_FALLBACKS.key?(extension) && File.exist?(v) && valid_image_file?(v, extension)
|
|
26
|
+
mime_type = EXTENSION_FALLBACKS[extension]
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
mime_type
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Detect a file mime type from URI
|
|
34
|
+
# @param [String] v URI
|
|
35
|
+
# @return [String] File mime type
|
|
36
|
+
def get_mime_type_from_uri(v)
|
|
37
|
+
uri = URI.parse(v)
|
|
38
|
+
|
|
39
|
+
unless uri.is_a?(URI::HTTP) || uri.is_a?(URI::HTTPS)
|
|
40
|
+
raise URI::InvalidURIError, "Only HTTP/HTTPS URIs are supported"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
response = UriUtils.fetch_headers(uri)
|
|
44
|
+
mime_type = response&.[]('content-type')&.split(';')&.first&.strip
|
|
45
|
+
|
|
46
|
+
if mime_type.nil? || mime_type.empty?
|
|
47
|
+
raise ArgumentError, "Unable to determine MIME type from response"
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
mime_type
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
private
|
|
54
|
+
|
|
55
|
+
def windows_platform?
|
|
56
|
+
RUBY_PLATFORM =~ /mswin|mingw|cygwin/
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def valid_image_file?(file_path, extension)
|
|
60
|
+
return false unless File.exist?(file_path)
|
|
14
61
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
62
|
+
# Check magic bytes for common image formats
|
|
63
|
+
begin
|
|
64
|
+
header = File.binread(file_path, 10)
|
|
65
|
+
case extension
|
|
66
|
+
when '.jpg', '.jpeg'
|
|
67
|
+
header[0..2].bytes == [0xFF, 0xD8, 0xFF] # JPEG magic bytes
|
|
68
|
+
when '.png'
|
|
69
|
+
header[0..7].bytes == [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A] # PNG magic bytes
|
|
70
|
+
when '.gif'
|
|
71
|
+
header[0..2] == 'GIF' # GIF magic bytes
|
|
72
|
+
else
|
|
73
|
+
false
|
|
74
|
+
end
|
|
75
|
+
rescue StandardError
|
|
76
|
+
false
|
|
77
|
+
end
|
|
78
|
+
end
|
|
20
79
|
end
|
|
21
80
|
end
|
|
22
81
|
end
|
|
@@ -91,8 +91,8 @@ module Axlsx
|
|
|
91
91
|
|
|
92
92
|
# serialized instance values at text nodes on a camelized element of the
|
|
93
93
|
# attribute name. You may pass in a block for evaluation against non nil
|
|
94
|
-
# values. We use an array for element attributes
|
|
95
|
-
# break the xml
|
|
94
|
+
# values. We use an array for element attributes because misordering will
|
|
95
|
+
# break the xml.
|
|
96
96
|
# @param [String] str The string instance to which serialized data is appended
|
|
97
97
|
# @param [Array] additional_attributes An array of additional attribute names.
|
|
98
98
|
# @return [String] The serialized output.
|
|
@@ -21,7 +21,7 @@ module Axlsx
|
|
|
21
21
|
alias :== :equal?
|
|
22
22
|
alias :eql? :equal?
|
|
23
23
|
|
|
24
|
-
#
|
|
24
|
+
# Creates a new typed list
|
|
25
25
|
# @param [Array, Class] type An array of Class objects or a single Class object
|
|
26
26
|
# @param [String] serialize_as The tag name to use in serialization
|
|
27
27
|
# @raise [ArgumentError] if all members of type are not Class objects
|
|
@@ -57,7 +57,7 @@ module Axlsx
|
|
|
57
57
|
# Transposes the list (without blowing up like ruby does)
|
|
58
58
|
# any non populated cell in the matrix will be a nil value
|
|
59
59
|
def transpose
|
|
60
|
-
return clone if size
|
|
60
|
+
return clone if size == 0
|
|
61
61
|
|
|
62
62
|
row_count = size
|
|
63
63
|
max_column_count = map { |row| row.cells.size }.max
|
|
@@ -90,21 +90,24 @@ module Axlsx
|
|
|
90
90
|
self
|
|
91
91
|
end
|
|
92
92
|
|
|
93
|
-
#
|
|
94
|
-
# @param [Array]
|
|
93
|
+
# Appends the elements of +others+ to self.
|
|
94
|
+
# @param [Array<Array>] others one or more arrays to join
|
|
95
95
|
# @raise [ArgumentError] if any of the values being joined are not
|
|
96
96
|
# one of the allowed types
|
|
97
97
|
# @return [SimpleTypedList]
|
|
98
|
-
def
|
|
99
|
-
|
|
100
|
-
|
|
98
|
+
def concat(*others)
|
|
99
|
+
others.each do |other|
|
|
100
|
+
other.each do |item|
|
|
101
|
+
self << item
|
|
102
|
+
end
|
|
101
103
|
end
|
|
102
|
-
|
|
104
|
+
self
|
|
103
105
|
end
|
|
104
106
|
|
|
105
|
-
#
|
|
107
|
+
# Pushes the given object on to the end of this array and returns the index
|
|
108
|
+
# of the item added.
|
|
106
109
|
# @param [Any] v the data to be added
|
|
107
|
-
# @raise [ArgumentError] if the value being added is not one
|
|
110
|
+
# @raise [ArgumentError] if the value being added is not one of the allowed types
|
|
108
111
|
# @return [Integer] returns the index of the item added.
|
|
109
112
|
def <<(v)
|
|
110
113
|
DataTypeValidator.validate :SimpleTypedList_push, @allowed_types, v
|
|
@@ -112,7 +115,17 @@ module Axlsx
|
|
|
112
115
|
size - 1
|
|
113
116
|
end
|
|
114
117
|
|
|
115
|
-
|
|
118
|
+
# Pushes the given object(s) on to the end of this array. This expression
|
|
119
|
+
# returns the array itself, so several appends may be chained together.
|
|
120
|
+
# @param [Any] values the data to be added
|
|
121
|
+
# @raise [ArgumentError] if any of the values being joined are not
|
|
122
|
+
# @return [SimpleTypedList]
|
|
123
|
+
def push(*values)
|
|
124
|
+
values.each do |value|
|
|
125
|
+
self << value
|
|
126
|
+
end
|
|
127
|
+
self
|
|
128
|
+
end
|
|
116
129
|
|
|
117
130
|
# delete the item from the list
|
|
118
131
|
# @param [Any] v The item to be deleted.
|
|
@@ -147,7 +160,7 @@ module Axlsx
|
|
|
147
160
|
super
|
|
148
161
|
end
|
|
149
162
|
|
|
150
|
-
# inserts an item at the index
|
|
163
|
+
# inserts an item at the index specified
|
|
151
164
|
# @param [Integer] index
|
|
152
165
|
# @param [Any] v
|
|
153
166
|
# @raise [ArgumentError] if the index is protected by locking
|
|
@@ -170,8 +183,7 @@ module Axlsx
|
|
|
170
183
|
end
|
|
171
184
|
|
|
172
185
|
def to_xml_string(str = +'')
|
|
173
|
-
|
|
174
|
-
el_name = serialize_as.to_s || (classname[0, 1].downcase + classname[1..])
|
|
186
|
+
el_name = serialize_as.to_s
|
|
175
187
|
str << '<' << el_name << ' count="' << size.to_s << '">'
|
|
176
188
|
each { |item| item.to_xml_string(str) }
|
|
177
189
|
str << '</' << el_name << '>'
|
data/lib/axlsx/util/storage.rb
CHANGED
|
@@ -85,16 +85,16 @@ module Axlsx
|
|
|
85
85
|
# @return [Integer] sector
|
|
86
86
|
attr_accessor :sector
|
|
87
87
|
|
|
88
|
-
# The 0 based index in the
|
|
88
|
+
# The 0 based index in the directories chain for this the left sibling of this storage.
|
|
89
89
|
|
|
90
90
|
# @return [Integer] left
|
|
91
91
|
attr_accessor :left
|
|
92
92
|
|
|
93
|
-
# The 0 based index in the
|
|
93
|
+
# The 0 based index in the directories chain for this the right sibling of this storage.
|
|
94
94
|
# @return [Integer] right
|
|
95
95
|
attr_accessor :right
|
|
96
96
|
|
|
97
|
-
# The 0 based index in the
|
|
97
|
+
# The 0 based index in the directories chain for the child of this storage.
|
|
98
98
|
# @return [Integer] child
|
|
99
99
|
attr_accessor :child
|
|
100
100
|
|
|
@@ -133,7 +133,7 @@ module Axlsx
|
|
|
133
133
|
@left = @right = @child = -1
|
|
134
134
|
@sector = @size = @created = @modified = 0
|
|
135
135
|
options.each do |o|
|
|
136
|
-
send("#{o[0]}=", o[1]) if respond_to? "#{o[0]}="
|
|
136
|
+
send(:"#{o[0]}=", o[1]) if respond_to? :"#{o[0]}="
|
|
137
137
|
end
|
|
138
138
|
@color ||= COLORS[:black]
|
|
139
139
|
@type ||= (data.nil? ? TYPES[:storage] : TYPES[:stream])
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'net/http'
|
|
4
|
+
require 'uri'
|
|
5
|
+
|
|
6
|
+
module Axlsx
|
|
7
|
+
# This module defines some utils related to mime type detection
|
|
8
|
+
module UriUtils
|
|
9
|
+
class << self
|
|
10
|
+
# Performs an HTTP GeT request fetching only headers
|
|
11
|
+
def fetch_headers(uri, redirect_limit = 5)
|
|
12
|
+
redirect_count = 0
|
|
13
|
+
use_get = false
|
|
14
|
+
|
|
15
|
+
while redirect_count < redirect_limit
|
|
16
|
+
case (response = fetch_headers_request(uri, use_get: use_get))
|
|
17
|
+
when Net::HTTPSuccess
|
|
18
|
+
return response
|
|
19
|
+
when Net::HTTPMethodNotAllowed, Net::HTTPNotImplemented
|
|
20
|
+
fail_response(response) if use_get
|
|
21
|
+
use_get = true
|
|
22
|
+
next # Retry current URL with GET
|
|
23
|
+
when Net::HTTPRedirection
|
|
24
|
+
uri = follow_redirect(uri, response)
|
|
25
|
+
redirect_count += 1
|
|
26
|
+
else
|
|
27
|
+
fail_response(response)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
raise ArgumentError, "Too many redirects (exceeded #{redirect_limit})"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def fetch_headers_request(uri, use_get: false)
|
|
37
|
+
Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
|
|
38
|
+
path = build_path(uri)
|
|
39
|
+
if use_get
|
|
40
|
+
http.request_get(path) { |response| break(response) } # Exit early with just headers
|
|
41
|
+
else
|
|
42
|
+
http.head(path)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def build_path(uri)
|
|
48
|
+
"#{uri.path.empty? ? '/' : uri.path}#{"?#{uri.query}" if uri.query}"
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def follow_redirect(original_uri, response)
|
|
52
|
+
location = response['location']
|
|
53
|
+
|
|
54
|
+
if location.nil? || location.empty?
|
|
55
|
+
raise ArgumentError, "Redirect response missing Location header"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
if location.start_with?('http://', 'https://')
|
|
59
|
+
URI.parse(location)
|
|
60
|
+
else
|
|
61
|
+
URI.join(original_uri, location)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def fail_response(response)
|
|
66
|
+
raise ArgumentError, "Failed to fetch resource: #{response.code} #{response.message}"
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
@@ -9,7 +9,7 @@ module Axlsx
|
|
|
9
9
|
# @param [Any] v The value to be validated
|
|
10
10
|
# @raise [ArgumentError] Raised if the value provided is not in the list of choices.
|
|
11
11
|
# @return [Boolean] true if validation succeeds.
|
|
12
|
-
def self.validate(name, choices, v)
|
|
12
|
+
def self.validate(name, choices, v) # rubocop:disable Naming/PredicateMethod
|
|
13
13
|
raise ArgumentError, format(ERR_RESTRICTION, v.to_s, name, choices.inspect) unless choices.include?(v)
|
|
14
14
|
|
|
15
15
|
true
|
|
@@ -81,7 +81,7 @@ module Axlsx
|
|
|
81
81
|
raise ArgumentError, format(ERR_ANGLE, v.inspect) unless v.to_i >= -5400000 && v.to_i <= 5400000
|
|
82
82
|
end
|
|
83
83
|
|
|
84
|
-
# Validates an unsigned
|
|
84
|
+
# Validates an unsigned integer
|
|
85
85
|
UINT_VALIDATOR = ->(arg) { arg.respond_to?(:>=) && arg >= 0 }
|
|
86
86
|
|
|
87
87
|
# Requires that the value is a Integer and is greater or equal to 0
|
|
@@ -268,19 +268,19 @@ module Axlsx
|
|
|
268
268
|
RestrictionValidator.validate :vertical_alignment, VALID_VERTICAL_ALIGNMENT_VALUES, v
|
|
269
269
|
end
|
|
270
270
|
|
|
271
|
-
VALID_CONTENT_TYPE_VALUES = [TABLE_CT, WORKBOOK_CT, APP_CT, RELS_CT, STYLES_CT, XML_CT, WORKSHEET_CT, SHARED_STRINGS_CT, CORE_CT, CHART_CT, JPEG_CT, GIF_CT, PNG_CT, DRAWING_CT, COMMENT_CT, VML_DRAWING_CT, PIVOT_TABLE_CT, PIVOT_TABLE_CACHE_DEFINITION_CT].freeze
|
|
271
|
+
VALID_CONTENT_TYPE_VALUES = [TABLE_CT, WORKBOOK_CT, APP_CT, RELS_CT, STYLES_CT, THEME_CT, XML_CT, WORKSHEET_CT, SHARED_STRINGS_CT, CORE_CT, CHART_CT, JPEG_CT, GIF_CT, PNG_CT, DRAWING_CT, COMMENT_CT, VML_DRAWING_CT, PIVOT_TABLE_CT, PIVOT_TABLE_CACHE_DEFINITION_CT].freeze
|
|
272
272
|
|
|
273
273
|
# Requires that the value is a valid content_type
|
|
274
|
-
# TABLE_CT, WORKBOOK_CT, APP_CT, RELS_CT, STYLES_CT, XML_CT, WORKSHEET_CT, SHARED_STRINGS_CT, CORE_CT, CHART_CT, DRAWING_CT, COMMENT_CT are allowed
|
|
274
|
+
# TABLE_CT, WORKBOOK_CT, APP_CT, RELS_CT, STYLES_CT, THEME_CT, XML_CT, WORKSHEET_CT, SHARED_STRINGS_CT, CORE_CT, CHART_CT, DRAWING_CT, COMMENT_CT are allowed
|
|
275
275
|
# @param [Any] v The value validated
|
|
276
276
|
def self.validate_content_type(v)
|
|
277
277
|
RestrictionValidator.validate :content_type, VALID_CONTENT_TYPE_VALUES, v
|
|
278
278
|
end
|
|
279
279
|
|
|
280
|
-
VALID_RELATIONSHIP_TYPE_VALUES = [XML_NS_R, TABLE_R, WORKBOOK_R, WORKSHEET_R, APP_R, RELS_R, CORE_R, STYLES_R, CHART_R, DRAWING_R, IMAGE_R, HYPERLINK_R, SHARED_STRINGS_R, COMMENT_R, VML_DRAWING_R, COMMENT_R_NULL, PIVOT_TABLE_R, PIVOT_TABLE_CACHE_DEFINITION_R].freeze
|
|
280
|
+
VALID_RELATIONSHIP_TYPE_VALUES = [XML_NS_R, TABLE_R, WORKBOOK_R, WORKSHEET_R, APP_R, RELS_R, CORE_R, STYLES_R, THEME_R, CHART_R, DRAWING_R, IMAGE_R, HYPERLINK_R, SHARED_STRINGS_R, COMMENT_R, VML_DRAWING_R, COMMENT_R_NULL, PIVOT_TABLE_R, PIVOT_TABLE_CACHE_DEFINITION_R].freeze
|
|
281
281
|
|
|
282
282
|
# Requires that the value is a valid relationship_type
|
|
283
|
-
# XML_NS_R, TABLE_R, WORKBOOK_R, WORKSHEET_R, APP_R, RELS_R, CORE_R, STYLES_R, CHART_R, DRAWING_R, IMAGE_R, HYPERLINK_R, SHARED_STRINGS_R are allowed
|
|
283
|
+
# XML_NS_R, TABLE_R, WORKBOOK_R, WORKSHEET_R, APP_R, RELS_R, CORE_R, STYLES_R, THEME_R, CHART_R, DRAWING_R, IMAGE_R, HYPERLINK_R, SHARED_STRINGS_R are allowed
|
|
284
284
|
# @param [Any] v The value validated
|
|
285
285
|
def self.validate_relationship_type(v)
|
|
286
286
|
RestrictionValidator.validate :relationship_type, VALID_RELATIONSHIP_TYPE_VALUES, v
|
data/lib/axlsx/version.rb
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
# <xsd:attribute name="shortcutKey" type="s:ST_Xstring" use="optional"/>
|
|
23
23
|
# <xsd:attribute name="publishToServer" type="xsd:boolean" use="optional" default="false"/>
|
|
24
24
|
# <xsd:attribute name="workbookParameter" type="xsd:boolean" use="optional" default="false"/>
|
|
25
|
-
# </xsd:
|
|
25
|
+
# </xsd:extension>
|
|
26
26
|
# </xsd:simpleContent>
|
|
27
27
|
|
|
28
28
|
module Axlsx
|
|
@@ -54,6 +54,7 @@ module Axlsx
|
|
|
54
54
|
include Axlsx::SerializedAttributes
|
|
55
55
|
include Axlsx::OptionsParser
|
|
56
56
|
include Axlsx::Accessors
|
|
57
|
+
|
|
57
58
|
# creates a new DefinedName.
|
|
58
59
|
# @param [String] formula - the formula the defined name references
|
|
59
60
|
# @param [Hash] options - A hash of key/value pairs that will be mapped to this instances attributes.
|
|
@@ -7,7 +7,7 @@ module Axlsx
|
|
|
7
7
|
# As a developer, you should never need to directly work against this class. Simply set 'use_shared_strings'
|
|
8
8
|
# on the package or workbook to generate a package that uses the shared strings table instead of inline strings.
|
|
9
9
|
# @note Serialization performance is affected by using this serialization method so if you do not need interoperability
|
|
10
|
-
# it is
|
|
10
|
+
# it is recommended that you use the default inline string method of serialization.
|
|
11
11
|
class SharedStringsTable
|
|
12
12
|
# The total number of strings in the workbook including duplicates
|
|
13
13
|
# Empty cells are treated as blank strings
|
|
@@ -29,7 +29,7 @@ module Axlsx
|
|
|
29
29
|
# @see Workbook#xml_space
|
|
30
30
|
attr_reader :xml_space
|
|
31
31
|
|
|
32
|
-
# Creates a new Shared Strings Table
|
|
32
|
+
# Creates a new Shared Strings Table against an array of cells
|
|
33
33
|
# @param [Array] cells This is an array of all of the cells in the workbook
|
|
34
34
|
# @param [Symbol] xml_space The xml:space behavior for the shared string table.
|
|
35
35
|
def initialize(cells, xml_space = :preserve)
|
|
@@ -54,7 +54,7 @@ module Axlsx
|
|
|
54
54
|
|
|
55
55
|
private
|
|
56
56
|
|
|
57
|
-
#
|
|
57
|
+
# Iterate over all of the cells in the array.
|
|
58
58
|
# if our unique cells array does not contain a sharable cell,
|
|
59
59
|
# add the cell to our unique cells array and set the ssti attribute on the index of this cell in the shared strings table
|
|
60
60
|
# if a sharable cell already exists in our unique_cells array, set the ssti attribute of the cell and move on.
|