summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--.travis.yml43
-rw-r--r--Gemfile11
-rw-r--r--README.md2
-rw-r--r--appveyor.yml23
-rw-r--r--axlsx.gemspec2
-rw-r--r--lib/axlsx/drawing/pic.rb2
-rw-r--r--lib/axlsx/drawing/scaling.rb4
-rw-r--r--lib/axlsx/drawing/view_3D.rb4
-rw-r--r--lib/axlsx/package.rb6
-rw-r--r--lib/axlsx/stylesheet/num_fmt.rb9
-rw-r--r--lib/axlsx/util/constants.rb2
-rw-r--r--lib/axlsx/util/simple_typed_list.rb2
-rw-r--r--lib/axlsx/util/validators.rb10
-rw-r--r--lib/axlsx/workbook/workbook.rb1
-rw-r--r--lib/axlsx/workbook/worksheet/cell.rb6
-rw-r--r--lib/axlsx/workbook/worksheet/cell_serializer.rb18
-rw-r--r--lib/axlsx/workbook/worksheet/merged_cells.rb2
-rw-r--r--lib/axlsx/workbook/worksheet/outline_pr.rb33
-rw-r--r--lib/axlsx/workbook/worksheet/pivot_table.rb33
-rw-r--r--lib/axlsx/workbook/worksheet/row.rb7
-rw-r--r--lib/axlsx/workbook/worksheet/sheet_pr.rb10
-rw-r--r--lib/axlsx/workbook/worksheet/worksheet.rb7
-rw-r--r--test/stylesheet/tc_styles.rb4
-rw-r--r--test/tc_axlsx.rb10
-rw-r--r--test/tc_helper.rb4
-rw-r--r--test/tc_package.rb5
-rw-r--r--test/util/tc_simple_typed_list.rb2
-rw-r--r--test/workbook/tc_workbook.rb6
-rw-r--r--test/workbook/worksheet/tc_cell.rb37
-rw-r--r--test/workbook/worksheet/tc_outline_pr.rb19
-rw-r--r--test/workbook/worksheet/tc_pivot_table.rb20
-rw-r--r--test/workbook/worksheet/tc_row.rb5
-rw-r--r--test/workbook/worksheet/tc_worksheet.rb19
33 files changed, 303 insertions, 65 deletions
diff --git a/.travis.yml b/.travis.yml
index 8371fef4..657f9173 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,28 +1,41 @@
language: ruby
-sudo: false
+sudo: required
+dist: trusty
+group: beta
cache: bundler
bundler_args: --without profile
-env:
- - JRUBY_OPTS="-Xcli.debug=true --debug"
+
notifications:
irc: "irc.freenode.org#axlsx"
email:
recipients:
on_success: always
-rvm:
- - 1.9.2
- - 1.9.3
- - 2.0
- - 2.1
- - 2.2
- - rbx
- - jruby-19mode
- - jruby-9.0.0.0
- - ruby-head
- - jruby-head
+
matrix:
+ include:
+ - rvm: 2.1
+ - rvm: 2.2.8
+ - rvm: 2.3.5
+ - rvm: 2.0.0
+ - rvm: 2.4.2
+ - rvm: rbx-3
+ - rvm: jruby-19mode
+ env: JRUBY_OPTS="-Xcli.debug=true --debug"
+ - rvm: jruby-9.1.8.0
+ env: JRUBY_OPTS="-Xcli.debug=true --debug"
+ - rvm: ruby-head
+ - rvm: jruby-head
+ env: JRUBY_OPTS="-Xcli.debug=true --debug"
allow_failures:
+ - rvm: rbx-3
- rvm: ruby-head
- - rvm: jruby-9.0.0.0
+ - rvm: jruby-9.1.8.0
- rvm: jruby-head
+
+# https://github.com/jruby/jruby/wiki/FAQs#why-is-jruby-so-slow-to-install-via-rvm
+# https://docs.travis-ci.com/user/installing-dependencies#Installing-Packages-with-the-APT-Addon
+addons:
+ apt:
+ packages:
+ - haveged
diff --git a/Gemfile b/Gemfile
index 3904ab32..89ed374d 100644
--- a/Gemfile
+++ b/Gemfile
@@ -2,18 +2,23 @@ source 'https://rubygems.org'
gemspec
group :test do
- gem 'rake', '>= 0.8.7'
+ if RUBY_VERSION.to_i < 2
+ gem 'rake', '>= 0.8.7', '< 11'
+ gem 'json', '< 2'
+ else
+ gem 'rake'
+ end
gem 'simplecov'
gem 'test-unit'
end
group :profile do
- gem 'ruby-prof'
+ gem 'ruby-prof', :platforms => :ruby
end
platforms :rbx do
gem 'rubysl'
gem 'rubysl-test-unit'
gem 'racc'
- gem 'rubinius-coverage', '~> 2.0'
+ gem 'rubinius-coverage', '~> 2.0'
end
diff --git a/README.md b/README.md
index 985c76cc..223b2f59 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
Axlsx: Office Open XML Spreadsheet Generation
====================================
-[![Build Status](https://secure.travis-ci.org/randym/axlsx.png?branch=master)](http://travis-ci.org/randym/axlsx/)
+[![Build Status](https://secure.travis-ci.org/randym/axlsx.svg?branch=master)](http://travis-ci.org/randym/axlsx/)
If you are using axlsx for commercial purposes, or just want to show your
appreciation for the gem, please don't hesitate to make a donation.
diff --git a/appveyor.yml b/appveyor.yml
new file mode 100644
index 00000000..0d7d5fce
--- /dev/null
+++ b/appveyor.yml
@@ -0,0 +1,23 @@
+version: 2.1.0.{build}-{branch}
+
+environment:
+ matrix:
+ - RUBY_VERSION: 23
+ - RUBY_VERSION: 22
+ - RUBY_VERSION: 21
+ - RUBY_VERSION: 200
+ - RUBY_VERSION: 193
+
+install:
+ - set PATH=C:\Ruby%RUBY_VERSION%\bin;%PATH%
+ - bundle install
+
+build: off
+
+before_test:
+ - ruby -v
+ - gem -v
+ - bundle -v
+
+test_script:
+ - bundle exec rake
diff --git a/axlsx.gemspec b/axlsx.gemspec
index b4cec557..228d5a98 100644
--- a/axlsx.gemspec
+++ b/axlsx.gemspec
@@ -18,7 +18,7 @@ Gem::Specification.new do |s|
s.test_files = Dir.glob("{test/**/*}")
s.add_runtime_dependency 'nokogiri', '>= 1.6.6'
- s.add_runtime_dependency 'rubyzip', '~> 1.1.7'
+ s.add_runtime_dependency 'rubyzip', '>= 1.2.1'
s.add_runtime_dependency "htmlentities", "~> 4.3.4"
s.add_runtime_dependency "mimemagic", "~> 0.3"
diff --git a/lib/axlsx/drawing/pic.rb b/lib/axlsx/drawing/pic.rb
index 275a6d06..5a418df0 100644
--- a/lib/axlsx/drawing/pic.rb
+++ b/lib/axlsx/drawing/pic.rb
@@ -53,7 +53,7 @@ module Axlsx
attr_reader :hyperlink
# Picture opacity
- # @return [Fixnum]
+ # @return [Integer]
attr_reader :opacity
# sets or updates a hyperlink for this image.
diff --git a/lib/axlsx/drawing/scaling.rb b/lib/axlsx/drawing/scaling.rb
index fcbea9f8..4c9d6888 100644
--- a/lib/axlsx/drawing/scaling.rb
+++ b/lib/axlsx/drawing/scaling.rb
@@ -6,7 +6,7 @@ module Axlsx
include Axlsx::OptionsParser
# creates a new Scaling object
- # @option options [Integer, Fixnum] logBase
+ # @option options [Integer] logBase
# @option options [Symbol] orientation
# @option options [Float] max
# @option options [Float] min
@@ -35,7 +35,7 @@ module Axlsx
attr_reader :min
# @see logBase
- def logBase=(v) DataTypeValidator.validate "Scaling.logBase", [Integer, Fixnum], v, lambda { |arg| arg >= 2 && arg <= 1000}; @logBase = v; end
+ def logBase=(v) DataTypeValidator.validate "Scaling.logBase", [Integer], v, lambda { |arg| arg >= 2 && arg <= 1000}; @logBase = v; end
# @see orientation
def orientation=(v) RestrictionValidator.validate "Scaling.orientation", [:minMax, :maxMin], v; @orientation = v; end
# @see max
diff --git a/lib/axlsx/drawing/view_3D.rb b/lib/axlsx/drawing/view_3D.rb
index 9c320b4a..55bbc6c3 100644
--- a/lib/axlsx/drawing/view_3D.rb
+++ b/lib/axlsx/drawing/view_3D.rb
@@ -86,12 +86,12 @@ module Axlsx
alias :rAngAx= :r_ang_ax=
# @see perspective
- def perspective=(v)
+ def perspective=(v)
RangeValidator.validate "View3D.perspective", 0, 240, v
@perspective = v
end
- # DataTypeValidator.validate "#{self.class}.perspective", [Integer, Fixnum], v, lambda {|arg| arg >= 0 && arg <= 240 }; @perspective = v; end
+ # DataTypeValidator.validate "#{self.class}.perspective", [Integer], v, lambda {|arg| arg >= 0 && arg <= 240 }; @perspective = v; end
# Serializes the object
# @param [String] str
diff --git a/lib/axlsx/package.rb b/lib/axlsx/package.rb
index 8a4f29dc..5b5ea14a 100644
--- a/lib/axlsx/package.rb
+++ b/lib/axlsx/package.rb
@@ -1,4 +1,4 @@
-# encoding: UTF-8
+# encoding: utf-8
module Axlsx
# Package is responsible for managing all the bits and peices that Open Office XML requires to make a valid
# xlsx document including valdation and serialization.
@@ -253,7 +253,9 @@ module Axlsx
parts << {:entry => "xl/#{sheet.rels_pn}", :doc => sheet.relationships, :schema => RELS_XSD}
parts << {:entry => "xl/#{sheet.pn}", :doc => sheet, :schema => SML_XSD}
end
- parts
+
+ # Sort parts for correct MIME detection
+ parts.sort_by { |part| part[:entry] }
end
# Performs xsd validation for a signle document
diff --git a/lib/axlsx/stylesheet/num_fmt.rb b/lib/axlsx/stylesheet/num_fmt.rb
index 8276ba18..1072d18a 100644
--- a/lib/axlsx/stylesheet/num_fmt.rb
+++ b/lib/axlsx/stylesheet/num_fmt.rb
@@ -73,5 +73,14 @@ module Axlsx
serialized_tag('numFmt', str)
end
+ # Override to avoid removing underscores
+ def serialized_attributes(str = '', additional_attributes = {})
+ attributes = declared_attributes.merge! additional_attributes
+ attributes.each do |key, value|
+ str << "#{Axlsx.camel(key, false)}=\"#{Axlsx.booleanize(value)}\" "
+ end
+ str
+ end
+
end
end
diff --git a/lib/axlsx/util/constants.rb b/lib/axlsx/util/constants.rb
index ea9b1ceb..64bae270 100644
--- a/lib/axlsx/util/constants.rb
+++ b/lib/axlsx/util/constants.rb
@@ -67,7 +67,7 @@ module Axlsx
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".freeze
+ CORE_R = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties".freeze
# digital signature rels namespace
DIGITAL_SIGNATURE_R = "http://schemas.openxmlformats.org/package/2006/relationships/digital- signature/signature".freeze
diff --git a/lib/axlsx/util/simple_typed_list.rb b/lib/axlsx/util/simple_typed_list.rb
index 95f5b3f2..77bed775 100644
--- a/lib/axlsx/util/simple_typed_list.rb
+++ b/lib/axlsx/util/simple_typed_list.rb
@@ -147,7 +147,7 @@ module Axlsx
# determines if the index is protected
# @param [Integer] index
def protected? index
- return false unless locked_at.is_a? Fixnum
+ return false unless locked_at.is_a? Integer
index < locked_at
end
diff --git a/lib/axlsx/util/validators.rb b/lib/axlsx/util/validators.rb
index 9c6f34aa..2b4afd8d 100644
--- a/lib/axlsx/util/validators.rb
+++ b/lib/axlsx/util/validators.rb
@@ -80,16 +80,16 @@ module Axlsx
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
+
+ # Requires that the value is a 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
+ # @raise [ArgumentError] raised if the value is not a 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, Integer, v, UINT_VALIDATOR)
end
- # Requires that the value is a Fixnum Integer or Float and is greater or equal to 0
+ # Requires that the value is a Integer or Float and is greater or equal to 0
# @param [Any] v The value validated
# @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
@@ -104,7 +104,7 @@ module Axlsx
end
# Requires that the value is a form that can be evaluated as a boolean in an xml document.
- # The value must be an instance of Fixnum, String, Integer, Symbol, TrueClass or FalseClass and
+ # The value must be an instance of String, Integer, Symbol, TrueClass or FalseClass and
# 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)
diff --git a/lib/axlsx/workbook/workbook.rb b/lib/axlsx/workbook/workbook.rb
index ddb13600..4ba44adb 100644
--- a/lib/axlsx/workbook/workbook.rb
+++ b/lib/axlsx/workbook/workbook.rb
@@ -11,6 +11,7 @@ require 'axlsx/workbook/worksheet/cell_serializer.rb'
require 'axlsx/workbook/worksheet/cell.rb'
require 'axlsx/workbook/worksheet/page_margins.rb'
require 'axlsx/workbook/worksheet/page_set_up_pr.rb'
+require 'axlsx/workbook/worksheet/outline_pr.rb'
require 'axlsx/workbook/worksheet/page_setup.rb'
require 'axlsx/workbook/worksheet/header_footer.rb'
require 'axlsx/workbook/worksheet/print_options.rb'
diff --git a/lib/axlsx/workbook/worksheet/cell.rb b/lib/axlsx/workbook/worksheet/cell.rb
index cd832f7b..777b7812 100644
--- a/lib/axlsx/workbook/worksheet/cell.rb
+++ b/lib/axlsx/workbook/worksheet/cell.rb
@@ -66,7 +66,7 @@ module Axlsx
:vertAlign, :sz, :color, :scheme].freeze
CELL_TYPES = [:date, :time, :float, :integer, :richtext,
- :string, :boolean, :iso_8601].freeze
+ :string, :boolean, :iso_8601, :text].freeze
# The index of the cellXfs item to be applied to this cell.
# @return [Integer]
@@ -123,7 +123,7 @@ module Axlsx
# Indicates if the cell is good for shared string table
def plain_string?
- type == :string && # String typed
+ (type == :string || type == :text) && # String typed
!is_text_run? && # No inline styles
[email protected]? && # Not nil
[email protected]? && # Not empty
@@ -368,7 +368,7 @@ module Axlsx
# TODO find a better way to do this as it accounts for 30% of
# processing time in benchmarking...
def clean_value
- if type == :string && !Axlsx::trust_input
+ if (type == :string || type == :text) && !Axlsx::trust_input
Axlsx::sanitize(::CGI.escapeHTML(@value.to_s))
else
@value.to_s
diff --git a/lib/axlsx/workbook/worksheet/cell_serializer.rb b/lib/axlsx/workbook/worksheet/cell_serializer.rb
index 9a9f9465..76a3c386 100644
--- a/lib/axlsx/workbook/worksheet/cell_serializer.rb
+++ b/lib/axlsx/workbook/worksheet/cell_serializer.rb
@@ -14,7 +14,7 @@ module Axlsx
method = cell.type
self.send(method, cell, str)
str << '</c>'
- end
+ end
# builds an xml text run based on this cells attributes.
# @param [String] str The string instance this run will be concated to.
@@ -22,7 +22,7 @@ module Axlsx
def run_xml_string(cell, str = '')
if cell.is_text_run?
valid = RichTextRun::INLINE_STYLES - [:value, :type]
- data = Hash[cell.instance_values.map{ |k, v| [k.to_sym, v] }]
+ data = Hash[cell.instance_values.map{ |k, v| [k.to_sym, v] }]
data = data.select { |key, value| valid.include?(key) && !value.nil? }
RichText.new(cell.value.to_s, data).to_xml_string(str)
elsif cell.contains_rich_text?
@@ -124,7 +124,7 @@ module Axlsx
inline_string_serialization cell, str
end
end
-
+
# Serializes cells that are of the type richtext
# @param [Cell] cell The cell that is being serialized
# @param [String] str The string the serialized content will be appended to.
@@ -137,6 +137,18 @@ module Axlsx
end
end
+ # Serializes cells that are of the type text
+ # @param [Cell] cell The cell that is being serialized
+ # @param [String] str The string the serialized content will be appended to.
+ # @return [String]
+ def text(cell, str)
+ if cell.ssti.nil?
+ inline_string_serialization cell, str
+ else
+ value_serialization 's', cell.ssti, str
+ end
+ end
+
private
def numeric(cell, str = '')
diff --git a/lib/axlsx/workbook/worksheet/merged_cells.rb b/lib/axlsx/workbook/worksheet/merged_cells.rb
index 6ea1edc9..67753bd3 100644
--- a/lib/axlsx/workbook/worksheet/merged_cells.rb
+++ b/lib/axlsx/workbook/worksheet/merged_cells.rb
@@ -19,6 +19,8 @@ module Axlsx
cells
elsif cells.is_a?(Array)
Axlsx::cell_range(cells, false)
+ elsif cells.is_a?(Row)
+ Axlsx::cell_range(cells, false)
end
end
diff --git a/lib/axlsx/workbook/worksheet/outline_pr.rb b/lib/axlsx/workbook/worksheet/outline_pr.rb
new file mode 100644
index 00000000..ae9ccf38
--- /dev/null
+++ b/lib/axlsx/workbook/worksheet/outline_pr.rb
@@ -0,0 +1,33 @@
+module Axlsx
+
+ # The OutlinePr class manages serialization of a worksheet's outlinePr element, which provides various
+ # options to control outlining.
+ class OutlinePr
+ include Axlsx::OptionsParser
+ include Axlsx::Accessors
+ include Axlsx::SerializedAttributes
+
+ serializable_attributes :summary_below,
+ :summary_right,
+ :apply_styles
+
+ # These attributes are all boolean so I'm doing a bit of a hand
+ # waving magic show to set up the attriubte accessors
+ boolean_attr_accessor :summary_below,
+ :summary_right,
+ :apply_styles
+
+ # Creates a new OutlinePr object
+ # @param [Worksheet] worksheet The worksheet that owns this OutlinePr object
+ def initialize(options = {})
+ parse_options options
+ end
+
+ # Serialize the object
+ # @param [String] str serialized output will be appended to this object if provided.
+ # @return [String]
+ def to_xml_string(str = '')
+ str << "<outlinePr #{serialized_attributes} />"
+ end
+ end
+end
diff --git a/lib/axlsx/workbook/worksheet/pivot_table.rb b/lib/axlsx/workbook/worksheet/pivot_table.rb
index 0d5f34e8..fffced0b 100644
--- a/lib/axlsx/workbook/worksheet/pivot_table.rb
+++ b/lib/axlsx/workbook/worksheet/pivot_table.rb
@@ -25,10 +25,20 @@ module Axlsx
@data = []
@pages = []
@subtotal = nil
+ @no_subtotals_on_headers = []
+ @style_info = {}
parse_options options
yield self if block_given?
end
+ # Defines the headers in which subtotals are not to be included
+ # @return[Array]
+ attr_accessor :no_subtotals_on_headers
+
+ # Style info for the pivot table
+ # @return[Hash]
+ attr_accessor :style_info
+
# The reference to the table data
# @return [String]
attr_reader :ref
@@ -163,7 +173,7 @@ module Axlsx
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)
+ str << pivot_field_for(cell_value,!no_subtotals_on_headers.include?(cell_value))
end
str << '</pivotFields>'
if rows.empty?
@@ -200,12 +210,21 @@ module Axlsx
unless data.empty?
str << "<dataFields count=\"#{data.size}\">"
data.each do |datum_value|
- str << "<dataField name='#{@subtotal} of #{datum_value[:ref]}' fld='#{header_index_of(datum_value[:ref])}' baseField='0' baseItem='0'"
+ # The correct name prefix in ["Sum","Average", etc...]
+ str << "<dataField name='#{(datum_value[:subtotal]||'')} of #{datum_value[:ref]}' fld='#{header_index_of(datum_value[:ref])}' baseField='0' baseItem='0'"
str << " subtotal='#{datum_value[:subtotal]}' " if datum_value[:subtotal]
str << "/>"
end
str << '</dataFields>'
end
+ # custom pivot table style
+ unless style_info.empty?
+ str << '<pivotTableStyleInfo'
+ style_info.each do |k,v|
+ str << ' ' << k.to_s << '="' << v.to_s << '"'
+ end
+ str << ' />'
+ end
str << '</pivotTableDefinition>'
end
@@ -241,13 +260,17 @@ module Axlsx
private
- def pivot_field_for(cell_ref)
+ def pivot_field_for(cell_ref, subtotal=true)
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>'
+ if subtotal
+ '<pivotField axis="axisRow" compact="0" outline="0" subtotalTop="0" showAll="0" includeNewItemsInFilter="1">' + '<items count="1"><item t="default"/></items>' + '</pivotField>'
+ else
+ '<pivotField axis="axisRow" compact="0" outline="0" subtotalTop="0" showAll="0" includeNewItemsInFilter="1" defaultSubtotal="0">' + '</pivotField>'
+ end
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>'
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="axisPage" 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>'
else
diff --git a/lib/axlsx/workbook/worksheet/row.rb b/lib/axlsx/workbook/worksheet/row.rb
index 078e281f..b394279f 100644
--- a/lib/axlsx/workbook/worksheet/row.rb
+++ b/lib/axlsx/workbook/worksheet/row.rb
@@ -103,6 +103,13 @@ module Axlsx
c
end
+ # sets the color for every cell in this row
+ def color=(color)
+ each_with_index do | cell, index |
+ cell.color = color.is_a?(Array) ? color[index] : color
+ end
+ end
+
# sets the style for every cell in this row
def style=(style)
each_with_index do | cell, index |
diff --git a/lib/axlsx/workbook/worksheet/sheet_pr.rb b/lib/axlsx/workbook/worksheet/sheet_pr.rb
index a299bc0f..fd6dad2b 100644
--- a/lib/axlsx/workbook/worksheet/sheet_pr.rb
+++ b/lib/axlsx/workbook/worksheet/sheet_pr.rb
@@ -1,6 +1,6 @@
module Axlsx
- # The SheetPr class manages serialization fo a worksheet's sheetPr element.
+ # The SheetPr class manages serialization of a worksheet's sheetPr element.
class SheetPr
include Axlsx::OptionsParser
include Axlsx::Accessors
@@ -33,6 +33,7 @@ module Axlsx
def initialize(worksheet, options={})
raise ArgumentError, "you must provide a worksheet" unless worksheet.is_a?(Worksheet)
@worksheet = worksheet
+ @outline_pr = nil
parse_options options
end
@@ -51,6 +52,7 @@ module Axlsx
update_properties
str << "<sheetPr #{serialized_attributes}>"
tab_color.to_xml_string(str, 'tabColor') if tab_color
+ outline_pr.to_xml_string(str) if @outline_pr
page_setup_pr.to_xml_string(str)
str << "</sheetPr>"
end
@@ -60,6 +62,12 @@ module Axlsx
def page_setup_pr
@page_setup_pr ||= PageSetUpPr.new
end
+
+ # The OutlinePr for this sheet pr object
+ # @return [OutlinePr]
+ def outline_pr
+ @outline_pr ||= OutlinePr.new
+ end
# @see tab_color
def tab_color=(v)
diff --git a/lib/axlsx/workbook/worksheet/worksheet.rb b/lib/axlsx/workbook/worksheet/worksheet.rb
index dc8da53f..f094c5cd 100644
--- a/lib/axlsx/workbook/worksheet/worksheet.rb
+++ b/lib/axlsx/workbook/worksheet/worksheet.rb
@@ -27,7 +27,7 @@ module Axlsx
yield self if block_given?
end
- serializable_attributes :sheet_id, :name, :state
+ serializable_attributes :sheet_id, :state
# Initalizes page margin, setup and print options
# @param [Hash] options Options passed in from the initializer
@@ -264,7 +264,7 @@ module Axlsx
@header_footer
end
- # convinience method to access all cells in this worksheet
+ # convenience method to access all cells in this worksheet
# @return [Array] cells
def cells
rows.flatten
@@ -555,7 +555,7 @@ module Axlsx
# @example This would set the first and third column widhts but leave the second column in autofit state.
# ws.column_widths 7.2, nil, 3
# @note For updating only a single column it is probably easier to just set the width of the ws.column_info[col_index].width directly
- # @param [Integer|Float|Fixnum|nil] widths
+ # @param [Integer|Float|nil] widths
def column_widths(*widths)
widths.each_with_index do |value, index|
next if value == nil
@@ -597,6 +597,7 @@ module Axlsx
add_autofilter_defined_name_to_workbook
str << '<sheet '
serialized_attributes str
+ str << ('name="' << name << '" ')
str << ('r:id="' << rId << '"></sheet>')
end
diff --git a/test/stylesheet/tc_styles.rb b/test/stylesheet/tc_styles.rb
index 98c8e3ef..eb1680ad 100644
--- a/test/stylesheet/tc_styles.rb
+++ b/test/stylesheet/tc_styles.rb
@@ -133,7 +133,7 @@ class TestStyles < Test::Unit::TestCase
:font_name => "woot font"
}
assert_equal(@styles.parse_font_options {}, nil, "noop if no font keys are set")
- assert_equal(@styles.parse_font_options(:b=>1).class, Fixnum, "return index of font if not :dxf type")
+ assert(@styles.parse_font_options(:b=>1).is_a?(Integer), "return index of font if not :dxf type")
assert_equal(@styles.parse_font_options(:b=>1, :type => :dxf).class, Axlsx::Font, "return font object if :dxf type")
f = @styles.parse_font_options(options.merge(:type => :dxf))
@@ -147,7 +147,7 @@ class TestStyles < Test::Unit::TestCase
def test_parse_fill_options
assert_equal(@styles.parse_fill_options {}, nil, "noop if no fill keys are set")
- assert_equal(@styles.parse_fill_options(:bg_color => "DE").class, Fixnum, "return index of fill if not :dxf type")
+ assert(@styles.parse_fill_options(:bg_color => "DE").is_a?(Integer), "return index of fill if not :dxf type")
assert_equal(@styles.parse_fill_options(:bg_color => "DE", :type => :dxf).class, Axlsx::Fill, "return fill object if :dxf type")
f = @styles.parse_fill_options(:bg_color => "DE", :type => :dxf)
assert(f.fill_type.bgColor.rgb == "FFDEDEDE")
diff --git a/test/tc_axlsx.rb b/test/tc_axlsx.rb
index 1be9166c..99832f63 100644
--- a/test/tc_axlsx.rb
+++ b/test/tc_axlsx.rb
@@ -45,6 +45,16 @@ class TestAxlsx < Test::Unit::TestCase
assert_equal(Axlsx.cell_range([c2, c1], true), "'Sheet &lt;''&gt;&quot; 1'!$A$1:$B$1")
end
+ def test_cell_range_row
+ p = Axlsx::Package.new
+ ws = p.workbook.add_worksheet
+ row = ws.add_row
+ row.add_cell
+ row.add_cell
+ row.add_cell
+ assert_equal("A1:C1", Axlsx.cell_range(row, false))
+ end
+
def test_name_to_indices
setup_wide
@wide_test_points.each do |key, value|
diff --git a/test/tc_helper.rb b/test/tc_helper.rb
index 96f545cd..396f19b2 100644
--- a/test/tc_helper.rb
+++ b/test/tc_helper.rb
@@ -7,4 +7,6 @@ end
require 'test/unit'
require "timecop"
-require "axlsx.rb" \ No newline at end of file
+require "axlsx.rb"
+# MIME detection for Microsoft Office 2007+ formats
+require 'mimemagic/overlay'
diff --git a/test/tc_package.rb b/test/tc_package.rb
index 0ad27f7d..58ff53b0 100644
--- a/test/tc_package.rb
+++ b/test/tc_package.rb
@@ -154,6 +154,11 @@ class TestPackage < Test::Unit::TestCase
assert package_1.to_stream.string == package_2.to_stream.string, "zip files are not identical"
end
+ def test_serialization_creates_files_with_excel_mime_type
+ assert_equal(MimeMagic.by_magic(@package.to_stream).type,
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
+ end
+
def test_validation
assert_equal(@package.validate.size, 0, @package.validate)
Axlsx::Workbook.send(:class_variable_set, :@@date1904, 9900)
diff --git a/test/util/tc_simple_typed_list.rb b/test/util/tc_simple_typed_list.rb
index 1596ac13..72bd6246 100644
--- a/test/util/tc_simple_typed_list.rb
+++ b/test/util/tc_simple_typed_list.rb
@@ -1,7 +1,7 @@
require 'tc_helper.rb'
class TestSimpleTypedList < Test::Unit::TestCase
def setup
- @list = Axlsx::SimpleTypedList.new Fixnum
+ @list = Axlsx::SimpleTypedList.new Integer
end
def teardown
diff --git a/test/workbook/tc_workbook.rb b/test/workbook/tc_workbook.rb
index 51dd01f4..ab400db1 100644
--- a/test/workbook/tc_workbook.rb
+++ b/test/workbook/tc_workbook.rb
@@ -136,4 +136,10 @@ class TestWorkbook < Test::Unit::TestCase
doc = Nokogiri::XML(@wb.to_xml_string)
assert_equal pivot_table.cache_definition.rId, doc.xpath("//xmlns:pivotCache").first["r:id"]
end
+
+ def test_worksheet_name_is_intact_after_serialized_into_xml
+ sheet = @wb.add_worksheet(:name => '_Example')
+ wb_xml = Nokogiri::XML(@wb.to_xml_string)
+ assert_equal sheet.name, wb_xml.xpath('//xmlns:workbook/xmlns:sheets/*[1]/@name').to_s
+ end
end
diff --git a/test/workbook/worksheet/tc_cell.rb b/test/workbook/worksheet/tc_cell.rb
index 5ae2a51f..f61a254f 100644
--- a/test/workbook/worksheet/tc_cell.rb
+++ b/test/workbook/worksheet/tc_cell.rb
@@ -238,7 +238,7 @@ class TestCell < Test::Unit::TestCase
@c.merge @row.cells.last
assert_equal(@c.row.worksheet.send(:merged_cells).last, "A1:C1")
end
-
+
def test_reverse_merge_with_cell
@c.row.add_cell 2
@c.row.add_cell 3
@@ -284,7 +284,7 @@ class TestCell < Test::Unit::TestCase
c_xml = Nokogiri::XML(@c.to_xml_string(1,1))
assert_equal(c_xml.xpath("/c[@s=1]").size, 1)
end
-
+
def test_to_xml_string_with_run
# Actually quite a number of similar run styles
# but the processing should be the same
@@ -294,7 +294,7 @@ class TestCell < Test::Unit::TestCase
@c.font_name = 'arial'
@c.color = 'FF0000'
c_xml = Nokogiri::XML(@c.to_xml_string(1,1))
- assert(c_xml.xpath("//b"))
+ assert(c_xml.xpath("//b").any?)
end
def test_to_xml_string_formula
@@ -303,8 +303,8 @@ class TestCell < Test::Unit::TestCase
sheet.add_row ["=IF(2+2=4,4,5)"]
end
doc = Nokogiri::XML(ws.to_xml_string)
- assert(doc.xpath("//f[@text()='IF(2+2=4,4,5)']"))
-
+ doc.remove_namespaces!
+ assert(doc.xpath("//f[text()='IF(2+2=4,4,5)']").any?)
end
def test_to_xml_string_array_formula
@@ -314,9 +314,24 @@ class TestCell < Test::Unit::TestCase
end
doc = Nokogiri::XML(ws.to_xml_string)
doc.remove_namespaces!
- assert(doc.xpath("//f[text()='SUM(C2:C11*D2:D11)']"))
- assert(doc.xpath("//f[@t='array']"))
- assert(doc.xpath("//f[@ref='A1']"))
+ assert(doc.xpath("//f[text()='SUM(C2:C11*D2:D11)']").any?)
+ assert(doc.xpath("//f[@t='array']").any?)
+ assert(doc.xpath("//f[@ref='A1']").any?)
+ end
+
+ def test_to_xml_string_text_formula
+ p = Axlsx::Package.new
+ ws = p.workbook.add_worksheet do |sheet|
+ sheet.add_row ["=1+1", "-1+1"], type: :text
+ end
+ doc = Nokogiri::XML(ws.to_xml_string)
+ doc.remove_namespaces!
+
+ assert(doc.xpath("//f[text()='1+1']").empty?)
+ assert(doc.xpath("//t[text()='=1+1']").any?)
+
+ assert(doc.xpath("//f[text()='1+1']").empty?)
+ assert(doc.xpath("//t[text()='-1+1']").any?)
end
def test_font_size_with_custom_style_and_no_sz
@@ -335,17 +350,17 @@ class TestCell < Test::Unit::TestCase
sz = @c.send(:font_size)
assert_equal(sz, 52)
end
-
+
def test_cell_with_sz
@c.sz = 25
assert_equal(25, @c.send(:font_size))
end
-
+
def test_to_xml
# TODO This could use some much more stringent testing related to the xml content generated!
@ws.add_row [Time.now, Date.today, true, 1, 1.0, "text", "=sum(A1:A2)", "2013-01-13T13:31:25.123"]
@ws.rows.last.cells[5].u = true
-
+
schema = Nokogiri::XML::Schema(File.open(Axlsx::SML_XSD))
doc = Nokogiri::XML(@ws.to_xml_string)
errors = []
diff --git a/test/workbook/worksheet/tc_outline_pr.rb b/test/workbook/worksheet/tc_outline_pr.rb
new file mode 100644
index 00000000..41a2b4ca
--- /dev/null
+++ b/test/workbook/worksheet/tc_outline_pr.rb
@@ -0,0 +1,19 @@
+require 'tc_helper.rb'
+
+class TestOutlinePr < Test::Unit::TestCase
+ def setup
+ @outline_pr = Axlsx::OutlinePr.new(:summary_below => false, :summary_right => true, :apply_styles => false)
+ end
+
+ def test_summary_below
+ assert_equal false, @outline_pr.summary_below
+ end
+
+ def test_summary_right
+ assert_equal true, @outline_pr.summary_right
+ end
+
+ def test_apply_styles
+ assert_equal false, @outline_pr.apply_styles
+ end
+end
diff --git a/test/workbook/worksheet/tc_pivot_table.rb b/test/workbook/worksheet/tc_pivot_table.rb
index 3c42d605..ff7f8b92 100644
--- a/test/workbook/worksheet/tc_pivot_table.rb
+++ b/test/workbook/worksheet/tc_pivot_table.rb
@@ -67,6 +67,26 @@ class TestPivotTable < Test::Unit::TestCase
assert_equal([{:ref=>"Sales", :subtotal => 'average'}], pivot_table.data)
end
+ def test_add_pivot_table_with_style_info
+ style_info_data = { :name=>"PivotStyleMedium9", :showRowHeaders=>"1", :showLastColumn=>"0"}
+ pivot_table = @ws.add_pivot_table('G5:G6', 'A1:E5', {:style_info=>style_info_data}) do |pt|
+ pt.rows = ['Year', 'Month']
+ pt.columns = ['Type']
+ pt.data = ['Sales']
+ pt.pages = ['Region']
+ end
+ assert_equal(style_info_data, pivot_table.style_info)
+ shared_test_pivot_table_xml_validity(pivot_table)
+ end
+
+ def test_add_pivot_table_with_row_without_subtotals
+ pivot_table = @ws.add_pivot_table('G5:G6', 'A1:D5', {:no_subtotals_on_headers=>['Year']}) do |pt|
+ pt.data = ['Sales']
+ pt.rows = ['Year','Month']
+ end
+ assert_equal(['Year'], pivot_table.no_subtotals_on_headers)
+ end
+
def test_header_indices
pivot_table = @ws.add_pivot_table('G5:G6', 'A1:E5')
assert_equal(0, pivot_table.header_index_of('Year' ))
diff --git a/test/workbook/worksheet/tc_row.rb b/test/workbook/worksheet/tc_row.rb
index 808e0138..43e7d23f 100644
--- a/test/workbook/worksheet/tc_row.rb
+++ b/test/workbook/worksheet/tc_row.rb
@@ -27,6 +27,11 @@ class TestRow < Test::Unit::TestCase
r.cells.each { |c| assert_equal(c.style,1) }
end
+ def test_color
+ r = @ws.add_row([1,2,3,4,5])
+ r.color = "FF00FF00"
+ r.cells.each { |c| assert_equal(c.color.rgb, "FF00FF00") }
+ end
def test_index
assert_equal(@row.row_index, @row.worksheet.rows.index(@row))
diff --git a/test/workbook/worksheet/tc_worksheet.rb b/test/workbook/worksheet/tc_worksheet.rb
index eb668d7f..166850e5 100644
--- a/test/workbook/worksheet/tc_worksheet.rb
+++ b/test/workbook/worksheet/tc_worksheet.rb
@@ -323,6 +323,13 @@ class TestWorksheet < Test::Unit::TestCase
assert_equal(doc.xpath('//xmlns:worksheet/xmlns:mergeCells/xmlns:mergeCell[@ref="E1:F1"]').size, 1)
end
+ def test_to_xml_string_merge_cells_row
+ row = @ws.add_row [1, "two"]
+ @ws.merge_cells row
+ doc = Nokogiri::XML(@ws.to_xml_string)
+ assert_equal(doc.xpath('//xmlns:worksheet/xmlns:mergeCells/xmlns:mergeCell[@ref="A1:B1"]').size, 1)
+ end
+
def test_to_xml_string_row_breaks
@ws.add_page_break("A1")
doc = Nokogiri::XML(@ws.to_xml_string)
@@ -476,7 +483,7 @@ class TestWorksheet < Test::Unit::TestCase
@ws.column_widths nil, 0.5
assert_equal(@ws.column_info[1].width, 0.5, 'eat my width')
assert_raise(ArgumentError, 'only accept unsigned ints') { @ws.column_widths 2, 7, -1 }
- assert_raise(ArgumentError, 'only accept Integer, Float or Fixnum') { @ws.column_widths 2, 7, "-1" }
+ assert_raise(ArgumentError, 'only accept Integer or Float') { @ws.column_widths 2, 7, "-1" }
end
def test_protect_range
@@ -573,5 +580,15 @@ class TestWorksheet < Test::Unit::TestCase
assert_raise(ArgumentError) { @wb.add_worksheet(:name => 'Sheet1') }
assert_equal(1, @wb.worksheets.size)
end
+
+ def test_worksheet_only_includes_outline_pr_when_set
+ doc = Nokogiri::XML(@ws.to_xml_string)
+ assert_equal(doc.xpath('//xmlns:worksheet/xmlns:sheetPr/xmlns:outlinePr').size, 0)
+ @ws.sheet_pr.outline_pr.summary_below = false
+ @ws.sheet_pr.outline_pr.summary_right = true
+ doc = Nokogiri::XML(@ws.to_xml_string)
+ assert_equal(doc.xpath('//xmlns:worksheet/xmlns:sheetPr/xmlns:outlinePr').size, 1)
+ assert_equal(doc.xpath('//xmlns:worksheet/xmlns:sheetPr/xmlns:outlinePr[@summaryBelow=0][@summaryRight=1]').size, 1)
+ end
end