caxlsx 3.0.0 → 3.1.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.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +126 -31
  3. data/README.md +78 -170
  4. data/examples/{image1.jpeg → assets/image1.jpeg} +0 -0
  5. data/examples/generate.rb +15 -0
  6. data/lib/axlsx.rb +2 -3
  7. data/lib/axlsx/drawing/bar_chart.rb +3 -3
  8. data/lib/axlsx/drawing/bar_series.rb +3 -5
  9. data/lib/axlsx/drawing/d_lbls.rb +1 -1
  10. data/lib/axlsx/drawing/pie_series.rb +1 -1
  11. data/lib/axlsx/drawing/series_title.rb +3 -1
  12. data/lib/axlsx/drawing/title.rb +3 -2
  13. data/lib/axlsx/package.rb +53 -19
  14. data/lib/axlsx/rels/relationship.rb +26 -25
  15. data/lib/axlsx/stylesheet/font.rb +10 -2
  16. data/lib/axlsx/util/constants.rb +2 -1
  17. data/lib/axlsx/util/mime_type_utils.rb +1 -1
  18. data/lib/axlsx/util/validators.rb +2 -2
  19. data/lib/axlsx/util/zip_command.rb +73 -0
  20. data/lib/axlsx/version.rb +1 -1
  21. data/lib/axlsx/workbook/workbook.rb +0 -9
  22. data/lib/axlsx/workbook/worksheet/cell.rb +32 -5
  23. data/lib/axlsx/workbook/worksheet/col.rb +8 -4
  24. data/lib/axlsx/workbook/worksheet/data_validation.rb +4 -4
  25. data/lib/axlsx/workbook/worksheet/pivot_table.rb +7 -2
  26. data/lib/axlsx/workbook/worksheet/pivot_table_cache_definition.rb +1 -1
  27. data/lib/axlsx/workbook/worksheet/rich_text_run.rb +1 -1
  28. data/lib/axlsx/workbook/worksheet/row.rb +6 -3
  29. data/lib/axlsx/workbook/worksheet/table.rb +1 -1
  30. data/lib/axlsx/workbook/worksheet/worksheet.rb +17 -4
  31. data/lib/caxlsx.rb +2 -0
  32. data/test/drawing/tc_drawing.rb +2 -2
  33. data/test/drawing/tc_hyperlink.rb +1 -1
  34. data/test/drawing/tc_one_cell_anchor.rb +1 -1
  35. data/test/drawing/tc_pic.rb +4 -4
  36. data/test/drawing/tc_pie_series.rb +2 -1
  37. data/test/drawing/tc_series_title.rb +21 -0
  38. data/test/drawing/tc_title.rb +16 -0
  39. data/test/fixtures/image1.gif +0 -0
  40. data/test/fixtures/image1.jpeg +0 -0
  41. data/test/fixtures/image1.jpg +0 -0
  42. data/test/fixtures/image1.png +0 -0
  43. data/test/fixtures/image1_fake.jpg +0 -0
  44. data/test/rels/tc_relationship.rb +8 -0
  45. data/test/stylesheet/tc_font.rb +14 -2
  46. data/test/stylesheet/tc_styles.rb +27 -1
  47. data/test/tc_axlsx.rb +6 -0
  48. data/test/tc_helper.rb +0 -2
  49. data/test/tc_package.rb +82 -13
  50. data/test/util/tc_mime_type_utils.rb +1 -1
  51. data/test/util/tc_validators.rb +1 -1
  52. data/test/workbook/worksheet/tc_cell.rb +68 -2
  53. data/test/workbook/worksheet/tc_col.rb +16 -1
  54. data/test/workbook/worksheet/tc_pivot_table.rb +8 -0
  55. data/test/workbook/worksheet/tc_pivot_table_cache_definition.rb +8 -0
  56. data/test/workbook/worksheet/tc_rich_text_run.rb +3 -2
  57. data/test/workbook/worksheet/tc_row.rb +38 -0
  58. data/test/workbook/worksheet/tc_table.rb +10 -0
  59. data/test/workbook/worksheet/tc_worksheet.rb +24 -15
  60. metadata +130 -151
  61. data/examples/2010_comments.rb +0 -17
  62. data/examples/anchor_swapping.rb +0 -28
  63. data/examples/auto_filter.rb +0 -25
  64. data/examples/basic_charts.rb +0 -58
  65. data/examples/chart_colors.rb +0 -88
  66. data/examples/colored_links.rb +0 -59
  67. data/examples/conditional_formatting/example_conditional_formatting.rb +0 -89
  68. data/examples/conditional_formatting/getting_barred.rb +0 -37
  69. data/examples/conditional_formatting/hitting_the_high_notes.rb +0 -37
  70. data/examples/conditional_formatting/scaled_colors.rb +0 -39
  71. data/examples/conditional_formatting/stop_and_go.rb +0 -37
  72. data/examples/data_validation.rb +0 -67
  73. data/examples/example.rb +0 -885
  74. data/examples/extractive.rb +0 -45
  75. data/examples/ios_preview.rb +0 -14
  76. data/examples/merge_cells.rb +0 -17
  77. data/examples/no_grid_with_borders.rb +0 -18
  78. data/examples/page_setup.rb +0 -11
  79. data/examples/pivot_table.rb +0 -39
  80. data/examples/pivot_test.rb +0 -63
  81. data/examples/sheet_protection.rb +0 -10
  82. data/examples/skydrive/real_example.rb +0 -63
  83. data/examples/split.rb +0 -16
  84. data/examples/styles.rb +0 -66
  85. data/examples/underline.rb +0 -13
  86. data/examples/wrap_text.rb +0 -21
  87. 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 'mimemagic'
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 three dimentional barchart (who would have guessed?) that you can add to your worksheet.
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 shabe of the bars or columns
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 shabe of the bars or columns
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 shabe of the bars or columns
19
- # must be one of [:percentStacked, :clustered, :standard, :stacked]
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
- # The shabe of the bars or columns
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
@@ -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 :bestFilt, :b, :ctr, :inBase, :inEnd, :l,
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>' << @text << '</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>'
@@ -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>' << @text << '</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>' << @text.to_s << '</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 valdation and serialization.
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 [Boolean] confirm_valid Validate the package prior to serialization.
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, confirm_valid=false)
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
- Relationship.clear_cached_instances
104
- Zip::OutputStream.open(output) do |zip|
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.clear_cached_instances
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 creat a package that does not validate it indicates that the internal
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 all instances of this class.
8
+ # Keeps track of relationship ids in use.
9
9
  # @return [Array]
