caxlsx 3.0.0 → 3.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +126 -31
- data/README.md +78 -170
- data/examples/{image1.jpeg → assets/image1.jpeg} +0 -0
- data/examples/generate.rb +15 -0
- data/lib/axlsx.rb +2 -3
- data/lib/axlsx/drawing/bar_chart.rb +3 -3
- data/lib/axlsx/drawing/bar_series.rb +3 -5
- data/lib/axlsx/drawing/d_lbls.rb +1 -1
- data/lib/axlsx/drawing/pie_series.rb +1 -1
- data/lib/axlsx/drawing/series_title.rb +3 -1
- data/lib/axlsx/drawing/title.rb +3 -2
- data/lib/axlsx/package.rb +53 -19
- data/lib/axlsx/rels/relationship.rb +26 -25
- data/lib/axlsx/stylesheet/font.rb +10 -2
- data/lib/axlsx/util/constants.rb +2 -1
- data/lib/axlsx/util/mime_type_utils.rb +1 -1
- data/lib/axlsx/util/validators.rb +2 -2
- data/lib/axlsx/util/zip_command.rb +73 -0
- data/lib/axlsx/version.rb +1 -1
- data/lib/axlsx/workbook/workbook.rb +0 -9
- data/lib/axlsx/workbook/worksheet/cell.rb +32 -5
- data/lib/axlsx/workbook/worksheet/col.rb +8 -4
- data/lib/axlsx/workbook/worksheet/data_validation.rb +4 -4
- data/lib/axlsx/workbook/worksheet/pivot_table.rb +7 -2
- data/lib/axlsx/workbook/worksheet/pivot_table_cache_definition.rb +1 -1
- data/lib/axlsx/workbook/worksheet/rich_text_run.rb +1 -1
- data/lib/axlsx/workbook/worksheet/row.rb +6 -3
- data/lib/axlsx/workbook/worksheet/table.rb +1 -1
- data/lib/axlsx/workbook/worksheet/worksheet.rb +17 -4
- data/lib/caxlsx.rb +2 -0
- data/test/drawing/tc_drawing.rb +2 -2
- data/test/drawing/tc_hyperlink.rb +1 -1
- data/test/drawing/tc_one_cell_anchor.rb +1 -1
- data/test/drawing/tc_pic.rb +4 -4
- data/test/drawing/tc_pie_series.rb +2 -1
- data/test/drawing/tc_series_title.rb +21 -0
- data/test/drawing/tc_title.rb +16 -0
- data/test/fixtures/image1.gif +0 -0
- data/test/fixtures/image1.jpeg +0 -0
- data/test/fixtures/image1.jpg +0 -0
- data/test/fixtures/image1.png +0 -0
- data/test/fixtures/image1_fake.jpg +0 -0
- data/test/rels/tc_relationship.rb +8 -0
- data/test/stylesheet/tc_font.rb +14 -2
- data/test/stylesheet/tc_styles.rb +27 -1
- data/test/tc_axlsx.rb +6 -0
- data/test/tc_helper.rb +0 -2
- data/test/tc_package.rb +82 -13
- data/test/util/tc_mime_type_utils.rb +1 -1
- data/test/util/tc_validators.rb +1 -1
- data/test/workbook/worksheet/tc_cell.rb +68 -2
- data/test/workbook/worksheet/tc_col.rb +16 -1
- data/test/workbook/worksheet/tc_pivot_table.rb +8 -0
- data/test/workbook/worksheet/tc_pivot_table_cache_definition.rb +8 -0
- data/test/workbook/worksheet/tc_rich_text_run.rb +3 -2
- data/test/workbook/worksheet/tc_row.rb +38 -0
- data/test/workbook/worksheet/tc_table.rb +10 -0
- data/test/workbook/worksheet/tc_worksheet.rb +24 -15
- metadata +130 -151
- data/examples/2010_comments.rb +0 -17
- data/examples/anchor_swapping.rb +0 -28
- data/examples/auto_filter.rb +0 -25
- data/examples/basic_charts.rb +0 -58
- data/examples/chart_colors.rb +0 -88
- data/examples/colored_links.rb +0 -59
- data/examples/conditional_formatting/example_conditional_formatting.rb +0 -89
- data/examples/conditional_formatting/getting_barred.rb +0 -37
- data/examples/conditional_formatting/hitting_the_high_notes.rb +0 -37
- data/examples/conditional_formatting/scaled_colors.rb +0 -39
- data/examples/conditional_formatting/stop_and_go.rb +0 -37
- data/examples/data_validation.rb +0 -67
- data/examples/example.rb +0 -885
- data/examples/extractive.rb +0 -45
- data/examples/ios_preview.rb +0 -14
- data/examples/merge_cells.rb +0 -17
- data/examples/no_grid_with_borders.rb +0 -18
- data/examples/page_setup.rb +0 -11
- data/examples/pivot_table.rb +0 -39
- data/examples/pivot_test.rb +0 -63
- data/examples/sheet_protection.rb +0 -10
- data/examples/skydrive/real_example.rb +0 -63
- data/examples/split.rb +0 -16
- data/examples/styles.rb +0 -66
- data/examples/underline.rb +0 -13
- data/examples/wrap_text.rb +0 -21
- data/lib/axlsx/util/parser.rb +0 -44
File without changes
|
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
files = if !ARGV.empty?
|
4
|
+
ARGV.select { |file| File.exist?(file) }
|
5
|
+
else
|
6
|
+
Dir['*_example.md']
|
7
|
+
end
|
8
|
+
|
9
|
+
files.each do |file|
|
10
|
+
puts "Executing #{file.split('.')[0].tr('_', ' ')}"
|
11
|
+
code = File.read(file).match(/```ruby(?<code>.+)```/m)[:code]
|
12
|
+
unless code.nil?
|
13
|
+
eval(['$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib"', code].join("\n"))
|
14
|
+
end
|
15
|
+
end
|
data/lib/axlsx.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
require 'htmlentities'
|
3
3
|
require 'axlsx/version.rb'
|
4
|
-
require '
|
4
|
+
require 'marcel'
|
5
5
|
|
6
6
|
require 'axlsx/util/simple_typed_list.rb'
|
7
7
|
require 'axlsx/util/constants.rb'
|
@@ -9,9 +9,8 @@ require 'axlsx/util/validators.rb'
|
|
9
9
|
require 'axlsx/util/accessors.rb'
|
10
10
|
require 'axlsx/util/serialized_attributes'
|
11
11
|
require 'axlsx/util/options_parser'
|
12
|
-
# to be included with parsable intitites.
|
13
|
-
#require 'axlsx/util/parser.rb'
|
14
12
|
require 'axlsx/util/mime_type_utils'
|
13
|
+
require 'axlsx/util/zip_command'
|
15
14
|
|
16
15
|
require 'axlsx/stylesheet/styles.rb'
|
17
16
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
module Axlsx
|
3
3
|
|
4
|
-
# The BarChart is a
|
4
|
+
# The BarChart is a two dimentional barchart that you can add to your worksheet.
|
5
5
|
# @see Worksheet#add_chart
|
6
6
|
# @see Chart#add_series
|
7
7
|
# @see Package#serialize
|
@@ -49,7 +49,7 @@ module Axlsx
|
|
49
49
|
@grouping ||= :clustered
|
50
50
|
end
|
51
51
|
|
52
|
-
# The
|
52
|
+
# The shape of the bars or columns
|
53
53
|
# must be one of [:cone, :coneToMax, :box, :cylinder, :pyramid, :pyramidToMax]
|
54
54
|
# @return [Symbol]
|
55
55
|
def shape
|
@@ -106,7 +106,7 @@ module Axlsx
|
|
106
106
|
end
|
107
107
|
alias :gapDepth= :gap_depth=
|
108
108
|
|
109
|
-
# The
|
109
|
+
# The shape of the bars or columns
|
110
110
|
# must be one of [:cone, :coneToMax, :box, :cylinder, :pyramid, :pyramidToMax]
|
111
111
|
def shape=(v)
|
112
112
|
RestrictionValidator.validate "BarChart.shape", [:cone, :coneToMax, :box, :cylinder, :pyramid, :pyramidToMax], v
|
@@ -15,9 +15,8 @@ module Axlsx
|
|
15
15
|
# @return [Array, SimpleTypedList]
|
16
16
|
attr_reader :labels
|
17
17
|
|
18
|
-
# The
|
19
|
-
# must be one of
|
20
|
-
# @return [Symbol]
|
18
|
+
# The shape of the bars or columns
|
19
|
+
# @return [Symbol] must be one of [:cone, :coneToMax, :box, :cylinder, :pyramid, :pyramidToMax]
|
21
20
|
attr_reader :shape
|
22
21
|
|
23
22
|
# An array of rgb colors to apply to your bar chart.
|
@@ -41,8 +40,7 @@ module Axlsx
|
|
41
40
|
# @see colors
|
42
41
|
def colors=(v) DataTypeValidator.validate "BarSeries.colors", [Array], v; @colors = v end
|
43
42
|
|
44
|
-
#
|
45
|
-
# must be one of [:cone, :coneToMax, :box, :cylinder, :pyramid, :pyramidToMax]
|
43
|
+
# @see shape
|
46
44
|
def shape=(v)
|
47
45
|
RestrictionValidator.validate "BarSeries.shape", [:cone, :coneToMax, :box, :cylinder, :pyramid, :pyramidToMax], v
|
48
46
|
@shape = v
|
data/lib/axlsx/drawing/d_lbls.rb
CHANGED
@@ -55,7 +55,7 @@ module Axlsx
|
|
55
55
|
|
56
56
|
# @see DLbls#d_lbl_pos
|
57
57
|
# Assigns the label postion for this data labels on this chart.
|
58
|
-
# Allowed positions are :
|
58
|
+
# Allowed positions are :bestFit, :b, :ctr, :inBase, :inEnd, :l,
|
59
59
|
# :outEnd, :r and :t
|
60
60
|
# The default is :bestFit
|
61
61
|
# @param [Symbol] label_position the postion you want to use.
|
@@ -47,7 +47,7 @@ module Axlsx
|
|
47
47
|
# @return [String]
|
48
48
|
def to_xml_string(str = '')
|
49
49
|
super(str) do
|
50
|
-
str << '<c:explosion val="' + @explosion + '"/>' unless @explosion.nil?
|
50
|
+
str << '<c:explosion val="' + @explosion.to_s + '"/>' unless @explosion.nil?
|
51
51
|
colors.each_with_index do |c, index|
|
52
52
|
str << '<c:dPt>'
|
53
53
|
str << ('<c:idx val="' << index.to_s << '"/>')
|
@@ -7,13 +7,15 @@ module Axlsx
|
|
7
7
|
# @param [String] str
|
8
8
|
# @return [String]
|
9
9
|
def to_xml_string(str = '')
|
10
|
+
clean_value = Axlsx::trust_input ? @text.to_s : ::CGI.escapeHTML(Axlsx::sanitize(@text.to_s))
|
11
|
+
|
10
12
|
str << '<c:tx>'
|
11
13
|
str << '<c:strRef>'
|
12
14
|
str << ('<c:f>' << Axlsx::cell_range([@cell]) << '</c:f>')
|
13
15
|
str << '<c:strCache>'
|
14
16
|
str << '<c:ptCount val="1"/>'
|
15
17
|
str << '<c:pt idx="0">'
|
16
|
-
str << ('<c:v>' <<
|
18
|
+
str << ('<c:v>' << clean_value << '</c:v>')
|
17
19
|
str << '</c:pt>'
|
18
20
|
str << '</c:strCache>'
|
19
21
|
str << '</c:strRef>'
|
data/lib/axlsx/drawing/title.rb
CHANGED
@@ -62,6 +62,7 @@ module Axlsx
|
|
62
62
|
def to_xml_string(str = '')
|
63
63
|
str << '<c:title>'
|
64
64
|
unless @text.empty?
|
65
|
+
clean_value = Axlsx::trust_input ? @text.to_s : ::CGI.escapeHTML(Axlsx::sanitize(@text.to_s))
|
65
66
|
str << '<c:tx>'
|
66
67
|
if @cell.is_a?(Cell)
|
67
68
|
str << '<c:strRef>'
|
@@ -69,7 +70,7 @@ module Axlsx
|
|
69
70
|
str << '<c:strCache>'
|
70
71
|
str << '<c:ptCount val="1"/>'
|
71
72
|
str << '<c:pt idx="0">'
|
72
|
-
str << ('<c:v>' <<
|
73
|
+
str << ('<c:v>' << clean_value << '</c:v>')
|
73
74
|
str << '</c:pt>'
|
74
75
|
str << '</c:strCache>'
|
75
76
|
str << '</c:strRef>'
|
@@ -80,7 +81,7 @@ module Axlsx
|
|
80
81
|
str << '<a:p>'
|
81
82
|
str << '<a:r>'
|
82
83
|
str << ('<a:rPr sz="' << @text_size.to_s << '"/>')
|
83
|
-
str << ('<a:t>' <<
|
84
|
+
str << ('<a:t>' << clean_value << '</a:t>')
|
84
85
|
str << '</a:r>'
|
85
86
|
str << '</a:p>'
|
86
87
|
str << '</c:rich>'
|
data/lib/axlsx/package.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
module Axlsx
|
3
3
|
# Package is responsible for managing all the bits and peices that Open Office XML requires to make a valid
|
4
|
-
# xlsx document including
|
4
|
+
# xlsx document including validation and serialization.
|
5
5
|
class Package
|
6
6
|
include Axlsx::OptionsParser
|
7
7
|
|
@@ -68,23 +68,20 @@ module Axlsx
|
|
68
68
|
@workbook
|
69
69
|
end
|
70
70
|
|
71
|
-
#def self.parse(input, confirm_valid = false)
|
72
|
-
# p = Package.new
|
73
|
-
# z = Zip::File.open(input)
|
74
|
-
# p.workbook = Workbook.parse z.get_entry(WORKBOOK_PN)
|
75
|
-
# p
|
76
|
-
#end
|
77
|
-
|
78
71
|
# @see workbook
|
79
72
|
def workbook=(workbook) DataTypeValidator.validate :Package_workbook, Workbook, workbook; @workbook = workbook; end
|
80
73
|
|
81
74
|
# Serialize your workbook to disk as an xlsx document.
|
82
75
|
#
|
83
76
|
# @param [String] output The name of the file you want to serialize your package to
|
84
|
-
# @param [
|
77
|
+
# @param [Hash] options
|
78
|
+
# @option options [Boolean] :confirm_valid Validate the package prior to serialization.
|
79
|
+
# @option options [String] :zip_command When `nil`, `#serialize` with RubyZip to
|
80
|
+
# zip the XLSX file contents. When a String, the provided zip command (e.g.,
|
81
|
+
# "zip") is used to zip the file contents (may be faster for large files)
|
85
82
|
# @return [Boolean] False if confirm_valid and validation errors exist. True if the package was serialized
|
86
83
|
# @note A tremendous amount of effort has gone into ensuring that you cannot create invalid xlsx documents.
|
87
|
-
# confirm_valid should be used in the rare case that you cannot open the serialized file.
|
84
|
+
# options[:confirm_valid] should be used in the rare case that you cannot open the serialized file.
|
88
85
|
# @see Package#validate
|
89
86
|
# @example
|
90
87
|
# # This is how easy it is to create a valid xlsx file. Of course you might want to add a sheet or two, and maybe some data, styles and charts.
|
@@ -95,16 +92,29 @@ module Axlsx
|
|
95
92
|
# # ......add cool stuff to your workbook......
|
96
93
|
# p.serialize("example.xlsx")
|
97
94
|
#
|
95
|
+
# # Serialize to a file, using a system zip binary
|
96
|
+
# p.serialize("example.xlsx", zip_command: "zip", confirm_valid: false)
|
97
|
+
# p.serialize("example.xlsx", zip_command: "/path/to/zip")
|
98
|
+
# p.serialize("example.xlsx", zip_command: "zip -1")
|
99
|
+
#
|
98
100
|
# # Serialize to a stream
|
99
101
|
# s = p.to_stream()
|
100
102
|
# File.open('example_streamed.xlsx', 'w') { |f| f.write(s.read) }
|
101
|
-
def serialize(output,
|
103
|
+
def serialize(output, options = {}, secondary_options = nil)
|
104
|
+
confirm_valid, zip_command = parse_serialize_options(options, secondary_options)
|
102
105
|
return false unless !confirm_valid || self.validate.empty?
|
103
|
-
|
104
|
-
|
106
|
+
zip_provider = if zip_command
|
107
|
+
ZipCommand.new(zip_command)
|
108
|
+
else
|
109
|
+
Zip::OutputStream
|
110
|
+
end
|
111
|
+
Relationship.initialize_ids_cache
|
112
|
+
zip_provider.open(output) do |zip|
|
105
113
|
write_parts(zip)
|
106
114
|
end
|
107
115
|
true
|
116
|
+
ensure
|
117
|
+
Relationship.clear_ids_cache
|
108
118
|
end
|
109
119
|
|
110
120
|
|
@@ -113,11 +123,13 @@ module Axlsx
|
|
113
123
|
# @return [StringIO|Boolean] False if confirm_valid and validation errors exist. rewound string IO if not.
|
114
124
|
def to_stream(confirm_valid=false)
|
115
125
|
return false unless !confirm_valid || self.validate.empty?
|
116
|
-
Relationship.
|
126
|
+
Relationship.initialize_ids_cache
|
117
127
|
zip = write_parts(Zip::OutputStream.new(StringIO.new, true))
|
118
128
|
stream = zip.close_buffer
|
119
129
|
stream.rewind
|
120
130
|
stream
|
131
|
+
ensure
|
132
|
+
Relationship.clear_ids_cache
|
121
133
|
end
|
122
134
|
|
123
135
|
# Encrypt the package into a CFB using the password provided
|
@@ -135,7 +147,7 @@ module Axlsx
|
|
135
147
|
# dcterms and xml namespaces. Those remote schema are included in this gem, and the original files have been altered to
|
136
148
|
# refer to the local versions.
|
137
149
|
#
|
138
|
-
# If by chance you are able to
|
150
|
+
# If by chance you are able to create a package that does not validate it indicates that the internal
|
139
151
|
# validation is not robust enough and needs to be improved. Please report your errors to the gem author.
|
140
152
|
# @see http://www.ecma-international.org/publications/standards/Ecma-376.htm
|
141
153
|
# @example
|
@@ -156,8 +168,8 @@ module Axlsx
|
|
156
168
|
private
|
157
169
|
|
158
170
|
# Writes the package parts to a zip archive.
|
159
|
-
# @param [Zip::OutputStream] zip
|
160
|
-
# @return [Zip::OutputStream]
|
171
|
+
# @param [Zip::OutputStream, ZipCommand] zip
|
172
|
+
# @return [Zip::OutputStream, ZipCommand]
|
161
173
|
def write_parts(zip)
|
162
174
|
p = parts
|
163
175
|
p.each do |part|
|
@@ -167,7 +179,7 @@ module Axlsx
|
|
167
179
|
end
|
168
180
|
unless part[:path].nil?
|
169
181
|
zip.put_next_entry(zip_entry_for_part(part))
|
170
|
-
zip.write IO.read(part[:path])
|
182
|
+
zip.write IO.read(part[:path], mode: "rb")
|
171
183
|
end
|
172
184
|
end
|
173
185
|
zip
|
@@ -349,6 +361,28 @@ module Axlsx
|
|
349
361
|
rels.lock
|
350
362
|
rels
|
351
363
|
end
|
364
|
+
|
365
|
+
# Parse the arguments of `#serialize`
|
366
|
+
# @return [Boolean, (String or nil)] Returns an array where the first value is
|
367
|
+
# `confirm_valid` and the second is the `zip_command`.
|
368
|
+
# @private
|
369
|
+
def parse_serialize_options(options, secondary_options)
|
370
|
+
if secondary_options
|
371
|
+
warn "[DEPRECATION] Axlsx::Package#serialize with 3 arguments is deprecated. " +
|
372
|
+
"Use keyword args instead e.g., package.serialize(output, confirm_valid: false, zip_command: 'zip')"
|
373
|
+
end
|
374
|
+
if options.is_a?(Hash)
|
375
|
+
options.merge!(secondary_options || {})
|
376
|
+
invalid_keys = options.keys - [:confirm_valid, :zip_command]
|
377
|
+
if invalid_keys.any?
|
378
|
+
raise ArgumentError.new("Invalid keyword arguments: #{invalid_keys}")
|
379
|
+
end
|
380
|
+
[options.fetch(:confirm_valid, false), options.fetch(:zip_command, nil)]
|
381
|
+
else
|
382
|
+
warn "[DEPRECATION] Axlsx::Package#serialize with confirm_valid as a boolean is deprecated. " +
|
383
|
+
"Use keyword args instead e.g., package.serialize(output, confirm_valid: false)"
|
384
|
+
parse_serialize_options((secondary_options || {}).merge(confirm_valid: options), nil)
|
385
|
+
end
|
386
|
+
end
|
352
387
|
end
|
353
388
|
end
|
354
|
-
|
@@ -5,32 +5,40 @@ module Axlsx
|
|
5
5
|
class Relationship
|
6
6
|
|
7
7
|
class << self
|
8
|
-
# Keeps track of
|
8
|
+
# Keeps track of relationship ids in use.
|
9
9
|
# @return [Array]
|
10
|
-
def
|
11
|
-
|
10
|
+
def ids_cache
|
11
|
+
Thread.current[:axlsx_relationship_ids_cache] ||= {}
|
12
12
|
end
|
13
|
-
|
14
|
-
#
|
13
|
+
|
14
|
+
# Initialize cached ids.
|
15
15
|
#
|
16
16
|
# This should be called before serializing a package (see {Package#serialize} and
|
17
17
|
# {Package#to_stream}) to make sure that serialization is idempotent (i.e.
|
18
18
|
# Relationship instances are generated with the same IDs everytime the package
|
19
19
|
# is serialized).
|
20
|
+
def initialize_ids_cache
|
21
|
+
Thread.current[:axlsx_relationship_ids_cache] = {}
|
22
|
+
end
|
23
|
+
|
24
|
+
# Clear cached ids.
|
20
25
|
#
|
21
|
-
#
|
26
|
+
# This should be called after serializing a package (see {Package#serialize} and
|
27
|
+
# {Package#to_stream}) to free the memory allocated for cache.
|
28
|
+
#
|
29
|
+
# Also, calling this avoids memory leaks (cached ids lingering around
|
22
30
|
# forever).
|
23
|
-
def
|
24
|
-
|
31
|
+
def clear_ids_cache
|
32
|
+
Thread.current[:axlsx_relationship_ids_cache] = nil
|
25
33
|
end
|
26
34
|
|
27
35
|
# Generate and return a unique id (eg. `rId123`) Used for setting {#Id}.
|
28
36
|
#
|
29
|
-
# The generated id depends on the number of cached
|
30
|
-
# {
|
37
|
+
# The generated id depends on the number of previously cached ids, so using
|
38
|
+
# {clear_ids_cache} will automatically reset the generated ids, too.
|
31
39
|
# @return [String]
|
32
40
|
def next_free_id
|
33
|
-
"rId#{
|
41
|
+
"rId#{ids_cache.size + 1}"
|
34
42
|
end
|
35
43
|
end
|
36
44
|
|
@@ -80,12 +88,7 @@ module Axlsx
|
|
80
88
|
self.Target=target
|
81
89
|
self.Type=type
|
82
90
|
self.TargetMode = options[:target_mode] if options[:target_mode]
|
83
|
-
@Id =
|
84
|
-
existing.Id
|
85
|
-
else
|
86
|
-
self.class.next_free_id
|
87
|
-
end
|
88
|
-
self.class.instances << self
|
91
|
+
@Id = (self.class.ids_cache[ids_cache_key] ||= self.class.next_free_id)
|
89
92
|
end
|
90
93
|
|
91
94
|
# @see Target
|
@@ -106,7 +109,7 @@ module Axlsx
|
|
106
109
|
str << '/>'
|
107
110
|
end
|
108
111
|
|
109
|
-
#
|
112
|
+
# A key that determines whether this relationship should use already generated id.
|
110
113
|
#
|
111
114
|
# Instances designating the same relationship need to use the same id. We can not simply
|
112
115
|
# compare the {#Target} attribute, though: `foo/bar.xml`, `../foo/bar.xml`,
|
@@ -116,13 +119,11 @@ module Axlsx
|
|
116
119
|
# then {#Target} will be an absolute URL and thus can safely be compared).
|
117
120
|
#
|
118
121
|
# @todo Implement comparison of {#Target} based on normalized path names.
|
119
|
-
# @
|
120
|
-
def
|
121
|
-
|
122
|
-
if self.TargetMode == :External
|
123
|
-
|
124
|
-
end
|
125
|
-
result
|
122
|
+
# @return [Array]
|
123
|
+
def ids_cache_key
|
124
|
+
key = [source_obj, self.Type, self.TargetMode]
|
125
|
+
key << self.Target if self.TargetMode == :External
|
126
|
+
key
|
126
127
|
end
|
127
128
|
|
128
129
|
end
|
@@ -76,7 +76,10 @@ module Axlsx
|
|
76
76
|
attr_reader :i
|
77
77
|
|
78
78
|
# Indicates if the font should be rendered underlined
|
79
|
-
#
|
79
|
+
# It must be one of :none, :single, :double, :singleAccounting, :doubleAccounting, true, false
|
80
|
+
# @return [String]
|
81
|
+
# @note
|
82
|
+
# true or false is for backwards compatibility and is reassigned to :single or :none respectively
|
80
83
|
attr_reader :u
|
81
84
|
|
82
85
|
# Indicates if the font should be rendered with a strikthrough
|
@@ -118,7 +121,12 @@ module Axlsx
|
|
118
121
|
# @see i
|
119
122
|
def i=(v) Axlsx::validate_boolean v; @i = v end
|
120
123
|
# @see u
|
121
|
-
def u=(v)
|
124
|
+
def u=(v)
|
125
|
+
v = :single if (v == true || v == 1 || v == :true || v == 'true')
|
126
|
+
v = :none if (v == false || v == 0 || v == :false || v == 'false')
|
127
|
+
Axlsx::validate_cell_u v
|
128
|
+
@u = v
|
129
|
+
end
|
122
130
|
# @see strike
|
123
131
|
def strike=(v) Axlsx::validate_boolean v; @strike = v end
|
124
132
|
# @see outline
|
data/lib/axlsx/util/constants.rb
CHANGED
@@ -393,7 +393,8 @@ module Axlsx
|
|
393
393
|
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|[+-](?:2[0-3]|[0-1][0-9]):[0-5][0-9])?\Z/.freeze
|
394
394
|
|
395
395
|
# FLOAT recognition
|
396
|
-
|
396
|
+
SAFE_FLOAT_REGEX = /\A[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]{1,2})?\Z/.freeze
|
397
|
+
MAYBE_FLOAT_REGEX = /\A[-+]?[0-9]*\.?[0-9]+[eE](?<exp>[-+]?[0-9]{3})\Z/.freeze
|
397
398
|
|
398
399
|
# Numeric recognition
|
399
400
|
NUMERIC_REGEX = /\A[+-]?\d+?\Z/.freeze
|
@@ -92,7 +92,7 @@ module Axlsx
|
|
92
92
|
|
93
93
|
# Requires that the value is a Integer or Float and is greater or equal to 0
|
94
94
|
# @param [Any] v The value validated
|
95
|
-
# @raise [ArgumentError] raised if the value is not a
|
95
|
+
# @raise [ArgumentError] raised if the value is not a Integer, Float value greater or equal to 0
|
96
96
|
# @return [Boolean] true if the data is valid
|
97
97
|
def self.validate_unsigned_numeric(v)
|
98
98
|
DataTypeValidator.validate(:unsigned_numeric, Numeric, v, UINT_VALIDATOR)
|
@@ -269,7 +269,7 @@ module Axlsx
|
|
269
269
|
# valid types must be one of custom, data, decimal, list, none, textLength, time, whole
|
270
270
|
# @param [Any] v The value validated
|
271
271
|
def self.validate_data_validation_type(v)
|
272
|
-
RestrictionValidator.validate :data_validation_type, [:custom, :data, :decimal, :list, :none, :textLength, :time, :whole], v
|
272
|
+
RestrictionValidator.validate :data_validation_type, [:custom, :data, :decimal, :list, :none, :textLength, :date, :time, :whole], v
|
273
273
|
end
|
274
274
|
|
275
275
|
# Requires that the value is a valid sheet view type.
|