diff options
| author | Jurriaan Pruis <[email protected]> | 2014-01-15 23:44:02 +0100 |
|---|---|---|
| committer | Jurriaan Pruis <[email protected]> | 2014-02-26 20:09:21 +0100 |
| commit | be8e00332c73439cf17083173ea74f1505100df9 (patch) | |
| tree | 383ec2e23fc0a14aa5ad90e139648a79814eeded | |
| parent | a271a7d0f26ecb26d01aad00e094744d6fe8b0d2 (diff) | |
| download | caxlsx-be8e00332c73439cf17083173ea74f1505100df9.tar.gz caxlsx-be8e00332c73439cf17083173ea74f1505100df9.zip | |
Huge refactoring
Do not create huge strings
Let Row inherit from SimpleTypedList
Optimized sanitizing
Optimized validation
And more..
108 files changed, 666 insertions, 726 deletions
diff --git a/lib/axlsx.rb b/lib/axlsx.rb index cb4ce635..b5df5916 100644 --- a/lib/axlsx.rb +++ b/lib/axlsx.rb @@ -10,6 +10,7 @@ require 'axlsx/util/serialized_attributes' require 'axlsx/util/options_parser' # to be included with parsable intitites. #require 'axlsx/util/parser.rb' +require 'axlsx/util/string' require 'axlsx/stylesheet/styles.rb' @@ -53,7 +54,7 @@ module Axlsx cells = sort_cells(cells) reference = "#{cells.first.reference(absolute)}:#{cells.last.reference(absolute)}" if absolute - escaped_name = cells.first.row.worksheet.name.gsub "'", "''" + escaped_name = cells.first.row.worksheet.name.gsub ''', "''" "'#{escaped_name}'!#{reference}" else reference @@ -65,7 +66,7 @@ module Axlsx # @param [Array] cells # @return [Array] def self.sort_cells(cells) - cells.sort { |x, y| [x.index, x.row.index] <=> [y.index, y.row.index] } + cells.sort { |x, y| [x.index, x.row.row_index] <=> [y.index, y.row.row_index] } end #global reference html entity encoding @@ -88,20 +89,21 @@ module Axlsx # @note This follows the standard spreadsheet convention of naming columns A to Z, followed by AA to AZ etc. # @return [String] def self.col_ref(index) - chars = [] + chars = '' while index >= 26 do - chars << ((index % 26) + 65).chr - index = (index / 26).to_i - 1 + index, char = index.divmod(26) + chars.prepend((char + 65).chr) + index -= 1 end - chars << (index + 65).chr - chars.reverse.join + chars.prepend((index + 65).chr) + chars end # @return [String] The alpha(column)numeric(row) reference for this sell. # @example Relative Cell Reference # ws.rows.first.cells.first.r #=> "A1" def self.cell_r(c_index, r_index) - Axlsx::col_ref(c_index).to_s << (r_index+1).to_s + col_ref(c_index) << (r_index+1).to_s end # Creates an array of individual cell references based on an excel reference range. @@ -113,7 +115,7 @@ module Axlsx end_col, end_row = name_to_indices($2) (start_row..end_row).to_a.map do |row_num| (start_col..end_col).to_a.map do |col_num| - "#{col_ref(col_num)}#{row_num+1}" + cell_r(col_num, row_num) end end end @@ -127,14 +129,14 @@ module Axlsx s.gsub(/_(.)/){ $1.upcase } end - # returns the provided string with all invalid control charaters - # removed. - # @param [String] str The sting to process - # @return [String] - def self.sanitize(str) - str.gsub(CONTROL_CHAR_REGEX, '') - end - + # returns the provided string with all invalid control charaters + # removed. + # @param [String] str The string to process + # @return [String] + def self.sanitize(str) + str.delete!(CONTROL_CHARS) + str + end # Instructs the serializer to not try to escape cell value input. # This will give you a huge speed bonus, but if you content has <, > or other xml character data diff --git a/lib/axlsx/content_type/abstract_content_type.rb b/lib/axlsx/content_type/abstract_content_type.rb index 0afaa53f..832ccce6 100644 --- a/lib/axlsx/content_type/abstract_content_type.rb +++ b/lib/axlsx/content_type/abstract_content_type.rb @@ -24,7 +24,7 @@ module Axlsx # Serialize the contenty type to xml def to_xml_string(node_name = '', str = '') str << "<#{node_name} " - str << instance_values.map { |key, value| '' << Axlsx::camel(key) << '="' << value.to_s << '"' }.join(' ') + str << instance_values.map { |key, value| Axlsx::camel(key) << '="' << value.to_s << '"' }.join(' ') str << '/>' end diff --git a/lib/axlsx/content_type/content_type.rb b/lib/axlsx/content_type/content_type.rb index 94d65296..5d36d685 100644 --- a/lib/axlsx/content_type/content_type.rb +++ b/lib/axlsx/content_type/content_type.rb @@ -16,7 +16,7 @@ module Axlsx # @return [String] def to_xml_string(str = '') str << '<?xml version="1.0" encoding="UTF-8"?>' - str << '<Types xmlns="' << XML_NS_T << '">' + str << ('<Types xmlns="' << XML_NS_T << '">') each { |type| type.to_xml_string(str) } str << '</Types>' end diff --git a/lib/axlsx/doc_props/app.rb b/lib/axlsx/doc_props/app.rb index e6774147..b0dadf40 100644 --- a/lib/axlsx/doc_props/app.rb +++ b/lib/axlsx/doc_props/app.rb @@ -222,7 +222,7 @@ module Axlsx # @return [String] def to_xml_string(str = '') str << '<?xml version="1.0" encoding="UTF-8"?>' - str << '<Properties xmlns="' << APP_NS << '" xmlns:vt="' << APP_NS_VT << '">' + str << ('<Properties xmlns="' << APP_NS << '" xmlns:vt="' << APP_NS_VT << '">') instance_values.each do |key, value| node_name = Axlsx.camel(key) str << "<#{node_name}>#{value}</#{node_name}>" diff --git a/lib/axlsx/doc_props/core.rb b/lib/axlsx/doc_props/core.rb index a74031f2..bb2da676 100644 --- a/lib/axlsx/doc_props/core.rb +++ b/lib/axlsx/doc_props/core.rb @@ -25,11 +25,11 @@ module Axlsx # @return [String] def to_xml_string(str = '') str << '<?xml version="1.0" encoding="UTF-8"?>' - str << '<cp:coreProperties xmlns:cp="' << CORE_NS << '" xmlns:dc="' << CORE_NS_DC << '" ' - str << 'xmlns:dcmitype="' << CORE_NS_DCMIT << '" xmlns:dcterms="' << CORE_NS_DCT << '" ' - str << 'xmlns:xsi="' << CORE_NS_XSI << '">' - str << '<dc:creator>' << self.creator << '</dc:creator>' - str << '<dcterms:created xsi:type="dcterms:W3CDTF">' << (created || Time.now).strftime('%Y-%m-%dT%H:%M:%S') << 'Z</dcterms:created>' + str << ('<cp:coreProperties xmlns:cp="' << CORE_NS << '" xmlns:dc="' << CORE_NS_DC << '" ') + str << ('xmlns:dcmitype="' << CORE_NS_DCMIT << '" xmlns:dcterms="' << CORE_NS_DCT << '" ') + str << ('xmlns:xsi="' << CORE_NS_XSI << '">') + str << ('<dc:creator>' << self.creator << '</dc:creator>') + str << ('<dcterms:created xsi:type="dcterms:W3CDTF">' << (created || Time.now).strftime('%Y-%m-%dT%H:%M:%S') << 'Z</dcterms:created>') str << '<cp:revision>0</cp:revision>' str << '</cp:coreProperties>' end diff --git a/lib/axlsx/drawing/axes.rb b/lib/axlsx/drawing/axes.rb index bc40e532..dff87a9b 100644 --- a/lib/axlsx/drawing/axes.rb +++ b/lib/axlsx/drawing/axes.rb @@ -32,7 +32,7 @@ module Axlsx if options[:ids] # CatAxis must come first in the XML (for Microsoft Excel at least) sorted = axes.sort_by { |name, axis| axis.kind_of?(CatAxis) ? 0 : 1 } - sorted.inject(str) { |string, axis| string << '<c:axId val="' << axis[1].id.to_s << '"/>' } + sorted.each { |axis| str << ('<c:axId val="' << axis[1].id.to_s << '"/>') } else axes.each { |axis| axis[1].to_xml_string(str) } end diff --git a/lib/axlsx/drawing/axis.rb b/lib/axlsx/drawing/axis.rb index 32e40373..7e677a2e 100644 --- a/lib/axlsx/drawing/axis.rb +++ b/lib/axlsx/drawing/axis.rb @@ -150,10 +150,10 @@ module Axlsx # @param [String] str # @return [String] def to_xml_string(str = '') - str << '<c:axId val="' << @id.to_s << '"/>' + str << ('<c:axId val="' << @id.to_s << '"/>') @scaling.to_xml_string str - str << '<c:delete val="'<< @delete.to_s << '"/>' - str << '<c:axPos val="' << @ax_pos.to_s << '"/>' + str << ('<c:delete val="' << @delete.to_s << '"/>') + str << ('<c:axPos val="' << @ax_pos.to_s << '"/>') str << '<c:majorGridlines>' # TODO shape properties need to be extracted into a class if gridlines == false @@ -165,21 +165,21 @@ module Axlsx end str << '</c:majorGridlines>' @title.to_xml_string(str) unless @title == nil - str << '<c:numFmt formatCode="' << @format_code << '" sourceLinked="1"/>' + str << ('<c:numFmt formatCode="' << @format_code << '" sourceLinked="1"/>') str << '<c:majorTickMark val="none"/>' str << '<c:minorTickMark val="none"/>' - str << '<c:tickLblPos val="' << @tick_lbl_pos.to_s << '"/>' + str << ('<c:tickLblPos val="' << @tick_lbl_pos.to_s << '"/>') # TODO - this is also being used for series colors # time to extract this into a class spPr - Shape Properties if @color str << '<c:spPr><a:ln><a:solidFill>' - str << '<a:srgbClr val="' << @color << '"/>' + str << ('<a:srgbClr val="' << @color << '"/>') str << '</a:solidFill></a:ln></c:spPr>' end # some potential value in implementing this in full. Very detailed! - str << '<c:txPr><a:bodyPr rot="' << @label_rotation.to_s << '"/><a:lstStyle/><a:p><a:pPr><a:defRPr/></a:pPr><a:endParaRPr/></a:p></c:txPr>' - str << '<c:crossAx val="' << @cross_axis.id.to_s << '"/>' - str << '<c:crosses val="' << @crosses.to_s << '"/>' + str << ('<c:txPr><a:bodyPr rot="' << @label_rotation.to_s << '"/><a:lstStyle/><a:p><a:pPr><a:defRPr/></a:pPr><a:endParaRPr/></a:p></c:txPr>') + str << ('<c:crossAx val="' << @cross_axis.id.to_s << '"/>') + str << ('<c:crosses val="' << @crosses.to_s << '"/>') end end diff --git a/lib/axlsx/drawing/bar_3D_chart.rb b/lib/axlsx/drawing/bar_3D_chart.rb index 755f334c..7d44eca6 100644 --- a/lib/axlsx/drawing/bar_3D_chart.rb +++ b/lib/axlsx/drawing/bar_3D_chart.rb @@ -125,19 +125,19 @@ module Axlsx # @param [String] str # @return [String] def to_xml_string(str = '') - super(str) do |str_inner| - str_inner << '<c:bar3DChart>' - str_inner << '<c:barDir val="' << bar_dir.to_s << '"/>' - str_inner << '<c:grouping val="' << grouping.to_s << '"/>' - str_inner << '<c:varyColors val="' << vary_colors.to_s << '"/>' - @series.each { |ser| ser.to_xml_string(str_inner) } - @d_lbls.to_xml_string(str_inner) if @d_lbls - str_inner << '<c:gapWidth val="' << @gap_width.to_s << '"/>' unless @gap_width.nil? - str_inner << '<c:gapDepth val="' << @gap_depth.to_s << '"/>' unless @gap_depth.nil? - str_inner << '<c:shape val="' << @shape.to_s << '"/>' unless @shape.nil? - axes.to_xml_string(str_inner, :ids => true) - str_inner << '</c:bar3DChart>' - axes.to_xml_string(str_inner) + super(str) do + str << '<c:bar3DChart>' + str << ('<c:barDir val="' << bar_dir.to_s << '"/>') + str << ('<c:grouping val="' << grouping.to_s << '"/>') + str << ('<c:varyColors val="' << vary_colors.to_s << '"/>') + @series.each { |ser| ser.to_xml_string(str) } + @d_lbls.to_xml_string(str) if @d_lbls + str << ('<c:gapWidth val="' << @gap_width.to_s << '"/>') unless @gap_width.nil? + str << ('<c:gapDepth val="' << @gap_depth.to_s << '"/>') unless @gap_depth.nil? + str << ('<c:shape val="' << @shape.to_s << '"/>') unless @shape.nil? + axes.to_xml_string(str, :ids => true) + str << '</c:bar3DChart>' + axes.to_xml_string(str) end end diff --git a/lib/axlsx/drawing/bar_series.rb b/lib/axlsx/drawing/bar_series.rb index d85345c9..a649a68a 100644 --- a/lib/axlsx/drawing/bar_series.rb +++ b/lib/axlsx/drawing/bar_series.rb @@ -52,20 +52,20 @@ module Axlsx # @param [String] str # @return [String] def to_xml_string(str = '') - super(str) do |str_inner| + super(str) do colors.each_with_index do |c, index| - str_inner << '<c:dPt>' - str_inner << '<c:idx val="' << index.to_s << '"/>' - str_inner << '<c:spPr><a:solidFill>' - str_inner << '<a:srgbClr val="' << c << '"/>' - str_inner << '</a:solidFill></c:spPr></c:dPt>' + str << '<c:dPt>' + str << ('<c:idx val="' << index.to_s << '"/>') + str << '<c:spPr><a:solidFill>' + str << ('<a:srgbClr val="' << c << '"/>') + str << '</a:solidFill></c:spPr></c:dPt>' end - @labels.to_xml_string(str_inner) unless @labels.nil? - @data.to_xml_string(str_inner) unless @data.nil? + @labels.to_xml_string(str) unless @labels.nil? + @data.to_xml_string(str) unless @data.nil? # this is actually only required for shapes other than box - str_inner << '<c:shape val="' << shape.to_s << '"></c:shape>' + str << ('<c:shape val="' << shape.to_s << '"></c:shape>') end end diff --git a/lib/axlsx/drawing/bubble_chart.rb b/lib/axlsx/drawing/bubble_chart.rb index 2f2c4595..e08e6f7c 100644 --- a/lib/axlsx/drawing/bubble_chart.rb +++ b/lib/axlsx/drawing/bubble_chart.rb @@ -37,14 +37,14 @@ module Axlsx # @param [String] str # @return [String] def to_xml_string(str = '') - super(str) do |str_inner| - str_inner << '<c:bubbleChart>' - str_inner << '<c:varyColors val="' << vary_colors.to_s << '"/>' - @series.each { |ser| ser.to_xml_string(str_inner) } - d_lbls.to_xml_string(str_inner) if @d_lbls - axes.to_xml_string(str_inner, :ids => true) - str_inner << '</c:bubbleChart>' - axes.to_xml_string(str_inner) + super(str) do + str << '<c:bubbleChart>' + str << ('<c:varyColors val="' << vary_colors.to_s << '"/>') + @series.each { |ser| ser.to_xml_string(str) } + d_lbls.to_xml_string(str) if @d_lbls + axes.to_xml_string(str, :ids => true) + str << '</c:bubbleChart>' + axes.to_xml_string(str) end str end diff --git a/lib/axlsx/drawing/bubble_series.rb b/lib/axlsx/drawing/bubble_series.rb index 6d263774..07b7be61 100644 --- a/lib/axlsx/drawing/bubble_series.rb +++ b/lib/axlsx/drawing/bubble_series.rb @@ -43,19 +43,19 @@ module Axlsx # @param [String] str # @return [String] def to_xml_string(str = '') - super(str) do |inner_str| + super(str) do # needs to override the super color here to push in ln/and something else! if color str << '<c:spPr><a:solidFill>' - str << '<a:srgbClr val="' << color << '"/>' + str << ('<a:srgbClr val="' << color << '"/>') str << '</a:solidFill>' str << '<a:ln><a:solidFill>' - str << '<a:srgbClr val="' << color << '"/></a:solidFill></a:ln>' + str << ('<a:srgbClr val="' << color << '"/></a:solidFill></a:ln>') str << '</c:spPr>' end - @xData.to_xml_string(inner_str) unless @xData.nil? - @yData.to_xml_string(inner_str) unless @yData.nil? - @bubbleSize.to_xml_string(inner_str) unless @bubbleSize.nil? + @xData.to_xml_string(str) unless @xData.nil? + @yData.to_xml_string(str) unless @yData.nil? + @bubbleSize.to_xml_string(str) unless @bubbleSize.nil? end str end diff --git a/lib/axlsx/drawing/cat_axis.rb b/lib/axlsx/drawing/cat_axis.rb index f32c23c9..6091b972 100644 --- a/lib/axlsx/drawing/cat_axis.rb +++ b/lib/axlsx/drawing/cat_axis.rb @@ -71,11 +71,11 @@ module Axlsx def to_xml_string(str = '') str << '<c:catAx>' super(str) - str << '<c:auto val="' << @auto.to_s << '"/>' - str << '<c:lblAlgn val="' << @lbl_algn.to_s << '"/>' - str << '<c:lblOffset val="' << @lbl_offset.to_i.to_s << '"/>' - str << '<c:tickLblSkip val="' << @tick_lbl_skip.to_s << '"/>' - str << '<c:tickMarkSkip val="' << @tick_mark_skip.to_s << '"/>' + str << ('<c:auto val="' << @auto.to_s << '"/>') + str << ('<c:lblAlgn val="' << @lbl_algn.to_s << '"/>') + str << ('<c:lblOffset val="' << @lbl_offset.to_i.to_s << '"/>') + str << ('<c:tickLblSkip val="' << @tick_lbl_skip.to_s << '"/>') + str << ('<c:tickMarkSkip val="' << @tick_mark_skip.to_s << '"/>') str << '</c:catAx>' end diff --git a/lib/axlsx/drawing/chart.rb b/lib/axlsx/drawing/chart.rb index c1d408e6..1d6b9293 100644 --- a/lib/axlsx/drawing/chart.rb +++ b/lib/axlsx/drawing/chart.rb @@ -151,19 +151,19 @@ module Axlsx # @return [String] def to_xml_string(str = '') str << '<?xml version="1.0" encoding="UTF-8"?>' - str << '<c:chartSpace xmlns:c="' << XML_NS_C << '" xmlns:a="' << XML_NS_A << '" xmlns:r="' << XML_NS_R << '">' - str << '<c:date1904 val="' << Axlsx::Workbook.date1904.to_s << '"/>' - str << '<c:style val="' << style.to_s << '"/>' + str << ('<c:chartSpace xmlns:c="' << XML_NS_C << '" xmlns:a="' << XML_NS_A << '" xmlns:r="' << XML_NS_R << '">') + str << ('<c:date1904 val="' << Axlsx::Workbook.date1904.to_s << '"/>') + str << ('<c:style val="' << style.to_s << '"/>') str << '<c:chart>' @title.to_xml_string str - str << '<c:autoTitleDeleted val="' << (@title == nil).to_s << '"/>' + str << ('<c:autoTitleDeleted val="' << (@title == nil).to_s << '"/>') @view_3D.to_xml_string(str) if @view_3D str << '<c:floor><c:thickness val="0"/></c:floor>' str << '<c:sideWall><c:thickness val="0"/></c:sideWall>' str << '<c:backWall><c:thickness val="0"/></c:backWall>' str << '<c:plotArea>' str << '<c:layout/>' - yield str if block_given? + yield if block_given? str << '</c:plotArea>' if @show_legend str << '<c:legend>' @@ -173,7 +173,7 @@ module Axlsx str << '</c:legend>' end str << '<c:plotVisOnly val="1"/>' - str << '<c:dispBlanksAs val="' << display_blanks_as.to_s << '"/>' + str << ('<c:dispBlanksAs val="' << display_blanks_as.to_s << '"/>') str << '<c:showDLblsOverMax val="1"/>' str << '</c:chart>' str << '<c:printSettings>' diff --git a/lib/axlsx/drawing/drawing.rb b/lib/axlsx/drawing/drawing.rb index e7fcba85..2b593606 100644 --- a/lib/axlsx/drawing/drawing.rb +++ b/lib/axlsx/drawing/drawing.rb @@ -155,7 +155,7 @@ module Axlsx # @return [String] def to_xml_string(str = '') str << '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' - str << '<xdr:wsDr xmlns:xdr="' << XML_NS_XDR << '" xmlns:a="' << XML_NS_A << '">' + str << ('<xdr:wsDr xmlns:xdr="' << XML_NS_XDR << '" xmlns:a="' << XML_NS_A << '">') anchors.each { |anchor| anchor.to_xml_string(str) } str << '</xdr:wsDr>' end diff --git a/lib/axlsx/drawing/graphic_frame.rb b/lib/axlsx/drawing/graphic_frame.rb index 9b921275..d44415b9 100644 --- a/lib/axlsx/drawing/graphic_frame.rb +++ b/lib/axlsx/drawing/graphic_frame.rb @@ -35,7 +35,7 @@ module Axlsx # macro attribute should be optional! str << '<xdr:graphicFrame>' str << '<xdr:nvGraphicFramePr>' - str << '<xdr:cNvPr id="' << @anchor.drawing.index.to_s << '" name="' << 'item_' << @anchor.drawing.index.to_s << '"/>' + str << ('<xdr:cNvPr id="' << @anchor.drawing.index.to_s << '" name="' << 'item_' << @anchor.drawing.index.to_s << '"/>') str << '<xdr:cNvGraphicFramePr/>' str << '</xdr:nvGraphicFramePr>' str << '<xdr:xfrm>' @@ -43,8 +43,8 @@ module Axlsx str << '<a:ext cx="0" cy="0"/>' str << '</xdr:xfrm>' str << '<a:graphic>' - str << '<a:graphicData uri="' << XML_NS_C << '">' - str << '<c:chart xmlns:c="' << XML_NS_C << '" xmlns:r="' << XML_NS_R << '" r:id="' << rId << '"/>' + str << ('<a:graphicData uri="' << XML_NS_C << '">') + str << ('<c:chart xmlns:c="' << XML_NS_C << '" xmlns:r="' << XML_NS_R << '" r:id="' << rId << '"/>') str << '</a:graphicData>' str << '</a:graphic>' str << '</xdr:graphicFrame>' diff --git a/lib/axlsx/drawing/hyperlink.rb b/lib/axlsx/drawing/hyperlink.rb index 850baeef..fcabd25b 100644 --- a/lib/axlsx/drawing/hyperlink.rb +++ b/lib/axlsx/drawing/hyperlink.rb @@ -93,9 +93,7 @@ module Axlsx # @param [String] str # @return [String] def to_xml_string(str = '') - str << '<a:hlinkClick ' - serialized_attributes str, {:'r:id' => relationship.Id, :'xmlns:r' => XML_NS_R } - str << '/>' + serialized_tag 'a:hlinkClick', str, {:'r:id' => relationship.Id, :'xmlns:r' => XML_NS_R } end end diff --git a/lib/axlsx/drawing/line_3D_chart.rb b/lib/axlsx/drawing/line_3D_chart.rb index 183f3250..4132655e 100644 --- a/lib/axlsx/drawing/line_3D_chart.rb +++ b/lib/axlsx/drawing/line_3D_chart.rb @@ -60,8 +60,8 @@ module Axlsx # @param [String] str # @return [String] def to_xml_string(str = '') - super(str) do |str_inner| - str_inner << '<c:gapDepth val="' << @gap_depth.to_s << '"/>' unless @gap_depth.nil? + super(str) do + str << ('<c:gapDepth val="' << @gap_depth.to_s << '"/>') unless @gap_depth.nil? end end end diff --git a/lib/axlsx/drawing/line_chart.rb b/lib/axlsx/drawing/line_chart.rb index 699050dc..a86355d5 100644 --- a/lib/axlsx/drawing/line_chart.rb +++ b/lib/axlsx/drawing/line_chart.rb @@ -76,16 +76,16 @@ module Axlsx # @param [String] str # @return [String] def to_xml_string(str = '') - super(str) do |str_inner| - str_inner << "<c:" << node_name << ">" - str_inner << '<c:grouping val="' << grouping.to_s << '"/>' - str_inner << '<c:varyColors val="' << vary_colors.to_s << '"/>' - @series.each { |ser| ser.to_xml_string(str_inner) } - @d_lbls.to_xml_string(str_inner) if @d_lbls - yield str_inner if block_given? - axes.to_xml_string(str_inner, :ids => true) - str_inner << "</c:" << node_name << ">" - axes.to_xml_string(str_inner) + super(str) do + str << ("<c:" << node_name << ">") + str << ('<c:grouping val="' << grouping.to_s << '"/>') + str << ('<c:varyColors val="' << vary_colors.to_s << '"/>') + @series.each { |ser| ser.to_xml_string(str) } + @d_lbls.to_xml_string(str) if @d_lbls + yield if block_given? + axes.to_xml_string(str, :ids => true) + str << ("</c:" << node_name << ">") + axes.to_xml_string(str) end end diff --git a/lib/axlsx/drawing/line_series.rb b/lib/axlsx/drawing/line_series.rb index 93478b8f..50df27b8 100644 --- a/lib/axlsx/drawing/line_series.rb +++ b/lib/axlsx/drawing/line_series.rb @@ -64,11 +64,11 @@ module Axlsx super(str) do if color str << '<c:spPr><a:solidFill>' - str << '<a:srgbClr val="' << color << '"/>' + str << ('<a:srgbClr val="' << color << '"/>') str << '</a:solidFill>' str << '<a:ln w="28800">' str << '<a:solidFill>' - str << '<a:srgbClr val="' << color << '"/>' + str << ('<a:srgbClr val="' << color << '"/>') str << '</a:solidFill>' str << '</a:ln>' str << '<a:round/>' @@ -77,7 +77,7 @@ module Axlsx str << '<c:marker><c:symbol val="none"/></c:marker>' unless @show_marker @labels.to_xml_string(str) unless @labels.nil? @data.to_xml_string(str) unless @data.nil? - str << '<c:smooth val="' << ((smooth) ? '1' : '0') << '"/>' + str << ('<c:smooth val="' << ((smooth) ? '1' : '0') << '"/>') end end diff --git a/lib/axlsx/drawing/marker.rb b/lib/axlsx/drawing/marker.rb index 6180a0f4..75876fa3 100644 --- a/lib/axlsx/drawing/marker.rb +++ b/lib/axlsx/drawing/marker.rb @@ -58,7 +58,7 @@ module Axlsx # @return [String] def to_xml_string(str = '') [:col, :colOff, :row, :rowOff].each do |k| - str << '<xdr:' << k.to_s << '>' << self.send(k).to_s << '</xdr:' << k.to_s << '>' + str << ('<xdr:' << k.to_s << '>' << self.send(k).to_s << '</xdr:' << k.to_s << '>') end end private diff --git a/lib/axlsx/drawing/num_data.rb b/lib/axlsx/drawing/num_data.rb index c1773f59..9b7a2587 100644 --- a/lib/axlsx/drawing/num_data.rb +++ b/lib/axlsx/drawing/num_data.rb @@ -38,13 +38,13 @@ module Axlsx # serialize the object def to_xml_string(str = "") - str << '<c:' << @tag_name.to_s << '>' - str << '<c:formatCode>' << format_code.to_s << '</c:formatCode>' - str << '<c:ptCount val="' << @pt.size.to_s << '"/>' + str << ('<c:' << @tag_name.to_s << '>') + str << ('<c:formatCode>' << format_code.to_s << '</c:formatCode>') + str << ('<c:ptCount val="' << @pt.size.to_s << '"/>') @pt.each_with_index do |num_val, index| num_val.to_xml_string index, str end - str << '</c:' << @tag_name.to_s << '>' + str << ('</c:' << @tag_name.to_s << '>') end end diff --git a/lib/axlsx/drawing/num_data_source.rb b/lib/axlsx/drawing/num_data_source.rb index c52b0fa8..e0e97e41 100644 --- a/lib/axlsx/drawing/num_data_source.rb +++ b/lib/axlsx/drawing/num_data_source.rb @@ -46,16 +46,16 @@ module Axlsx # serialize the object # @param [String] str def to_xml_string(str="") - str << '<c:' << tag_name.to_s << '>' + str << ('<c:' << tag_name.to_s << '>') if @f - str << '<c:' << @ref_tag_name.to_s << '>' - str << '<c:f>' << @f.to_s << '</c:f>' + str << ('<c:' << @ref_tag_name.to_s << '>') + str << ('<c:f>' << @f.to_s << '</c:f>') end @data.to_xml_string str if @f - str << '</c:' << @ref_tag_name.to_s << '>' + str << ('</c:' << @ref_tag_name.to_s << '>') end - str << '</c:' << tag_name.to_s << '>' + str << ('</c:' << tag_name.to_s << '>') end end end diff --git a/lib/axlsx/drawing/num_val.rb b/lib/axlsx/drawing/num_val.rb index ed655732..bd733cb7 100644 --- a/lib/axlsx/drawing/num_val.rb +++ b/lib/axlsx/drawing/num_val.rb @@ -26,7 +26,7 @@ module Axlsx # serialize the object def to_xml_string(idx, str = "") Axlsx::validate_unsigned_int(idx) - str << '<c:pt idx="' << idx.to_s << '" formatCode="' << format_code << '"><c:v>' << v.to_s << '</c:v></c:pt>' + str << ('<c:pt idx="' << idx.to_s << '" formatCode="' << format_code << '"><c:v>' << v.to_s << '</c:v></c:pt>') end end end diff --git a/lib/axlsx/drawing/one_cell_anchor.rb b/lib/axlsx/drawing/one_cell_anchor.rb index faf78278..1ae7c1b9 100644 --- a/lib/axlsx/drawing/one_cell_anchor.rb +++ b/lib/axlsx/drawing/one_cell_anchor.rb @@ -77,7 +77,7 @@ module Axlsx str << '<xdr:from>' from.to_xml_string(str) str << '</xdr:from>' - str << '<xdr:ext cx="' << ext[:cx].to_s << '" cy="' << ext[:cy].to_s << '"/>' + str << ('<xdr:ext cx="' << ext[:cx].to_s << '" cy="' << ext[:cy].to_s << '"/>') @object.to_xml_string(str) str << '<xdr:clientData/>' str << '</xdr:oneCellAnchor>' diff --git a/lib/axlsx/drawing/pic.rb b/lib/axlsx/drawing/pic.rb index d001ad8f..571e9047 100644 --- a/lib/axlsx/drawing/pic.rb +++ b/lib/axlsx/drawing/pic.rb @@ -165,17 +165,16 @@ module Axlsx def to_xml_string(str = '') str << '<xdr:pic>' str << '<xdr:nvPicPr>' - str << '<xdr:cNvPr id="2" name="' << name.to_s << '" descr="' << descr.to_s << '">' + str << ('<xdr:cNvPr id="2" name="' << name.to_s << '" descr="' << descr.to_s << '">') @hyperlink.to_xml_string(str) if @hyperlink.is_a?(Hyperlink) str << '</xdr:cNvPr><xdr:cNvPicPr>' picture_locking.to_xml_string(str) str << '</xdr:cNvPicPr></xdr:nvPicPr>' str << '<xdr:blipFill>' - str << '<a:blip xmlns:r ="' << XML_NS_R << '" r:embed="' << relationship.Id << '"/>' + str << ('<a:blip xmlns:r ="' << XML_NS_R << '" r:embed="' << relationship.Id << '"/>') str << '<a:stretch><a:fillRect/></a:stretch></xdr:blipFill><xdr:spPr>' str << '<a:xfrm><a:off x="0" y="0"/><a:ext cx="2336800" cy="2161540"/></a:xfrm>' str << '<a:prstGeom prst="rect"><a:avLst/></a:prstGeom></xdr:spPr></xdr:pic>' - end private diff --git a/lib/axlsx/drawing/picture_locking.rb b/lib/axlsx/drawing/picture_locking.rb index e77dac37..d97fb6c2 100644 --- a/lib/axlsx/drawing/picture_locking.rb +++ b/lib/axlsx/drawing/picture_locking.rb @@ -35,9 +35,7 @@ module Axlsx # @param [String] str # @return [String] def to_xml_string(str = '') - str << '<a:picLocks ' - serialized_attributes str - str << '/>' + serialized_tag('a:picLocks', str) end end diff --git a/lib/axlsx/drawing/pie_3D_chart.rb b/lib/axlsx/drawing/pie_3D_chart.rb index 4e61f4a1..f87e6d4e 100644 --- a/lib/axlsx/drawing/pie_3D_chart.rb +++ b/lib/axlsx/drawing/pie_3D_chart.rb @@ -34,13 +34,12 @@ module Axlsx # @param [String] str # @return [String] def to_xml_string(str = '') - super(str) do |str_inner| - - str_inner << '<c:pie3DChart>' - str_inner << '<c:varyColors val="' << vary_colors.to_s << '"/>' - @series.each { |ser| ser.to_xml_string(str_inner) } + super(str) do + str << '<c:pie3DChart>' + str << ('<c:varyColors val="' << vary_colors.to_s << '"/>') + @series.each { |ser| ser.to_xml_string(str) } d_lbls.to_xml_string(str) if @d_lbls - str_inner << '</c:pie3DChart>' + str << '</c:pie3DChart>' end end diff --git a/lib/axlsx/drawing/pie_series.rb b/lib/axlsx/drawing/pie_series.rb index 28056c43..31a6b265 100644 --- a/lib/axlsx/drawing/pie_series.rb +++ b/lib/axlsx/drawing/pie_series.rb @@ -46,17 +46,17 @@ module Axlsx # @param [String] str # @return [String] def to_xml_string(str = '') - super(str) do |str_inner| - str_inner << '<c:explosion val="' << @explosion << '"/>' unless @explosion.nil? + super(str) do + str << '<c:explosion val="' + @explosion + '"/>' unless @explosion.nil? colors.each_with_index do |c, index| str << '<c:dPt>' - str << '<c:idx val="' << index.to_s << '"/>' + str << ('<c:idx val="' << index.to_s << '"/>') str << '<c:spPr><a:solidFill>' - str << '<a:srgbClr val="' << c << '"/>' + str << ('<a:srgbClr val="' << c << '"/>') str << '</a:solidFill></c:spPr></c:dPt>' end - @labels.to_xml_string str_inner unless @labels.nil? - @data.to_xml_string str_inner unless @data.nil? + @labels.to_xml_string str unless @labels.nil? + @data.to_xml_string str unless @data.nil? end str end diff --git a/lib/axlsx/drawing/scaling.rb b/lib/axlsx/drawing/scaling.rb index b45bd4ce..fcbea9f8 100644 --- a/lib/axlsx/drawing/scaling.rb +++ b/lib/axlsx/drawing/scaling.rb @@ -49,10 +49,10 @@ module Axlsx # @return [String] def to_xml_string(str = '') str << '<c:scaling>' - str << '<c:logBase val="' << @logBase.to_s << '"/>' unless @logBase.nil? - str << '<c:orientation val="' << @orientation.to_s << '"/>' unless @orientation.nil? - str << '<c:min val="' << @min.to_s << '"/>' unless @min.nil? - str << '<c:max val="' << @max.to_s << '"/>' unless @max.nil? + str << ('<c:logBase val="' << @logBase.to_s << '"/>') unless @logBase.nil? + str << ('<c:orientation val="' << @orientation.to_s << '"/>') unless @orientation.nil? + str << ('<c:min val="' << @min.to_s << '"/>') unless @min.nil? + str << ('<c:max val="' << @max.to_s << '"/>') unless @max.nil? str << '</c:scaling>' end diff --git a/lib/axlsx/drawing/scatter_chart.rb b/lib/axlsx/drawing/scatter_chart.rb index 18d3126c..f3df1b3e 100644 --- a/lib/axlsx/drawing/scatter_chart.rb +++ b/lib/axlsx/drawing/scatter_chart.rb @@ -51,15 +51,15 @@ module Axlsx # @param [String] str # @return [String] def to_xml_string(str = '') - super(str) do |str_inner| - str_inner << '<c:scatterChart>' - str_inner << '<c:scatterStyle val="' << scatter_style.to_s << '"/>' - str_inner << '<c:varyColors val="' << vary_colors.to_s << '"/>' - @series.each { |ser| ser.to_xml_string(str_inner) } - d_lbls.to_xml_string(str_inner) if @d_lbls - axes.to_xml_string(str_inner, :ids => true) - str_inner << '</c:scatterChart>' - axes.to_xml_string(str_inner) + super(str) do + str << '<c:scatterChart>' + str << ('<c:scatterStyle val="' << scatter_style.to_s << '"/>') + str << ('<c:varyColors val="' << vary_colors.to_s << '"/>') + @series.each { |ser| ser.to_xml_string(str) } + d_lbls.to_xml_string(str) if @d_lbls + axes.to_xml_string(str, :ids => true) + str << '</c:scatterChart>' + axes.to_xml_string(str) end str end diff --git a/lib/axlsx/drawing/scatter_series.rb b/lib/axlsx/drawing/scatter_series.rb index 6084c110..28962230 100644 --- a/lib/axlsx/drawing/scatter_series.rb +++ b/lib/axlsx/drawing/scatter_series.rb @@ -38,26 +38,26 @@ module Axlsx # @param [String] str # @return [String] def to_xml_string(str = '') - super(str) do |inner_str| + super(str) do # needs to override the super color here to push in ln/and something else! if color str << '<c:spPr><a:solidFill>' - str << '<a:srgbClr val="' << color << '"/>' + str << ('<a:srgbClr val="' << color << '"/>') str << '</a:solidFill>' str << '<a:ln><a:solidFill>' - str << '<a:srgbClr val="' << color << '"/></a:solidFill></a:ln>' + str << ('<a:srgbClr val="' << color << '"/></a:solidFill></a:ln>') str << '</c:spPr>' str << '<c:marker>' str << '<c:spPr><a:solidFill>' - str << '<a:srgbClr val="' << color << '"/>' + str << ('<a:srgbClr val="' << color << '"/>') str << '</a:solidFill>' str << '<a:ln><a:solidFill>' - str << '<a:srgbClr val="' << color << '"/></a:solidFill></a:ln>' + str << ('<a:srgbClr val="' << color << '"/></a:solidFill></a:ln>') str << '</c:spPr>' str << '</c:marker>' end - @xData.to_xml_string(inner_str) unless @xData.nil? - @yData.to_xml_string(inner_str) unless @yData.nil? + @xData.to_xml_string(str) unless @xData.nil? + @yData.to_xml_string(str) unless @yData.nil? end str end diff --git a/lib/axlsx/drawing/ser_axis.rb b/lib/axlsx/drawing/ser_axis.rb index 54e2c60e..fd7f7602 100644 --- a/lib/axlsx/drawing/ser_axis.rb +++ b/lib/axlsx/drawing/ser_axis.rb @@ -35,8 +35,8 @@ module Axlsx def to_xml_string(str = '') str << '<c:serAx>' super(str) - str << '<c:tickLblSkip val="' << @tick_lbl_skip.to_s << '"/>' unless @tick_lbl_skip.nil? - str << '<c:tickMarkSkip val="' << @tick_mark_skip.to_s << '"/>' unless @tick_mark_skip.nil? + str << ('<c:tickLblSkip val="' << @tick_lbl_skip.to_s << '"/>') unless @tick_lbl_skip.nil? + str << ('<c:tickMarkSkip val="' << @tick_mark_skip.to_s << '"/>') unless @tick_mark_skip.nil? str << '</c:serAx>' end end diff --git a/lib/axlsx/drawing/series.rb b/lib/axlsx/drawing/series.rb index c9f467d5..0218f5ce 100644 --- a/lib/axlsx/drawing/series.rb +++ b/lib/axlsx/drawing/series.rb @@ -59,10 +59,10 @@ module Axlsx # @return [String] def to_xml_string(str = '') str << '<c:ser>' - str << '<c:idx val="' << index.to_s << '"/>' - str << '<c:order val="' << (order || index).to_s << '"/>' + str << ('<c:idx val="' << index.to_s << '"/>') + str << ('<c:order val="' << (order || index).to_s << '"/>') title.to_xml_string(str) unless title.nil? - yield str if block_given? + yield if block_given? str << '</c:ser>' end end diff --git a/lib/axlsx/drawing/series_title.rb b/lib/axlsx/drawing/series_title.rb index 658be425..9ef97304 100644 --- a/lib/axlsx/drawing/series_title.rb +++ b/lib/axlsx/drawing/series_title.rb @@ -9,11 +9,11 @@ module Axlsx def to_xml_string(str = '') str << '<c:tx>' str << '<c:strRef>' - str << '<c:f>' << Axlsx::cell_range([@cell]) << '</c:f>' + str << ('<c:f>' << Axlsx::cell_range([@cell]) << '</c:f>') str << '<c:strCache>' str << '<c:ptCount val="1"/>' str << '<c:pt idx="0">' - str << '<c:v>' << @text << '</c:v>' + str << ('<c:v>' << @text << '</c:v>') str << '</c:pt>' str << '</c:strCache>' str << '</c:strRef>' diff --git a/lib/axlsx/drawing/str_data.rb b/lib/axlsx/drawing/str_data.rb index 9965ec1d..4da69ec0 100644 --- a/lib/axlsx/drawing/str_data.rb +++ b/lib/axlsx/drawing/str_data.rb @@ -29,12 +29,12 @@ module Axlsx # serialize the object def to_xml_string(str = "") - str << '<c:' << @tag_name.to_s << '>' - str << '<c:ptCount val="' << @pt.size.to_s << '"/>' + str << ('<c:' << @tag_name.to_s << '>') + str << ('<c:ptCount val="' << @pt.size.to_s << '"/>') @pt.each_with_index do |value, index| value.to_xml_string index, str end - str << '</c:' << @tag_name.to_s << '>' + str << ('</c:' << @tag_name.to_s << '>') end end diff --git a/lib/axlsx/drawing/str_val.rb b/lib/axlsx/drawing/str_val.rb index 68cee270..b0692784 100644 --- a/lib/axlsx/drawing/str_val.rb +++ b/lib/axlsx/drawing/str_val.rb @@ -26,7 +26,7 @@ module Axlsx # serialize the object def to_xml_string(idx, str = "") Axlsx::validate_unsigned_int(idx) - str << '<c:pt idx="' << idx.to_s << '"><c:v>' << v.to_s << '</c:v></c:pt>' + str << ('<c:pt idx="' << idx.to_s << '"><c:v>' << v.to_s << '</c:v></c:pt>') end end end diff --git a/lib/axlsx/drawing/title.rb b/lib/axlsx/drawing/title.rb index 5292a177..4e278689 100644 --- a/lib/axlsx/drawing/title.rb +++ b/lib/axlsx/drawing/title.rb @@ -48,11 +48,11 @@ module Axlsx str << '<c:tx>' if @cell.is_a?(Cell) str << '<c:strRef>' - str << '<c:f>' << Axlsx::cell_range([@cell]) << '</c:f>' + str << ('<c:f>' << Axlsx::cell_range([@cell]) << '</c:f>') str << '<c:strCache>' str << '<c:ptCount val="1"/>' str << '<c:pt idx="0">' - str << '<c:v>' << @text << '</c:v>' + str << ('<c:v>' << @text << '</c:v>') str << '</c:pt>' str << '</c:strCache>' str << '</c:strRef>' @@ -62,7 +62,7 @@ module Axlsx str << '<a:lstStyle/>' str << '<a:p>' str << '<a:r>' - str << '<a:t>' << @text.to_s << '</a:t>' + str << ('<a:t>' << @text.to_s << '</a:t>') str << '</a:r>' str << '</a:p>' str << '</c:rich>' diff --git a/lib/axlsx/drawing/val_axis.rb b/lib/axlsx/drawing/val_axis.rb index 0e7a0800..430cf70f 100644 --- a/lib/axlsx/drawing/val_axis.rb +++ b/lib/axlsx/drawing/val_axis.rb @@ -29,7 +29,7 @@ module Axlsx def to_xml_string(str = '') str << '<c:valAx>' super(str) - str << '<c:crossBetween val="' << @cross_between.to_s << '"/>' + str << ('<c:crossBetween val="' << @cross_between.to_s << '"/>') str << '</c:valAx>' end diff --git a/lib/axlsx/drawing/vml_drawing.rb b/lib/axlsx/drawing/vml_drawing.rb index 39358a6c..ac39c63d 100644 --- a/lib/axlsx/drawing/vml_drawing.rb +++ b/lib/axlsx/drawing/vml_drawing.rb @@ -20,7 +20,7 @@ module Axlsx # @param [String] str # @return [String] def to_xml_string(str = '') - str = <<BAD_PROGRAMMER + str << <<BAD_PROGRAMMER <xml xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel"> diff --git a/lib/axlsx/package.rb b/lib/axlsx/package.rb index 6cc72a09..bbc15db3 100644 --- a/lib/axlsx/package.rb +++ b/lib/axlsx/package.rb @@ -22,7 +22,7 @@ module Axlsx # @example Package.new :author => 'you!', :workbook => Workbook.new def initialize(options={}) @workbook = nil - @core, @app = Core.new, App.new + @core, @app = Core.new, App.new @core.creator = options[:author] || @core.creator @core.created = options[:created_at] parse_options options @@ -76,7 +76,7 @@ module Axlsx #end # @see workbook - def workbook=(workbook) DataTypeValidator.validate "Package.workbook", Workbook, workbook; @workbook = workbook; end + def workbook=(workbook) DataTypeValidator.validate :Package_workbook, Workbook, workbook; @workbook = workbook; end # Serialize your workbook to disk as an xlsx document. # @@ -146,7 +146,13 @@ module Axlsx def validate errors = [] parts.each do |part| - errors.concat validate_single_doc(part[:schema], part[:doc]) unless part[:schema].nil? + unless part[:schema].nil? + if part[:doc].is_a? String + errors.concat validate_single_doc(part[:schema], part[:doc]) + else + errors.concat validate_single_doc(part[:schema], part[:doc].to_xml_string) + end + end end errors end @@ -159,10 +165,15 @@ module Axlsx def write_parts(zip) p = parts p.each do |part| + #next unless part[:entry] == CORE_PN unless part[:doc].nil? zip.put_next_entry(zip_entry_for_part(part)) - entry = ['1.9.2', '1.9.3'].include?(RUBY_VERSION) ? part[:doc].force_encoding('BINARY') : part[:doc] - zip.puts(entry) + if part[:doc].is_a? String + entry = ['1.9.2', '1.9.3'].include?(RUBY_VERSION) ? part[:doc].force_encoding('BINARY') : part[:doc] + zip.puts(entry) + else + part[:doc].to_xml_string(zip) + end end unless part[:path].nil? zip.put_next_entry(zip_entry_for_part(part)) @@ -194,40 +205,40 @@ module Axlsx # @private def parts parts = [ - {:entry => RELS_PN, :doc => relationships.to_xml_string, :schema => RELS_XSD}, - {:entry => "xl/#{STYLES_PN}", :doc => workbook.styles.to_xml_string, :schema => SML_XSD}, - {:entry => CORE_PN, :doc => @core.to_xml_string, :schema => CORE_XSD}, - {:entry => APP_PN, :doc => @app.to_xml_string, :schema => APP_XSD}, - {:entry => WORKBOOK_RELS_PN, :doc => workbook.relationships.to_xml_string, :schema => RELS_XSD}, - {:entry => CONTENT_TYPES_PN, :doc => content_types.to_xml_string, :schema => CONTENT_TYPES_XSD}, - {:entry => WORKBOOK_PN, :doc => workbook.to_xml_string, :schema => SML_XSD} + {:entry => RELS_PN, :doc => relationships, :schema => RELS_XSD}, + {:entry => "xl/#{STYLES_PN}", :doc => workbook.styles, :schema => SML_XSD}, + {:entry => CORE_PN, :doc => @core, :schema => CORE_XSD}, + {:entry => APP_PN, :doc => @app, :schema => APP_XSD}, + {:entry => WORKBOOK_RELS_PN, :doc => workbook.relationships, :schema => RELS_XSD}, + {:entry => CONTENT_TYPES_PN, :doc => content_types, :schema => CONTENT_TYPES_XSD}, + {:entry => WORKBOOK_PN, :doc => workbook, :schema => SML_XSD} ] workbook.drawings.each do |drawing| - parts << {:entry => "xl/#{drawing.rels_pn}", :doc => drawing.relationships.to_xml_string, :schema => RELS_XSD} - parts << {:entry => "xl/#{drawing.pn}", :doc => drawing.to_xml_string, :schema => DRAWING_XSD} + parts << {:entry => "xl/#{drawing.rels_pn}", :doc => drawing.relationships, :schema => RELS_XSD} + parts << {:entry => "xl/#{drawing.pn}", :doc => drawing, :schema => DRAWING_XSD} end workbook.tables.each do |table| - parts << {:entry => "xl/#{table.pn}", :doc => table.to_xml_string, :schema => SML_XSD} + parts << {:entry => "xl/#{table.pn}", :doc => table, :schema => SML_XSD} end workbook.pivot_tables.each do |pivot_table| cache_definition = pivot_table.cache_definition - parts << {:entry => "xl/#{pivot_table.rels_pn}", :doc => pivot_table.relationships.to_xml_string, :schema => RELS_XSD} - parts << {:entry => "xl/#{pivot_table.pn}", :doc => pivot_table.to_xml_string} #, :schema => SML_XSD} - parts << {:entry => "xl/#{cache_definition.pn}", :doc => cache_definition.to_xml_string} #, :schema => SML_XSD} + parts << {:entry => "xl/#{pivot_table.rels_pn}", :doc => pivot_table.relationships, :schema => RELS_XSD} + parts << {:entry => "xl/#{pivot_table.pn}", :doc => pivot_table} #, :schema => SML_XSD} + parts << {:entry => "xl/#{cache_definition.pn}", :doc => cache_definition} #, :schema => SML_XSD} end workbook.comments.each do|comment| if comment.size > 0 - parts << { :entry => "xl/#{comment.pn}", :doc => comment.to_xml_string, :schema => SML_XSD } - parts << { :entry => "xl/#{comment.vml_drawing.pn}", :doc => comment.vml_drawing.to_xml_string, :schema => nil } + parts << { :entry => "xl/#{comment.pn}", :doc => comment, :schema => SML_XSD } + parts << { :entry => "xl/#{comment.vml_drawing.pn}", :doc => comment.vml_drawing, :schema => nil } end end workbook.charts.each do |chart| - parts << {:entry => "xl/#{chart.pn}", :doc => chart.to_xml_string, :schema => DRAWING_XSD} + parts << {:entry => "xl/#{chart.pn}", :doc => chart, :schema => DRAWING_XSD} end workbook.images.each do |image| @@ -235,12 +246,12 @@ module Axlsx end if use_shared_strings - parts << {:entry => "xl/#{SHARED_STRINGS_PN}", :doc => workbook.shared_strings.to_xml_string, :schema => SML_XSD} + parts << {:entry => "xl/#{SHARED_STRINGS_PN}", :doc => workbook.shared_strings, :schema => SML_XSD} end workbook.worksheets.each do |sheet| - parts << {:entry => "xl/#{sheet.rels_pn}", :doc => sheet.relationships.to_xml_string, :schema => RELS_XSD} - parts << {:entry => "xl/#{sheet.pn}", :doc => sheet.to_xml_string, :schema => SML_XSD} + parts << {:entry => "xl/#{sheet.rels_pn}", :doc => sheet.relationships, :schema => RELS_XSD} + parts << {:entry => "xl/#{sheet.pn}", :doc => sheet, :schema => SML_XSD} end parts end @@ -326,8 +337,8 @@ module Axlsx # @private def base_content_types c_types = ContentType.new() - c_types << Default.new(:ContentType => RELS_CT, :Extension => RELS_EX) - c_types << Default.new(:Extension => XML_EX, :ContentType => XML_CT) + c_types << Default.new(:ContentType => RELS_CT, :Extension => RELS_EX) + c_types << Default.new(:Extension => XML_EX, :ContentType => XML_CT) c_types << Override.new(:PartName => "/#{APP_PN}", :ContentType => APP_CT) c_types << Override.new(:PartName => "/#{CORE_PN}", :ContentType => CORE_CT) c_types << Override.new(:PartName => "/xl/#{STYLES_PN}", :ContentType => STYLES_CT) diff --git a/lib/axlsx/rels/relationship.rb b/lib/axlsx/rels/relationship.rb index a6b7bdd2..99dad367 100644 --- a/lib/axlsx/rels/relationship.rb +++ b/lib/axlsx/rels/relationship.rb @@ -102,7 +102,7 @@ module Axlsx def to_xml_string(str = '') h = self.instance_values.reject{|k, _| k == "source_obj"} str << '<Relationship ' - str << h.map { |key, value| '' << key.to_s << '="' << Axlsx::coder.encode(value.to_s) << '"'}.join(' ') + str << (h.map { |key, value| '' << key.to_s << '="' << Axlsx::coder.encode(value.to_s) << '"'}.join(' ')) str << '/>' end diff --git a/lib/axlsx/rels/relationships.rb b/lib/axlsx/rels/relationships.rb index a9c73f7d..b855abcd 100644 --- a/lib/axlsx/rels/relationships.rb +++ b/lib/axlsx/rels/relationships.rb @@ -15,12 +15,12 @@ require 'axlsx/rels/relationship.rb' # @see Relationship#source_obj # @return [Relationship] def for(source_obj) - @list.find{ |rel| rel.source_obj == source_obj } + find{ |rel| rel.source_obj == source_obj } end def to_xml_string(str = '') str << '<?xml version="1.0" encoding="UTF-8"?>' - str << '<Relationships xmlns="' << RELS_R << '">' + str << ('<Relationships xmlns="' << RELS_R << '">') each{ |rel| rel.to_xml_string(str) } str << '</Relationships>' end diff --git a/lib/axlsx/stylesheet/border_pr.rb b/lib/axlsx/stylesheet/border_pr.rb index 12b20d09..cba0e475 100644 --- a/lib/axlsx/stylesheet/border_pr.rb +++ b/lib/axlsx/stylesheet/border_pr.rb @@ -62,9 +62,9 @@ module Axlsx # @param [String] str # @return [String] def to_xml_string(str = '') - str << '<' << @name.to_s << ' style="' << @style.to_s << '">' + str << ('<' << @name.to_s << ' style="' << @style.to_s << '">') @color.to_xml_string(str) if @color.is_a?(Color) - str << '</' << @name.to_s << '>' + str << ('</' << @name.to_s << '>') end end diff --git a/lib/axlsx/stylesheet/cell_alignment.rb b/lib/axlsx/stylesheet/cell_alignment.rb index 95f171df..715a0b3e 100644 --- a/lib/axlsx/stylesheet/cell_alignment.rb +++ b/lib/axlsx/stylesheet/cell_alignment.rb @@ -125,9 +125,7 @@ module Axlsx # @param [String] str # @return [String] def to_xml_string(str = '') - str << '<alignment ' - serialized_attributes str - str << '/>' + serialized_tag('alignment', str) end end diff --git a/lib/axlsx/stylesheet/cell_protection.rb b/lib/axlsx/stylesheet/cell_protection.rb index 9f8093ae..ac32cb96 100644 --- a/lib/axlsx/stylesheet/cell_protection.rb +++ b/lib/axlsx/stylesheet/cell_protection.rb @@ -34,9 +34,7 @@ module Axlsx # @param [String] str # @return [String] def to_xml_string(str = '') - str << '<protection ' - serialized_attributes str - str << '/>' + serialized_tag('protection', str) end end diff --git a/lib/axlsx/stylesheet/cell_style.rb b/lib/axlsx/stylesheet/cell_style.rb index 202c0cc2..2e8da880 100644 --- a/lib/axlsx/stylesheet/cell_style.rb +++ b/lib/axlsx/stylesheet/cell_style.rb @@ -64,9 +64,7 @@ module Axlsx # @param [String] str # @return [String] def to_xml_string(str = '') - str << '<cellStyle ' - serialized_attributes str - str << '/>' + serialized_tag('cellStyle', str) end end diff --git a/lib/axlsx/stylesheet/color.rb b/lib/axlsx/stylesheet/color.rb index e736af7f..2b6c126f 100644 --- a/lib/axlsx/stylesheet/color.rb +++ b/lib/axlsx/stylesheet/color.rb @@ -70,9 +70,7 @@ module Axlsx # @param [String] str # @return [String] def to_xml_string(str = '', tag_name = 'color') - str << "<" << tag_name << " " - serialized_attributes str - str << "/>" + serialized_tag('' + tag_name + '', str) end end end diff --git a/lib/axlsx/stylesheet/font.rb b/lib/axlsx/stylesheet/font.rb index 03da52e5..6d77d58b 100644 --- a/lib/axlsx/stylesheet/font.rb +++ b/lib/axlsx/stylesheet/font.rb @@ -140,7 +140,7 @@ module Axlsx def to_xml_string(str = '') str << '<font>' instance_values.each do |k, v| - v.is_a?(Color) ? v.to_xml_string(str) : (str << '<' << k.to_s << ' val="' << v.to_s << '"/>') + v.is_a?(Color) ? v.to_xml_string(str) : (str << ('<' << k.to_s << ' val="' << v.to_s << '"/>')) end str << '</font>' end diff --git a/lib/axlsx/stylesheet/gradient_stop.rb b/lib/axlsx/stylesheet/gradient_stop.rb index 94ca4795..a76da6a6 100644 --- a/lib/axlsx/stylesheet/gradient_stop.rb +++ b/lib/axlsx/stylesheet/gradient_stop.rb @@ -29,7 +29,7 @@ module Axlsx # @param [String] str # @return [String] def to_xml_string(str = '') - str << '<stop position="' << position.to_s << '">' + str << ('<stop position="' << position.to_s << '">') self.color.to_xml_string(str) str << '</stop>' end diff --git a/lib/axlsx/stylesheet/num_fmt.rb b/lib/axlsx/stylesheet/num_fmt.rb index 7016c989..8276ba18 100644 --- a/lib/axlsx/stylesheet/num_fmt.rb +++ b/lib/axlsx/stylesheet/num_fmt.rb @@ -70,9 +70,7 @@ module Axlsx # @param [String] str # @return [String] def to_xml_string(str = '') - str << '<numFmt ' - serialized_attributes str - str << '/>' + serialized_tag('numFmt', str) end end diff --git a/lib/axlsx/stylesheet/pattern_fill.rb b/lib/axlsx/stylesheet/pattern_fill.rb index 504624e6..059f15bb 100644 --- a/lib/axlsx/stylesheet/pattern_fill.rb +++ b/lib/axlsx/stylesheet/pattern_fill.rb @@ -59,7 +59,7 @@ module Axlsx # @param [String] str # @return [String] def to_xml_string(str = '') - str << '<patternFill patternType="' << patternType.to_s << '">' + str << ('<patternFill patternType="' << patternType.to_s << '">') if fgColor.is_a?(Color) fgColor.to_xml_string str, "fgColor" end diff --git a/lib/axlsx/stylesheet/styles.rb b/lib/axlsx/stylesheet/styles.rb index 7970e0c1..c7283324 100644 --- a/lib/axlsx/stylesheet/styles.rb +++ b/lib/axlsx/stylesheet/styles.rb @@ -362,7 +362,7 @@ module Axlsx # @param [String] str # @return [String] def to_xml_string(str = '') - str << '<styleSheet xmlns="' << XML_NS << '">' + str << ('<styleSheet xmlns="' << XML_NS << '">') [:numFmts, :fonts, :fills, :borders, :cellStyleXfs, :cellXfs, :cellStyles, :dxfs, :tableStyles].each do |key| self.instance_values[key.to_s].to_xml_string(str) unless self.instance_values[key.to_s].nil? end diff --git a/lib/axlsx/stylesheet/table_style_element.rb b/lib/axlsx/stylesheet/table_style_element.rb index 2ffc8af1..593c5950 100644 --- a/lib/axlsx/stylesheet/table_style_element.rb +++ b/lib/axlsx/stylesheet/table_style_element.rb @@ -70,9 +70,7 @@ module Axlsx # @param [String] str # @return [String] def to_xml_string(str = '') - str << '<tableStyleElement ' - serialized_attributes str - str << '/>' + serialized_tag('tableStyleElement', str) end end diff --git a/lib/axlsx/util/accessors.rb b/lib/axlsx/util/accessors.rb index a33fdccc..a678b041 100644 --- a/lib/axlsx/util/accessors.rb +++ b/lib/axlsx/util/accessors.rb @@ -19,7 +19,7 @@ module Axlsx # @param [Array] symbols An array of symbols representing the # names of the attributes you will add to your class. def string_attr_accessor(*symbols) - validated_attr_accessor(symbols, 'validate_string') + validated_attr_accessor(symbols, :validate_string) end @@ -27,25 +27,25 @@ module Axlsx # @param [Array] symbols An array of symbols representing the # names of the attributes you will add to your class def unsigned_int_attr_accessor(*symbols) - validated_attr_accessor(symbols, 'validate_unsigned_int') + validated_attr_accessor(symbols, :validate_unsigned_int) end # Creates one or more float (double?) attr_accessors # @param [Array] symbols An array of symbols representing the # names of the attributes you will add to your class def float_attr_accessor(*symbols) - validated_attr_accessor(symbols, 'validate_float') + validated_attr_accessor(symbols, :validate_float) end # Creates on or more boolean validated attr_accessors # @param [Array] symbols An array of symbols representing the # names of the attributes you will add to your class. def boolean_attr_accessor(*symbols) - validated_attr_accessor(symbols, 'validate_boolean') + validated_attr_accessor(symbols, :validate_boolean) end # Template for defining validated write accessors - SETTER = "def %s=(value) Axlsx::%s(value); @%s = value; end" + SETTER = "def %s=(value) Axlsx::%s(value); @%s = value; end".freeze # Creates the reader and writer access methods # @param [Array] symbols The names of the attributes to create @@ -55,7 +55,7 @@ module Axlsx def validated_attr_accessor(symbols, validator) symbols.each do |symbol| attr_reader symbol - module_eval(SETTER % [symbol.to_s, validator, symbol.to_s], __FILE__, __LINE__) + module_eval(SETTER % [symbol, validator, symbol], __FILE__, __LINE__) end end end diff --git a/lib/axlsx/util/constants.rb b/lib/axlsx/util/constants.rb index d3e0ad5c..ea9b1ceb 100644 --- a/lib/axlsx/util/constants.rb +++ b/lib/axlsx/util/constants.rb @@ -1,263 +1,263 @@ module Axlsx # XML Encoding - ENCODING = "UTF-8" + ENCODING = "UTF-8".freeze # spreadsheetML namespace - XML_NS = "http://schemas.openxmlformats.org/spreadsheetml/2006/main" + XML_NS = "http://schemas.openxmlformats.org/spreadsheetml/2006/main".freeze # content-types namespace - XML_NS_T = "http://schemas.openxmlformats.org/package/2006/content-types" + XML_NS_T = "http://schemas.openxmlformats.org/package/2006/content-types".freeze # extended-properties namespace - APP_NS = "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties" + APP_NS = "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties".freeze # doc props namespace - APP_NS_VT = "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes" + APP_NS_VT = "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes".freeze # core properties namespace - CORE_NS = "http://schemas.openxmlformats.org/package/2006/metadata/core-properties" + CORE_NS = "http://schemas.openxmlformats.org/package/2006/metadata/core-properties".freeze # dc elements (core) namespace - CORE_NS_DC = "http://purl.org/dc/elements/1.1/" + CORE_NS_DC = "http://purl.org/dc/elements/1.1/".freeze # dcmit (core) namespcace - CORE_NS_DCMIT = "http://purl.org/dc/dcmitype/" + CORE_NS_DCMIT = "http://purl.org/dc/dcmitype/".freeze # dc terms namespace - CORE_NS_DCT = "http://purl.org/dc/terms/" + CORE_NS_DCT = "http://purl.org/dc/terms/".freeze # xml schema namespace - CORE_NS_XSI = "http://www.w3.org/2001/XMLSchema-instance" + CORE_NS_XSI = "http://www.w3.org/2001/XMLSchema-instance".freeze # Digital signature namespace - DIGITAL_SIGNATURE_NS = "http://schemas.openxmlformats.org/package/2006/digital-signature" + DIGITAL_SIGNATURE_NS = "http://schemas.openxmlformats.org/package/2006/digital-signature".freeze # spreadsheet drawing namespace - XML_NS_XDR = "http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing" + XML_NS_XDR = "http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing".freeze # drawing namespace - XML_NS_A = "http://schemas.openxmlformats.org/drawingml/2006/main" + XML_NS_A = "http://schemas.openxmlformats.org/drawingml/2006/main".freeze # chart namespace - XML_NS_C = "http://schemas.openxmlformats.org/drawingml/2006/chart" + XML_NS_C = "http://schemas.openxmlformats.org/drawingml/2006/chart".freeze # relationships namespace - XML_NS_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships" + XML_NS_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships".freeze # relationships name space - RELS_R = "http://schemas.openxmlformats.org/package/2006/relationships" + RELS_R = "http://schemas.openxmlformats.org/package/2006/relationships".freeze # table rels namespace - TABLE_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/table" + TABLE_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/table".freeze # pivot table rels namespace - PIVOT_TABLE_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotTable" + PIVOT_TABLE_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotTable".freeze # pivot table cache definition namespace - PIVOT_TABLE_CACHE_DEFINITION_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotCacheDefinition" + PIVOT_TABLE_CACHE_DEFINITION_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/pivotCacheDefinition".freeze # workbook rels namespace - WORKBOOK_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" + WORKBOOK_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument".freeze # worksheet rels namespace - WORKSHEET_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" + WORKSHEET_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet".freeze # app rels namespace - APP_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" + APP_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties".freeze # core rels namespace - CORE_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/metadata/core-properties" + CORE_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/metadata/core-properties".freeze # digital signature rels namespace - DIGITAL_SIGNATURE_R = "http://schemas.openxmlformats.org/package/2006/relationships/digital- signature/signature" + DIGITAL_SIGNATURE_R = "http://schemas.openxmlformats.org/package/2006/relationships/digital- signature/signature".freeze # styles rels namespace - STYLES_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" + STYLES_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles".freeze # shared strings namespace - SHARED_STRINGS_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings" + SHARED_STRINGS_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings".freeze # drawing rels namespace - DRAWING_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing" + DRAWING_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing".freeze # chart rels namespace - CHART_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart" + CHART_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart".freeze # image rels namespace - IMAGE_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" + IMAGE_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image".freeze # hyperlink rels namespace - HYPERLINK_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink" + HYPERLINK_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink".freeze # comment rels namespace - COMMENT_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments" + COMMENT_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments".freeze # comment relation for nil target - COMMENT_R_NULL = "http://purl.oclc.org/ooxml/officeDocument/relationships/comments" + COMMENT_R_NULL = "http://purl.oclc.org/ooxml/officeDocument/relationships/comments".freeze #vml drawing relation namespace VML_DRAWING_R = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing' # VML Drawing content type - VML_DRAWING_CT = "application/vnd.openxmlformats-officedocument.vmlDrawing" + VML_DRAWING_CT = "application/vnd.openxmlformats-officedocument.vmlDrawing".freeze # table content type - TABLE_CT = "application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml" + TABLE_CT = "application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml".freeze # pivot table content type - PIVOT_TABLE_CT = "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotTable+xml" + PIVOT_TABLE_CT = "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotTable+xml".freeze # pivot table cache definition content type - PIVOT_TABLE_CACHE_DEFINITION_CT = "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheDefinition+xml" + PIVOT_TABLE_CACHE_DEFINITION_CT = "application/vnd.openxmlformats-officedocument.spreadsheetml.pivotCacheDefinition+xml".freeze # workbook content type - WORKBOOK_CT = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml" + WORKBOOK_CT = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml".freeze # app content type - APP_CT = "application/vnd.openxmlformats-officedocument.extended-properties+xml" + APP_CT = "application/vnd.openxmlformats-officedocument.extended-properties+xml".freeze # rels content type - RELS_CT = "application/vnd.openxmlformats-package.relationships+xml" + RELS_CT = "application/vnd.openxmlformats-package.relationships+xml".freeze # styles content type - STYLES_CT = "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml" + STYLES_CT = "application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml".freeze # xml content type - XML_CT = "application/xml" + XML_CT = "application/xml".freeze # worksheet content type - WORKSHEET_CT = "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml" + WORKSHEET_CT = "application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml".freeze # shared strings content type - SHARED_STRINGS_CT = "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml" + SHARED_STRINGS_CT = "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml".freeze # core content type - CORE_CT = "application/vnd.openxmlformats-package.core-properties+xml" + CORE_CT = "application/vnd.openxmlformats-package.core-properties+xml".freeze # digital signature xml content type - DIGITAL_SIGNATURE_XML_CT = "application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml" + DIGITAL_SIGNATURE_XML_CT = "application/vnd.openxmlformats-package.digital-signature-xmlsignature+xml".freeze # digital signature origin content type - DIGITAL_SIGNATURE_ORIGIN_CT = "application/vnd.openxmlformats-package.digital-signature-origin" + DIGITAL_SIGNATURE_ORIGIN_CT = "application/vnd.openxmlformats-package.digital-signature-origin".freeze # digital signature certificate content type - DIGITAL_SIGNATURE_CERTIFICATE_CT = "application/vnd.openxmlformats-package.digital-signature-certificate" + DIGITAL_SIGNATURE_CERTIFICATE_CT = "application/vnd.openxmlformats-package.digital-signature-certificate".freeze # chart content type - CHART_CT = "application/vnd.openxmlformats-officedocument.drawingml.chart+xml" + CHART_CT = "application/vnd.openxmlformats-officedocument.drawingml.chart+xml".freeze # comments content type - COMMENT_CT = "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml" + COMMENT_CT = "application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml".freeze # jpeg content type - JPEG_CT = "image/jpeg" + JPEG_CT = "image/jpeg".freeze # gif content type - GIF_CT = "image/gif" + GIF_CT = "image/gif".freeze # png content type - PNG_CT = "image/png" + PNG_CT = "image/png".freeze #drawing content type - DRAWING_CT = "application/vnd.openxmlformats-officedocument.drawing+xml" + DRAWING_CT = "application/vnd.openxmlformats-officedocument.drawing+xml".freeze # xml content type extensions - XML_EX = "xml" + XML_EX = "xml".freeze # jpeg extension - JPEG_EX = "jpeg" + JPEG_EX = "jpeg".freeze # gif extension - GIF_EX = "gif" + GIF_EX = "gif".freeze # png extension - PNG_EX = "png" + PNG_EX = "png".freeze # rels content type extension - RELS_EX = "rels" + RELS_EX = "rels".freeze # workbook part - WORKBOOK_PN = "xl/workbook.xml" + WORKBOOK_PN = "xl/workbook.xml".freeze # styles part - STYLES_PN = "styles.xml" + STYLES_PN = "styles.xml".freeze # shared_strings part - SHARED_STRINGS_PN = "sharedStrings.xml" + SHARED_STRINGS_PN = "sharedStrings.xml".freeze # app part - APP_PN = "docProps/app.xml" + APP_PN = "docProps/app.xml".freeze # core part - CORE_PN = "docProps/core.xml" + CORE_PN = "docProps/core.xml".freeze # content types part - CONTENT_TYPES_PN = "[Content_Types].xml" + CONTENT_TYPES_PN = "[Content_Types].xml".freeze # rels part - RELS_PN = "_rels/.rels" + RELS_PN = "_rels/.rels".freeze # workbook rels part - WORKBOOK_RELS_PN = "xl/_rels/workbook.xml.rels" + WORKBOOK_RELS_PN = "xl/_rels/workbook.xml.rels".freeze # worksheet part - WORKSHEET_PN = "worksheets/sheet%d.xml" + WORKSHEET_PN = "worksheets/sheet%d.xml".freeze # worksheet rels part - WORKSHEET_RELS_PN = "worksheets/_rels/sheet%d.xml.rels" + WORKSHEET_RELS_PN = "worksheets/_rels/sheet%d.xml.rels".freeze # drawing part - DRAWING_PN = "drawings/drawing%d.xml" + DRAWING_PN = "drawings/drawing%d.xml".freeze # drawing rels part - DRAWING_RELS_PN = "drawings/_rels/drawing%d.xml.rels" + DRAWING_RELS_PN = "drawings/_rels/drawing%d.xml.rels".freeze # vml drawing part - VML_DRAWING_PN = "drawings/vmlDrawing%d.vml" + VML_DRAWING_PN = "drawings/vmlDrawing%d.vml".freeze # drawing part - TABLE_PN = "tables/table%d.xml" + TABLE_PN = "tables/table%d.xml".freeze # pivot table parts - PIVOT_TABLE_PN = "pivotTables/pivotTable%d.xml" + PIVOT_TABLE_PN = "pivotTables/pivotTable%d.xml".freeze # pivot table cache definition part name - PIVOT_TABLE_CACHE_DEFINITION_PN = "pivotCache/pivotCacheDefinition%d.xml" + PIVOT_TABLE_CACHE_DEFINITION_PN = "pivotCache/pivotCacheDefinition%d.xml".freeze # pivot table rels parts - PIVOT_TABLE_RELS_PN = "pivotTables/_rels/pivotTable%d.xml.rels" + PIVOT_TABLE_RELS_PN = "pivotTables/_rels/pivotTable%d.xml.rels".freeze # chart part - CHART_PN = "charts/chart%d.xml" + CHART_PN = "charts/chart%d.xml".freeze # chart part - IMAGE_PN = "media/image%d.%s" + IMAGE_PN = "media/image%d.%s".freeze # comment part - COMMENT_PN = "comments%d.xml" + COMMENT_PN = "comments%d.xml".freeze # location of schema files for validation - SCHEMA_BASE = File.dirname(__FILE__)+'/../../schema/' + SCHEMA_BASE = (File.dirname(__FILE__)+'/../../schema/').freeze # App validation schema - APP_XSD = SCHEMA_BASE + "shared-documentPropertiesExtended.xsd" + APP_XSD = (SCHEMA_BASE + "shared-documentPropertiesExtended.xsd").freeze # core validation schema - CORE_XSD = SCHEMA_BASE + "opc-coreProperties.xsd" + CORE_XSD = (SCHEMA_BASE + "opc-coreProperties.xsd").freeze # content types validation schema - CONTENT_TYPES_XSD = SCHEMA_BASE + "opc-contentTypes.xsd" + CONTENT_TYPES_XSD = (SCHEMA_BASE + "opc-contentTypes.xsd").freeze # rels validation schema - RELS_XSD = SCHEMA_BASE + "opc-relationships.xsd" + RELS_XSD = (SCHEMA_BASE + "opc-relationships.xsd").freeze # spreadsheetML validation schema - SML_XSD = SCHEMA_BASE + "sml.xsd" + SML_XSD = (SCHEMA_BASE + "sml.xsd").freeze # drawing validation schema - DRAWING_XSD = SCHEMA_BASE + "dml-spreadsheetDrawing.xsd" + DRAWING_XSD = (SCHEMA_BASE + "dml-spreadsheetDrawing.xsd").freeze # number format id for pecentage formatting using the default formatting id. NUM_FMT_PERCENT = 9 @@ -275,37 +275,37 @@ module Axlsx STYLE_DATE = 2 # error messages RestrictionValidor - ERR_RESTRICTION = "Invalid Data: %s. %s must be one of %s." + ERR_RESTRICTION = "Invalid Data: %s. %s must be one of %s.".freeze # error message DataTypeValidator - ERR_TYPE = "Invalid Data %s for %s. must be %s." + ERR_TYPE = "Invalid Data %s for %s. must be %s.".freeze # error message for RegexValidator - ERR_REGEX = "Invalid Data. %s does not match %s." + ERR_REGEX = "Invalid Data. %s does not match %s.".freeze # error message for RangeValidator - ERR_RANGE = "Invalid Data. %s must be between %s and %s, (inclusive:%s) you gave: %s" + ERR_RANGE = "Invalid Data. %s must be between %s and %s, (inclusive:%s) you gave: %s".freeze # error message for sheets that use a name which is longer than 31 bytes - ERR_SHEET_NAME_TOO_LONG = "Your worksheet name '%s' is too long. Worksheet names must be 31 characters (bytes) or less" + ERR_SHEET_NAME_TOO_LONG = "Your worksheet name '%s' is too long. Worksheet names must be 31 characters (bytes) or less".freeze # error message for sheets that use a name which include invalid characters - ERR_SHEET_NAME_CHARACTER_FORBIDDEN = "Your worksheet name '%s' contains a character which is not allowed by MS Excel and will cause repair warnings. Please change the name of your sheet." + ERR_SHEET_NAME_CHARACTER_FORBIDDEN = "Your worksheet name '%s' contains a character which is not allowed by MS Excel and will cause repair warnings. Please change the name of your sheet.".freeze # error message for duplicate sheet names - ERR_DUPLICATE_SHEET_NAME = "There is already a worksheet in this workbook named '%s'. Please use a unique name" + ERR_DUPLICATE_SHEET_NAME = "There is already a worksheet in this workbook named '%s'. Please use a unique name".freeze # error message when user does not provide color and or style options for border in Style#add_sytle - ERR_INVALID_BORDER_OPTIONS = "border hash must include both style and color. e.g. :border => { :color => 'FF000000', :style => :thin }. You provided: %s" + ERR_INVALID_BORDER_OPTIONS = "border hash must include both style and color. e.g. :border => { :color => 'FF000000', :style => :thin }. You provided: %s".freeze # error message for invalid border id reference - ERR_INVALID_BORDER_ID = "The border id you specified (%s) does not exist. Please add a border with Style#add_style before referencing its index." + ERR_INVALID_BORDER_ID = "The border id you specified (%s) does not exist. Please add a border with Style#add_style before referencing its index.".freeze # error message for invalid angles - ERR_ANGLE = "Angles must be a value between -90 and 90. You provided: %s" + ERR_ANGLE = "Angles must be a value between -90 and 90. You provided: %s".freeze # error message for non 'integerish' value - ERR_INTEGERISH = "You value must be, or be castable via to_i, an Integer. You provided %s" + ERR_INTEGERISH = "You value must be, or be castable via to_i, an Integer. You provided %s".freeze # Regex to match forbidden control characters # The following will be automatically stripped from worksheets. @@ -383,10 +383,15 @@ module Axlsx # x0D Carriage Return (Cr) # x09 Character Tabulation # @see http://www.codetable.net/asciikeycodes - pattern = "[\x0-\x08\x0B\x0C\x0E-\x1F]" - pattern= pattern.respond_to?(:encode) ? pattern.encode('UTF-8') : pattern - + pattern = "\x0-\x08\x0B\x0C\x0E-\x1F" + pattern = pattern.respond_to?(:encode) ? pattern.encode('UTF-8') : pattern + # The regular expression used to remove control characters from worksheets - CONTROL_CHAR_REGEX = Regexp.new(pattern, 'n') - + CONTROL_CHARS = pattern.freeze + + 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 + + FLOAT_REGEX = /\A[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?\Z/.freeze + + NUMERIC_REGEX = /\A[+-]?\d+?\Z/.freeze end diff --git a/lib/axlsx/util/options_parser.rb b/lib/axlsx/util/options_parser.rb index 07dd128b..9b6d1766 100644 --- a/lib/axlsx/util/options_parser.rb +++ b/lib/axlsx/util/options_parser.rb @@ -8,7 +8,8 @@ module Axlsx # @param [Hash] options Options to parse. def parse_options(options={}) options.each do |key, value| - self.send("#{key}=", value) if self.respond_to?("#{key}=") && value != nil + key = :"#{key}=" + self.send(key, value) if !value.nil? && self.respond_to?(key) end end end diff --git a/lib/axlsx/util/parser.rb b/lib/axlsx/util/parser.rb index 7719a6d1..78b819bd 100644 --- a/lib/axlsx/util/parser.rb +++ b/lib/axlsx/util/parser.rb @@ -9,28 +9,28 @@ module Axlsx # parse and assign string attribute def parse_string attr_name, xpath - send("#{attr_name.to_s}=", parse_value(xpath)) + send("#{attr_name}=", parse_value(xpath)) end # parse convert and assign node text to symbol def parse_symbol attr_name, xpath v = parse_value xpath v = v.to_sym unless v.nil? - send("#{attr_name.to_s}=", v) + send("#{attr_name}=", v) end # parse, convert and assign note text to integer def parse_integer attr_name, xpath v = parse_value xpath v = v.to_i if v.respond_to?(:to_i) - send("#{attr_name.to_s}=", v) + send("#{attr_name}=", v) end # parse, convert and assign node text to float def parse_float attr_name, xpath v = parse_value xpath v = v.to_f if v.respond_to?(:to_f) - send("#{attr_name.to_s}=", v) + send("#{attr_name}=", v) end # return node text based on xpath diff --git a/lib/axlsx/util/serialized_attributes.rb b/lib/axlsx/util/serialized_attributes.rb index 2a651ede..0b71c70b 100644 --- a/lib/axlsx/util/serialized_attributes.rb +++ b/lib/axlsx/util/serialized_attributes.rb @@ -18,9 +18,7 @@ module Axlsx end # a reader for those attributes - def xml_attributes - @xml_attributes - end + attr_reader :xml_attributes # This helper registers the attributes that will be formatted as elements. def serializable_element_attributes(*symbols) @@ -28,8 +26,20 @@ module Axlsx end # attr reader for element attributes - def xml_element_attributes - @xml_element_attributes + attr_reader :xml_element_attributes + end + + # creates a XML tag with serialized attributes + # @see SerializedAttributes#serialized_attributes + def serialized_tag(tagname, str, additional_attributes = {}, &block) + str << "<#{tagname} " + serialized_attributes(str, additional_attributes) + if block_given? + str << '>' + yield + str << "</#{tagname}>" + else + str << '/>' end end diff --git a/lib/axlsx/util/simple_typed_list.rb b/lib/axlsx/util/simple_typed_list.rb index 54dae6f3..95f5b3f2 100644 --- a/lib/axlsx/util/simple_typed_list.rb +++ b/lib/axlsx/util/simple_typed_list.rb @@ -8,7 +8,7 @@ module Axlsx # @param [Array, Class] type An array of Class objects or a single Class object # @param [String] serialize_as The tag name to use in serialization # @raise [ArgumentError] if all members of type are not Class objects - def initialize type, serialize_as=nil + def initialize type, serialize_as=nil, start_size = 0 if type.is_a? Array type.each { |item| raise ArgumentError, "All members of type must be Class objects" unless item.is_a? Class } @allowed_types = type @@ -16,9 +16,8 @@ module Axlsx raise ArgumentError, "Type must be a Class object or array of Class objects" unless type.is_a? Class @allowed_types = [type] end - @list = [] - @locked_at = nil - @serialize_as = serialize_as + @serialize_as = serialize_as unless serialize_as.nil? + @list = Array.new(start_size) end # The class constants of allowed types @@ -27,7 +26,9 @@ module Axlsx # The index below which items cannot be removed # @return [Integer] - attr_reader :locked_at + def locked_at + defined?(@locked_at) ? @locked_at : nil + end # The tag name to use when serializing this object # by default the parent node for all items in the list is the classname of the first allowed type with the first letter in lowercase. @@ -54,6 +55,7 @@ module Axlsx end result end + # Lock this list at the current size # @return [self] def lock @@ -61,18 +63,18 @@ module Axlsx self end - def to_ary - @list - end - - alias :to_a :to_ary - # Unlock the list # @return [self] def unlock @locked_at = nil self end + + def to_ary + @list + end + + alias :to_a :to_ary # join operator # @param [Array] v the array to join @@ -81,7 +83,7 @@ module Axlsx # @return [SimpleTypedList] def +(v) v.each do |item| - DataTypeValidator.validate "SimpleTypedList.+", @allowed_types, item + DataTypeValidator.validate :SimpleTypedList_plus, @allowed_types, item @list << item end end @@ -91,19 +93,21 @@ module Axlsx # @raise [ArgumentError] if the value being added is not one fo the allowed types # @return [Integer] returns the index of the item added. def <<(v) - DataTypeValidator.validate "SimpleTypedList.<<", @allowed_types, v + DataTypeValidator.validate :SimpleTypedList_push, @allowed_types, v @list << v @list.size - 1 - end + end + alias :push :<< + # delete the item from the list # @param [Any] v The item to be deleted. # @raise [ArgumentError] if the item's index is protected by locking # @return [Any] The item deleted def delete(v) - return unless @list.include? v - raise ArgumentError, "Item is protected and cannot be deleted" if protected? @list.index(v) + return unless include? v + raise ArgumentError, "Item is protected and cannot be deleted" if protected? index(v) @list.delete v end @@ -122,7 +126,7 @@ module Axlsx # @raise [ArgumentError] if the index is protected by locking # @raise [ArgumentError] if the item is not one of the allowed types def []=(index, v) - DataTypeValidator.validate "SimpleTypedList.<<", @allowed_types, v + DataTypeValidator.validate :SimpleTypedList_insert, @allowed_types, v raise ArgumentError, "Item is protected and cannot be changed" if protected? index @list[index] = v v @@ -134,7 +138,7 @@ module Axlsx # @raise [ArgumentError] if the index is protected by locking # @raise [ArgumentError] if the index is not one of the allowed types def insert(index, v) - DataTypeValidator.validate "SimpleTypedList.<<", @allowed_types, v + DataTypeValidator.validate :SimpleTypedList_insert, @allowed_types, v raise ArgumentError, "Item is protected and cannot be changed" if protected? index @list.insert(index, v) v @@ -143,38 +147,10 @@ module Axlsx # determines if the index is protected # @param [Integer] index def protected? index - return false unless @locked_at.is_a? Fixnum - index < @locked_at + return false unless locked_at.is_a? Fixnum + index < locked_at end - # override the equality method so that this object can be compared to a simple array. - # if this object's list is equal to the specifiec array, we return true. - def ==(v) - v == @list - end - # method_mission override to pass allowed methods to the list. - # @note - # the following methods are not allowed - # :replace - # :insert - # :collect! - # :map! - # :pop - # :delete_if - # :reverse! - # :shift - # :shuffle! - # :slice! - # :sort! - # :uniq! - # :unshift - # :zip - # :flatten! - # :fill - # :drop - # :drop_while - # :delete_if - # :clear DESTRUCTIVE = ['replace', 'insert', 'collect!', 'map!', 'pop', 'delete_if', 'reverse!', 'shift', 'shuffle!', 'slice!', 'sort!', 'uniq!', 'unshift', 'zip', 'flatten!', 'fill', 'drop', 'drop_while', @@ -188,13 +164,13 @@ module Axlsx end } end - + def to_xml_string(str = '') classname = @allowed_types[0].name.split('::').last el_name = serialize_as.to_s || (classname[0,1].downcase + classname[1..-1]) - str << '<' << el_name << ' count="' << @list.size.to_s << '">' - @list.each { |item| item.to_xml_string(str) } - str << '</' << el_name << '>' + str << ('<' << el_name << ' count="' << size.to_s << '">') + each { |item| item.to_xml_string(str) } + str << ('</' << el_name << '>') end end diff --git a/lib/axlsx/util/storage.rb b/lib/axlsx/util/storage.rb index 9f8afb7f..40cd4a45 100644 --- a/lib/axlsx/util/storage.rb +++ b/lib/axlsx/util/storage.rb @@ -6,14 +6,14 @@ module Axlsx # Packing for the Storage when pushing an array of items into a byte stream # Name, name length, type, color, left sibling, right sibling, child, classid, state, created, modified, sector, size - PACKING = "s32 s1 c2 l3 x16 x4 q2 l q" + PACKING = "s32 s1 c2 l3 x16 x4 q2 l q".freeze # storage types TYPES = { :root=>5, :stream=>2, :storage=>1 - } + }.freeze # Creates a byte string for this storage # @return [String] @@ -45,7 +45,7 @@ module Axlsx # Sets the color for this storage # @param [Integer] v Must be one of the COLORS constant hash values def color=(v) - RestrictionValidator.validate "Storage.color", COLORS.values, v + RestrictionValidator.validate :storage_color, COLORS.values, v @color = v end @@ -116,7 +116,7 @@ module Axlsx # Sets the type for this storage. # @param [Integer] v the type to specify must be one of the TYPES constant hash values. def type=(v) - RestrictionValidator.validate "Storage.type", TYPES.values, v + RestrictionValidator.validate :storage_type, TYPES.values, v @type = v end diff --git a/lib/axlsx/util/string.rb b/lib/axlsx/util/string.rb new file mode 100644 index 00000000..8def6e5b --- /dev/null +++ b/lib/axlsx/util/string.rb @@ -0,0 +1,7 @@ +unless String.method_defined? :prepend + class String + def prepend(other_str) + insert(0, other_str) + end + end +end
\ No newline at end of file diff --git a/lib/axlsx/util/validators.rb b/lib/axlsx/util/validators.rb index bdea6a1d..c9ee2e6e 100644 --- a/lib/axlsx/util/validators.rb +++ b/lib/axlsx/util/validators.rb @@ -52,19 +52,17 @@ module Axlsx # @return [Boolean] true if validation succeeds. # @see validate_boolean def self.validate(name, types, v, other=false) - types = [types] unless types.is_a? Array 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| return if v.ancestors.include?(t) } - else - types.each { |t| return if v.is_a?(t) } + v_class = v.is_a?(Class) ? v : v.class + Array(types).each do |t| + return if v_class <= t end raise ArgumentError, (ERR_TYPE % [v.inspect, name, types.inspect]) end end - + # Requires that the value can be converted to an integer # @para, [Any] v the value to validate @@ -80,12 +78,15 @@ module Axlsx def self.validate_angle(v) raise ArgumentError, (ERR_ANGLE % v.inspect) unless (v.to_i >= -5400000 && v.to_i <= 5400000) end + + UINT_VALIDATOR = lambda { |arg| arg.respond_to?(:>=) && arg >= 0 } + # Requires that the value is a Fixnum or Integer and is greater or equal to 0 # @param [Any] v The value validated # @raise [ArgumentError] raised if the value is not a Fixnum or Integer value greater or equal to 0 # @return [Boolean] true if the data is valid def self.validate_unsigned_int(v) - DataTypeValidator.validate(:unsigned_int, [Fixnum, Integer], v, lambda { |arg| arg.respond_to?(:>=) && arg >= 0 }) + DataTypeValidator.validate(:unsigned_int, Integer, v, UINT_VALIDATOR) end # Requires that the value is a Fixnum Integer or Float and is greater or equal to 0 @@ -93,13 +94,13 @@ module Axlsx # @raise [ArgumentError] raised if the value is not a Fixnun, Integer, Float value greater or equal to 0 # @return [Boolean] true if the data is valid def self.validate_unsigned_numeric(v) - DataTypeValidator.validate("Invalid column width", [Fixnum, Integer, Float], v, lambda { |arg| arg.respond_to?(:>=) && arg.to_i >= 0 }) + DataTypeValidator.validate(:unsigned_numeric, Numeric, v, UINT_VALIDATOR) end - # Requires that the value is a Fixnum or Integer + # Requires that the value is a Integer # @param [Any] v The value validated def self.validate_int(v) - DataTypeValidator.validate :unsigned_int, [Fixnum, Integer], v + DataTypeValidator.validate :signed_int, Integer, v end # Requires that the value is a form that can be evaluated as a boolean in an xml document. @@ -107,7 +108,7 @@ module Axlsx # it must be one of 0, 1, "true", "false", :true, :false, true, false, "0", or "1" # @param [Any] v The value validated def self.validate_boolean(v) - DataTypeValidator.validate(:boolean, [Fixnum, String, Integer, Symbol, TrueClass, FalseClass], v, lambda { |arg| [0, 1, "true", "false", :true, :false, true, false, "0", "1"].include?(arg) }) + DataTypeValidator.validate(:boolean, [String, Integer, Symbol, TrueClass, FalseClass], v, lambda { |arg| [0, 1, "true", "false", :true, :false, true, false, "0", "1"].include?(arg) }) end # Requires that the value is a String @@ -130,12 +131,12 @@ module Axlsx # Requires that the value is an integer ranging from 10 to 400. def self.validate_scale_10_400(v) - DataTypeValidator.validate "page_scale", [Fixnum, Integer], v, lambda { |arg| arg >= 10 && arg <= 400 } + DataTypeValidator.validate "page_scale", Integer, v, lambda { |arg| arg >= 10 && arg <= 400 } end # Requires that the value is an integer ranging from 10 to 400 or 0. def self.validate_scale_0_10_400(v) - DataTypeValidator.validate "page_scale", [Fixnum, Integer], v, lambda { |arg| arg == 0 || (arg >= 10 && arg <= 400) } + DataTypeValidator.validate "page_scale", Integer, v, lambda { |arg| arg == 0 || (arg >= 10 && arg <= 400) } end # Requires that the value is one of :default, :landscape, or :portrait. diff --git a/lib/axlsx/workbook/defined_name.rb b/lib/axlsx/workbook/defined_name.rb index 136f98cd..283a8e9d 100644 --- a/lib/axlsx/workbook/defined_name.rb +++ b/lib/axlsx/workbook/defined_name.rb @@ -120,11 +120,9 @@ module Axlsx def to_xml_string(str='') raise ArgumentError, 'you must specify the name for this defined name. Please read the documentation for Axlsx::DefinedName for more details' unless name - str << '<definedName ' - str << 'name="' << name << '" ' + str << ('<definedName ' << 'name="' << name << '" ') serialized_attributes str - str << '>' << @formula - str << '</definedName>' + str << ('>' << @formula << '</definedName>') end end end diff --git a/lib/axlsx/workbook/defined_names.rb b/lib/axlsx/workbook/defined_names.rb index fd7800a3..11f10a56 100644 --- a/lib/axlsx/workbook/defined_names.rb +++ b/lib/axlsx/workbook/defined_names.rb @@ -11,8 +11,8 @@ module Axlsx # @param [String] str # @return [String] def to_xml_string(str = '') - return if @list.empty? - str << "<definedNames>" + return if empty? + str << '<definedNames>' each { |defined_name| defined_name.to_xml_string(str) } str << '</definedNames>' end diff --git a/lib/axlsx/workbook/shared_strings_table.rb b/lib/axlsx/workbook/shared_strings_table.rb index ed6643f2..ebec6e67 100644 --- a/lib/axlsx/workbook/shared_strings_table.rb +++ b/lib/axlsx/workbook/shared_strings_table.rb @@ -47,10 +47,10 @@ module Axlsx # @param [String] str # @return [String] def to_xml_string(str='') - str << '<?xml version="1.0" encoding="UTF-8"?><sst xmlns="' << XML_NS << '"' - str << ' count="' << @count.to_s << '" uniqueCount="' << unique_count.to_s << '"' - str << ' xml:space="' << xml_space.to_s << '">' << @shared_xml_string << '</sst>' - str = Axlsx::sanitize(str) + Axlsx::sanitize(@shared_xml_string) + str << ('<?xml version="1.0" encoding="UTF-8"?><sst xmlns="' << XML_NS << '"') + str << (' count="' << @count.to_s << '" uniqueCount="' << unique_count.to_s << '"') + str << (' xml:space="' << xml_space.to_s << '">' << @shared_xml_string << '</sst>') end private diff --git a/lib/axlsx/workbook/workbook.rb b/lib/axlsx/workbook/workbook.rb index edd1d0d7..040628d3 100644 --- a/lib/axlsx/workbook/workbook.rb +++ b/lib/axlsx/workbook/workbook.rb @@ -338,8 +338,8 @@ require 'axlsx/workbook/worksheet/selection.rb' def to_xml_string(str='') add_worksheet(name: 'Sheet1') unless worksheets.size > 0 str << '<?xml version="1.0" encoding="UTF-8"?>' - str << '<workbook xmlns="' << XML_NS << '" xmlns:r="' << XML_NS_R << '">' - str << '<workbookPr date1904="' << @@date1904.to_s << '"/>' + str << ('<workbook xmlns="' << XML_NS << '" xmlns:r="' << XML_NS_R << '">') + str << ('<workbookPr date1904="' << @@date1904.to_s << '"/>') views.to_xml_string(str) str << '<sheets>' worksheets.each { |sheet| sheet.to_sheet_node_xml_string(str) } @@ -348,7 +348,7 @@ require 'axlsx/workbook/worksheet/selection.rb' unless pivot_tables.empty? str << '<pivotCaches>' pivot_tables.each do |pivot_table| - str << '<pivotCache cacheId="' << pivot_table.cache_definition.cache_id.to_s << '" r:id="' << pivot_table.cache_definition.rId << '"/>' + str << ('<pivotCache cacheId="' << pivot_table.cache_definition.cache_id.to_s << '" r:id="' << pivot_table.cache_definition.rId << '"/>') end str << '</pivotCaches>' end diff --git a/lib/axlsx/workbook/workbook_views.rb b/lib/axlsx/workbook/workbook_views.rb index 4e69f19e..c32bd632 100644 --- a/lib/axlsx/workbook/workbook_views.rb +++ b/lib/axlsx/workbook/workbook_views.rb @@ -11,7 +11,7 @@ module Axlsx # @param [String] str # @return [String] def to_xml_string(str = '') - return if @list.empty? + return if empty? str << "<bookViews>" each { |view| view.to_xml_string(str) } str << '</bookViews>' diff --git a/lib/axlsx/workbook/worksheet/auto_filter/filters.rb b/lib/axlsx/workbook/worksheet/auto_filter/filters.rb index f26a8442..faa22374 100644 --- a/lib/axlsx/workbook/worksheet/auto_filter/filters.rb +++ b/lib/axlsx/workbook/worksheet/auto_filter/filters.rb @@ -237,9 +237,7 @@ include Axlsx::SerializedAttributes # Serialize the object to xml # @param [String] str The string object this serialization will be concatenated to. def to_xml_string(str = '') - str << '<dateGroupItem ' - serialized_attributes str - str << '/>' + serialized_tag('dateGroupItem', str) end end end diff --git a/lib/axlsx/workbook/worksheet/break.rb b/lib/axlsx/workbook/worksheet/break.rb index b2902248..2e40a265 100644 --- a/lib/axlsx/workbook/worksheet/break.rb +++ b/lib/axlsx/workbook/worksheet/break.rb @@ -28,9 +28,7 @@ module Axlsx # serializes the break to xml def to_xml_string(str='') - str << '<brk ' - serialized_attributes str - str << '></brk>' + serialized_tag('brk', str) end end end diff --git a/lib/axlsx/workbook/worksheet/cell.rb b/lib/axlsx/workbook/worksheet/cell.rb index 6e3512c5..138efa34 100644 --- a/lib/axlsx/workbook/worksheet/cell.rb +++ b/lib/axlsx/workbook/worksheet/cell.rb @@ -30,17 +30,23 @@ module Axlsx # @option options [String] color an 8 letter rgb specification # @option options [Number] formula_value The value to cache for a formula cell. # @option options [Symbol] scheme must be one of :none, major, :minor - def initialize(row, value="", options={}) - self.row=row - @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 - @style ||= 0 - @type ||= cell_type_from_value(value) - @value = cast_value(value) + def initialize(row, value = nil, options = {}) + @row = row + # Do not use instance vars if not needed to use less RAM + # And do not call parse_options on frequently used options + # to get less GC cycles + type = options.delete(:type) || cell_type_from_value(value) + self.type = type unless type == :string + + + val = options.delete(:style) + self.style = val unless val.nil? || val == 0 + val = options.delete(:formula_value) + self.formula_value = val unless val.nil? + + parse_options(options) + + self.value = value end # this is the cached value for formula cells. If you want the values to render in iOS/Mac OSX preview @@ -53,15 +59,20 @@ module Axlsx # needs to define bla=(v) and bla methods on the class that hook into a # set_attr method that kicks the suplied validator and updates the instance_variable # for the key - INLINE_STYLES = ['value', 'type', 'font_name', 'charset', - 'family', 'b', 'i', 'strike','outline', - 'shadow', 'condense', 'extend', 'u', - 'vertAlign', 'sz', 'color', 'scheme'] + INLINE_STYLES = [:value, :type, :font_name, :charset, + :family, :b, :i, :strike, :outline, + :shadow, :condense, :extend, :u, + :vertAlign, :sz, :color, :scheme].freeze + + CELL_TYPES = [:date, :time, :float, :integer, + :string, :boolean, :iso_8601].freeze # The index of the cellXfs item to be applied to this cell. # @return [Integer] # @see Axlsx::Styles - attr_reader :style + def style + defined?(@style) ? @style : 0 + end # The row this cell belongs to. # @return [Row] @@ -78,18 +89,21 @@ module Axlsx # :string to :integer or :float, type conversions always return 0 or 0.0 # :string, :integer, or :float to :time conversions always return the original value as a string and set the cells type to :string. # No support is currently implemented for parsing time strings. - attr_reader :type + def type + defined?(@type) ? @type : :string + end + # @see type def type=(v) - RestrictionValidator.validate "Cell.type", [:date, :time, :float, :integer, :string, :boolean, :iso_8601], v - @type=v - self.value = @value unless @value.nil? + RestrictionValidator.validate :cell_type, CELL_TYPES, v + @type = v + self.value = @value unless !defined?(@value) || @value.nil? end - # The value of this cell. # @return [String, Integer, Float, Time, Boolean] casted value based on cell's type attribute. attr_reader :value + # @see value def value=(v) #TODO: consider doing value based type determination first? @@ -99,16 +113,16 @@ module Axlsx # Indicates that the cell has one or more of the custom cell styles applied. # @return [Boolean] def is_text_run? - @is_text_run ||= false + defined?(@is_text_run) && @is_text_run end # Indicates if the cell is good for shared string table def plain_string? - @type == :string && # String typed + type == :string && # String typed !is_text_run? && # No inline styles [email protected]? && # Not nil [email protected]? && # Not empty - [email protected]_with?('=') # Not a formula + [email protected]_with?(?=) # Not a formula end # The inline font_name property for the cell @@ -231,7 +245,7 @@ module Axlsx attr_reader :vertAlign # @see vertAlign def vertAlign=(v) - RestrictionValidator.validate "Cell.vertAlign", [:baseline, :subscript, :superscript], v + RestrictionValidator.validate :cell_vertAlign, [:baseline, :subscript, :superscript], v set_run_style nil, :vertAlign, v end @@ -241,7 +255,7 @@ module Axlsx attr_reader :scheme # @see scheme def scheme=(v) - RestrictionValidator.validate "Cell.schema", [:none, :major, :minor], v + RestrictionValidator.validate :cell_scheme, [:none, :major, :minor], v set_run_style nil, :scheme, v end @@ -251,14 +265,14 @@ module Axlsx # @return [Integer] The index of the cell in the containing row. def index - @row.cells.index(self) + @row.index(self) end # @return [String] The alpha(column)numeric(row) reference for this sell. # @example Relative Cell Reference # ws.rows.first.cells.first.r #=> "A1" def r - Axlsx::cell_r index, @row.index + Axlsx::cell_r index, @row.row_index end # @return [String] The absolute alpha(column)numeric(row) reference for this sell. @@ -272,14 +286,14 @@ module Axlsx # @raise [ArgumentError] Invalid cellXfs id if the value provided is not within cellXfs items range. def style=(v) Axlsx::validate_unsigned_int(v) - count = @styles.cellXfs.size + count = styles.cellXfs.size raise ArgumentError, "Invalid cellXfs id" unless v < count @style = v end - # @return [Array] of x/y coordinates in the cheet for this cell. + # @return [Array] of x/y coordinates in the sheet for this cell. def pos - [index, row.index] + [index, row.row_index] end # Merges all the cells in a range created between this cell and the cell or string name for a cell provided @@ -304,17 +318,14 @@ module Axlsx end def is_formula? - @type == :string && @value.to_s.start_with?('=') + type == :string && @value.to_s.start_with?(?=) end # This is still not perfect... - # - scaling is not linear as font sizes increst - # - different fonts have different mdw and char widths + # - scaling is not linear as font sizes increase def autowidth - return if is_formula? || value == nil - mdw = 1.78 #This is the widest width of 0..9 in arial@10px) - font_scale = (font_size/10.0).to_f - ((value.to_s.count(Worksheet.thin_chars) * mdw + 5) / mdw * 256) / 256.0 * font_scale + return if is_formula? || value.nil? + (value.to_s.count(Worksheet::THIN_CHARS) + 3.0) * (font_size/10.0) end # returns the absolute or relative string style reference for @@ -326,7 +337,6 @@ module Axlsx absolute ? r_abs : r end - # Creates a defined name in the workbook for this cell. def name=(label) row.worksheet.workbook.add_defined_name "#{row.worksheet.name}!#{r_abs}", name: label @@ -334,25 +344,27 @@ module Axlsx end # returns the name of the cell - def name - @name - end + attr_reader :name private + + def styles + row.worksheet.styles + end # we scale the font size if bold style is applied to either the style font or # the cell itself. Yes, it is a bit of a hack, but it is much better than using # imagemagick and loading metrics for every character. def font_size - font = @styles.fonts[@styles.cellXfs[style].fontId] || @styles.fonts[0] - size_from_styles = (font.b || b) ? font.sz * 1.5 : font.sz - sz || size_from_styles + return sz if sz + font = styles.fonts[styles.cellXfs[style].fontId] || styles.fonts[0] + (font.b || (defined?(@b) && @b)) ? (font.sz * 1.5) : font.sz end # Utility method for setting inline style attributes - def set_run_style( validator, attr, value) - return unless INLINE_STYLES.include?(attr.to_s) - Axlsx.send(validator, value) unless validator == nil + def set_run_style(validator, attr, value) + return unless INLINE_STYLES.include?(attr.to_sym) + Axlsx.send(validator, value) unless validator.nil? self.instance_variable_set :"@#{attr.to_s}", value @is_text_run = true end @@ -363,9 +375,6 @@ module Axlsx @ssti = v end - # assigns the owning row for this cell. - def row=(v) @row=v end - # Determines the cell type based on the cell value. # @note This is only used when a cell is created but no :type option is specified, the following rules apply: # 1. If the value is an instance of Date, the type is set to :date @@ -381,14 +390,11 @@ module Axlsx :time elsif v.is_a?(TrueClass) || v.is_a?(FalseClass) :boolean - elsif v.to_s =~ /\A[+-]?\d+?\Z/ #numeric + elsif v.to_s =~ Axlsx::NUMERIC_REGEX :integer - elsif v.to_s =~ /\A[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?\Z/ #float + elsif v.to_s =~ Axlsx::FLOAT_REGEX :float - # \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 - 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/ + elsif v.to_s =~ Axlsx::ISO_8601_REGEX :iso_8601 else :string @@ -401,26 +407,27 @@ module Axlsx # @see Axlsx#date1904 def cast_value(v) return nil if v.nil? - if @type == :date + case type + when :date self.style = STYLE_DATE if self.style == 0 v - elsif (@type == :time && v.is_a?(Time)) || (@type == :time && v.respond_to?(:to_time)) + when :time self.style = STYLE_DATE if self.style == 0 v.respond_to?(:to_time) ? v.to_time : v - elsif @type == :float + when :float v.to_f - elsif @type == :integer + when :integer v.to_i - elsif @type == :boolean + when :boolean v ? 1 : 0 - elsif @type == :iso_8601 + when :iso_8601 #consumer is responsible for ensuring the iso_8601 format when specifying this type v else - @type = :string # TODO find a better way to do this as it accounts for 30% of # processing time in benchmarking... - Axlsx::trust_input ? v.to_s : ::CGI.escapeHTML(v.to_s) + + Axlsx::trust_input ? v.to_s : ::CGI.escapeHTML(Axlsx::sanitize(v.to_s)) end end diff --git a/lib/axlsx/workbook/worksheet/cell_serializer.rb b/lib/axlsx/workbook/worksheet/cell_serializer.rb index 1fb8f5d8..77844ea6 100644 --- a/lib/axlsx/workbook/worksheet/cell_serializer.rb +++ b/lib/axlsx/workbook/worksheet/cell_serializer.rb @@ -11,9 +11,9 @@ module Axlsx # @param [String] str The string to apend serialization to. # @return [String] 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 << '" ' + 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 + method = cell.type self.send(method, cell, str) str << '</c>' end @@ -24,22 +24,22 @@ module Axlsx # @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' } + data = cell.instance_values.reject{ |key, value| value == nil || key == 'value' || key == 'type' } keys = data.keys & Cell::INLINE_STYLES - str << "<r><rPr>" + str << '<r><rPr>' keys.each do |key| case key - when 'font_name' - str << "<rFont val='"<< cell.font_name << "'/>" - when 'color' + 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 << "'/>" + str << ('<' << key.to_s << ' val="' << data[key].to_s << '"/>') end end - str << "</rPr>" << "<t>" << cell.value.to_s << "</t></r>" + str << ('</rPr><t>' << cell.value.to_s << '</t></r>') else - str << "<t>" << cell.value.to_s << "</t>" + str << ('<t>' << cell.value.to_s << '</t>') end str end @@ -48,7 +48,7 @@ module Axlsx # @param [Cell] cell The cell that is being serialized # @param [String] str The string the serialized content will be appended to. # @return [String] - def iso_8601_type_serialization(cell, str='') + def iso_8601(cell, str='') value_serialization 'd', cell.value, str end @@ -57,7 +57,7 @@ module Axlsx # @param [Cell] cell The cell that is being serialized # @param [String] str The string the serialized content will be appended to. # @return [String] - def date_type_serialization(cell, str='') + def date(cell, str='') value_serialization false, DateTimeConverter::date_to_serial(cell.value).to_s, str end @@ -65,7 +65,7 @@ module Axlsx # @param [Cell] cell The cell that is being serialized # @param [String] str The string the serialized content will be appended to. # @return [String] - def time_type_serialization(cell, str='') + def time(cell, str='') value_serialization false, DateTimeConverter::time_to_serial(cell.value).to_s, str end @@ -73,7 +73,7 @@ module Axlsx # @param [Cell] cell The cell that is being serialized # @param [String] str The string the serialized content will be appended to. # @return [String] - def boolean_type_serialization(cell, str='') + def boolean(cell, str='') value_serialization 'b', cell.value.to_s, str end @@ -81,16 +81,16 @@ module Axlsx # @param [Cell] cell The cell that is being serialized # @param [String] str The string the serialized content will be appended to. # @return [String] - def float_type_serialization(cell, str='') - numeric_type_serialization cell, str + def float(cell, str='') + numeric cell, str end # Serializes cells that are type integer # @param [Cell] cell The cell that is being serialized # @param [String] str The string the serialized content will be appended to. # @return [String] - def integer_type_serialization(cell, str = '') - numeric_type_serialization cell, str + def integer(cell, str = '') + numeric cell, str end @@ -99,8 +99,8 @@ module Axlsx # @param [String] str The string the serialized content will be appended to. # @return [String] 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? + str << ('t="str"><f>' << cell.value.to_s.sub('=', '') << '</f>') + str << ('<v>' << cell.formula_value.to_s << '</v>') unless cell.formula_value.nil? end # Serializes cells that are type inline_string @@ -108,7 +108,7 @@ module Axlsx # @param [String] str The string the serialized content will be appended to. # @return [String] def inline_string_serialization(cell, str = '') - str << 't="inlineStr">' << '<is>' + str << 't="inlineStr"><is>' run_xml_string cell, str str << '</is>' end @@ -117,7 +117,7 @@ module Axlsx # @param [Cell] cell The cell that is being serialized # @param [String] str The string the serialized content will be appended to. # @return [String] - def string_type_serialization(cell, str='') + def string(cell, str='') if cell.is_formula? formula_serialization cell, str elsif !cell.ssti.nil? @@ -129,13 +129,13 @@ module Axlsx private - def numeric_type_serialization(cell, str = '') + def numeric(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>' + str << ('t="' << serialization_type << '"') if serialization_type + str << ('><v>' << serialization_value << '</v>') end diff --git a/lib/axlsx/workbook/worksheet/cfvo.rb b/lib/axlsx/workbook/worksheet/cfvo.rb index 7fcd8253..c2a4c781 100644 --- a/lib/axlsx/workbook/worksheet/cfvo.rb +++ b/lib/axlsx/workbook/worksheet/cfvo.rb @@ -54,9 +54,7 @@ module Axlsx # @param [String] str # @return [String] def to_xml_string(str = '') - str << '<cfvo ' - serialized_attributes str - str << ' />' + serialized_tag('cfvo', str) end end end diff --git a/lib/axlsx/workbook/worksheet/cfvos.rb b/lib/axlsx/workbook/worksheet/cfvos.rb index d642bfc6..0b5a21b3 100644 --- a/lib/axlsx/workbook/worksheet/cfvos.rb +++ b/lib/axlsx/workbook/worksheet/cfvos.rb @@ -9,7 +9,7 @@ module Axlsx end def to_xml_string(str='') - @list.each { |cfvo| cfvo.to_xml_string(str) } + each { |cfvo| cfvo.to_xml_string(str) } end end end diff --git a/lib/axlsx/workbook/worksheet/col.rb b/lib/axlsx/workbook/worksheet/col.rb index 0a3edf87..01086ac3 100644 --- a/lib/axlsx/workbook/worksheet/col.rb +++ b/lib/axlsx/workbook/worksheet/col.rb @@ -122,22 +122,19 @@ module Axlsx # @param [Boolean] use_autowidth If this is false, the cell's # autowidth value will be ignored. def update_width(cell, fixed_width=nil, use_autowidth=true) - if fixed_width.is_a? Numeric - self.width = fixed_width - elsif use_autowidth - cell_width = cell.autowidth - self.width = cell_width unless (width || 0) > (cell_width || 0) - #self.width = [width || 0, cell.autowidth || 0].max - end + if fixed_width.is_a? Numeric + self.width = fixed_width + elsif use_autowidth + cell_width = cell.autowidth + self.width = cell_width unless (width || 0) > (cell_width || 0) + end end # Serialize this columns data to an xml string # @param [String] str # @return [String] def to_xml_string(str = '') - str << '<col ' - serialized_attributes str - str << '/>' + serialized_tag('col', str) end end diff --git a/lib/axlsx/workbook/worksheet/col_breaks.rb b/lib/axlsx/workbook/worksheet/col_breaks.rb index 63ba8292..2f1ec1b0 100644 --- a/lib/axlsx/workbook/worksheet/col_breaks.rb +++ b/lib/axlsx/workbook/worksheet/col_breaks.rb @@ -16,7 +16,7 @@ module Axlsx # Break will be passed to the created break object. # @see Break def add_break(options) - @list << Break.new(options.merge(:max => 1048575, :man => true)) + self << Break.new(options.merge(:max => 1048575, :man => true)) last end @@ -27,7 +27,7 @@ module Axlsx # </colBreaks> def to_xml_string(str='') return if empty? - str << '<colBreaks count="' << @list.size.to_s << '" manualBreakCount="' << @list.size.to_s << '">' + str << ('<colBreaks count="' << size.to_s << '" manualBreakCount="' << size.to_s << '">') each { |brk| brk.to_xml_string(str) } str << '</colBreaks>' end diff --git a/lib/axlsx/workbook/worksheet/comment.rb b/lib/axlsx/workbook/worksheet/comment.rb index 7035f4cf..e5dbe41c 100644 --- a/lib/axlsx/workbook/worksheet/comment.rb +++ b/lib/axlsx/workbook/worksheet/comment.rb @@ -24,11 +24,10 @@ module Axlsx string_attr_accessor :text, :author boolean_attr_accessor :visible - # The owning Comments object + # The owning Comments object # @return [Comments] attr_reader :comments - # The string based cell position reference (e.g. 'A1') that determines the positioning of this comment # @return [String|Cell] attr_reader :ref @@ -53,7 +52,7 @@ module Axlsx # @see ref def ref=(v) - Axlsx::DataTypeValidator.validate "Comment.ref", [String, Cell], v + Axlsx::DataTypeValidator.validate :comment_ref, [String, Cell], v @ref = v if v.is_a?(String) @ref = v.r if v.is_a?(Cell) end @@ -63,15 +62,15 @@ module Axlsx # @return [String] def to_xml_string(str = "") author = @comments.authors[author_index] - str << '<comment ref="' << ref << '" authorId="' << author_index.to_s << '">' + str << ('<comment ref="' << ref << '" authorId="' << author_index.to_s << '">') str << '<text>' unless author.to_s == "" str << '<r><rPr><b/><color indexed="81"/></rPr>' - str << "<t>" << ::CGI.escapeHTML(author.to_s) << ":\n</t></r>" + str << ("<t>" << ::CGI.escapeHTML(author.to_s) << ":\n</t></r>") end str << '<r>' str << '<rPr><color indexed="81"/></rPr>' - str << '<t>' << ::CGI.escapeHTML(text) << '</t></r></text>' + str << ('<t>' << ::CGI.escapeHTML(text) << '</t></r></text>') str << '</comment>' end diff --git a/lib/axlsx/workbook/worksheet/comments.rb b/lib/axlsx/workbook/worksheet/comments.rb index 4023c4b8..dfc6d143 100644 --- a/lib/axlsx/workbook/worksheet/comments.rb +++ b/lib/axlsx/workbook/worksheet/comments.rb @@ -42,15 +42,15 @@ module Axlsx raise ArgumentError, "Comment require an author" unless options[:author] raise ArgumentError, "Comment requires text" unless options[:text] raise ArgumentError, "Comment requires ref" unless options[:ref] - @list << Comment.new(self, options) - yield @list.last if block_given? - @list.last + self << Comment.new(self, options) + yield last if block_given? + last end # A sorted list of the unique authors in the contained comments # @return [Array] def authors - @list.map { |comment| comment.author.to_s }.uniq.sort + map { |comment| comment.author.to_s }.uniq.sort end # The relationships required by this object @@ -65,14 +65,12 @@ module Axlsx # @return [String] def to_xml_string(str="") str << '<?xml version="1.0" encoding="UTF-8"?>' - str << '<comments xmlns="' << XML_NS << '">' - str << '<authors>' + str << ('<comments xmlns="' << XML_NS << '"><authors>') authors.each do |author| - str << '<author>' << author.to_s << '</author>' + str << ('<author>' << author.to_s << '</author>') end - str << '</authors>' - str << '<commentList>' - @list.each do |comment| + str << '</authors><commentList>' + each do |comment| comment.to_xml_string str end str << '</commentList></comments>' diff --git a/lib/axlsx/workbook/worksheet/conditional_formatting.rb b/lib/axlsx/workbook/worksheet/conditional_formatting.rb index eabf570e..7b1783bd 100644 --- a/lib/axlsx/workbook/worksheet/conditional_formatting.rb +++ b/lib/axlsx/workbook/worksheet/conditional_formatting.rb @@ -74,7 +74,7 @@ module Axlsx # @param [String] str # @return [String] def to_xml_string(str = '') - str << '<conditionalFormatting sqref="' << sqref << '">' + str << ('<conditionalFormatting sqref="' << sqref << '">') str << rules.collect{ |rule| rule.to_xml_string }.join(' ') str << '</conditionalFormatting>' end diff --git a/lib/axlsx/workbook/worksheet/conditional_formatting_rule.rb b/lib/axlsx/workbook/worksheet/conditional_formatting_rule.rb index 916b31c2..13374bc4 100644 --- a/lib/axlsx/workbook/worksheet/conditional_formatting_rule.rb +++ b/lib/axlsx/workbook/worksheet/conditional_formatting_rule.rb @@ -210,7 +210,7 @@ module Axlsx str << '<cfRule ' serialized_attributes str str << '>' - str << '<formula>' << [*self.formula].join('</formula><formula>') << '</formula>' if @formula + str << ('<formula>' << [*self.formula].join('</formula><formula>') << '</formula>') if @formula @color_scale.to_xml_string(str) if @color_scale && @type == :colorScale @data_bar.to_xml_string(str) if @data_bar && @type == :dataBar @icon_set.to_xml_string(str) if @icon_set && @type == :iconSet diff --git a/lib/axlsx/workbook/worksheet/data_bar.rb b/lib/axlsx/workbook/worksheet/data_bar.rb index e67f76a4..e6455f1c 100644 --- a/lib/axlsx/workbook/worksheet/data_bar.rb +++ b/lib/axlsx/workbook/worksheet/data_bar.rb @@ -107,12 +107,10 @@ module Axlsx # @param [String] str # @return [String] def to_xml_string(str="") - str << '<dataBar ' - serialized_attributes str - str << '>' - value_objects.to_xml_string(str) - self.color.to_xml_string(str) - str << '</dataBar>' + serialized_tag('dataBar', str) do + value_objects.to_xml_string(str) + self.color.to_xml_string(str) + end end private diff --git a/lib/axlsx/workbook/worksheet/data_validation.rb b/lib/axlsx/workbook/worksheet/data_validation.rb index 92a42a11..67aef4e5 100644 --- a/lib/axlsx/workbook/worksheet/data_validation.rb +++ b/lib/axlsx/workbook/worksheet/data_validation.rb @@ -33,7 +33,7 @@ module Axlsx end # instance values that must be serialized as their own elements - e.g. not attributes. - CHILD_ELEMENTS = [:formula1, :formula2] + CHILD_ELEMENTS = [:formula1, :formula2].freeze # Formula1 # Available for type whole, decimal, date, time, textLength, list, custom @@ -218,8 +218,8 @@ module Axlsx str << '<dataValidation ' str << instance_values.map { |key, value| '' << key << '="' << value.to_s << '"' if (valid_attributes.include?(key.to_sym) and not CHILD_ELEMENTS.include?(key.to_sym)) }.join(' ') str << '>' - str << '<formula1>' << self.formula1 << '</formula1>' if @formula1 and valid_attributes.include?(:formula1) - str << '<formula2>' << self.formula2 << '</formula2>' if @formula2 and valid_attributes.include?(:formula2) + str << ('<formula1>' << self.formula1 << '</formula1>') if @formula1 and valid_attributes.include?(:formula1) + str << ('<formula2>' << self.formula2 << '</formula2>') if @formula2 and valid_attributes.include?(:formula2) str << '</dataValidation>' end diff --git a/lib/axlsx/workbook/worksheet/dimension.rb b/lib/axlsx/workbook/worksheet/dimension.rb index 552fc001..a7f9b792 100644 --- a/lib/axlsx/workbook/worksheet/dimension.rb +++ b/lib/axlsx/workbook/worksheet/dimension.rb @@ -43,13 +43,13 @@ module Axlsx # The first cell in the dimension # @return [String] def first_cell_reference - dimension_reference(worksheet.rows.first.cells.first, Dimension.default_first) + dimension_reference(worksheet.rows.first.first, Dimension.default_first) end # the last cell in the dimension # @return [String] def last_cell_reference - dimension_reference(worksheet.rows.last.cells.last, Dimension.default_last) + dimension_reference(worksheet.rows.last.last, Dimension.default_last) end private diff --git a/lib/axlsx/workbook/worksheet/header_footer.rb b/lib/axlsx/workbook/worksheet/header_footer.rb index 98f586c3..db684fc9 100644 --- a/lib/axlsx/workbook/worksheet/header_footer.rb +++ b/lib/axlsx/workbook/worksheet/header_footer.rb @@ -42,13 +42,11 @@ module Axlsx # @param [String] str # @return [String] def to_xml_string(str = '') - str << "<headerFooter " - serialized_attributes str - str << ">" - serialized_element_attributes(str) do |value| - value = ::CGI.escapeHTML(value) + serialized_tag('headerFooter', str) do + serialized_element_attributes(str) do |value| + value = ::CGI.escapeHTML(value) + end end - str << "</headerFooter>" end end end diff --git a/lib/axlsx/workbook/worksheet/icon_set.rb b/lib/axlsx/workbook/worksheet/icon_set.rb index 461c0630..400a8c47 100644 --- a/lib/axlsx/workbook/worksheet/icon_set.rb +++ b/lib/axlsx/workbook/worksheet/icon_set.rb @@ -63,11 +63,9 @@ module Axlsx # @param [String] str # @return [String] def to_xml_string(str="") - str << '<iconSet ' - serialized_attributes str - str << '>' - @value_objects.each { |cfvo| cfvo.to_xml_string(str) } - str << '</iconSet>' + serialized_tag('iconSet', str) do + @value_objects.each { |cfvo| cfvo.to_xml_string(str) } + end end private diff --git a/lib/axlsx/workbook/worksheet/merged_cells.rb b/lib/axlsx/workbook/worksheet/merged_cells.rb index 8850e295..6ea1edc9 100644 --- a/lib/axlsx/workbook/worksheet/merged_cells.rb +++ b/lib/axlsx/workbook/worksheet/merged_cells.rb @@ -15,7 +15,7 @@ module Axlsx # collection. This can be an array of actual cells or a string style # range like 'A1:C1' def add(cells) - @list << if cells.is_a?(String) + self << if cells.is_a?(String) cells elsif cells.is_a?(Array) Axlsx::cell_range(cells, false) @@ -26,7 +26,7 @@ module Axlsx # @param [String] str # @return [String] def to_xml_string(str = '') - return if @list.empty? + return if empty? str << "<mergeCells count='#{size}'>" each { |merged_cell| str << "<mergeCell ref='#{merged_cell}'></mergeCell>" } str << '</mergeCells>' diff --git a/lib/axlsx/workbook/worksheet/page_margins.rb b/lib/axlsx/workbook/worksheet/page_margins.rb index 6b1b3a7b..b3f8ddee 100644 --- a/lib/axlsx/workbook/worksheet/page_margins.rb +++ b/lib/axlsx/workbook/worksheet/page_margins.rb @@ -91,9 +91,7 @@ module Axlsx # @note For compatibility, this is a noop unless custom margins have been specified. # @see #custom_margins_specified? def to_xml_string(str = '') - str << '<pageMargins ' - serialized_attributes str - str << '/>' + serialized_tag('pageMargins', str) end end end diff --git a/lib/axlsx/workbook/worksheet/page_set_up_pr.rb b/lib/axlsx/workbook/worksheet/page_set_up_pr.rb index f52156c7..03378a1a 100644 --- a/lib/axlsx/workbook/worksheet/page_set_up_pr.rb +++ b/lib/axlsx/workbook/worksheet/page_set_up_pr.rb @@ -38,7 +38,7 @@ module Axlsx # serialize to xml def to_xml_string(str='') - str << '<pageSetUpPr ' << serialized_attributes << '/>' + str << ('<pageSetUpPr ' << serialized_attributes << '/>') end end end diff --git a/lib/axlsx/workbook/worksheet/page_setup.rb b/lib/axlsx/workbook/worksheet/page_setup.rb index ec76cd61..fc29b0c5 100644 --- a/lib/axlsx/workbook/worksheet/page_setup.rb +++ b/lib/axlsx/workbook/worksheet/page_setup.rb @@ -234,9 +234,7 @@ module Axlsx # @param [String] str # @return [String] def to_xml_string(str = '') - str << '<pageSetup ' - serialized_attributes str - str << '/>' + serialized_tag('pageSetup', str) end end end diff --git a/lib/axlsx/workbook/worksheet/pane.rb b/lib/axlsx/workbook/worksheet/pane.rb index a34b3140..2bc77495 100644 --- a/lib/axlsx/workbook/worksheet/pane.rb +++ b/lib/axlsx/workbook/worksheet/pane.rb @@ -124,9 +124,7 @@ module Axlsx # @return [String] def to_xml_string(str = '') finalize - str << '<pane ' - serialized_attributes str - str << '/>' + serialized_tag 'pane', str end private diff --git a/lib/axlsx/workbook/worksheet/pivot_table.rb b/lib/axlsx/workbook/worksheet/pivot_table.rb index 63819da5..0d5f34e8 100644 --- a/lib/axlsx/workbook/worksheet/pivot_table.rb +++ b/lib/axlsx/workbook/worksheet/pivot_table.rb @@ -159,9 +159,9 @@ module Axlsx # @return [String] def to_xml_string(str = '') str << '<?xml version="1.0" encoding="UTF-8"?>' - str << '<pivotTableDefinition xmlns="' << XML_NS << '" name="' << name << '" cacheId="' << cache_definition.cache_id.to_s << '" dataOnRows="1" applyNumberFormats="0" applyBorderFormats="0" applyFontFormats="0" applyPatternFormats="0" applyAlignmentFormats="0" applyWidthHeightFormats="1" dataCaption="Data" showMultipleLabel="0" showMemberPropertyTips="0" useAutoFormatting="1" indent="0" compact="0" compactData="0" gridDropZones="1" multipleFieldFilters="0">' - str << '<location firstDataCol="1" firstDataRow="1" firstHeaderRow="1" ref="' << ref << '"/>' - str << '<pivotFields count="' << header_cells_count.to_s << '">' + str << ('<pivotTableDefinition xmlns="' << XML_NS << '" name="' << name << '" cacheId="' << cache_definition.cache_id.to_s << '" dataOnRows="1" applyNumberFormats="0" applyBorderFormats="0" applyFontFormats="0" applyPatternFormats="0" applyAlignmentFormats="0" applyWidthHeightFormats="1" dataCaption="Data" showMultipleLabel="0" showMemberPropertyTips="0" useAutoFormatting="1" indent="0" compact="0" compactData="0" gridDropZones="1" multipleFieldFilters="0">') + str << ( '<location firstDataCol="1" firstDataRow="1" firstHeaderRow="1" ref="' << ref << '"/>') + str << ( '<pivotFields count="' << header_cells_count.to_s << '">') header_cell_values.each do |cell_value| str << pivot_field_for(cell_value) end @@ -170,12 +170,12 @@ module Axlsx str << '<rowFields count="1"><field x="-2"/></rowFields>' str << '<rowItems count="2"><i><x/></i> <i i="1"><x v="1"/></i></rowItems>' else - str << '<rowFields count="' << rows.size.to_s << '">' + str << ('<rowFields count="' << rows.size.to_s << '">') rows.each do |row_value| - str << '<field x="' << header_index_of(row_value).to_s << '"/>' + str << ('<field x="' << header_index_of(row_value).to_s << '"/>') end str << '</rowFields>' - str << '<rowItems count="' << rows.size.to_s << '">' + str << ('<rowItems count="' << rows.size.to_s << '">') rows.size.times do |i| str << '<i/>' end @@ -184,16 +184,16 @@ module Axlsx if columns.empty? str << '<colItems count="1"><i/></colItems>' else - str << '<colFields count="' << columns.size.to_s << '">' + str << ('<colFields count="' << columns.size.to_s << '">') columns.each do |column_value| - str << '<field x="' << header_index_of(column_value).to_s << '"/>' + str << ('<field x="' << header_index_of(column_value).to_s << '"/>') end str << '</colFields>' end unless pages.empty? - str << '<pageFields count="' << pages.size.to_s << '">' + str << ('<pageFields count="' << pages.size.to_s << '">') pages.each do |page_value| - str << '<pageField fld="' << header_index_of(page_value).to_s << '"/>' + str << ('<pageField fld="' << header_index_of(page_value).to_s << '"/>') end str << '</pageFields>' end @@ -243,31 +243,24 @@ module Axlsx def pivot_field_for(cell_ref) if rows.include? cell_ref - '<pivotField axis="axisRow" compact="0" outline="0" subtotalTop="0" showAll="0" includeNewItemsInFilter="1">' << - '<items count="1"><item t="default"/></items>' << - '</pivotField>' + '<pivotField axis="axisRow" compact="0" outline="0" subtotalTop="0" showAll="0" includeNewItemsInFilter="1">' + '<items count="1"><item t="default"/></items>' + '</pivotField>' elsif columns.include? cell_ref - '<pivotField axis="axisCol" compact="0" outline="0" subtotalTop="0" showAll="0" includeNewItemsInFilter="1">' << - '<items count="1"><item t="default"/></items>' << - '</pivotField>' + '<pivotField axis="axisCol" compact="0" outline="0" subtotalTop="0" showAll="0" includeNewItemsInFilter="1">' + '<items count="1"><item t="default"/></items>' + '</pivotField>' elsif pages.include? cell_ref - '<pivotField axis="axisCol" compact="0" outline="0" subtotalTop="0" showAll="0" includeNewItemsInFilter="1">' << - '<items count="1"><item t="default"/></items>' << - '</pivotField>' + '<pivotField axis="axisCol" compact="0" outline="0" subtotalTop="0" showAll="0" includeNewItemsInFilter="1">' + '<items count="1"><item t="default"/></items>' + '</pivotField>' elsif data_refs.include? cell_ref - '<pivotField dataField="1" compact="0" outline="0" subtotalTop="0" showAll="0" includeNewItemsInFilter="1">' << - '</pivotField>' + '<pivotField dataField="1" compact="0" outline="0" subtotalTop="0" showAll="0" includeNewItemsInFilter="1">' + '</pivotField>' else - '<pivotField compact="0" outline="0" subtotalTop="0" showAll="0" includeNewItemsInFilter="1">' << - '</pivotField>' + '<pivotField compact="0" outline="0" subtotalTop="0" showAll="0" includeNewItemsInFilter="1">' + '</pivotField>' end end + def data_refs data.map { |hash| hash[:ref] } end + def header_range range.gsub(/^(\w+?)(\d+)\:(\w+?)\d+$/, '\1\2:\3\2') end - end end diff --git a/lib/axlsx/workbook/worksheet/pivot_table_cache_definition.rb b/lib/axlsx/workbook/worksheet/pivot_table_cache_definition.rb index 665384f4..f136b663 100644 --- a/lib/axlsx/workbook/worksheet/pivot_table_cache_definition.rb +++ b/lib/axlsx/workbook/worksheet/pivot_table_cache_definition.rb @@ -47,13 +47,13 @@ module Axlsx # @return [String] def to_xml_string(str = '') str << '<?xml version="1.0" encoding="UTF-8"?>' - str << '<pivotCacheDefinition xmlns="' << XML_NS << '" xmlns:r="' << XML_NS_R << '" invalid="1" refreshOnLoad="1" recordCount="0">' + str << ('<pivotCacheDefinition xmlns="' << XML_NS << '" xmlns:r="' << XML_NS_R << '" invalid="1" refreshOnLoad="1" recordCount="0">') str << '<cacheSource type="worksheet">' - str << '<worksheetSource ref="' << pivot_table.range << '" sheet="' << pivot_table.data_sheet.name << '"/>' + str << ( '<worksheetSource ref="' << pivot_table.range << '" sheet="' << pivot_table.data_sheet.name << '"/>') str << '</cacheSource>' - str << '<cacheFields count="' << pivot_table.header_cells_count.to_s << '">' + str << ( '<cacheFields count="' << pivot_table.header_cells_count.to_s << '">') pivot_table.header_cells.each do |cell| - str << '<cacheField name="' << cell.value << '" numFmtId="0">' + str << ( '<cacheField name="' << cell.value << '" numFmtId="0">') str << '<sharedItems count="0">' str << '</sharedItems>' str << '</cacheField>' diff --git a/lib/axlsx/workbook/worksheet/print_options.rb b/lib/axlsx/workbook/worksheet/print_options.rb index cb9bcd1d..e57c2094 100644 --- a/lib/axlsx/workbook/worksheet/print_options.rb +++ b/lib/axlsx/workbook/worksheet/print_options.rb @@ -33,9 +33,7 @@ module Axlsx # @param [String] str # @return [String] def to_xml_string(str = '') - str << '<printOptions ' - serialized_attributes str - str << '/>' + serialized_tag 'printOptions', str end end end diff --git a/lib/axlsx/workbook/worksheet/protected_range.rb b/lib/axlsx/workbook/worksheet/protected_range.rb index 15904292..e990f1cb 100644 --- a/lib/axlsx/workbook/worksheet/protected_range.rb +++ b/lib/axlsx/workbook/worksheet/protected_range.rb @@ -41,9 +41,7 @@ module Axlsx # our output to that object. Use this - it helps limit the number of # objects created during serialization def to_xml_string(str="") - str << '<protectedRange ' - serialized_attributes str - str << '/>' + serialized_tag 'protectedRange', str end end end diff --git a/lib/axlsx/workbook/worksheet/protected_ranges.rb b/lib/axlsx/workbook/worksheet/protected_ranges.rb index 1231d752..46a2546b 100644 --- a/lib/axlsx/workbook/worksheet/protected_ranges.rb +++ b/lib/axlsx/workbook/worksheet/protected_ranges.rb @@ -20,7 +20,7 @@ module Axlsx elsif cells.is_a?(SimpleTypedList) || cells.is_a?(Array) Axlsx::cell_range(cells, false) end - @list << ProtectedRange.new(:sqref => sqref, :name => "Range#{size}") + self << ProtectedRange.new(:sqref => sqref, :name => "Range#{size}") last end diff --git a/lib/axlsx/workbook/worksheet/row.rb b/lib/axlsx/workbook/worksheet/row.rb index 5e335ca5..00ae71a9 100644 --- a/lib/axlsx/workbook/worksheet/row.rb +++ b/lib/axlsx/workbook/worksheet/row.rb @@ -3,10 +3,10 @@ module Axlsx # A Row is a single row in a worksheet. # @note The recommended way to manage rows and cells is to use Worksheet#add_row # @see Worksheet#add_row - class Row - + class Row < SimpleTypedList include SerializedAttributes include Accessors + # No support is provided for the following attributes # spans # thickTop @@ -28,11 +28,10 @@ module Axlsx # @see Row#array_to_cells # @see Cell def initialize(worksheet, values=[], options={}) - @ht = nil self.worksheet = worksheet - @cells = SimpleTypedList.new Cell - @worksheet.rows << self - self.height = options.delete(:height) if options[:height] + super(Cell, nil, values.size) + self.height = options.delete(:height) + worksheet.rows << self array_to_cells(values, options) end @@ -46,14 +45,10 @@ module Axlsx # @return [Worksheet] attr_reader :worksheet - # The cells this row holds - # @return [SimpleTypedList] - attr_reader :cells - # Row height measured in point size. There is no margin padding on row height. # @return [Float] def height - @ht + defined?(@ht) ? @ht : nil end # Outlining level of the row, when outlining is on @@ -77,11 +72,12 @@ module Axlsx Axlsx.validate_unsigned_numeric(v) @outline_level = v end + alias :outlineLevel= :outline_level= # The index of this row in the worksheet # @return [Integer] - def index + def row_index worksheet.rows.index(self) end @@ -90,50 +86,48 @@ module Axlsx # @param [String] str The string this rows xml will be appended to. # @return [String] def to_xml_string(r_index, str = '') - str << '<row ' - serialized_attributes(str, { :r => r_index + 1 }) - str << '>' - @cells.each_with_index { |cell, c_index| cell.to_xml_string(r_index, c_index, str) } - str << '</row>' + serialized_tag('row', str, :r => r_index + 1) do + tmp = '' # time / memory tradeoff, lots of calls to rubyzip costs more + # time.. + each_with_index { |cell, c_index| cell.to_xml_string(r_index, c_index, tmp) } + str << tmp + end end # Adds a single sell to the row based on the data provided and updates the worksheet's autofit data. # @return [Cell] - def add_cell(value="", options={}) + def add_cell(value = '', options = {}) c = Cell.new(self, value, options) - worksheet.send(:update_column_info, self.cells, []) + self << c + worksheet.send(:update_column_info, self, []) c end # sets the style for every cell in this row def style=(style) - cells.each_with_index do | cell, index | - s = style.is_a?(Array) ? style[index] : style - cell.style = s + each_with_index do | cell, index | + cell.style = style.is_a?(Array) ? style[index] : style end end - # returns the cells in this row as an array - # This lets us transpose the rows into columns - # @return [Array] - def to_ary - @cells.to_ary - end - # @see height def height=(v) - Axlsx::validate_unsigned_numeric(v) unless v.nil? - @ht = v + Axlsx::validate_unsigned_numeric(v) @custom_height = true + @ht = v end - @ht + end + + # return cells + def cells + self end private # assigns the owning worksheet for this row - def worksheet=(v) DataTypeValidator.validate "Row.worksheet", Worksheet, v; @worksheet=v; end + def worksheet=(v) DataTypeValidator.validate :row_worksheet, Worksheet, v; @worksheet=v; end # Converts values, types, and style options into cells and associates them with this row. # A new cell is created for each item in the values array. @@ -145,26 +139,14 @@ module Axlsx # @option options [Array, Symbol] types # @option options [Array, Integer] style def array_to_cells(values, options={}) - values = values - DataTypeValidator.validate 'Row.array_to_cells', Array, values + DataTypeValidator.validate :array_to_cells, Array, values types, style, formula_values = options.delete(:types), options.delete(:style), options.delete(:formula_values) values.each_with_index do |value, index| + options[:style] = style.is_a?(Array) ? style[index] : style if style + options[:type] = types.is_a?(Array) ? types[index] : types if types + options[:formula_value] = formula_values[index] if formula_values.is_a?(Array) - #WTF IS THIS PAP? - cell_style = style.is_a?(Array) ? style[index] : style - options[:style] = cell_style if cell_style - - cell_type = types.is_a?(Array)? types[index] : types - options[:type] = cell_type if cell_type - - formula_value = formula_values[index] if formula_values.is_a?(Array) - options[:formula_value] = formula_value if formula_value - - Cell.new(self, value, options) - - options.delete(:style) - options.delete(:type) - options.delete(:formula_value) + self[index] = Cell.new(self, value, options) end end end diff --git a/lib/axlsx/workbook/worksheet/row_breaks.rb b/lib/axlsx/workbook/worksheet/row_breaks.rb index 1765c241..c6ec89a9 100644 --- a/lib/axlsx/workbook/worksheet/row_breaks.rb +++ b/lib/axlsx/workbook/worksheet/row_breaks.rb @@ -14,7 +14,7 @@ module Axlsx # @see Break def add_break(options) # force feed the excel default - @list << Break.new(options.merge(:max => 16383, :man => true)) + self << Break.new(options.merge(:max => 16383, :man => true)) last end @@ -25,7 +25,7 @@ module Axlsx # </rowBreaks> def to_xml_string(str='') return if empty? - str << '<rowBreaks count="' << @list.size.to_s << '" manualBreakCount="' << @list.size.to_s << '">' + str << ('<rowBreaks count="' << self.size.to_s << '" manualBreakCount="' << self.size.to_s << '">') each { |brk| brk.to_xml_string(str) } str << '</rowBreaks>' end diff --git a/lib/axlsx/workbook/worksheet/selection.rb b/lib/axlsx/workbook/worksheet/selection.rb index 432216b7..fcb06c13 100644 --- a/lib/axlsx/workbook/worksheet/selection.rb +++ b/lib/axlsx/workbook/worksheet/selection.rb @@ -95,9 +95,7 @@ module Axlsx # @param [String] str # @return [String] def to_xml_string(str = '') - str << '<selection ' - serialized_attributes str - str << '/>' + serialized_tag 'selection', str end end end diff --git a/lib/axlsx/workbook/worksheet/sheet_data.rb b/lib/axlsx/workbook/worksheet/sheet_data.rb index f9297711..a7b8735b 100644 --- a/lib/axlsx/workbook/worksheet/sheet_data.rb +++ b/lib/axlsx/workbook/worksheet/sheet_data.rb @@ -17,7 +17,9 @@ module Axlsx # @return [String] def to_xml_string(str = '') str << '<sheetData>' - worksheet.rows.each_with_index{ |row, index| row.to_xml_string(index, str) } + worksheet.rows.each_with_index do |row, index| + row.to_xml_string(index, str) + end str << '</sheetData>' end diff --git a/lib/axlsx/workbook/worksheet/sheet_protection.rb b/lib/axlsx/workbook/worksheet/sheet_protection.rb index 5ff888ea..c6142be5 100644 --- a/lib/axlsx/workbook/worksheet/sheet_protection.rb +++ b/lib/axlsx/workbook/worksheet/sheet_protection.rb @@ -76,9 +76,7 @@ module Axlsx # @param [String] str # @return [String] def to_xml_string(str = '') - str << '<sheetProtection ' - serialized_attributes str - str << '/>' + serialized_tag('sheetProtection', str) end private diff --git a/lib/axlsx/workbook/worksheet/table.rb b/lib/axlsx/workbook/worksheet/table.rb index 94474c57..6df71828 100644 --- a/lib/axlsx/workbook/worksheet/table.rb +++ b/lib/axlsx/workbook/worksheet/table.rb @@ -58,7 +58,7 @@ module Axlsx # @param [String, Cell] v # @return [Title] def name=(v) - DataTypeValidator.validate "#{self.class}.name", [String], v + DataTypeValidator.validate :table_name, [String], v if v.is_a?(String) @name = v end @@ -75,12 +75,12 @@ module Axlsx # @return [String] def to_xml_string(str = '') str << '<?xml version="1.0" encoding="UTF-8"?>' - str << '<table xmlns="' << XML_NS << '" id="' << (index+1).to_s << '" name="' << @name << '" displayName="' << @name.gsub(/\s/,'_') << '" ' - str << 'ref="' << @ref << '" totalsRowShown="0">' - str << '<autoFilter ref="' << @ref << '"/>' - str << '<tableColumns count="' << header_cells.length.to_s << '">' + str << ('<table xmlns="' << XML_NS << '" id="' << (index+1).to_s << '" name="' << @name << '" displayName="' << @name.gsub(/\s/,'_') << '" ') + str << ('ref="' << @ref << '" totalsRowShown="0">') + str << ('<autoFilter ref="' << @ref << '"/>') + str << ('<tableColumns count="' << header_cells.length.to_s << '">') header_cells.each_with_index do |cell,index| - str << '<tableColumn id ="' << (index+1).to_s << '" name="' << cell.value << '"/>' + str << ('<tableColumn id ="' << (index+1).to_s << '" name="' << cell.value << '"/>') end str << '</tableColumns>' table_style_info.to_xml_string(str) diff --git a/lib/axlsx/workbook/worksheet/table_style_info.rb b/lib/axlsx/workbook/worksheet/table_style_info.rb index 0e41ea50..22d85d41 100644 --- a/lib/axlsx/workbook/worksheet/table_style_info.rb +++ b/lib/axlsx/workbook/worksheet/table_style_info.rb @@ -43,9 +43,7 @@ module Axlsx # seralizes this object to an xml string # @param [String] str the string to contact this objects serialization to. def to_xml_string(str = '') - str << '<tableStyleInfo ' - serialized_attributes str - str << '/>' + serialized_tag('tableStyleInfo', str) end end end diff --git a/lib/axlsx/workbook/worksheet/tables.rb b/lib/axlsx/workbook/worksheet/tables.rb index 814f995f..624c96c4 100644 --- a/lib/axlsx/workbook/worksheet/tables.rb +++ b/lib/axlsx/workbook/worksheet/tables.rb @@ -23,7 +23,7 @@ module Axlsx def to_xml_string(str = "") return if empty? str << "<tableParts count='#{size}'>" - @list.each { |table| str << "<tablePart r:id='#{table.rId}'/>" } + each { |table| str << "<tablePart r:id='#{table.rId}'/>" } str << '</tableParts>' end end diff --git a/lib/axlsx/workbook/worksheet/worksheet.rb b/lib/axlsx/workbook/worksheet/worksheet.rb index f034a000..a2d58562 100644 --- a/lib/axlsx/workbook/worksheet/worksheet.rb +++ b/lib/axlsx/workbook/worksheet/worksheet.rb @@ -7,12 +7,8 @@ module Axlsx include Axlsx::SerializedAttributes # definition of characters which are less than the maximum width of 0-9 in the default font for use in String#count. # This is used for autowidth calculations - # @return [String] - def self.thin_chars - # removed 'e' and 'y' from this list - as a GUESS - @thin_chars ||= "^.acfijklrstxzFIJL()-" - end - + THIN_CHARS = '^.acfijklrstxzFIJL()-'.freeze + # Creates a new worksheet. # @note the recommended way to manage worksheets is Workbook#add_worksheet # @see Workbook#add_worksheet @@ -47,7 +43,7 @@ module Axlsx # The name of the worksheet # @return [String] def name - @name ||= "Sheet" + (index+1).to_s + @name ||= "Sheet" + (index+1).to_s end # Specifies the visible state of this sheet. Allowed states are @@ -57,7 +53,7 @@ module Axlsx # :very_hidden sheets should be inaccessible to end users. # @param [Symbol] sheet_state The visible state for this sheet. def state=(sheet_state) - RestrictionValidator.validate "Worksheet#state", [:visible, :hidden, :very_hidden], sheet_state + RestrictionValidator.validate :worksheet_state, [:visible, :hidden, :very_hidden], sheet_state @state = sheet_state end @@ -148,7 +144,7 @@ module Axlsx # @return [SimpleTypedList] # @see Worksheet#add_row def rows - @rows ||= SimpleTypedList.new Row + @rows ||= SimpleTypedList.new Row end # returns the sheet data as columns @@ -365,7 +361,7 @@ module Axlsx # @param [String] v # @see auto_filter def auto_filter=(v) - DataTypeValidator.validate "Worksheet.auto_filter", String, v + DataTypeValidator.validate :worksheet_auto_filter, String, v auto_filter.range = v end @@ -447,7 +443,7 @@ module Axlsx # @option options [Float] height the row's height (in points) def add_row(values=[], options={}) Row.new(self, values, options) - update_column_info @rows.last.cells, options.delete(:widths) || [] + update_column_info @rows.last, options.delete(:widths) yield @rows.last if block_given? @rows.last end @@ -541,7 +537,7 @@ module Axlsx # @example # ws.add_page_break("A4") def add_page_break(cell) - DataTypeValidator.validate "Worksheet#add_page_break cell", [String, Cell], cell + DataTypeValidator.validate :worksheet_page_break, [String, Cell], cell column_index, row_index = if cell.is_a?(String) Axlsx.name_to_indices(cell) else @@ -578,7 +574,7 @@ module Axlsx # @see README.md for an example def col_style(index, style, options={}) offset = options.delete(:row_offset) || 0 - cells = @rows[(offset..-1)].map { |row| row.cells[index] }.flatten.compact + cells = @rows[(offset..-1)].map { |row| row[index] }.flatten.compact cells.each { |cell| cell.style = style } end @@ -601,23 +597,21 @@ module Axlsx add_autofilter_defined_name_to_workbook str << '<sheet ' serialized_attributes str - str << "r:id='" << rId << "'" - str << '></sheet>' + str << ("r:id='" << rId << '\'></sheet>') end # Serializes the worksheet object to an xml string # This intentionally does not use nokogiri for performance reasons # @return [String] - def to_xml_string + def to_xml_string str='' add_autofilter_defined_name_to_workbook auto_filter.apply if auto_filter.range - str = '<?xml version="1.0" encoding="UTF-8"?>' + str << '<?xml version="1.0" encoding="UTF-8"?>' str << worksheet_node serializable_parts.each do |item| item.to_xml_string(str) if item end str << '</worksheet>' - Axlsx::sanitize(str) end # The worksheet relationships. This is managed automatically by the worksheet @@ -651,7 +645,7 @@ module Axlsx def name_to_cell(name) col_index, row_index = *Axlsx::name_to_indices(name) r = rows[row_index] - r.cells[col_index] if r + r[col_index] if r end # shortcut method to access styles direclty from the worksheet @@ -704,7 +698,7 @@ module Axlsx end def validate_sheet_name(name) - DataTypeValidator.validate "Worksheet.name", String, name + DataTypeValidator.validate :worksheet_name, String, name raise ArgumentError, (ERR_SHEET_NAME_TOO_LONG % name) if name.size > 31 raise ArgumentError, (ERR_SHEET_NAME_CHARACTER_FORBIDDEN % name) if '[]*/\?:'.chars.any? { |char| name.include? char } name = Axlsx::coder.encode(name) @@ -724,8 +718,8 @@ module Axlsx def range(*cell_def) first, last = cell_def cells = [] - rows[(first.row.index..last.row.index)].each do |r| - r.cells[(first.index..last.index)].each do |c| + rows[(first.row.row_index..last.row.row_index)].each do |r| + r[(first.index..last.index)].each do |c| cells << c end end @@ -763,7 +757,7 @@ module Axlsx # Helper method for parsingout the root node for worksheet # @return [String] def worksheet_node - "<worksheet xmlns=\"%s\" xmlns:r=\"%s\" xml:space=\"#{xml_space}\">" % [XML_NS, XML_NS_R] + "<worksheet xmlns=\"#{XML_NS}\" xmlns:r=\"#{XML_NS_R}\" xml:space=\"#{xml_space}\">" end def sheet_data @@ -782,11 +776,12 @@ module Axlsx def workbook=(v) DataTypeValidator.validate "Worksheet.workbook", Workbook, v; @workbook = v; end - def update_column_info(cells, widths=[]) + def update_column_info(cells, widths=nil) cells.each_with_index do |cell, index| + width = widths ? widths[index] : nil col = find_or_create_column_info(index) - next if widths[index] == :ignore - col.update_width(cell, widths[index], workbook.use_autowidth) + next if width == :ignore + col.update_width(cell, width, workbook.use_autowidth) end end diff --git a/lib/axlsx/workbook/worksheet/worksheet_hyperlinks.rb b/lib/axlsx/workbook/worksheet/worksheet_hyperlinks.rb index 7659655a..a242f0f8 100644 --- a/lib/axlsx/workbook/worksheet/worksheet_hyperlinks.rb +++ b/lib/axlsx/workbook/worksheet/worksheet_hyperlinks.rb @@ -15,8 +15,8 @@ module Axlsx # @see WorksheetHyperlink#initialize # @return [WorksheetHyperlink] def add(options) - @list << WorksheetHyperlink.new(@worksheet, options) - @list.last + self << WorksheetHyperlink.new(@worksheet, options) + last end # The relationships required by this collection's hyperlinks @@ -31,7 +31,7 @@ module Axlsx def to_xml_string(str='') return if empty? str << '<hyperlinks>' - @list.each { |hyperlink| hyperlink.to_xml_string(str) } + each { |hyperlink| hyperlink.to_xml_string(str) } str << '</hyperlinks>' end end diff --git a/test/util/tc_simple_typed_list.rb b/test/util/tc_simple_typed_list.rb index d74cc9cc..1596ac13 100644 --- a/test/util/tc_simple_typed_list.rb +++ b/test/util/tc_simple_typed_list.rb @@ -72,7 +72,6 @@ class TestSimpleTypedList < Test::Unit::TestCase def test_equality @list.push 1 @list.push 2 - assert_equal(@list, [1,2]) - + assert_equal(@list.to_ary, [1,2]) end end diff --git a/test/workbook/worksheet/tc_cell.rb b/test/workbook/worksheet/tc_cell.rb index baa7a9f1..e42cf09f 100644 --- a/test/workbook/worksheet/tc_cell.rb +++ b/test/workbook/worksheet/tc_cell.rb @@ -34,7 +34,7 @@ class TestCell < Test::Unit::TestCase end def test_pos - assert_equal(@c.pos, [@c.index, @c.row.index]) + assert_equal(@c.pos, [@c.index, @c.row.index(@c)]) end def test_r diff --git a/test/workbook/worksheet/tc_row.rb b/test/workbook/worksheet/tc_row.rb index d847d475..8a057c26 100644 --- a/test/workbook/worksheet/tc_row.rb +++ b/test/workbook/worksheet/tc_row.rb @@ -29,7 +29,7 @@ class TestRow < Test::Unit::TestCase def test_index - assert_equal(@row.index, @row.worksheet.rows.index(@row)) + assert_equal(@row.row_index, @row.worksheet.rows.index(@row)) end def test_add_cell diff --git a/test/workbook/worksheet/tc_worksheet.rb b/test/workbook/worksheet/tc_worksheet.rb index 74253613..b399b306 100644 --- a/test/workbook/worksheet/tc_worksheet.rb +++ b/test/workbook/worksheet/tc_worksheet.rb @@ -398,10 +398,13 @@ class TestWorksheet < Test::Unit::TestCase end def test_to_xml_string_with_illegal_chars + old = Axlsx::trust_input + Axlsx::trust_input = false nasties = "\v\u2028\u0001\u0002\u0003\u0004\u0005\u0006\u0007\u0008\u001f" @ws.add_row [nasties] - assert_equal(0, @ws.rows.last.cells.last.value.index("\v")) - assert_equal(nil,@ws.to_xml_string.index("\v")) + assert_equal(nil, @ws.rows.last.cells.last.value.index("\v")) + assert_equal(nil, @ws.to_xml_string.index("\v")) + Axlsx::trust_input = old end def test_to_xml_string_with_newlines |
