summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRandy Morgan <[email protected]>2013-01-10 18:27:27 +0900
committerRandy Morgan <[email protected]>2013-01-10 18:27:27 +0900
commit58e8dd8a2b1a4a85ac77bf680914daf16eb695f1 (patch)
tree980bf825b4b5c5fb55ef55b1b7f0ea2eb9b13533
parentf7eeb07abfa1c58552847b2b38787f44cd3e2d24 (diff)
downloadcaxlsx-58e8dd8a2b1a4a85ac77bf680914daf16eb695f1.tar.gz
caxlsx-58e8dd8a2b1a4a85ac77bf680914daf16eb695f1.zip
reduced processing of 3000 rows from 3+ seconds to just under 2
-rw-r--r--lib/axlsx.rb7
-rw-r--r--lib/axlsx/util/validators.rb13
-rw-r--r--lib/axlsx/workbook/shared_strings_table.rb2
-rw-r--r--lib/axlsx/workbook/workbook.rb1
-rw-r--r--lib/axlsx/workbook/worksheet/cell.rb81
-rw-r--r--lib/axlsx/workbook/worksheet/cell_serializer.rb94
-rw-r--r--lib/axlsx/workbook/worksheet/col.rb4
-rw-r--r--test/benchmark.rb1
-rw-r--r--test/profile.rb1
9 files changed, 121 insertions, 83 deletions
diff --git a/lib/axlsx.rb b/lib/axlsx.rb
index 91391db5..c5fcfed0 100644
--- a/lib/axlsx.rb
+++ b/lib/axlsx.rb
@@ -124,5 +124,10 @@ module Axlsx
s = s.capitalize if all_caps
s.gsub(/_(.)/){ $1.upcase }
end
-
+ def self.trust_input
+ @trust_input ||= false
+ end
+ def self.trust_input=(v)
+ @trust_input=v
+ end
end
diff --git a/lib/axlsx/util/validators.rb b/lib/axlsx/util/validators.rb
index aa8eb1ac..739a4de2 100644
--- a/lib/axlsx/util/validators.rb
+++ b/lib/axlsx/util/validators.rb
@@ -51,17 +51,18 @@ module Axlsx
# @raise [ArugumentError] Raised if the class of the value provided is not in the specified array of types or the block passed returns false
# @return [Boolean] true if validation succeeds.
# @see validate_boolean
- def self.validate(name, types, v, other= lambda{|arg| true })
+ def self.validate(name, types, v, other=false)
types = [types] unless types.is_a? Array
- valid_type = false
+ if other.is_a?(Proc)
+ raise ArgumentError, (ERR_TYPE % [v.inspect, name, types.inspect]) unless other.call(v)
+ end
if v.class == Class
- types.each { |t| valid_type = true if v.ancestors.include?(t) }
+ types.each { |t| return if v.ancestors.include?(t) }
else
- types.each { |t| valid_type = true if v.is_a?(t) }
+ types.each { |t| return if v.is_a?(t) }
end
- raise ArgumentError, (ERR_TYPE % [v.inspect, name, types.inspect]) unless (other.call(v) && valid_type)
+ raise ArgumentError, (ERR_TYPE % [v.inspect, name, types.inspect])
end
- true
end
diff --git a/lib/axlsx/workbook/shared_strings_table.rb b/lib/axlsx/workbook/shared_strings_table.rb
index 61402aec..43e8a1a8 100644
--- a/lib/axlsx/workbook/shared_strings_table.rb
+++ b/lib/axlsx/workbook/shared_strings_table.rb
@@ -58,7 +58,7 @@ module Axlsx
cell.send :ssti=, index
else
cell.send :ssti=, @index
- @shared_xml_string << '<si>' << cell.run_xml_string << '</si>'
+ @shared_xml_string << '<si>' << CellSerializer.run_xml_string(cell) << '</si>'
@unique_cells[cell_hash] = @index
@index += 1
end
diff --git a/lib/axlsx/workbook/workbook.rb b/lib/axlsx/workbook/workbook.rb
index 576367ba..e329ae74 100644
--- a/lib/axlsx/workbook/workbook.rb
+++ b/lib/axlsx/workbook/workbook.rb
@@ -5,6 +5,7 @@ require 'axlsx/workbook/worksheet/auto_filter/auto_filter.rb'
require 'axlsx/workbook/worksheet/date_time_converter.rb'
require 'axlsx/workbook/worksheet/protected_range.rb'
require 'axlsx/workbook/worksheet/protected_ranges.rb'
+require 'axlsx/workbook/worksheet/cell_serializer.rb'
require 'axlsx/workbook/worksheet/cell.rb'
require 'axlsx/workbook/worksheet/page_margins.rb'
require 'axlsx/workbook/worksheet/page_set_up_pr.rb'
diff --git a/lib/axlsx/workbook/worksheet/cell.rb b/lib/axlsx/workbook/worksheet/cell.rb
index 626b0969..7617bb0f 100644
--- a/lib/axlsx/workbook/worksheet/cell.rb
+++ b/lib/axlsx/workbook/worksheet/cell.rb
@@ -32,8 +32,9 @@ module Axlsx
# @option options [Symbol] scheme must be one of :none, major, :minor
def initialize(row, value="", options={})
self.row=row
- @value = @font_name = @charset = @family = @b = @i = @strike = @outline = @shadow = nil
- @formula_value = @condense = @u = @vertAlign = @sz = @color = @scheme = @extend = @ssti = nil
+ @value = nil
+ #@value = @font_name = @charset = @family = @b = @i = @strike = @outline = @shadow = nil
+ #@formula_value = @condense = @u = @vertAlign = @sz = @color = @scheme = @extend = @ssti = nil
@styles = row.worksheet.workbook.styles
@row.cells << self
parse_options options
@@ -293,42 +294,13 @@ module Axlsx
self.row.worksheet.merge_cells "#{self.r}:#{range_end}" unless range_end.nil?
end
- # builds an xml text run based on this cells attributes.
- # @param [String] str The string instance this run will be concated to.
- # @return [String]
- def run_xml_string(str = '')
- if is_text_run?
- data = instance_values.reject{|key, value| value == nil || key == 'value' || key == 'type' }
- keys = data.keys & INLINE_STYLES
- str << "<r><rPr>"
- keys.each do |key|
- case key
- when 'font_name'
- str << "<rFont val='"<< @font_name << "'/>"
- when 'color'
- str << data[key].to_xml_string
- else
- str << "<" << key.to_s << " val='" << data[key].to_s << "'/>"
- end
- end
- str << "</rPr>" << "<t>" << value.to_s << "</t></r>"
- else
- str << "<t>" << value.to_s << "</t>"
- end
- str
- end
-
# Serializes the cell
# @param [Integer] r_index The row index for the cell
# @param [Integer] c_index The cell index in the row.
# @param [String] str The string index the cell content will be appended to. Defaults to empty string.
# @return [String] xml text for the cell
def to_xml_string(r_index, c_index, str = '')
- str << '<c r="' << Axlsx::cell_r(c_index, r_index) << '" s="' << @style.to_s << '" '
- return str << '/>' if @value.nil?
- method = (@type.to_s << '_type_serialization').to_sym
- self.send(method, str)
- str << '</c>'
+ CellSerializer.to_xml_string r_index, c_index, self, str
end
def is_formula?
@@ -397,9 +369,9 @@ module Axlsx
:time
elsif v.is_a?(TrueClass) || v.is_a?(FalseClass)
:boolean
- elsif v.to_s.match(/\A[+-]?\d+?\Z/) #numeric
+ elsif v.to_s =~ /\A[+-]?\d+?\Z/ #numeric
:integer
- elsif v.to_s.match(/\A[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?\Z/) #float
+ elsif v.to_s =~ /\A[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?\Z/ #float
:float
else
:string
@@ -428,46 +400,7 @@ module Axlsx
@type = :string
# TODO find a better way to do this as it accounts for 30% of
# processing time in benchmarking...
- ::CGI.escapeHTML(v.to_s)
- end
- end
-
- def date_type_serialization(str='')
- value_serialization 'd', DateTimeConverter::date_to_serial(@value).to_s, str
- end
-
- def time_type_serialization(str='')
- value_serialization 'd', DateTimeConverter::time_to_serial(@value).to_s, str
- end
-
- def boolean_type_serialization(str='')
- value_serialization 'b', @value.to_s, str
- end
-
- def float_type_serialization(str='')
- numeric_type_serialization str
- end
-
- def integer_type_serialization(str = '')
- numeric_type_serialization str
- end
-
- def numeric_type_serialization(str = '')
- value_serialization('n', @value.to_s, str)
- end
-
- def value_serialization(serialization_type, serialization_value, str = '')
- str << 't="' << serialization_type << '"><v>' << serialization_value << '</v>'
- end
-
- def string_type_serialization(str='')
- if is_formula?
- str << 't="str">' << '<f>' << value.to_s.sub('=', '') << '</f>'
- str << '<v>' << formula_value.to_s << '</v>' unless formula_value.nil?
- value_serialization 's', @ssti.to_s, str
- else
- str << 't="inlineStr">' << '<is>' << run_xml_string << '</is>'
+ Axlsx::trust_input ? v.to_s : ::CGI.escapeHTML(v.to_s)
end
end
diff --git a/lib/axlsx/workbook/worksheet/cell_serializer.rb b/lib/axlsx/workbook/worksheet/cell_serializer.rb
new file mode 100644
index 00000000..c7f43f45
--- /dev/null
+++ b/lib/axlsx/workbook/worksheet/cell_serializer.rb
@@ -0,0 +1,94 @@
+module Axlsx
+ class CellSerializer
+ class << self
+ def to_xml_string(row_index, column_index, cell, str='')
+ str << '<c r="' << Axlsx::cell_r(column_index, row_index) << '" s="' << cell.style.to_s << '" '
+ return str << '/>' if cell.value.nil?
+ method = (cell.type.to_s << '_type_serialization').to_sym
+ self.send(method, cell, str)
+ str << '</c>'
+ end
+
+
+ # builds an xml text run based on this cells attributes.
+ # @param [String] str The string instance this run will be concated to.
+ # @return [String]
+ def run_xml_string(cell, str = '')
+ if cell.is_text_run?
+ data = cell.instance_values.reject{|key, value| value == nil || key == 'value' || key == 'type' }
+ keys = data.keys & Cell::INLINE_STYLES
+ str << "<r><rPr>"
+ keys.each do |key|
+ case key
+ when 'font_name'
+ str << "<rFont val='"<< cell.font_name << "'/>"
+ when 'color'
+ str << data[key].to_xml_string
+ else
+ str << "<" << key.to_s << " val='" << data[key].to_s << "'/>"
+ end
+ end
+ str << "</rPr>" << "<t>" << cell.value.to_s << "</t></r>"
+ else
+ str << "<t>" << cell.value.to_s << "</t>"
+ end
+ str
+ end
+
+
+ def iso_8601_type_serialization(cell, str='')
+ value_serialization 'd', cell.value, str
+ end
+
+ def date_type_serialization(cell, str='')
+ value_serialization false, DateTimeConverter::date_to_serial(cell.value).to_s, str
+ end
+
+ def time_type_serialization(cell, str='')
+ value_serialization false, DateTimeConverter::time_to_serial(cell.value).to_s, str
+ end
+
+ def boolean_type_serialization(cell, str='')
+ value_serialization 'b', cell.value.to_s, str
+ end
+
+ def float_type_serialization(cell, str='')
+ numeric_type_serialization cell, str
+ end
+
+ def integer_type_serialization(cell, str = '')
+ numeric_type_serialization cell, str
+ end
+
+ def numeric_type_serialization(cell, str = '')
+ value_serialization 'n', cell.value.to_s, str
+ end
+
+ def value_serialization(serialization_type, serialization_value, str = '')
+ str << 't="' << serialization_type << '"' if serialization_type
+ str << '><v>' << serialization_value << '</v>'
+ end
+
+ def formula_serialization(cell, str='')
+ str << 't="str">' << '<f>' << cell.value.to_s.sub('=', '') << '</f>'
+ str << '<v>' << cell.formula_value.to_s << '</v>' unless cell.formula_value.nil?
+ end
+
+ def inline_string_serialization(cell, str = '')
+ str << 't="inlineStr">' << '<is>'
+ run_xml_string cell, str
+ str << '</is>'
+ end
+
+ def string_type_serialization(cell, str='')
+ if cell.is_formula?
+ formula_serialization cell, str
+ elsif !cell.ssti.nil?
+ value_serialization 's', cell.ssti.to_s, str
+ else
+ inline_string_serialization cell, str
+ end
+ end
+ end
+ end
+end
diff --git a/lib/axlsx/workbook/worksheet/col.rb b/lib/axlsx/workbook/worksheet/col.rb
index 42997a2b..0a3edf87 100644
--- a/lib/axlsx/workbook/worksheet/col.rb
+++ b/lib/axlsx/workbook/worksheet/col.rb
@@ -125,7 +125,9 @@ module Axlsx
if fixed_width.is_a? Numeric
self.width = fixed_width
elsif use_autowidth
- self.width = [width || 0, cell.autowidth || 0].max
+ cell_width = cell.autowidth
+ self.width = cell_width unless (width || 0) > (cell_width || 0)
+ #self.width = [width || 0, cell.autowidth || 0].max
end
end
diff --git a/test/benchmark.rb b/test/benchmark.rb
index 33bf7d2c..2ef82eaf 100644
--- a/test/benchmark.rb
+++ b/test/benchmark.rb
@@ -4,6 +4,7 @@ $:.unshift "#{File.dirname(__FILE__)}/../lib"
require 'axlsx'
require 'csv'
require 'benchmark'
+Axlsx::trust_input = true
row = []
input = (32..126).to_a.pack('U*').chars.to_a
20.times { row << input.shuffle.join}
diff --git a/test/profile.rb b/test/profile.rb
index 0190dc16..8e4218fd 100644
--- a/test/profile.rb
+++ b/test/profile.rb
@@ -8,6 +8,7 @@
$:.unshift "#{File.dirname(__FILE__)}/../lib"
require 'axlsx'
require 'perftools'
+Axlsx.trust_input = true
row = []
# Taking worst case scenario of all string data
input = (32..126).to_a.pack('U*').chars.to_a