10
- def instances
11
- @instances ||= []
10
+ def ids_cache
11
+ Thread.current[:axlsx_relationship_ids_cache] ||= {}
12
12
  end
13
-
14
- # Clear cached instances.
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
- # Also, calling this avoids memory leaks (cached instances lingering around
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 clear_cached_instances
24
- @instances = []
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 instances, so using
30
- # {clear_cached_instances} will automatically reset the generated ids, too.
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#{@instances.size + 1}"
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 = if (existing = self.class.instances.find{ |i| should_use_same_id_as?(i) })
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
- # Whether this relationship should use the same id as `other`.
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
- # @param other [Relationship]
120
- def should_use_same_id_as?(other)
121
- result = self.source_obj == other.source_obj && self.Type == other.Type && self.TargetMode == other.TargetMode
122
- if self.TargetMode == :External
123
- result &&= self.Target == other.Target
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
- # @return [Boolean]
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) Axlsx::validate_boolean v; @u = v end
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
@@ -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
- FLOAT_REGEX = /\A[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?\Z/.freeze
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
@@ -5,7 +5,7 @@ module Axlsx
5
5
  # @param [String] v File path
6
6
  # @return [String] File mime type
7
7
  def self.get_mime_type(v)
8
- MimeMagic.by_magic(File.open(v)).to_s
8
+ Marcel::MimeType.for(Pathname.new(v))
9
9
  end
10
10
  end
11
11
  end
@@ -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 Fixnun, Integer, Float value greater or equal to 0
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.