From 2e1285f8f47a147035637e3c2d26246c941b3f2e Mon Sep 17 00:00:00 2001 From: Sean Duckett Date: Wed, 22 Feb 2012 14:14:21 -0600 Subject: A sample file that causes Excel 2011 to make repairs, and it's repaired version. --- examples/test_export-repaired.xlsx | Bin 0 -> 8315 bytes examples/test_export.xlsx | Bin 0 -> 3708 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 examples/test_export-repaired.xlsx create mode 100644 examples/test_export.xlsx diff --git a/examples/test_export-repaired.xlsx b/examples/test_export-repaired.xlsx new file mode 100644 index 00000000..e71522c4 Binary files /dev/null and b/examples/test_export-repaired.xlsx differ diff --git a/examples/test_export.xlsx b/examples/test_export.xlsx new file mode 100644 index 00000000..4e06b644 Binary files /dev/null and b/examples/test_export.xlsx differ -- cgit v1.2.3 From c5c938b5f8f2dadf0c3192c1a21e6995d691c555 Mon Sep 17 00:00:00 2001 From: Joseph HALTER Date: Wed, 22 Feb 2012 22:17:04 +0100 Subject: Ignore Gemfile.lock --- .gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..b844b143 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +Gemfile.lock -- cgit v1.2.3 From 7c4d091a9aae49d25ef2e5313dbfcfc6e2f46790 Mon Sep 17 00:00:00 2001 From: Joseph HALTER Date: Wed, 22 Feb 2012 22:17:33 +0100 Subject: Extract date and time to serial converting and put serious tests on it --- lib/axlsx/workbook/workbook.rb | 1 + lib/axlsx/workbook/worksheet/cell.rb | 9 +--- lib/axlsx/workbook/worksheet/converter.rb | 21 ++++++++++ test/workbook/worksheet/tc_converter.rb | 69 +++++++++++++++++++++++++++++++ 4 files changed, 93 insertions(+), 7 deletions(-) create mode 100644 lib/axlsx/workbook/worksheet/converter.rb create mode 100644 test/workbook/worksheet/tc_converter.rb diff --git a/lib/axlsx/workbook/workbook.rb b/lib/axlsx/workbook/workbook.rb index 51f38b50..c19c3521 100644 --- a/lib/axlsx/workbook/workbook.rb +++ b/lib/axlsx/workbook/workbook.rb @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- module Axlsx +require 'axlsx/workbook/worksheet/converter.rb' require 'axlsx/workbook/worksheet/cell.rb' require 'axlsx/workbook/worksheet/row.rb' require 'axlsx/workbook/worksheet/worksheet.rb' diff --git a/lib/axlsx/workbook/worksheet/cell.rb b/lib/axlsx/workbook/worksheet/cell.rb index 160fc6c8..167dfc97 100644 --- a/lib/axlsx/workbook/worksheet/cell.rb +++ b/lib/axlsx/workbook/worksheet/cell.rb @@ -316,15 +316,10 @@ module Axlsx end elsif @type == :date # TODO: See if this is subject to the same restriction as Time below - epoc = Workbook.date1904 ? Date.new(1904) : Date.new(1900) - v = (@value-epoc).to_f + v = Converter.date_to_serial @value, Workbook.date1904 xml.c(:r => r, :s => style) { xml.v v } elsif @type == :time - # Using hardcoded offsets here as some operating systems will not except a 'negative' offset from the ruby epoc. - epoc1900 = -2209021200 #Time.local(1900, 1, 1) - epoc1904 = -2082877200 #Time.local(1904, 1, 1) - epoc = Workbook.date1904 ? epoc1904 : epoc1900 - v = ((@value.localtime.to_f - epoc) /60.0/60.0/24.0).to_f + v = Converter.time_to_serial @value, Workbook.date1904 xml.c(:r => r, :s => style) { xml.v v } elsif @type == :boolean xml.c(:r => r, :s => style, :t => :b) { xml.v value } diff --git a/lib/axlsx/workbook/worksheet/converter.rb b/lib/axlsx/workbook/worksheet/converter.rb new file mode 100644 index 00000000..8df08f34 --- /dev/null +++ b/lib/axlsx/workbook/worksheet/converter.rb @@ -0,0 +1,21 @@ +# encoding: UTF-8 +require "date" + +module Axlsx + class Converter + def date_to_serial(date, date1904=false) + epoc = date1904 ? Date.new(1904) : Date.new(1899, 12, 30) + (date-epoc).to_f + end + + def time_to_serial(time, date1904=false) + # Using hardcoded offsets here as some operating systems will not except + # a 'negative' offset from the ruby epoc. + epoc1900 = -2209161600 # Time.utc(1899, 12, 30).to_i + epoc1904 = -2082844800 # Time.utc(1904, 1, 1).to_i + seconds_per_day = 86400 # 60*60*24 + epoc = date1904 ? epoc1904 : epoc1900 + (time.to_f - epoc)/seconds_per_day + end + end +end diff --git a/test/workbook/worksheet/tc_converter.rb b/test/workbook/worksheet/tc_converter.rb new file mode 100644 index 00000000..3919382a --- /dev/null +++ b/test/workbook/worksheet/tc_converter.rb @@ -0,0 +1,69 @@ +require 'test/unit' +require 'axlsx.rb' + +class TestConverter < Test::Unit::TestCase + def setup + @converter = Axlsx::Converter.new + @margin_of_error = 0.000_001 + end + + def test_date_to_serial_1900 + { # examples taken straight from the spec + "1893-08-05" => -2338.0, + "1900-01-01" => 2.0, + "1910-02-03" => 3687.0, + "2006-02-01" => 38749.0, + "9999-12-31" => 2958465.0, + }.each do |date_string, expected| + serial = @converter.date_to_serial Date.parse(date_string) + assert_equal serial, expected + end + end + + def test_date_to_serial_1904 + { # examples taken straight from the spec + "1893-08-05" => -3800.0, + "1904-01-01" => 0.0, + "1910-02-03" => 2225.0, + "2006-02-01" => 37287.0, + "9999-12-31" => 2957003.0, + }.each do |date_string, expected| + serial = @converter.date_to_serial Date.parse(date_string), true + assert_equal serial, expected + end + end + + def test_time_to_serial_1900 + { # examples taken straight from the spec + "1893-08-05T00:00:01Z" => -2337.999989, + "1899-12-28T18:00:00Z" => -1.25, + "1910-02-03T10:05:54Z" => 3687.4207639, + "1900-01-01T12:00:00Z" => 2.5, # wrongly indicated as 1.5 in the spec! + "9999-12-31T23:59:59Z" => 2958465.9999884, + }.each do |time_string, expected| + serial = @converter.time_to_serial Time.parse(time_string) + assert_in_delta serial, expected, @margin_of_error + end + end + + def test_time_to_serial_1904 + { # examples taken straight from the spec + "1893-08-05T00:00:01Z" => -3799.999989, + "1910-02-03T10:05:54Z" => 2225.4207639, + "1904-01-01T12:00:00Z" => 0.5000000, + "9999-12-31T23:59:59Z" => 2957003.9999884, + }.each do |time_string, expected| + serial = @converter.time_to_serial Time.parse(time_string), true + assert_in_delta serial, expected, @margin_of_error + end + end + + def test_timezone + utc = Time.utc 2012 # January 1st, 2012 at 0:00 UTC + local = Time.new 2012, 1, 1, 1, 0, 0, 3600 # January 1st, 2012 at 1:00 GMT+1 + assert_equal local, utc + assert_equal @converter.time_to_serial(local), @converter.time_to_serial(utc) + assert_equal @converter.time_to_serial(local, true), @converter.time_to_serial(utc, true) + end + +end -- cgit v1.2.3 From de603d4bfc1964cf24fe2ab4c917a5cbcfebef88 Mon Sep 17 00:00:00 2001 From: Jonathan Tron Date: Wed, 22 Feb 2012 23:12:52 +0100 Subject: Fix my name in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 56a9a21c..2dbfd879 100644 --- a/README.md +++ b/README.md @@ -327,7 +327,7 @@ Please see the {file:CHANGELOG.md} document for past release information. [ffmike](https://github.com/ffmike) - for knocking down an over restrictive i18n dependency, massive patience and great communication skills. -[JohnathanTron](https://github.com/JonathanTron) - for giving the gem some style, and making sure it applies. +[JonathanTron](https://github.com/JonathanTron) - for giving the gem some style, and making sure it applies. #Copyright and License ---------- -- cgit v1.2.3 From 6f4e9dd176bd56ec6c95c4441775ada2f5855203 Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Thu, 23 Feb 2012 09:44:33 +0900 Subject: renaming for clarity, a bit of docs and some patches to spec for AWSOME date/time converter as negative date/time does not parse in some environments under 1.8.7 --- lib/axlsx/workbook/workbook.rb | 2 +- lib/axlsx/workbook/worksheet/converter.rb | 21 ------ .../workbook/worksheet/date_time_converter.rb | 25 ++++++++ test/workbook/worksheet/tc_converter.rb | 69 -------------------- test/workbook/worksheet/tc_date_time_converter.rb | 75 ++++++++++++++++++++++ 5 files changed, 101 insertions(+), 91 deletions(-) delete mode 100644 lib/axlsx/workbook/worksheet/converter.rb create mode 100644 lib/axlsx/workbook/worksheet/date_time_converter.rb delete mode 100644 test/workbook/worksheet/tc_converter.rb create mode 100644 test/workbook/worksheet/tc_date_time_converter.rb diff --git a/lib/axlsx/workbook/workbook.rb b/lib/axlsx/workbook/workbook.rb index c19c3521..8a6eb629 100644 --- a/lib/axlsx/workbook/workbook.rb +++ b/lib/axlsx/workbook/workbook.rb @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- module Axlsx -require 'axlsx/workbook/worksheet/converter.rb' +require 'axlsx/workbook/worksheet/date_time_converter.rb' require 'axlsx/workbook/worksheet/cell.rb' require 'axlsx/workbook/worksheet/row.rb' require 'axlsx/workbook/worksheet/worksheet.rb' diff --git a/lib/axlsx/workbook/worksheet/converter.rb b/lib/axlsx/workbook/worksheet/converter.rb deleted file mode 100644 index 8df08f34..00000000 --- a/lib/axlsx/workbook/worksheet/converter.rb +++ /dev/null @@ -1,21 +0,0 @@ -# encoding: UTF-8 -require "date" - -module Axlsx - class Converter - def date_to_serial(date, date1904=false) - epoc = date1904 ? Date.new(1904) : Date.new(1899, 12, 30) - (date-epoc).to_f - end - - def time_to_serial(time, date1904=false) - # Using hardcoded offsets here as some operating systems will not except - # a 'negative' offset from the ruby epoc. - epoc1900 = -2209161600 # Time.utc(1899, 12, 30).to_i - epoc1904 = -2082844800 # Time.utc(1904, 1, 1).to_i - seconds_per_day = 86400 # 60*60*24 - epoc = date1904 ? epoc1904 : epoc1900 - (time.to_f - epoc)/seconds_per_day - end - end -end diff --git a/lib/axlsx/workbook/worksheet/date_time_converter.rb b/lib/axlsx/workbook/worksheet/date_time_converter.rb new file mode 100644 index 00000000..ee6d4a8a --- /dev/null +++ b/lib/axlsx/workbook/worksheet/date_time_converter.rb @@ -0,0 +1,25 @@ +# encoding: UTF-8 +require "date" + +module Axlsx + # The DateTimeConverter class converts both data and time types to their apprpriate excel serializations + class DateTimeConverter + + # The date_to_serial method converts dates to their excel serialized forms + # @param [Date] date the date to be serialized + def date_to_serial(date) + epoc = Axlsx::Workbook::date1904 ? Date.new(1904) : Date.new(1899, 12, 30) + (date-epoc).to_f + end + + def time_to_serial(time) + # Using hardcoded offsets here as some operating systems will not except + # a 'negative' offset from the ruby epoc. + epoc1900 = -2209161600 # Time.utc(1899, 12, 30).to_i + epoc1904 = -2082844800 # Time.utc(1904, 1, 1).to_i + seconds_per_day = 86400 # 60*60*24 + epoc = Axlsx::Workbook::date1904 ? epoc1904 : epoc1900 + (time.to_f - epoc)/seconds_per_day + end + end +end diff --git a/test/workbook/worksheet/tc_converter.rb b/test/workbook/worksheet/tc_converter.rb deleted file mode 100644 index 3919382a..00000000 --- a/test/workbook/worksheet/tc_converter.rb +++ /dev/null @@ -1,69 +0,0 @@ -require 'test/unit' -require 'axlsx.rb' - -class TestConverter < Test::Unit::TestCase - def setup - @converter = Axlsx::Converter.new - @margin_of_error = 0.000_001 - end - - def test_date_to_serial_1900 - { # examples taken straight from the spec - "1893-08-05" => -2338.0, - "1900-01-01" => 2.0, - "1910-02-03" => 3687.0, - "2006-02-01" => 38749.0, - "9999-12-31" => 2958465.0, - }.each do |date_string, expected| - serial = @converter.date_to_serial Date.parse(date_string) - assert_equal serial, expected - end - end - - def test_date_to_serial_1904 - { # examples taken straight from the spec - "1893-08-05" => -3800.0, - "1904-01-01" => 0.0, - "1910-02-03" => 2225.0, - "2006-02-01" => 37287.0, - "9999-12-31" => 2957003.0, - }.each do |date_string, expected| - serial = @converter.date_to_serial Date.parse(date_string), true - assert_equal serial, expected - end - end - - def test_time_to_serial_1900 - { # examples taken straight from the spec - "1893-08-05T00:00:01Z" => -2337.999989, - "1899-12-28T18:00:00Z" => -1.25, - "1910-02-03T10:05:54Z" => 3687.4207639, - "1900-01-01T12:00:00Z" => 2.5, # wrongly indicated as 1.5 in the spec! - "9999-12-31T23:59:59Z" => 2958465.9999884, - }.each do |time_string, expected| - serial = @converter.time_to_serial Time.parse(time_string) - assert_in_delta serial, expected, @margin_of_error - end - end - - def test_time_to_serial_1904 - { # examples taken straight from the spec - "1893-08-05T00:00:01Z" => -3799.999989, - "1910-02-03T10:05:54Z" => 2225.4207639, - "1904-01-01T12:00:00Z" => 0.5000000, - "9999-12-31T23:59:59Z" => 2957003.9999884, - }.each do |time_string, expected| - serial = @converter.time_to_serial Time.parse(time_string), true - assert_in_delta serial, expected, @margin_of_error - end - end - - def test_timezone - utc = Time.utc 2012 # January 1st, 2012 at 0:00 UTC - local = Time.new 2012, 1, 1, 1, 0, 0, 3600 # January 1st, 2012 at 1:00 GMT+1 - assert_equal local, utc - assert_equal @converter.time_to_serial(local), @converter.time_to_serial(utc) - assert_equal @converter.time_to_serial(local, true), @converter.time_to_serial(utc, true) - end - -end diff --git a/test/workbook/worksheet/tc_date_time_converter.rb b/test/workbook/worksheet/tc_date_time_converter.rb new file mode 100644 index 00000000..a039282a --- /dev/null +++ b/test/workbook/worksheet/tc_date_time_converter.rb @@ -0,0 +1,75 @@ +# -*- coding: utf-8 -*- +require 'test/unit' +require 'axlsx.rb' + +class TestDateTimeConverter < Test::Unit::TestCase + def setup + @converter = Axlsx::DateTimeConverter.new + @margin_of_error = 0.000_001 + end + + def test_date_to_serial_1900 + Axlsx::Workbook.date1904 = false + { # examples taken straight from the spec + # "1893-08-05" => -2338.0, # ruby 1.8.7 cannot parse negative dates in some environments + "1900-01-01" => 2.0, + "1910-02-03" => 3687.0, + "2006-02-01" => 38749.0, + "9999-12-31" => 2958465.0, + }.each do |date_string, expected| + serial = @converter.date_to_serial Date.parse(date_string) + assert_equal serial, expected + end + end + + def test_date_to_serial_1904 + Axlsx::Workbook.date1904 = true + { # examples taken straight from the spec + # "1893-08-05" => -3800.0, # ruby 1.8.7 cannot parse negative dates in some environments + "1904-01-01" => 0.0, + "1910-02-03" => 2225.0, + "2006-02-01" => 37287.0, + "9999-12-31" => 2957003.0, + }.each do |date_string, expected| + serial = @converter.date_to_serial Date.parse(date_string) + assert_equal serial, expected + end + end + + def test_time_to_serial_1900 + Axlsx::Workbook.date1904 = false + { # examples taken straight from the spec + # "1893-08-05T00:00:01Z" => -2337.999989, # ruby 1.8.7 cannot parse negative dates in some environments + # "1899-12-28T18:00:00Z" => -1.25, # ruby 1.8.7 cannot parse negative dates in some environments + "1910-02-03T10:05:54Z" => 3687.4207639, + "1900-01-01T12:00:00Z" => 2.5, # wrongly indicated as 1.5 in the spec! + "9999-12-31T23:59:59Z" => 2958465.9999884, + }.each do |time_string, expected| + serial = @converter.time_to_serial Time.parse(time_string) + assert_in_delta serial, expected, @margin_of_error + end + end + + def test_time_to_serial_1904 + Axlsx::Workbook.date1904 = true + { # examples taken straight from the spec + # "1893-08-05T00:00:01Z" => -3799.999989, # ruby 1.8.7 cannot parse negative dates in some environments + "1910-02-03T10:05:54Z" => 2225.4207639, + "1904-01-01T12:00:00Z" => 0.5000000, + "9999-12-31T23:59:59Z" => 2957003.9999884, + }.each do |time_string, expected| + serial = @converter.time_to_serial Time.parse(time_string) + assert_in_delta serial, expected, @margin_of_error + end + end + + def test_timezone + utc = Time.utc 2012 # January 1st, 2012 at 0:00 UTC + local = Time.new 2012, 1, 1, 1, 0, 0, 3600 # January 1st, 2012 at 1:00 GMT+1 + assert_equal local, utc + assert_equal @converter.time_to_serial(local), @converter.time_to_serial(utc) + Axlsx::Workbook.date1904 = true + assert_equal @converter.time_to_serial(local), @converter.time_to_serial(utc) + end + +end -- cgit v1.2.3 From 3ef96c6b8738da64ae8e37a6bd3cc1a5e8bb1ad9 Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Thu, 23 Feb 2012 10:09:17 +0900 Subject: ruby version conditional specs to deal with epoc issues http://ruby-doc.org/core-1.8.7/Time.html --- test/workbook/worksheet/tc_date_time_converter.rb | 92 +++++++++++++++-------- 1 file changed, 62 insertions(+), 30 deletions(-) diff --git a/test/workbook/worksheet/tc_date_time_converter.rb b/test/workbook/worksheet/tc_date_time_converter.rb index a039282a..9bc5b311 100644 --- a/test/workbook/worksheet/tc_date_time_converter.rb +++ b/test/workbook/worksheet/tc_date_time_converter.rb @@ -9,42 +9,65 @@ class TestDateTimeConverter < Test::Unit::TestCase end def test_date_to_serial_1900 - Axlsx::Workbook.date1904 = false - { # examples taken straight from the spec - # "1893-08-05" => -2338.0, # ruby 1.8.7 cannot parse negative dates in some environments - "1900-01-01" => 2.0, - "1910-02-03" => 3687.0, - "2006-02-01" => 38749.0, - "9999-12-31" => 2958465.0, - }.each do |date_string, expected| + Axlsx::Workbook.date1904 = false + tests = if RUBY_VERSION == '1.8.7' + { # examples taken straight from the spec + "2006-02-01" => 38749.0, + "9999-12-31" => 2958465.0 + } + else + { + "1893-08-05" => -2338.0, # ruby 1.8.7 cannot parse negative dates in some environments + "1900-01-01" => 2.0, + "1910-02-03" => 3687.0, + "2006-02-01" => 38749.0, + "9999-12-31" => 2958465.0 + } + end + tests.each do |date_string, expected| serial = @converter.date_to_serial Date.parse(date_string) assert_equal serial, expected end end def test_date_to_serial_1904 - Axlsx::Workbook.date1904 = true - { # examples taken straight from the spec - # "1893-08-05" => -3800.0, # ruby 1.8.7 cannot parse negative dates in some environments - "1904-01-01" => 0.0, - "1910-02-03" => 2225.0, - "2006-02-01" => 37287.0, - "9999-12-31" => 2957003.0, - }.each do |date_string, expected| + Axlsx::Workbook.date1904 = true + tests = if RUBY_VERSION == '1.8.7' + { # examples taken straight from the spec + "2006-02-01" => 37287.0, + "9999-12-31" => 2957003.0 + } + else + { + "1893-08-05" => -3800.0, # ruby 1.8.7 cannot parse negative dates in some environments + "1904-01-01" => 0.0, + "1910-02-03" => 2225.0, + "2006-02-01" => 37287.0, + "9999-12-31" => 2957003.0 + } + end + tests.each do |date_string, expected| serial = @converter.date_to_serial Date.parse(date_string) assert_equal serial, expected end end def test_time_to_serial_1900 - Axlsx::Workbook.date1904 = false - { # examples taken straight from the spec - # "1893-08-05T00:00:01Z" => -2337.999989, # ruby 1.8.7 cannot parse negative dates in some environments - # "1899-12-28T18:00:00Z" => -1.25, # ruby 1.8.7 cannot parse negative dates in some environments - "1910-02-03T10:05:54Z" => 3687.4207639, - "1900-01-01T12:00:00Z" => 2.5, # wrongly indicated as 1.5 in the spec! - "9999-12-31T23:59:59Z" => 2958465.9999884, - }.each do |time_string, expected| + Axlsx::Workbook.date1904 = false + tests = if RUBY_VERSION == '1.8.7' + { + "9999-12-31T23:59:59Z" => 2958465.9999884 + } + else + { + "1893-08-05T00:00:01Z" => -2337.999989, + "1899-12-28T18:00:00Z" => -1.25, + "1910-02-03T10:05:54Z" => 3687.4207639, + "1900-01-01T12:00:00Z" => 2.5, # wrongly indicated as 1.5 in the spec! + "9999-12-31T23:59:59Z" => 2958465.9999884 + } + end + tests.each do |time_string, expected| serial = @converter.time_to_serial Time.parse(time_string) assert_in_delta serial, expected, @margin_of_error end @@ -52,12 +75,21 @@ class TestDateTimeConverter < Test::Unit::TestCase def test_time_to_serial_1904 Axlsx::Workbook.date1904 = true - { # examples taken straight from the spec - # "1893-08-05T00:00:01Z" => -3799.999989, # ruby 1.8.7 cannot parse negative dates in some environments - "1910-02-03T10:05:54Z" => 2225.4207639, - "1904-01-01T12:00:00Z" => 0.5000000, - "9999-12-31T23:59:59Z" => 2957003.9999884, - }.each do |time_string, expected| + # ruby 1.8.7 cannot parse dates prior to epoc. see http://ruby-doc.org/core-1.8.7/Time.html + + tests = if RUBY_VERSION == '1.8.7' + { # examples taken straight from the spec + "9999-12-31T23:59:59Z" => 2957003.9999884, + } + else + { # examples taken straight from the spec + "1893-08-05T00:00:01Z" => -3799.999989, + "1910-02-03T10:05:54Z" => 2225.4207639, + "1904-01-01T12:00:00Z" => 0.5000000, + "9999-12-31T23:59:59Z" => 2957003.9999884 + } + end + tests.each do |time_string, expected| serial = @converter.time_to_serial Time.parse(time_string) assert_in_delta serial, expected, @margin_of_error end -- cgit v1.2.3 From b2eba54917583a97f478d0ed4ef4eb4b0be173bf Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Thu, 23 Feb 2012 10:51:26 +0900 Subject: disable timezone testing for 1.8.7 for now --- test/workbook/worksheet/tc_date_time_converter.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/test/workbook/worksheet/tc_date_time_converter.rb b/test/workbook/worksheet/tc_date_time_converter.rb index 9bc5b311..bd3d044d 100644 --- a/test/workbook/worksheet/tc_date_time_converter.rb +++ b/test/workbook/worksheet/tc_date_time_converter.rb @@ -96,6 +96,7 @@ class TestDateTimeConverter < Test::Unit::TestCase end def test_timezone + return if RUBY_VERSION == '1.8.7' # temporarily forcing this to only run on 1.9.2 and 1.9.3 as Time.new is quite different in 1.8.7 utc = Time.utc 2012 # January 1st, 2012 at 0:00 UTC local = Time.new 2012, 1, 1, 1, 0, 0, 3600 # January 1st, 2012 at 1:00 GMT+1 assert_equal local, utc -- cgit v1.2.3 From 4a8b7a55a377f84bcae4aa187878c151c237dbaa Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Thu, 23 Feb 2012 11:48:08 +0900 Subject: out of time to play with this. We will need to create some 1.8.7 valid test later. --- lib/axlsx/workbook/worksheet/date_time_converter.rb | 8 ++++++-- test/workbook/worksheet/tc_date_time_converter.rb | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/axlsx/workbook/worksheet/date_time_converter.rb b/lib/axlsx/workbook/worksheet/date_time_converter.rb index ee6d4a8a..18d5e59f 100644 --- a/lib/axlsx/workbook/worksheet/date_time_converter.rb +++ b/lib/axlsx/workbook/worksheet/date_time_converter.rb @@ -5,13 +5,17 @@ module Axlsx # The DateTimeConverter class converts both data and time types to their apprpriate excel serializations class DateTimeConverter - # The date_to_serial method converts dates to their excel serialized forms + # The date_to_serial method converts Date objects to the equivelant excel serialized forms # @param [Date] date the date to be serialized + # @return [Numeric] def date_to_serial(date) epoc = Axlsx::Workbook::date1904 ? Date.new(1904) : Date.new(1899, 12, 30) (date-epoc).to_f end - + + # The time_to_serial methond converts a Time object its excel serialized form. + # @param [Time] time the time to be serialized + # @return [Numeric] def time_to_serial(time) # Using hardcoded offsets here as some operating systems will not except # a 'negative' offset from the ruby epoc. diff --git a/test/workbook/worksheet/tc_date_time_converter.rb b/test/workbook/worksheet/tc_date_time_converter.rb index bd3d044d..34e25d3b 100644 --- a/test/workbook/worksheet/tc_date_time_converter.rb +++ b/test/workbook/worksheet/tc_date_time_converter.rb @@ -56,7 +56,7 @@ class TestDateTimeConverter < Test::Unit::TestCase Axlsx::Workbook.date1904 = false tests = if RUBY_VERSION == '1.8.7' { - "9999-12-31T23:59:59Z" => 2958465.9999884 + #"9999-12-31T23:59:59Z" => 2958465.9999884 } else { @@ -79,7 +79,7 @@ class TestDateTimeConverter < Test::Unit::TestCase tests = if RUBY_VERSION == '1.8.7' { # examples taken straight from the spec - "9999-12-31T23:59:59Z" => 2957003.9999884, + #"9999-12-31T23:59:59Z" => 2957003.9999884, } else { # examples taken straight from the spec -- cgit v1.2.3 From 4acf7505e4a4ca6d726dc26b7f08266a2e0d8958 Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Thu, 23 Feb 2012 19:50:16 +0900 Subject: worksheet names need to be limited to 31 characters --- lib/axlsx/util/constants.rb | 3 +++ lib/axlsx/workbook/worksheet/worksheet.rb | 2 ++ test/workbook/worksheet/tc_worksheet.rb | 5 +++++ 3 files changed, 10 insertions(+) diff --git a/lib/axlsx/util/constants.rb b/lib/axlsx/util/constants.rb index b2cbad26..e9a0a02a 100644 --- a/lib/axlsx/util/constants.rb +++ b/lib/axlsx/util/constants.rb @@ -224,6 +224,9 @@ module Axlsx # error message for RegexValidator ERR_REGEX = "Invalid Data. %s does not match %s." + # 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" + # 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" end diff --git a/lib/axlsx/workbook/worksheet/worksheet.rb b/lib/axlsx/workbook/worksheet/worksheet.rb index 5284c475..a8846913 100644 --- a/lib/axlsx/workbook/worksheet/worksheet.rb +++ b/lib/axlsx/workbook/worksheet/worksheet.rb @@ -116,9 +116,11 @@ module Axlsx end # The name of the worksheet + # The name of a worksheet must be unique in the workbook, and must not exceed 31 characters # @param [String] v def name=(v) DataTypeValidator.validate "Worksheet.name", String, v + raise ArgumentError, (ERR_SHEET_NAME_TOO_LONG % v) if v.size > 31 sheet_names = @workbook.worksheets.map { |s| s.name } raise ArgumentError, (ERR_DUPLICATE_SHEET_NAME % v) if sheet_names.include?(v) @name=v diff --git a/test/workbook/worksheet/tc_worksheet.rb b/test/workbook/worksheet/tc_worksheet.rb index 4a358c2c..a3d146c4 100644 --- a/test/workbook/worksheet/tc_worksheet.rb +++ b/test/workbook/worksheet/tc_worksheet.rb @@ -129,6 +129,11 @@ class TestWorksheet < Test::Unit::TestCase assert_raise(ArgumentError, "worksheet name must be unique") { n = @ws.name; @ws.workbook.add_worksheet(:name=> @ws) } end + def test_name_size + assert_raise(ArgumentError, "name too long!") { @ws.name = Array.new(32, "A").to_s } + assert_nothing_raised { @ws.name = Array.new(31, "A").to_s } + end + def test_update_auto_with_data small = @ws.workbook.styles.add_style(:sz=>2) big = @ws.workbook.styles.add_style(:sz=>10) -- cgit v1.2.3 From 91077e382b7d18e70ce075dad9af6b116eafa5ba Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Thu, 23 Feb 2012 19:53:13 +0900 Subject: patch for variations between Array#to_s between ruby versions. --- test/workbook/worksheet/tc_worksheet.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/workbook/worksheet/tc_worksheet.rb b/test/workbook/worksheet/tc_worksheet.rb index a3d146c4..c2444820 100644 --- a/test/workbook/worksheet/tc_worksheet.rb +++ b/test/workbook/worksheet/tc_worksheet.rb @@ -130,8 +130,8 @@ class TestWorksheet < Test::Unit::TestCase end def test_name_size - assert_raise(ArgumentError, "name too long!") { @ws.name = Array.new(32, "A").to_s } - assert_nothing_raised { @ws.name = Array.new(31, "A").to_s } + assert_raise(ArgumentError, "name too long!") { @ws.name = Array.new(32, "A").join('') } + assert_nothing_raised { @ws.name = Array.new(31, "A").join('') } end def test_update_auto_with_data -- cgit v1.2.3 From 6a93c109acf064ad81882e910593b8bfce79d412 Mon Sep 17 00:00:00 2001 From: Joseph HALTER Date: Fri, 24 Feb 2012 11:16:18 +0100 Subject: Fix DateTimeConverter tests --- test/workbook/worksheet/tc_date_time_converter.rb | 80 ++++++++++++++--------- 1 file changed, 50 insertions(+), 30 deletions(-) diff --git a/test/workbook/worksheet/tc_date_time_converter.rb b/test/workbook/worksheet/tc_date_time_converter.rb index 34e25d3b..78053a6d 100644 --- a/test/workbook/worksheet/tc_date_time_converter.rb +++ b/test/workbook/worksheet/tc_date_time_converter.rb @@ -6,70 +6,84 @@ class TestDateTimeConverter < Test::Unit::TestCase def setup @converter = Axlsx::DateTimeConverter.new @margin_of_error = 0.000_001 + @extended_time_range = begin + Time.parse "1893-08-05" + Time.parse "9999-12-31T23:59:59Z" + true + rescue + false + end end def test_date_to_serial_1900 Axlsx::Workbook.date1904 = false - tests = if RUBY_VERSION == '1.8.7' + tests = if @extended_time_range { # examples taken straight from the spec - "2006-02-01" => 38749.0, - "9999-12-31" => 2958465.0 - } - else - { - "1893-08-05" => -2338.0, # ruby 1.8.7 cannot parse negative dates in some environments + "1893-08-05" => -2338.0, "1900-01-01" => 2.0, "1910-02-03" => 3687.0, "2006-02-01" => 38749.0, "9999-12-31" => 2958465.0 } + else + { # examples taken inside the possible values + "1970-01-01" => 25569.0, # Unix epoch + "1970-01-02" => 25570.0, + "2006-02-01" => 38749.0, + "2038-01-19" => 50424.0, # max date using signed timestamp in 32bit + } end tests.each do |date_string, expected| serial = @converter.date_to_serial Date.parse(date_string) - assert_equal serial, expected + assert_equal expected, serial end end def test_date_to_serial_1904 Axlsx::Workbook.date1904 = true - tests = if RUBY_VERSION == '1.8.7' + tests = if @extended_time_range { # examples taken straight from the spec + "1893-08-05" => -3800.0, + "1904-01-01" => 0.0, + "1910-02-03" => 2225.0, "2006-02-01" => 37287.0, "9999-12-31" => 2957003.0 } else - { - "1893-08-05" => -3800.0, # ruby 1.8.7 cannot parse negative dates in some environments - "1904-01-01" => 0.0, - "1910-02-03" => 2225.0, + { # examples taken inside the possible values + "1970-01-01" => 24107.0, # Unix epoch + "1970-01-02" => 24108.0, "2006-02-01" => 37287.0, - "9999-12-31" => 2957003.0 + "2038-01-19" => 48962.0, # max date using signed timestamp in 32bit } end tests.each do |date_string, expected| serial = @converter.date_to_serial Date.parse(date_string) - assert_equal serial, expected + assert_equal expected, serial end end def test_time_to_serial_1900 Axlsx::Workbook.date1904 = false - tests = if RUBY_VERSION == '1.8.7' - { - #"9999-12-31T23:59:59Z" => 2958465.9999884 - } - else - { + tests = if @extended_time_range + { # examples taken straight from the spec "1893-08-05T00:00:01Z" => -2337.999989, "1899-12-28T18:00:00Z" => -1.25, "1910-02-03T10:05:54Z" => 3687.4207639, "1900-01-01T12:00:00Z" => 2.5, # wrongly indicated as 1.5 in the spec! "9999-12-31T23:59:59Z" => 2958465.9999884 } + else + { # examples taken inside the possible values + "1970-01-01T00:00:00Z" => 25569.0, # Unix epoch + "1970-01-01T12:00:00Z" => 25569.5, + "2000-01-01T00:00:00Z" => 36526.0, + "2038-01-19T03:14:07Z" => 50424.134803, # max signed timestamp in 32bit + } end tests.each do |time_string, expected| serial = @converter.time_to_serial Time.parse(time_string) - assert_in_delta serial, expected, @margin_of_error + assert_in_delta expected, serial, @margin_of_error end end @@ -77,28 +91,34 @@ class TestDateTimeConverter < Test::Unit::TestCase Axlsx::Workbook.date1904 = true # ruby 1.8.7 cannot parse dates prior to epoc. see http://ruby-doc.org/core-1.8.7/Time.html - tests = if RUBY_VERSION == '1.8.7' - { # examples taken straight from the spec - #"9999-12-31T23:59:59Z" => 2957003.9999884, - } - else + tests = if @extended_time_range { # examples taken straight from the spec "1893-08-05T00:00:01Z" => -3799.999989, "1910-02-03T10:05:54Z" => 2225.4207639, "1904-01-01T12:00:00Z" => 0.5000000, "9999-12-31T23:59:59Z" => 2957003.9999884 } + else + { # examples taken inside the possible values + "1970-01-01T00:00:00Z" => 24107.0, # Unix epoch + "1970-01-01T12:00:00Z" => 24107.5, + "2000-01-01T00:00:00Z" => 35064.0, + "2038-01-19T03:14:07Z" => 48962.134803, # max signed timestamp in 32bit + } end tests.each do |time_string, expected| serial = @converter.time_to_serial Time.parse(time_string) - assert_in_delta serial, expected, @margin_of_error + assert_in_delta expected, serial, @margin_of_error end end def test_timezone - return if RUBY_VERSION == '1.8.7' # temporarily forcing this to only run on 1.9.2 and 1.9.3 as Time.new is quite different in 1.8.7 utc = Time.utc 2012 # January 1st, 2012 at 0:00 UTC - local = Time.new 2012, 1, 1, 1, 0, 0, 3600 # January 1st, 2012 at 1:00 GMT+1 + local = begin + Time.new 2012, 1, 1, 1, 0, 0, 3600 # January 1st, 2012 at 1:00 GMT+1 + rescue ArgumentError + Time.parse "2012-01-01 01:00:00 +0100" + end assert_equal local, utc assert_equal @converter.time_to_serial(local), @converter.time_to_serial(utc) Axlsx::Workbook.date1904 = true -- cgit v1.2.3 From 228ffa672ad993489529bff2128ecc65d42046e8 Mon Sep 17 00:00:00 2001 From: Stefan Daschek Date: Fri, 24 Feb 2012 22:30:39 +0100 Subject: Add support for page margins to worksheet. --- lib/axlsx/workbook/workbook.rb | 1 + lib/axlsx/workbook/worksheet/page_margins.rb | 89 +++++++++++++++++++++++ lib/axlsx/workbook/worksheet/worksheet.rb | 6 ++ test/workbook/worksheet/tc_page_margins.rb | 105 +++++++++++++++++++++++++++ 4 files changed, 201 insertions(+) create mode 100644 lib/axlsx/workbook/worksheet/page_margins.rb create mode 100644 test/workbook/worksheet/tc_page_margins.rb diff --git a/lib/axlsx/workbook/workbook.rb b/lib/axlsx/workbook/workbook.rb index 8a6eb629..47af692b 100644 --- a/lib/axlsx/workbook/workbook.rb +++ b/lib/axlsx/workbook/workbook.rb @@ -3,6 +3,7 @@ module Axlsx require 'axlsx/workbook/worksheet/date_time_converter.rb' require 'axlsx/workbook/worksheet/cell.rb' +require 'axlsx/workbook/worksheet/page_margins.rb' require 'axlsx/workbook/worksheet/row.rb' require 'axlsx/workbook/worksheet/worksheet.rb' require 'axlsx/workbook/shared_strings_table.rb' diff --git a/lib/axlsx/workbook/worksheet/page_margins.rb b/lib/axlsx/workbook/worksheet/page_margins.rb new file mode 100644 index 00000000..86c686c5 --- /dev/null +++ b/lib/axlsx/workbook/worksheet/page_margins.rb @@ -0,0 +1,89 @@ +module Axlsx + # PageMargins specify the margins when printing a worksheet. + # + # For compatibility, PageMargins serialize to an empty string, unless at least one custom margin value + # has been specified. Otherwise, it serializes to a PageMargin element specifying all 6 margin values + # (using default values for margins that have not been specified explicitly). + # + # @see Worksheet#page_margins + class PageMargins + + # Default left and right margin (in inches) + DEFAULT_LEFT_RIGHT = 0.5 + + # Default top and bottom margins (in inches) + DEFAULT_TOP_BOTTOM = 1.00 + + # Default header and footer margins (in inches) + DEFAULT_HEADER_FOOTER = 0.50 + + # Left margin (in inches) + # @return [Float] + attr_reader :left + + # Right margin (in inches) + # @return [Float] + attr_reader :right + + # Top margin (in inches) + # @return [Float] + attr_reader :top + + # Bottom margin (in inches) + # @return [Float] + attr_reader :bottom + + # Header margin (in inches) + # @return [Float] + attr_reader :header + + # Footer margin (in inches) + # @return [Float] + attr_reader :footer + + def initialize + # Default values taken from MS Excel for Mac 2011 + @left = @right = DEFAULT_LEFT_RIGHT + @top = @bottom = DEFAULT_TOP_BOTTOM + @header = @footer = DEFAULT_HEADER_FOOTER + + @custom_margins_specified = false + end + + # True if custom page margins have been specified. + def custom_margins_specified? + @custom_margins_specified + end + + # Set some or all margins at once. + # @param [Hash] margins the margins to set (possible keys are :left, :right, :top, :bottom, :header and :footer). + def set(margins) + margins.select do |k, v| + next unless [:left, :right, :top, :bottom, :header, :footer].include? k + send("#{k}=", v) + end + end + + # @see left + def left=(v); Axlsx::validate_unsigned_numeric(v); @custom_margins_specified = true; @left = v end + # @see right + def right=(v); Axlsx::validate_unsigned_numeric(v); @custom_margins_specified = true; @right = v end + # @see top + def top=(v); Axlsx::validate_unsigned_numeric(v); @custom_margins_specified = true; @top = v end + # @see bottom + def bottom=(v); Axlsx::validate_unsigned_numeric(v); @custom_margins_specified = true; @bottom = v end + # @see header + def header=(v); Axlsx::validate_unsigned_numeric(v); @custom_margins_specified = true; @header = v end + # @see footer + def footer=(v); Axlsx::validate_unsigned_numeric(v); @custom_margins_specified = true; @footer = v end + + # Serializes the page margins element + # @note For compatibility, this is a noop unless custom margins have been specified. + # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. + # @see #custom_margins_specified? + def to_xml(xml) + return unless custom_margins_specified? + xml.pageMargins :left => left, :right => right, :top => top, :bottom => bottom, :header => header, :footer => footer + end + end +end \ No newline at end of file diff --git a/lib/axlsx/workbook/worksheet/worksheet.rb b/lib/axlsx/workbook/worksheet/worksheet.rb index a8846913..ca2c51d6 100644 --- a/lib/axlsx/workbook/worksheet/worksheet.rb +++ b/lib/axlsx/workbook/worksheet/worksheet.rb @@ -35,6 +35,10 @@ module Axlsx # @return Array attr_reader :auto_filter + # Page margins for printing the worksheet. + # @return [PageMargins] + attr_reader :page_margins + # Creates a new worksheet. # @note the recommended way to manage worksheets is Workbook#add_worksheet # @see Workbook#add_worksheet @@ -50,6 +54,7 @@ module Axlsx @magick_draw = Magick::Draw.new @cols = SimpleTypedList.new Cell @merged_cells = [] + @page_margins = PageMargins.new end # convinience method to access all cells in this worksheet @@ -321,6 +326,7 @@ module Axlsx } xml.autoFilter :ref=>@auto_filter if @auto_filter xml.mergeCells(:count=>@merged_cells.size) { @merged_cells.each { | mc | xml.mergeCell(:ref=>mc) } } unless @merged_cells.empty? + @page_margins.to_xml(xml) xml.drawing :"r:id"=>"rId1" if @drawing } end diff --git a/test/workbook/worksheet/tc_page_margins.rb b/test/workbook/worksheet/tc_page_margins.rb new file mode 100644 index 00000000..6f2e6fdb --- /dev/null +++ b/test/workbook/worksheet/tc_page_margins.rb @@ -0,0 +1,105 @@ +require 'test/unit' +require 'axlsx.rb' + +class TestPageMargins < Test::Unit::TestCase + + def setup + p = Axlsx::Package.new + ws = p.workbook.add_worksheet :name=>"hmmm" + @pm = ws.page_margins + end + + def test_initialize + assert_equal(false, @pm.custom_margins_specified?) + assert_equal(Axlsx::PageMargins::DEFAULT_LEFT_RIGHT, @pm.left) + assert_equal(Axlsx::PageMargins::DEFAULT_LEFT_RIGHT, @pm.right) + assert_equal(Axlsx::PageMargins::DEFAULT_TOP_BOTTOM, @pm.top) + assert_equal(Axlsx::PageMargins::DEFAULT_TOP_BOTTOM, @pm.bottom) + assert_equal(Axlsx::PageMargins::DEFAULT_HEADER_FOOTER, @pm.header) + assert_equal(Axlsx::PageMargins::DEFAULT_HEADER_FOOTER, @pm.footer) + end + + def test_custom_margins_specified + @pm.left = 0.5 + assert(@pm.custom_margins_specified?) + end + + def test_set_all_values + @pm.set(:left => 1.1, :right => 1.2, :top => 1.3, :bottom => 1.4, :header => 0.8, :footer => 0.9) + assert(@pm.custom_margins_specified?) + assert_equal(1.1, @pm.left) + assert_equal(1.2, @pm.right) + assert_equal(1.3, @pm.top) + assert_equal(1.4, @pm.bottom) + assert_equal(0.8, @pm.header) + assert_equal(0.9, @pm.footer) + end + + def test_set_some_values + @pm.set(:left => 1.1, :right => 1.2) + assert(@pm.custom_margins_specified?) + assert_equal(1.1, @pm.left) + assert_equal(1.2, @pm.right) + assert_equal(Axlsx::PageMargins::DEFAULT_TOP_BOTTOM, @pm.top) + assert_equal(Axlsx::PageMargins::DEFAULT_TOP_BOTTOM, @pm.bottom) + assert_equal(Axlsx::PageMargins::DEFAULT_HEADER_FOOTER, @pm.header) + assert_equal(Axlsx::PageMargins::DEFAULT_HEADER_FOOTER, @pm.footer) + end + + def test_to_xml + @pm.left = 1.1 + @pm.right = 1.2 + @pm.top = 1.3 + @pm.bottom = 1.4 + @pm.header = 0.8 + @pm.footer = 0.9 + xml = Nokogiri::XML::Builder.new + @pm.to_xml(xml) + doc = Nokogiri::XML.parse(xml.to_xml) + assert_equal(1, doc.xpath(".//pageMargins[@left=1.1][@right=1.2][@top=1.3][@bottom=1.4][@header=0.8][@footer=0.9]").size) + end + + def test_to_xml_is_noop_unless_custom_margins_specified + assert_equal(false, @pm.custom_margins_specified?) + xml = Nokogiri::XML::Builder.new + @pm.to_xml(xml) + doc = Nokogiri::XML.parse(xml.to_xml) + assert_equal(0, doc.children.size) + end + + def test_left + assert_raise(ArgumentError) { @pm.left = -1.2 } + assert_nothing_raised { @pm.left = 1.5 } + assert_equal(@pm.left, 1.5) + end + + def test_right + assert_raise(ArgumentError) { @pm.right = -1.2 } + assert_nothing_raised { @pm.right = 1.5 } + assert_equal(@pm.right, 1.5) + end + + def test_top + assert_raise(ArgumentError) { @pm.top = -1.2 } + assert_nothing_raised { @pm.top = 1.5 } + assert_equal(@pm.top, 1.5) + end + + def test_bottom + assert_raise(ArgumentError) { @pm.bottom = -1.2 } + assert_nothing_raised { @pm.bottom = 1.5 } + assert_equal(@pm.bottom, 1.5) + end + + def test_header + assert_raise(ArgumentError) { @pm.header = -1.2 } + assert_nothing_raised { @pm.header = 1.5 } + assert_equal(@pm.header, 1.5) + end + + def test_footer + assert_raise(ArgumentError) { @pm.footer = -1.2 } + assert_nothing_raised { @pm.footer = 1.5 } + assert_equal(@pm.footer, 1.5) + end +end -- cgit v1.2.3 From 1488c198ecef2654424a925c536e20b9ff79e9b0 Mon Sep 17 00:00:00 2001 From: Stefan Daschek Date: Fri, 24 Feb 2012 23:03:02 +0100 Subject: Fix default value for left/right margins. --- lib/axlsx/workbook/worksheet/page_margins.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/axlsx/workbook/worksheet/page_margins.rb b/lib/axlsx/workbook/worksheet/page_margins.rb index 86c686c5..cef6dcbf 100644 --- a/lib/axlsx/workbook/worksheet/page_margins.rb +++ b/lib/axlsx/workbook/worksheet/page_margins.rb @@ -9,7 +9,7 @@ module Axlsx class PageMargins # Default left and right margin (in inches) - DEFAULT_LEFT_RIGHT = 0.5 + DEFAULT_LEFT_RIGHT = 0.75 # Default top and bottom margins (in inches) DEFAULT_TOP_BOTTOM = 1.00 -- cgit v1.2.3 From 5d0c81118bac73ab0b18804ca1a3039db9cb69dd Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Sat, 25 Feb 2012 17:11:56 +0900 Subject: add support for page margin initialization options as well as adding an option to worksheet initialization so we can do stuff like this: workbook.add_worksheet(:page_margins => {:top=> 1.9}) and yielding the page_margins object off the worksheet for stuff like: worksheet.page_margins do |pm| pm.left = 0.7 end --- lib/axlsx/workbook/workbook.rb | 1 + lib/axlsx/workbook/worksheet/page_margins.rb | 35 +++++++++++++++++++--------- lib/axlsx/workbook/worksheet/worksheet.rb | 30 ++++++++++++++++++++---- test/workbook/worksheet/tc_page_margins.rb | 13 ++++++++++- test/workbook/worksheet/tc_worksheet.rb | 23 ++++++++++++++++++ 5 files changed, 86 insertions(+), 16 deletions(-) diff --git a/lib/axlsx/workbook/workbook.rb b/lib/axlsx/workbook/workbook.rb index 47af692b..b3b10fac 100644 --- a/lib/axlsx/workbook/workbook.rb +++ b/lib/axlsx/workbook/workbook.rb @@ -136,6 +136,7 @@ require 'axlsx/workbook/shared_strings_table.rb' # Adds a worksheet to this workbook # @return [Worksheet] # @option options [String] name The name of the worksheet. + # @option options [Hash] page_margins The page margins for the worksheet. # @see Worksheet#initialize def add_worksheet(options={}) worksheet = Worksheet.new(self, options) diff --git a/lib/axlsx/workbook/worksheet/page_margins.rb b/lib/axlsx/workbook/worksheet/page_margins.rb index cef6dcbf..ab67337b 100644 --- a/lib/axlsx/workbook/worksheet/page_margins.rb +++ b/lib/axlsx/workbook/worksheet/page_margins.rb @@ -5,7 +5,9 @@ module Axlsx # has been specified. Otherwise, it serializes to a PageMargin element specifying all 6 margin values # (using default values for margins that have not been specified explicitly). # + # @note The recommended way to manage page margins is via Worksheet#page_margins # @see Worksheet#page_margins + # @see Worksheet#initialize class PageMargins # Default left and right margin (in inches) @@ -41,18 +43,29 @@ module Axlsx # @return [Float] attr_reader :footer - def initialize + # Creates a new PageMargins object + # @option options [Numeric] left The left margin in inches + # @option options [Numeric] right The right margin in inches + # @option options [Numeric] bottom The bottom margin in inches + # @option options [Numeric] top The top margin in inches + # @option options [Numeric] header The header margin in inches + # @option options [Numeric] footer The footer margin in inches + def initialize(options={}) # Default values taken from MS Excel for Mac 2011 @left = @right = DEFAULT_LEFT_RIGHT @top = @bottom = DEFAULT_TOP_BOTTOM @header = @footer = DEFAULT_HEADER_FOOTER - - @custom_margins_specified = false + + options.each do |o| + self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}=" + end end # True if custom page margins have been specified. def custom_margins_specified? - @custom_margins_specified + !(@left == @right && @right == DEFAULT_LEFT_RIGHT && + @top == @bottom && @bottom == DEFAULT_TOP_BOTTOM && + @header == @footer && @footer == DEFAULT_HEADER_FOOTER) end # Set some or all margins at once. @@ -65,17 +78,17 @@ module Axlsx end # @see left - def left=(v); Axlsx::validate_unsigned_numeric(v); @custom_margins_specified = true; @left = v end + def left=(v); Axlsx::validate_unsigned_numeric(v); @left = v end # @see right - def right=(v); Axlsx::validate_unsigned_numeric(v); @custom_margins_specified = true; @right = v end + def right=(v); Axlsx::validate_unsigned_numeric(v); @right = v end # @see top - def top=(v); Axlsx::validate_unsigned_numeric(v); @custom_margins_specified = true; @top = v end + def top=(v); Axlsx::validate_unsigned_numeric(v); @top = v end # @see bottom - def bottom=(v); Axlsx::validate_unsigned_numeric(v); @custom_margins_specified = true; @bottom = v end + def bottom=(v); Axlsx::validate_unsigned_numeric(v); @bottom = v end # @see header - def header=(v); Axlsx::validate_unsigned_numeric(v); @custom_margins_specified = true; @header = v end + def header=(v); Axlsx::validate_unsigned_numeric(v); @header = v end # @see footer - def footer=(v); Axlsx::validate_unsigned_numeric(v); @custom_margins_specified = true; @footer = v end + def footer=(v); Axlsx::validate_unsigned_numeric(v); @footer = v end # Serializes the page margins element # @note For compatibility, this is a noop unless custom margins have been specified. @@ -86,4 +99,4 @@ module Axlsx xml.pageMargins :left => left, :right => right, :top => top, :bottom => bottom, :header => header, :footer => footer end end -end \ No newline at end of file +end diff --git a/lib/axlsx/workbook/worksheet/worksheet.rb b/lib/axlsx/workbook/worksheet/worksheet.rb index ca2c51d6..3882b1db 100644 --- a/lib/axlsx/workbook/worksheet/worksheet.rb +++ b/lib/axlsx/workbook/worksheet/worksheet.rb @@ -36,13 +36,33 @@ module Axlsx attr_reader :auto_filter # Page margins for printing the worksheet. + # @example + # wb = Axlsx::Package.new.workbook + # # using options when creating the worksheet. + # ws = wb.add_worksheet :page_margins => {:left => 1.9, :header => 0.1} + # + # # use the set method of the page_margins object + # ws.page_margins.set(:bottom => 3, :footer => 0.7) + # + # # set page margins in a block + # ws.page_margins do |margins| + # margins.right = 6 + # margins.top = 0.2 + # end + # @see PageMargins#initialize # @return [PageMargins] - attr_reader :page_margins + # @yeilds self + def page_margins + @page_margins ||= PageMargins.new + yield @page_margins if block_given? + @page_margins + end # Creates a new worksheet. # @note the recommended way to manage worksheets is Workbook#add_worksheet # @see Workbook#add_worksheet - # @option options [String] name The name of this sheet. + # @option options [String] name The name of this worksheet. + # @option options [Hash] page_margins A hash containing page margins for this worksheet. @see PageMargins def initialize(wb, options={}) @drawing = nil @auto_filter = nil @@ -51,10 +71,12 @@ module Axlsx @workbook.worksheets << self @auto_fit_data = [] self.name = options[:name] || "Sheet" + (index+1).to_s + @magick_draw = Magick::Draw.new @cols = SimpleTypedList.new Cell @merged_cells = [] - @page_margins = PageMargins.new + + @page_margins = PageMargins.new options[:page_margins] if options[:page_margins] end # convinience method to access all cells in this worksheet @@ -326,7 +348,7 @@ module Axlsx } xml.autoFilter :ref=>@auto_filter if @auto_filter xml.mergeCells(:count=>@merged_cells.size) { @merged_cells.each { | mc | xml.mergeCell(:ref=>mc) } } unless @merged_cells.empty? - @page_margins.to_xml(xml) + page_margins.to_xml(xml) xml.drawing :"r:id"=>"rId1" if @drawing } end diff --git a/test/workbook/worksheet/tc_page_margins.rb b/test/workbook/worksheet/tc_page_margins.rb index 6f2e6fdb..ed3d90d8 100644 --- a/test/workbook/worksheet/tc_page_margins.rb +++ b/test/workbook/worksheet/tc_page_margins.rb @@ -18,7 +18,18 @@ class TestPageMargins < Test::Unit::TestCase assert_equal(Axlsx::PageMargins::DEFAULT_HEADER_FOOTER, @pm.header) assert_equal(Axlsx::PageMargins::DEFAULT_HEADER_FOOTER, @pm.footer) end - + + def test_initialize_with_options + optioned = Axlsx::PageMargins.new(:left => 2, :right => 3, :top => 2, :bottom => 1, :header => 0.1, :footer => 0.1) + assert_equal(true, optioned.custom_margins_specified?) + assert_equal(2, optioned.left) + assert_equal(3, optioned.right) + assert_equal(2, optioned.top) + assert_equal(1, optioned.bottom) + assert_equal(0.1, optioned.header) + assert_equal(0.1, optioned.footer) + end + def test_custom_margins_specified @pm.left = 0.5 assert(@pm.custom_margins_specified?) diff --git a/test/workbook/worksheet/tc_worksheet.rb b/test/workbook/worksheet/tc_worksheet.rb index c2444820..d7e52f73 100644 --- a/test/workbook/worksheet/tc_worksheet.rb +++ b/test/workbook/worksheet/tc_worksheet.rb @@ -13,6 +13,29 @@ class TestWorksheet < Test::Unit::TestCase assert_equal(ws.pn, "worksheets/sheet2.xml") end + def test_page_margins + assert(@ws.page_margins.is_a? Axlsx::PageMargins) + end + + def test_page_margins_yeild + @ws.page_margins do |pm| + assert(pm.is_a? Axlsx::PageMargins) + assert(@ws.page_margins == pm) + end + end + + def test_initialization_options + page_margins = {:left => 2, :right => 2, :bottom => 2, :top => 2, :header => 2, :footer => 2} + optioned = @ws.workbook.add_worksheet(:name => 'bob', :page_margins => page_margins) + assert_equal(optioned.page_margins.left, page_margins[:left]) + assert_equal(optioned.page_margins.right, page_margins[:right]) + assert_equal(optioned.page_margins.top, page_margins[:top]) + assert_equal(optioned.page_margins.bottom, page_margins[:bottom]) + assert_equal(optioned.page_margins.header, page_margins[:header]) + assert_equal(optioned.page_margins.footer, page_margins[:footer]) + assert_equal(optioned.name, 'bob') + end + def test_rels_pn assert_equal(@ws.rels_pn, "worksheets/_rels/sheet1.xml.rels") ws = @ws.workbook.add_worksheet -- cgit v1.2.3 From 1cebe7fa50b71bb0b7d2e6dd0f934a2eb9e1e80b Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Sat, 25 Feb 2012 17:21:42 +0900 Subject: readme and examples updates --- README.md | 22 +++++++++++++++++++++- examples/example.rb | 7 +++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2dbfd879..24c5bf58 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ Feature List **3. Custom Styles: With guaranteed document validity, you can style borders, alignment, fills, fonts, and number formats in a single line of code. Those styles can be applied to an entire row, or a single cell anywhere in your workbook. -**4. Automatic type support: Axlsx will automatically determine the type of data you are generating. In this release Float, Integer, String and Time types are automatically identified and serialized to your spreadsheet. +**4. Automatic type support: Axlsx will automatically determine the type of data you are generating. In this release Float, Integer, String, Date, Time and Boolean types are automatically identified and serialized to your spreadsheet. **5. Automatic and fixed column widths: Axlsx will automatically determine the appropriate width for your columns based on the content in the worksheet, or use any value you specify for the really funky stuff. @@ -60,6 +60,8 @@ Feature List **14. Output to file or StringIO +**15. Support for page margins + Installing ---------- @@ -272,6 +274,12 @@ To install Axlsx, use the following command: sheet.column_widths nil, 3 end +##Specify Page Margins for printing + margins = {:left => 3, :right => 3, :top => 1.2, :bottom => 1.2, :header => 0.7, :footer => 0.7} + wb.add_worksheet(:name => "print margins", :page_margins => margins) do |sheet| + sheet.add_row["this sheet uses customized page margins for printing"] + end + ##Validate and Serialize p.validate.each { |e| puts e.message } @@ -301,6 +309,14 @@ This gem has 100% test coverage using test/unit. To execute tests for this gem, #Changelog --------- +- ** March.??.12**: 1.0.18 release + https://github.com/randym/axlsx/compare/1.0.17...1.0.18 + - bugfix custom borders are not properly applied when using styles.add_style + - interop worksheet names must be 31 characters or less or some versions of office complain about repairs + - added type support for :boolean and :date types cell values + - iterop added some elements so that rubyXL can parse sheets generated with axlsx + - added support for fixed column widths + - ** February.14.12**: 1.0.17 release https://github.com/randym/axlsx/compare/1.0.16...1.0.17 - Added in support for serializing to StringIO @@ -329,6 +345,10 @@ Please see the {file:CHANGELOG.md} document for past release information. [JonathanTron](https://github.com/JonathanTron) - for giving the gem some style, and making sure it applies. +[JosephHalter](https://github.com/JosephHalter) - for making sure we arrive at the right time on the right date. + +[noniq](https://github.com/noniq) - for keeping true to the gem's style, and making sure what we put on paper does not get marginalized. + #Copyright and License ---------- diff --git a/examples/example.rb b/examples/example.rb index 3487044a..41a08c50 100644 --- a/examples/example.rb +++ b/examples/example.rb @@ -201,6 +201,12 @@ sheet.column_widths nil, 3 end +##Specify Page Margins for printing + margins = {:left => 3, :right => 3, :top => 1.2, :bottom => 1.2, :header => 0.7, :footer => 0.7} + wb.add_worksheet(:name => "print margins", :page_margins => margins) do |sheet| + sheet.add_row["this sheet uses customized page margins for printing"] + end + ##Validate and Serialize p.validate.each { |e| puts e.message } @@ -216,5 +222,6 @@ p.serialize("shared_strings_example.xlsx") + -- cgit v1.2.3 From ffa1b357ea69f3b4d16c806cbd448fa447792ebe Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Sat, 25 Feb 2012 17:24:43 +0900 Subject: beef-up the gitignore --- .gitignore | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.gitignore b/.gitignore index b844b143..b1cc5c00 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,9 @@ Gemfile.lock +doc +unzip +coverage +.yardoc +*.gem +*.xlsx +*.*~ +.DS_Store \ No newline at end of file -- cgit v1.2.3 From 3b81ff15cdd6e1b337fdab70965418234d1e8453 Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Sun, 26 Feb 2012 18:54:29 +0900 Subject: Taking advantage of Stafan's excellent suggestion to take advantage of lazy loading page margins. --- lib/axlsx/workbook/worksheet/page_margins.rb | 8 -------- lib/axlsx/workbook/worksheet/worksheet.rb | 2 +- test/workbook/worksheet/tc_page_margins.rb | 16 ---------------- test/workbook/worksheet/tc_worksheet.rb | 13 +++++++++++++ 4 files changed, 14 insertions(+), 25 deletions(-) diff --git a/lib/axlsx/workbook/worksheet/page_margins.rb b/lib/axlsx/workbook/worksheet/page_margins.rb index ab67337b..f41e3426 100644 --- a/lib/axlsx/workbook/worksheet/page_margins.rb +++ b/lib/axlsx/workbook/worksheet/page_margins.rb @@ -61,13 +61,6 @@ module Axlsx end end - # True if custom page margins have been specified. - def custom_margins_specified? - !(@left == @right && @right == DEFAULT_LEFT_RIGHT && - @top == @bottom && @bottom == DEFAULT_TOP_BOTTOM && - @header == @footer && @footer == DEFAULT_HEADER_FOOTER) - end - # Set some or all margins at once. # @param [Hash] margins the margins to set (possible keys are :left, :right, :top, :bottom, :header and :footer). def set(margins) @@ -95,7 +88,6 @@ module Axlsx # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. # @see #custom_margins_specified? def to_xml(xml) - return unless custom_margins_specified? xml.pageMargins :left => left, :right => right, :top => top, :bottom => bottom, :header => header, :footer => footer end end diff --git a/lib/axlsx/workbook/worksheet/worksheet.rb b/lib/axlsx/workbook/worksheet/worksheet.rb index 3882b1db..7622aba0 100644 --- a/lib/axlsx/workbook/worksheet/worksheet.rb +++ b/lib/axlsx/workbook/worksheet/worksheet.rb @@ -348,7 +348,7 @@ module Axlsx } xml.autoFilter :ref=>@auto_filter if @auto_filter xml.mergeCells(:count=>@merged_cells.size) { @merged_cells.each { | mc | xml.mergeCell(:ref=>mc) } } unless @merged_cells.empty? - page_margins.to_xml(xml) + page_margins.to_xml(xml) if @page_margins xml.drawing :"r:id"=>"rId1" if @drawing } end diff --git a/test/workbook/worksheet/tc_page_margins.rb b/test/workbook/worksheet/tc_page_margins.rb index ed3d90d8..3368129c 100644 --- a/test/workbook/worksheet/tc_page_margins.rb +++ b/test/workbook/worksheet/tc_page_margins.rb @@ -10,7 +10,6 @@ class TestPageMargins < Test::Unit::TestCase end def test_initialize - assert_equal(false, @pm.custom_margins_specified?) assert_equal(Axlsx::PageMargins::DEFAULT_LEFT_RIGHT, @pm.left) assert_equal(Axlsx::PageMargins::DEFAULT_LEFT_RIGHT, @pm.right) assert_equal(Axlsx::PageMargins::DEFAULT_TOP_BOTTOM, @pm.top) @@ -21,7 +20,6 @@ class TestPageMargins < Test::Unit::TestCase def test_initialize_with_options optioned = Axlsx::PageMargins.new(:left => 2, :right => 3, :top => 2, :bottom => 1, :header => 0.1, :footer => 0.1) - assert_equal(true, optioned.custom_margins_specified?) assert_equal(2, optioned.left) assert_equal(3, optioned.right) assert_equal(2, optioned.top) @@ -30,14 +28,9 @@ class TestPageMargins < Test::Unit::TestCase assert_equal(0.1, optioned.footer) end - def test_custom_margins_specified - @pm.left = 0.5 - assert(@pm.custom_margins_specified?) - end def test_set_all_values @pm.set(:left => 1.1, :right => 1.2, :top => 1.3, :bottom => 1.4, :header => 0.8, :footer => 0.9) - assert(@pm.custom_margins_specified?) assert_equal(1.1, @pm.left) assert_equal(1.2, @pm.right) assert_equal(1.3, @pm.top) @@ -48,7 +41,6 @@ class TestPageMargins < Test::Unit::TestCase def test_set_some_values @pm.set(:left => 1.1, :right => 1.2) - assert(@pm.custom_margins_specified?) assert_equal(1.1, @pm.left) assert_equal(1.2, @pm.right) assert_equal(Axlsx::PageMargins::DEFAULT_TOP_BOTTOM, @pm.top) @@ -70,14 +62,6 @@ class TestPageMargins < Test::Unit::TestCase assert_equal(1, doc.xpath(".//pageMargins[@left=1.1][@right=1.2][@top=1.3][@bottom=1.4][@header=0.8][@footer=0.9]").size) end - def test_to_xml_is_noop_unless_custom_margins_specified - assert_equal(false, @pm.custom_margins_specified?) - xml = Nokogiri::XML::Builder.new - @pm.to_xml(xml) - doc = Nokogiri::XML.parse(xml.to_xml) - assert_equal(0, doc.children.size) - end - def test_left assert_raise(ArgumentError) { @pm.left = -1.2 } assert_nothing_raised { @pm.left = 1.5 } diff --git a/test/workbook/worksheet/tc_worksheet.rb b/test/workbook/worksheet/tc_worksheet.rb index d7e52f73..b290f06b 100644 --- a/test/workbook/worksheet/tc_worksheet.rb +++ b/test/workbook/worksheet/tc_worksheet.rb @@ -139,6 +139,19 @@ class TestWorksheet < Test::Unit::TestCase assert(errors.empty?, "error free validation") end + def test_valid_with_page_margins + @ws.page_margins.set :left => 9 + schema = Nokogiri::XML::Schema(File.open(Axlsx::SML_XSD)) + doc = Nokogiri::XML(@ws.to_xml) + errors = [] + schema.validate(doc).each do |error| + errors.push error + puts error.message + end + assert(errors.empty?, "error free validation") + + end + def test_relationships assert(@ws.relationships.empty?, "No Drawing relationship until you add a chart") c = @ws.add_chart Axlsx::Pie3DChart -- cgit v1.2.3 From 4fa61b0242704f3406737a6cbb6a39c46690a489 Mon Sep 17 00:00:00 2001 From: Stefan Daschek Date: Mon, 27 Feb 2012 12:28:45 +0100 Subject: Add support for underlined text. --- lib/axlsx/stylesheet/font.rb | 7 +++++++ lib/axlsx/stylesheet/styles.rb | 5 +++-- test/stylesheet/tc_font.rb | 8 ++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/lib/axlsx/stylesheet/font.rb b/lib/axlsx/stylesheet/font.rb index d3eea3b2..1d9bc5d4 100644 --- a/lib/axlsx/stylesheet/font.rb +++ b/lib/axlsx/stylesheet/font.rb @@ -54,6 +54,10 @@ module Axlsx # @return [Boolean] attr_reader :i + # Indicates if the font should be rendered underlined + # @return [Boolean] + attr_reader :u + # Indicates if the font should be rendered with a strikthrough # @return [Boolean] attr_reader :strike @@ -89,6 +93,7 @@ module Axlsx # @option options [Integer] family # @option options [Boolean] b # @option options [Boolean] i + # @option options [Boolean] u # @option options [Boolean] strike # @option options [Boolean] outline # @option options [Boolean] shadow @@ -111,6 +116,8 @@ module Axlsx def b=(v) Axlsx::validate_boolean v; @b = v end # @see i def i=(v) Axlsx::validate_boolean v; @i = v end + # @see u + def u=(v) Axlsx::validate_boolean v; @u = v end # @see strike def strike=(v) Axlsx::validate_boolean v; @strike = v end # @see outline diff --git a/lib/axlsx/stylesheet/styles.rb b/lib/axlsx/stylesheet/styles.rb index 633fbcad..955a8b1e 100644 --- a/lib/axlsx/stylesheet/styles.rb +++ b/lib/axlsx/stylesheet/styles.rb @@ -125,6 +125,7 @@ module Axlsx # @option options [Integer] sz The text size # @option options [Boolean] b Indicates if the text should be bold # @option options [Boolean] i Indicates if the text should be italicised + # @option options [Boolean] u Indicates if the text should be underlined # @option options [Boolean] strike Indicates if the text should be rendered with a strikethrough # @option options [Boolean] strike Indicates if the text should be rendered with a shadow # @option options [Integer] charset The character set to use. @@ -210,9 +211,9 @@ module Axlsx 0 end - fontId = if (options.values_at(:fg_color, :sz, :b, :i, :strike, :outline, :shadow, :charset, :family, :font_name).length) + fontId = if (options.values_at(:fg_color, :sz, :b, :i, :u, :strike, :outline, :shadow, :charset, :family, :font_name).length) font = Font.new() - [:b, :i, :strike, :outline, :shadow, :charset, :family, :sz].each { |k| font.send("#{k}=", options[k]) unless options[k].nil? } + [:b, :i, :u, :strike, :outline, :shadow, :charset, :family, :sz].each { |k| font.send("#{k}=", options[k]) unless options[k].nil? } font.color = Color.new(:rgb => options[:fg_color]) unless options[:fg_color].nil? font.name = options[:font_name] unless options[:font_name].nil? fonts << font diff --git a/test/stylesheet/tc_font.rb b/test/stylesheet/tc_font.rb index f4b18776..141c285e 100644 --- a/test/stylesheet/tc_font.rb +++ b/test/stylesheet/tc_font.rb @@ -17,6 +17,7 @@ class TestFont < Test::Unit::TestCase assert_equal(@item.family, nil) assert_equal(@item.b, nil) assert_equal(@item.i, nil) + assert_equal(@item.u, nil) assert_equal(@item.strike, nil) assert_equal(@item.outline, nil) assert_equal(@item.shadow, nil) @@ -61,6 +62,13 @@ class TestFont < Test::Unit::TestCase assert_nothing_raised { @item.i = true } assert_equal(@item.i, true) end + + # def u=(v) Axlsx::validate_boolean v; @u = v end + def test_u + assert_raise(ArgumentError) { @item.u = -7 } + assert_nothing_raised { @item.u = true } + assert_equal(@item.u, true) + end # def strike=(v) Axlsx::validate_boolean v; @strike = v end def test_strike -- cgit v1.2.3 From 0257768200922b0dd33eb6e666824d53d61c035c Mon Sep 17 00:00:00 2001 From: Stefan Daschek Date: Mon, 27 Feb 2012 21:11:36 +0100 Subject: Add support for rows with custom height. --- README.md | 4 ++-- lib/axlsx/workbook/worksheet/row.rb | 22 ++++++++++++++++--- lib/axlsx/workbook/worksheet/worksheet.rb | 4 ++++ test/workbook/worksheet/tc_row.rb | 36 +++++++++++++++++++++++++++++++ test/workbook/worksheet/tc_worksheet.rb | 4 ++++ 5 files changed, 65 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 24c5bf58..bf32b8de 100644 --- a/README.md +++ b/README.md @@ -84,14 +84,14 @@ To install Axlsx, use the following command: sheet.add_row [1, 2, 3] end -##Using Custom Styles +##Using Custom Styles and Row Heights wb.styles do |s| black_cell = s.add_style :bg_color => "00", :fg_color => "FF", :sz => 14, :alignment => { :horizontal=> :center } blue_cell = s.add_style :bg_color => "0000FF", :fg_color => "FF", :sz => 20, :alignment => { :horizontal=> :center } wb.add_worksheet(:name => "Custom Styles") do |sheet| sheet.add_row ["Text Autowidth", "Second", "Third"], :style => [black_cell, blue_cell, black_cell] - sheet.add_row [1, 2, 3], :style => Axlsx::STYLE_THIN_BORDER + sheet.add_row [1, 2, 3], :style => Axlsx::STYLE_THIN_BORDER, :height => 20 end end diff --git a/lib/axlsx/workbook/worksheet/row.rb b/lib/axlsx/workbook/worksheet/row.rb index 9c35a302..e24514bc 100644 --- a/lib/axlsx/workbook/worksheet/row.rb +++ b/lib/axlsx/workbook/worksheet/row.rb @@ -13,12 +13,14 @@ module Axlsx # @return [SimpleTypedList] attr_reader :cells + # The height of this row in points, if set explicitly. + # @return [Float] + attr_reader :height + # TODO 18.3.1.73 # collapsed # customFormat - # customHeight # hidden - # ht (height) # outlineLevel # ph # s (style) @@ -39,12 +41,14 @@ module Axlsx # @option options [Array] values # @option options [Array, Symbol] types # @option options [Array, Integer] style + # @option options [Float] height the row's height (in points) # @see Row#array_to_cells # @see Cell def initialize(worksheet, values=[], options={}) self.worksheet = worksheet @cells = SimpleTypedList.new Cell @worksheet.rows << self + self.height = options.delete(:height) if options[:height] array_to_cells(values, options) end @@ -58,7 +62,9 @@ module Axlsx # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. # @return [String] def to_xml(xml) - xml.row(:r => index+1) { @cells.each { |cell| cell.to_xml(xml) } } + attrs = {:r => index+1} + attrs.merge!(:customHeight => 1, :ht => height) if custom_height? + xml.row(attrs) { |xml| @cells.each { |cell| cell.to_xml(xml) } } end # Adds a singel sell to the row based on the data provided and updates the worksheet's autofit data. @@ -84,6 +90,16 @@ module Axlsx @cells.to_ary end + # @see height + def height=(v); Axlsx::validate_unsigned_numeric(v) unless v.nil?; @height = v end + + # true if the row height has been manually set + # @return [Boolean] + # @see #height + def custom_height? + @height != nil + end + private # assigns the owning worksheet for this row diff --git a/lib/axlsx/workbook/worksheet/worksheet.rb b/lib/axlsx/workbook/worksheet/worksheet.rb index 7622aba0..63ff1310 100644 --- a/lib/axlsx/workbook/worksheet/worksheet.rb +++ b/lib/axlsx/workbook/worksheet/worksheet.rb @@ -205,6 +205,9 @@ module Axlsx # # ws.add_row ['I wish', 'for a fish', 'on my fish wish dish'], :widths=>[:ignore, :auto, 80] # + # @example - specify a fixed height for a row + # ws.add_row ['I wish', 'for a fish', 'on my fish wish dish'], :height => 40 + # # @example - create and use a style for all cells in the row # blue = ws.styles.add_style :color => "#00FF00" # ws.add_row [1, 2, 3], :style=>blue @@ -225,6 +228,7 @@ module Axlsx # @option options [Array, Symbol] types # @option options [Array, Integer] style # @option options [Array] widths each member of the widths array will affect how auto_fit behavies. + # @option options [Float] height the row's height (in points) def add_row(values=[], options={}) Row.new(self, values, options) update_auto_fit_data @rows.last.cells, options.delete(:widths) || [] diff --git a/test/workbook/worksheet/tc_row.rb b/test/workbook/worksheet/tc_row.rb index f9b589e3..38c910c5 100644 --- a/test/workbook/worksheet/tc_row.rb +++ b/test/workbook/worksheet/tc_row.rb @@ -12,6 +12,14 @@ class TestRow < Test::Unit::TestCase def test_initialize assert(@row.cells.empty?, "no cells by default") assert_equal(@row.worksheet, @ws, "has a reference to the worksheet") + assert_nil(@row.height, "height defaults to nil") + assert(!@row.custom_height?, "no custom height by default") + end + + def test_initialize_with_fixed_height + row = @ws.add_row([1,2,3,4,5], :height=>40) + assert_equal(40, row.height) + assert(row.custom_height?) end def test_style @@ -33,4 +41,32 @@ class TestRow < Test::Unit::TestCase r = @ws.add_row [1,2,3], :style=>0, :types=>:integer assert_equal(r.cells.size, 3) end + + def test_custom_height + @row.height = 20 + assert(@row.custom_height?) + end + + def test_height + assert_raise(ArgumentError) { @row.height = -3 } + assert_nothing_raised { @row.height = 15 } + assert_equal(15, @row.height) + end + + def test_to_xml_without_custom_height + xml = Nokogiri::XML::Builder.new + @row.to_xml(xml) + doc = Nokogiri::XML.parse(xml.to_xml) + assert_equal(0, doc.xpath(".//row[@ht]").size) + assert_equal(0, doc.xpath(".//row[@customHeight]").size) + end + + def test_to_xml_with_custom_height + @row.height = 20 + xml = Nokogiri::XML::Builder.new + @row.to_xml(xml) + doc = Nokogiri::XML.parse(xml.to_xml) + assert_equal(1, doc.xpath(".//row[@ht=20][@customHeight=1]").size) + end + end diff --git a/test/workbook/worksheet/tc_worksheet.rb b/test/workbook/worksheet/tc_worksheet.rb index b290f06b..ac71fce3 100644 --- a/test/workbook/worksheet/tc_worksheet.rb +++ b/test/workbook/worksheet/tc_worksheet.rb @@ -218,6 +218,10 @@ class TestWorksheet < Test::Unit::TestCase assert_equal(@ws.send(:auto_width, {:sz=>11, :longest => "This is a really long string", :fixed=>0.2}), 0.2, "fixed rules!") end + def test_fixed_height + @ws.add_row [1, 2, 3], :height => 40 + assert_equal(40, @ws.rows[-1].height) + end def test_set_column_width -- cgit v1.2.3 From cc3cf0a1b89fb766278e924930ee7f87bd085a55 Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Tue, 28 Feb 2012 13:39:35 +0900 Subject: referencing Converter, which is now known as DateTimeConverter. This should have been caught in the specs, so I will update them later to make sure we cover this path. --- lib/axlsx/workbook/worksheet/cell.rb | 80 ++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/lib/axlsx/workbook/worksheet/cell.rb b/lib/axlsx/workbook/worksheet/cell.rb index 167dfc97..dd3fddef 100644 --- a/lib/axlsx/workbook/worksheet/cell.rb +++ b/lib/axlsx/workbook/worksheet/cell.rb @@ -1,61 +1,61 @@ # encoding: UTF-8 module Axlsx - # A cell in a worksheet. + # A cell in a worksheet. # Cell stores inforamation requried to serialize a single worksheet cell to xml. You must provde the Row that the cell belongs to and the cells value. The data type will automatically be determed if you do not specify the :type option. The default style will be applied if you do not supply the :style option. Changing the cell's type will recast the value to the type specified. Altering the cell's value via the property accessor will also automatically cast the provided value to the cell's type. # @example Manually creating and manipulating Cell objects - # ws = Workbook.new.add_worksheet + # ws = Workbook.new.add_worksheet # # This is the simple, and recommended way to create cells. Data types will automatically be determined for you. # ws.add_row :values => [1,"fish",Time.now] # # # but you can also do this # r = ws.add_row # r.add_cell 1 - # + # # # or even this # r = ws.add_row # c = Cell.new row, 1, :value=>integer # # # cells can also be accessed via Row#cells. The example here changes the cells type, which will automatically updated the value from 1 to 1.0 # r.cells.last.type = :float - # + # # @note The recommended way to generate cells is via Worksheet#add_row - # + # # @see Worksheet#add_row class Cell # An array of available inline styes. - INLINE_STYLES = ['value', 'type', 'font_name', 'charset', - 'family', 'b', 'i', 'strike','outline', - 'shadow', 'condense', 'extend', 'u', + INLINE_STYLES = ['value', 'type', 'font_name', 'charset', + 'family', 'b', 'i', 'strike','outline', + 'shadow', 'condense', 'extend', 'u', 'vertAlign', 'sz', 'color', 'scheme'] # The index of the cellXfs item to be applied to this cell. - # @return [Integer] + # @return [Integer] # @see Axlsx::Styles attr_reader :style # The row this cell belongs to. # @return [Row] attr_reader :row - + # The cell's data type. Currently only six types are supported, :date, :time, :float, :integer, :string and :boolean. - # Changing the type for a cell will recast the value into that type. If no type option is specified in the constructor, the type is + # Changing the type for a cell will recast the value into that type. If no type option is specified in the constructor, the type is # automatically determed. # @see Cell#cell_type_from_value - # @return [Symbol] The type of data this cell's value is cast to. + # @return [Symbol] The type of data this cell's value is cast to. # @raise [ArgumentExeption] Cell.type must be one of [:date, time, :float, :integer, :string, :boolean] - # @note + # @note # If the value provided cannot be cast into the type specified, type is changed to :string and the following logic is applied. - # :string to :integer or :float, type conversions always return 0 or 0.0 + # :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 # @see type - def type=(v) - RestrictionValidator.validate "Cell.type", [:date, :time, :float, :integer, :string, :boolean], v - @type=v + def type=(v) + RestrictionValidator.validate "Cell.type", [:date, :time, :float, :integer, :string, :boolean], v + @type=v self.value = @value unless @value.nil? end @@ -68,7 +68,7 @@ module Axlsx #TODO: consider doing value based type determination first? @value = cast_value(v) end - + # The inline font_name property for the cell # @return [String] attr_reader :font_name @@ -139,7 +139,7 @@ module Axlsx # @return [Color] attr_reader :color # @param [String] The 8 character representation for an rgb color #FFFFFFFF" - def color=(v) + def color=(v) @color = v.is_a?(Color) ? v : Color.new(:rgb=>v) end @@ -164,7 +164,7 @@ module Axlsx def scheme=(v) RestrictionValidator.validate "Cell.schema", [:none, :major, :minor], v; @scheme = v; end # @param [Row] row The row this cell belongs to. - # @param [Any] value The value associated with this cell. + # @param [Any] value The value associated with this cell. # @option options [Symbol] type The intended data type for this cell. If not specified the data type will be determined internally based on the vlue provided. # @option options [Integer] style The index of the cellXfs item to be applied to this cell. If not specified, the default style (0) will be applied. # @option options [String] font_name @@ -183,11 +183,11 @@ module Axlsx # @option options [String] color an 8 letter rgb specification # @option options [Symbol] scheme must be one of :none, major, :minor def initialize(row, value="", options={}) - self.row=row + self.row=row @font_name = @charset = @family = @b = @i = @strike = @outline = @shadow = nil @condense = @u = @vertAlign = @sz = @color = @scheme = @extend = @ssti = nil @styles = row.worksheet.workbook.styles - @row.cells << self + @row.cells << self options.each do |o| self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}=" end @@ -199,7 +199,7 @@ module Axlsx # The Shared Strings Table index for this cell # @return [Integer] attr_reader :ssti - + # equality comparison to test value, type and inline style attributes # this is how we work out if the cell needs to be added or already exists in the shared strings table def shareable(v) @@ -221,14 +221,14 @@ module Axlsx # @return [String] The alpha(column)numeric(row) reference for this sell. # @example Relative Cell Reference - # ws.rows.first.cells.first.r #=> "A1" + # ws.rows.first.cells.first.r #=> "A1" def r - "#{col_ref}#{@row.index+1}" + "#{col_ref}#{@row.index+1}" end # @return [String] The absolute alpha(column)numeric(row) reference for this sell. # @example Absolute Cell Reference - # ws.rows.first.cells.first.r #=> "$A$1" + # ws.rows.first.cells.first.r #=> "$A$1" def r_abs "$#{r.split('').join('$')}" end @@ -257,7 +257,7 @@ module Axlsx target.r end self.row.worksheet.merge_cells "#{self.r}:#{range_end}" unless range_end.nil? - end + end # builds an xml text run based on this cells attributes. This is extracted from to_xml so that shared strings can use it. # @param [Nokogiri::XML::Builder] xml The document builder instance this output will be added to. @@ -288,14 +288,14 @@ module Axlsx } else xml.t @value.to_s - end + end end # Serializes the cell # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. # @return [String] xml text for the cell - def to_xml(xml) - if @type == :string + def to_xml(xml) + if @type == :string #parse formula if @value.start_with?('=') xml.c(:r => r, :t=>:str, :s=>style) { @@ -316,10 +316,10 @@ module Axlsx end elsif @type == :date # TODO: See if this is subject to the same restriction as Time below - v = Converter.date_to_serial @value, Workbook.date1904 + v = DateTimeConverter.date_to_serial @value xml.c(:r => r, :s => style) { xml.v v } elsif @type == :time - v = Converter.time_to_serial @value, Workbook.date1904 + v = DateTimeConverter.time_to_serial @value xml.c(:r => r, :s => style) { xml.v v } elsif @type == :boolean xml.c(:r => r, :s => style, :t => :b) { xml.v value } @@ -328,17 +328,17 @@ module Axlsx end end - private + private # @see ssti - def ssti=(v) + def ssti=(v) Axlsx::validate_unsigned_int(v) @ssti = v end # assigns the owning row for this cell. def row=(v) DataTypeValidator.validate "Cell.row", Row, v; @row=v end - + # converts the column index into alphabetical values. # @note This follows the standard spreadsheet convention of naming columns A to Z, followed by AA to AZ etc. # @return [String] @@ -353,7 +353,7 @@ module Axlsx chars.reverse.join end - # Determines the cell type based on the cell value. + # 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 # 2. If the value is an instance of Time, the type is set to :time @@ -361,7 +361,7 @@ module Axlsx # 4. :float and :integer types are determined by regular expression matching. # 5. Anything that does not meet either of the above is determined to be :string. # @return [Symbol] The determined type - def cell_type_from_value(v) + def cell_type_from_value(v) if v.is_a?(Date) :date elsif v.is_a?(Time) @@ -377,8 +377,8 @@ module Axlsx end end - # Cast the value into this cells data type. - # @note + # Cast the value into this cells data type. + # @note # About Time - Time in OOXML is *different* from what you might expect. The history as to why is interesting, but you can safely assume that if you are generating docs on a mac, you will want to specify Workbook.1904 as true when using time typed values. # @see Axlsx#date1904 def cast_value(v) @@ -398,6 +398,6 @@ module Axlsx @type = :string v.to_s end - end + end end end -- cgit v1.2.3 From 3144c84e008bb6232afcce7dfa4fec0918e46573 Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Tue, 28 Feb 2012 13:40:21 +0900 Subject: typo in examples --- examples/example.rb | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/examples/example.rb b/examples/example.rb index 41a08c50..caafd274 100644 --- a/examples/example.rb +++ b/examples/example.rb @@ -39,25 +39,25 @@ ##Add an Image wb.add_worksheet(:name => "Images") do |sheet| - img = File.expand_path('examples/image1.jpeg') + img = File.expand_path('examples/image1.jpeg') sheet.add_image(:image_src => img, :noSelect => true, :noMove => true) do |image| image.width=720 image.height=666 image.start_at 2, 2 end - end + end ##Add an Image with a hyperlink wb.add_worksheet(:name => "Image with Hyperlink") do |sheet| - img = File.expand_path('examples/image1.jpeg') + img = File.expand_path('examples/image1.jpeg') sheet.add_image(:image_src => img, :noSelect => true, :noMove => true, :hyperlink=>"http://axlsx.blogspot.com") do |image| image.width=720 image.height=666 image.hyperlink.tooltip = "Labeled Link" image.start_at 2, 2 end - end + end ##Asian Language Support @@ -65,7 +65,7 @@ sheet.add_row ["日本語"] sheet.add_row ["华语/華語"] sheet.add_row ["한국어/조선말"] - end + end ##Styling Columns @@ -104,7 +104,7 @@ # cell level style overrides via sheet range sheet["A1:D1"].each { |c| c.color = "FF0000"} sheet['A1:D2'].each { |c| c.style = Axlsx::STYLE_THIN_BORDER } - end + end ##Using formula @@ -131,7 +131,7 @@ sheet.merge_cells("A4:C4") sheet["A1:D1"].each { |c| c.color = "FF0000"} sheet["A1:D4"].each { |c| c.style = Axlsx::STYLE_THIN_BORDER } - end + end ##Generating A Bar Chart @@ -142,7 +142,7 @@ sheet.add_chart(Axlsx::Bar3DChart, :start_at => "A4", :end_at => "F17") do |chart| chart.add_series :data => sheet["A3:C3"], :labels => sheet["A2:C2"], :title => sheet["A1"] end - end + end ##Generating A Pie Chart @@ -152,7 +152,7 @@ sheet.add_chart(Axlsx::Pie3DChart, :start_at => [0,2], :end_at => [5, 15], :title => "example 3: Pie Chart") do |chart| chart.add_series :data => sheet["A2:D2"], :labels => sheet["A1:D1"] end - end + end ##Data over time @@ -166,9 +166,9 @@ sheet.add_chart(Axlsx::Bar3DChart) do |chart| chart.start_at "B7" chart.end_at "H27" - chart.add_series(:data => sheet["B2:B5"], :labels => sheet["A2:A5"], :title => sheet["B1"]) - end - end + chart.add_series(:data => sheet["B2:B5"], :labels => sheet["A2:A5"], :title => sheet["B1"]) + end + end ##Generating A Line Chart @@ -179,9 +179,9 @@ chart.start_at 0, 2 chart.end_at 10, 15 chart.add_series :data => sheet["B1:E1"], :title => sheet["A1"] - chart.add_series :data => sheet["B2:E2"], :title => sheet["A2"] - end - end + chart.add_series :data => sheet["B2:E2"], :title => sheet["A2"] + end + end ##Auto Filter @@ -192,7 +192,7 @@ sheet.add_row ["19.2", "1 min 28 sec", "about 10 hours ago", "1.9.2"] sheet.add_row ["19.3", "1 min 35 sec", "about 10 hours ago", "1.9.3"] sheet.auto_filter = "A2:D5" - end + end ##Specifying Column Widths @@ -204,7 +204,7 @@ ##Specify Page Margins for printing margins = {:left => 3, :right => 3, :top => 1.2, :bottom => 1.2, :header => 0.7, :footer => 0.7} wb.add_worksheet(:name => "print margins", :page_margins => margins) do |sheet| - sheet.add_row["this sheet uses customized page margins for printing"] + sheet.add_row ["this sheet uses customized page margins for printing"] end ##Validate and Serialize @@ -223,5 +223,5 @@ - + -- cgit v1.2.3 From a40d5ed93eda8a95c14a6db8cee7f0c2e70f26ae Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Tue, 28 Feb 2012 14:17:17 +0900 Subject: patching time converter and specs as well as fixing warnings related to uninitialized row#height and worksheet#page_margins --- lib/axlsx/workbook/worksheet/cell.rb | 4 +- .../workbook/worksheet/date_time_converter.rb | 8 +- lib/axlsx/workbook/worksheet/row.rb | 25 +++--- lib/axlsx/workbook/worksheet/worksheet.rb | 89 +++++++++++----------- test/workbook/worksheet/tc_date_time_converter.rb | 25 +++--- 5 files changed, 75 insertions(+), 76 deletions(-) diff --git a/lib/axlsx/workbook/worksheet/cell.rb b/lib/axlsx/workbook/worksheet/cell.rb index dd3fddef..62fa539f 100644 --- a/lib/axlsx/workbook/worksheet/cell.rb +++ b/lib/axlsx/workbook/worksheet/cell.rb @@ -316,10 +316,10 @@ module Axlsx end elsif @type == :date # TODO: See if this is subject to the same restriction as Time below - v = DateTimeConverter.date_to_serial @value + v = DateTimeConverter::date_to_serial @value xml.c(:r => r, :s => style) { xml.v v } elsif @type == :time - v = DateTimeConverter.time_to_serial @value + v = DateTimeConverter::time_to_serial @value xml.c(:r => r, :s => style) { xml.v v } elsif @type == :boolean xml.c(:r => r, :s => style, :t => :b) { xml.v value } diff --git a/lib/axlsx/workbook/worksheet/date_time_converter.rb b/lib/axlsx/workbook/worksheet/date_time_converter.rb index 18d5e59f..5a572781 100644 --- a/lib/axlsx/workbook/worksheet/date_time_converter.rb +++ b/lib/axlsx/workbook/worksheet/date_time_converter.rb @@ -2,13 +2,13 @@ require "date" module Axlsx - # The DateTimeConverter class converts both data and time types to their apprpriate excel serializations + # The DateTimeConverter class converts both data and time types to their apprpriate excel serializations class DateTimeConverter - + # The date_to_serial method converts Date objects to the equivelant excel serialized forms # @param [Date] date the date to be serialized # @return [Numeric] - def date_to_serial(date) + def self.date_to_serial(date) epoc = Axlsx::Workbook::date1904 ? Date.new(1904) : Date.new(1899, 12, 30) (date-epoc).to_f end @@ -16,7 +16,7 @@ module Axlsx # The time_to_serial methond converts a Time object its excel serialized form. # @param [Time] time the time to be serialized # @return [Numeric] - def time_to_serial(time) + def self.time_to_serial(time) # Using hardcoded offsets here as some operating systems will not except # a 'negative' offset from the ruby epoc. epoc1900 = -2209161600 # Time.utc(1899, 12, 30).to_i diff --git a/lib/axlsx/workbook/worksheet/row.rb b/lib/axlsx/workbook/worksheet/row.rb index e24514bc..bb6a92a8 100644 --- a/lib/axlsx/workbook/worksheet/row.rb +++ b/lib/axlsx/workbook/worksheet/row.rb @@ -39,12 +39,13 @@ module Axlsx # If the style option is not defined, the default style (0) is applied to each cell. # @param [Worksheet] worksheet # @option options [Array] values - # @option options [Array, Symbol] types - # @option options [Array, Integer] style + # @option options [Array, Symbol] types + # @option options [Array, Integer] style # @option options [Float] height the row's height (in points) # @see Row#array_to_cells # @see Cell def initialize(worksheet, values=[], options={}) + @height = nil self.worksheet = worksheet @cells = SimpleTypedList.new Cell @worksheet.rows << self @@ -54,17 +55,17 @@ module Axlsx # The index of this row in the worksheet # @return [Integer] - def index + def index worksheet.rows.index(self) end - + # Serializes the row # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. # @return [String] def to_xml(xml) attrs = {:r => index+1} attrs.merge!(:customHeight => 1, :ht => height) if custom_height? - xml.row(attrs) { |xml| @cells.each { |cell| cell.to_xml(xml) } } + xml.row(attrs) { |ixml| @cells.each { |cell| cell.to_xml(ixml) } } end # Adds a singel sell to the row based on the data provided and updates the worksheet's autofit data. @@ -74,7 +75,7 @@ module Axlsx update_auto_fit_data c end - + # sets the style for every cell in this row def style=(style) cells.each_with_index do | cell, index | @@ -84,7 +85,7 @@ module Axlsx end # returns the cells in this row as an array - # This lets us transpose the rows into columns + # This lets us transpose the rows into columns # @return [Array] def to_ary @cells.to_ary @@ -104,7 +105,7 @@ module Axlsx # assigns the owning worksheet for this row def worksheet=(v) DataTypeValidator.validate "Row.worksheet", Worksheet, v; @worksheet=v; end - + # Tell the worksheet to update autofit data for the columns based on this row's cells. # @return [SimpleTypedList] def update_auto_fit_data @@ -119,13 +120,13 @@ module Axlsx # If the style option is defined and is an Integer, it is applied to all cells created. # If the style option is an array, style is applied by index for each cell. # @option options [Array] values - # @option options [Array, Symbol] types - # @option options [Array, Integer] style + # @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 types, style = options.delete(:types), options.delete(:style) - values.each_with_index do |value, index| + values.each_with_index do |value, index| 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 @@ -134,5 +135,5 @@ module Axlsx end end end - + end diff --git a/lib/axlsx/workbook/worksheet/worksheet.rb b/lib/axlsx/workbook/worksheet/worksheet.rb index 63ff1310..cd0c6c97 100644 --- a/lib/axlsx/workbook/worksheet/worksheet.rb +++ b/lib/axlsx/workbook/worksheet/worksheet.rb @@ -1,9 +1,9 @@ # encoding: UTF-8 module Axlsx - - # The Worksheet class represents a worksheet in the workbook. + + # The Worksheet class represents a worksheet in the workbook. class Worksheet - + # The name of the worksheet # @return [String] attr_reader :name @@ -21,7 +21,7 @@ module Axlsx # An array of content based calculated column widths. # @note a single auto fit data item is a hash with :longest => [String] and :sz=> [Integer] members. - # @return [Array] of Hash + # @return [Array] of Hash attr_reader :auto_fit_data # An array of merged cell ranges e.d "A1:B3" @@ -34,16 +34,16 @@ module Axlsx # The first row is considered the header, while subsequent rows are considerd to be data. # @return Array attr_reader :auto_filter - + # Page margins for printing the worksheet. # @example # wb = Axlsx::Package.new.workbook # # using options when creating the worksheet. # ws = wb.add_worksheet :page_margins => {:left => 1.9, :header => 0.1} - # + # # # use the set method of the page_margins object # ws.page_margins.set(:bottom => 3, :footer => 0.7) - # + # # # set page margins in a block # ws.page_margins do |margins| # margins.right = 6 @@ -57,15 +57,14 @@ module Axlsx yield @page_margins if block_given? @page_margins end - + # Creates a new worksheet. # @note the recommended way to manage worksheets is Workbook#add_worksheet # @see Workbook#add_worksheet # @option options [String] name The name of this worksheet. # @option options [Hash] page_margins A hash containing page margins for this worksheet. @see PageMargins def initialize(wb, options={}) - @drawing = nil - @auto_filter = nil + @drawing = @page_margins = @auto_filter = nil @rows = SimpleTypedList.new Row self.workbook = wb @workbook.worksheets << self @@ -75,7 +74,7 @@ module Axlsx @magick_draw = Magick::Draw.new @cols = SimpleTypedList.new Cell @merged_cells = [] - + @page_margins = PageMargins.new options[:page_margins] if options[:page_margins] end @@ -85,26 +84,26 @@ module Axlsx rows.flatten end - # Creates merge information for this worksheet. + # Creates merge information for this worksheet. # Cells can be merged by calling the merge_cells method on a worksheet. - # @example This would merge the three cells C1..E1 # + # @example This would merge the three cells C1..E1 # # worksheet.merge_cells "C1:E1" # # you can also provide an array of cells to be merged # worksheet.merge_cells worksheet.rows.first.cells[(2..4)] # #alternatively you can do it from a single cell # worksheet["C1"].merge worksheet["E1"] - # @param [Array, string] + # @param [Array, string] def merge_cells(cells) @merged_cells << if cells.is_a?(String) cells elsif cells.is_a?(Array) cells = cells.sort { |x, y| x.r <=> y.r } "#{cells.first.r}:#{cells.last.r}" - end + end end - # The demensions of a worksheet. This is not actually a required element by the spec, + # The demensions of a worksheet. This is not actually a required element by the spec, # but at least a few other document readers expect this for conversion # @return [String] the A1:B2 style reference for the first and last row column intersection in the workbook def dimension @@ -145,18 +144,18 @@ module Axlsx # The name of the worksheet # The name of a worksheet must be unique in the workbook, and must not exceed 31 characters # @param [String] v - def name=(v) + def name=(v) DataTypeValidator.validate "Worksheet.name", String, v raise ArgumentError, (ERR_SHEET_NAME_TOO_LONG % v) if v.size > 31 sheet_names = @workbook.worksheets.map { |s| s.name } - raise ArgumentError, (ERR_DUPLICATE_SHEET_NAME % v) if sheet_names.include?(v) - @name=v + raise ArgumentError, (ERR_DUPLICATE_SHEET_NAME % v) if sheet_names.include?(v) + @name=v end # The auto filter range for the worksheet # @param [String] v # @see auto_filter - def auto_filter=(v) + def auto_filter=(v) DataTypeValidator.validate "Worksheet.auto_filter", String, v @auto_filter = v end @@ -196,7 +195,7 @@ module Axlsx # Adds a row to the worksheet and updates auto fit data # @example - put a vanilla row in your spreadsheet # ws.add_row [1, 'fish on my pl', '8'] - # + # # @example - specify a fixed width for a column in your spreadsheet # # The first column will ignore the content of this cell when calculating column autowidth. # # The second column will include this text in calculating the columns autowidth @@ -222,11 +221,11 @@ module Axlsx # @example - force the second cell to be a float value # ws.add_row [3, 4, 5], :types => [nil, :float] # - # @see Worksheet#column_widths + # @see Worksheet#column_widths # @return [Row] # @option options [Array] values - # @option options [Array, Symbol] types - # @option options [Array, Integer] style + # @option options [Array, Symbol] types + # @option options [Array, Integer] style # @option options [Array] widths each member of the widths array will affect how auto_fit behavies. # @option options [Float] height the row's height (in points) def add_row(values=[], options={}) @@ -268,7 +267,7 @@ module Axlsx # @see README.md for an example def col_style(index, style, options={}) offset = options.delete(:row_offset) || 0 - @rows[(offset..-1)].each do |r| + @rows[(offset..-1)].each do |r| cells = r.cells[index] next unless cells if cells.is_a?(Array) @@ -279,13 +278,13 @@ module Axlsx end end - # This is a helper method that Lets you specify a fixed width for multiple columns in a worksheet in one go. + # This is a helper method that Lets you specify a fixed width for multiple columns in a worksheet in one go. # Axlsx is sparse, so if you have not set data for a column, you cannot set the width. # Setting a fixed column width to nil will revert the behaviour back to calculating the width for you. # @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 ws.auto_fit_data[col_index][:fixed] directly - # @param [Integer|Float|Fixnum|nil] values + # @param [Integer|Float|Fixnum|nil] values def column_widths(*args) args.each_with_index do |value, index| raise ArgumentError, "Invalid column specification" unless index < @auto_fit_data.size @@ -294,14 +293,14 @@ module Axlsx end end - # Adds a chart to this worksheets drawing. This is the recommended way to create charts for your worksheet. This method wraps the complexity of dealing with ooxml drawing, anchors, markers graphic frames chart objects and all the other dirty details. + # Adds a chart to this worksheets drawing. This is the recommended way to create charts for your worksheet. This method wraps the complexity of dealing with ooxml drawing, anchors, markers graphic frames chart objects and all the other dirty details. # @param [Class] chart_type # @option options [Array] start_at # @option options [Array] end_at # @option options [Cell, String] title # @option options [Boolean] show_legend - # @option options [Integer] style - # @note each chart type also specifies additional options + # @option options [Integer] style + # @note each chart type also specifies additional options # @see Chart # @see Pie3DChart # @see Bar3DChart @@ -326,12 +325,12 @@ module Axlsx # @return [String] def to_xml builder = Nokogiri::XML::Builder.new(:encoding => ENCODING) do |xml| - xml.worksheet(:xmlns => XML_NS, + xml.worksheet(:xmlns => XML_NS, :'xmlns:r' => XML_NS_R) { # another patch for the folks at rubyXL as thier parser depends on this optional element. xml.dimension :ref=>dimension unless rows.size == 0 # this is required by rubyXL, spec says who cares - but it seems they didnt notice - xml.sheetViews { + xml.sheetViews { xml.sheetView(:tabSelected => 1, :workbookViewId => index) { xml.selection :activeCell=>"A1", :sqref => "A1" } @@ -353,7 +352,7 @@ module Axlsx xml.autoFilter :ref=>@auto_filter if @auto_filter xml.mergeCells(:count=>@merged_cells.size) { @merged_cells.each { | mc | xml.mergeCell(:ref=>mc) } } unless @merged_cells.empty? page_margins.to_xml(xml) if @page_margins - xml.drawing :"r:id"=>"rId1" if @drawing + xml.drawing :"r:id"=>"rId1" if @drawing } end builder.to_xml(:save_with => 0) @@ -367,16 +366,16 @@ module Axlsx r end - private + private # assigns the owner workbook for this worksheet def workbook=(v) DataTypeValidator.validate "Worksheet.workbook", Workbook, v; @workbook = v; end - # Updates auto fit data. - # We store an auto_fit_data item for each column. when a row is added we multiple the font size by the length of the text to + # Updates auto fit data. + # We store an auto_fit_data item for each column. when a row is added we multiple the font size by the length of the text to # attempt to identify the longest cell in the column. This is not 100% accurate as it needs to take into account - # any formatting that will be applied to the data, as well as the actual rendering size when the length and size is equal - # for two cells. + # any formatting that will be applied to the data, as well as the actual rendering size when the length and size is equal + # for two cells. # @return [Array] of Cell objects # @param [Array] cells an array of cells @@ -406,12 +405,12 @@ module Axlsx end cells end - + # Determines the proper width for a column based on content. - # @note + # @note # width = Truncate([!{Number of Characters} * !{Maximum Digit Width} + !{5 pixel padding}]/!{Maximum Digit Width}*256)/256 # @return [Float] - # @param [Hash] A hash of auto_fit_data + # @param [Hash] A hash of auto_fit_data def auto_width(col) return col[:fixed] unless col[:fixed] == nil @@ -424,21 +423,21 @@ module Axlsx end # Something to look into: - # width calculation actually needs to be done agains the formatted value for items that apply a + # width calculation actually needs to be done agains the formatted value for items that apply a # format # def excel_format(cell) # # The most common case. # return time.value.to_s if cell.style == 0 # - # # The second most common case + # # The second most common case # num_fmt = workbook.styles.cellXfs[items.style].numFmtId # return value.to_s if num_fmt == 0 - # + # # format_code = workbook.styles.numFmts[num_fmt] # # need to find some exceptionally fast way of parsing value according to # # an excel format_code # item.value.to_s - # end + # end end end diff --git a/test/workbook/worksheet/tc_date_time_converter.rb b/test/workbook/worksheet/tc_date_time_converter.rb index 78053a6d..529da917 100644 --- a/test/workbook/worksheet/tc_date_time_converter.rb +++ b/test/workbook/worksheet/tc_date_time_converter.rb @@ -4,7 +4,6 @@ require 'axlsx.rb' class TestDateTimeConverter < Test::Unit::TestCase def setup - @converter = Axlsx::DateTimeConverter.new @margin_of_error = 0.000_001 @extended_time_range = begin Time.parse "1893-08-05" @@ -25,7 +24,7 @@ class TestDateTimeConverter < Test::Unit::TestCase "2006-02-01" => 38749.0, "9999-12-31" => 2958465.0 } - else + else { # examples taken inside the possible values "1970-01-01" => 25569.0, # Unix epoch "1970-01-02" => 25570.0, @@ -34,7 +33,7 @@ class TestDateTimeConverter < Test::Unit::TestCase } end tests.each do |date_string, expected| - serial = @converter.date_to_serial Date.parse(date_string) + serial = Axlsx::DateTimeConverter::date_to_serial Date.parse(date_string) assert_equal expected, serial end end @@ -58,7 +57,7 @@ class TestDateTimeConverter < Test::Unit::TestCase } end tests.each do |date_string, expected| - serial = @converter.date_to_serial Date.parse(date_string) + serial = Axlsx::DateTimeConverter::date_to_serial Date.parse(date_string) assert_equal expected, serial end end @@ -67,8 +66,8 @@ class TestDateTimeConverter < Test::Unit::TestCase Axlsx::Workbook.date1904 = false tests = if @extended_time_range { # examples taken straight from the spec - "1893-08-05T00:00:01Z" => -2337.999989, - "1899-12-28T18:00:00Z" => -1.25, + "1893-08-05T00:00:01Z" => -2337.999989, + "1899-12-28T18:00:00Z" => -1.25, "1910-02-03T10:05:54Z" => 3687.4207639, "1900-01-01T12:00:00Z" => 2.5, # wrongly indicated as 1.5 in the spec! "9999-12-31T23:59:59Z" => 2958465.9999884 @@ -82,7 +81,7 @@ class TestDateTimeConverter < Test::Unit::TestCase } end tests.each do |time_string, expected| - serial = @converter.time_to_serial Time.parse(time_string) + serial = Axlsx::DateTimeConverter::time_to_serial Time.parse(time_string) assert_in_delta expected, serial, @margin_of_error end end @@ -90,10 +89,10 @@ class TestDateTimeConverter < Test::Unit::TestCase def test_time_to_serial_1904 Axlsx::Workbook.date1904 = true # ruby 1.8.7 cannot parse dates prior to epoc. see http://ruby-doc.org/core-1.8.7/Time.html - + tests = if @extended_time_range { # examples taken straight from the spec - "1893-08-05T00:00:01Z" => -3799.999989, + "1893-08-05T00:00:01Z" => -3799.999989, "1910-02-03T10:05:54Z" => 2225.4207639, "1904-01-01T12:00:00Z" => 0.5000000, "9999-12-31T23:59:59Z" => 2957003.9999884 @@ -106,8 +105,8 @@ class TestDateTimeConverter < Test::Unit::TestCase "2038-01-19T03:14:07Z" => 48962.134803, # max signed timestamp in 32bit } end - tests.each do |time_string, expected| - serial = @converter.time_to_serial Time.parse(time_string) + tests.each do |time_string, expected| + serial = Axlsx::DateTimeConverter::time_to_serial Time.parse(time_string) assert_in_delta expected, serial, @margin_of_error end end @@ -120,9 +119,9 @@ class TestDateTimeConverter < Test::Unit::TestCase Time.parse "2012-01-01 01:00:00 +0100" end assert_equal local, utc - assert_equal @converter.time_to_serial(local), @converter.time_to_serial(utc) + assert_equal Axlsx::DateTimeConverter::time_to_serial(local), Axlsx::DateTimeConverter::time_to_serial(utc) Axlsx::Workbook.date1904 = true - assert_equal @converter.time_to_serial(local), @converter.time_to_serial(utc) + assert_equal Axlsx::DateTimeConverter::time_to_serial(local), Axlsx::DateTimeConverter::time_to_serial(utc) end end -- cgit v1.2.3 From 6419f49f36c422a3595310c4f73e295789be489d Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Tue, 28 Feb 2012 18:42:26 +0900 Subject: testing to_xml validitiy --- test/workbook/worksheet/tc_cell.rb | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/test/workbook/worksheet/tc_cell.rb b/test/workbook/worksheet/tc_cell.rb index f288a867..97a9951b 100644 --- a/test/workbook/worksheet/tc_cell.rb +++ b/test/workbook/worksheet/tc_cell.rb @@ -10,7 +10,7 @@ class TestCell < Test::Unit::TestCase @row = @ws.add_row @c = @row.add_cell 1, :type=>:float, :style=>1 end - + def test_initialize assert_equal(@row.cells.last, @c, "the cell was added to the row") assert_equal(@c.type, :float, "type option is applied") @@ -46,7 +46,7 @@ class TestCell < Test::Unit::TestCase def test_style assert_raise(ArgumentError, "must reject invalid style indexes") { @c.style=@c.row.worksheet.workbook.styles.cellXfs.size } - assert_nothing_raised("must allow valid style index changes") {@c.style=1} + assert_nothing_raised("must allow valid style index changes") {@c.style=1} assert_equal(@c.style, 1) end @@ -54,7 +54,7 @@ class TestCell < Test::Unit::TestCase assert_raise(ArgumentError, "type must be :string, :integer, :float, :date, :time, :boolean") { @c.type = :array } assert_nothing_raised("type can be changed") { @c.type = :string } assert_equal(@c.value, "1.0", "changing type casts the value") - + assert_equal(@row.add_cell(Time.now).type, :time, 'time should be time') assert_equal(@row.add_cell(Date.today).type, :date, 'date should be date') assert_equal(@row.add_cell(true).type, :boolean, 'boolean should be boolean') @@ -83,7 +83,7 @@ class TestCell < Test::Unit::TestCase assert_equal(@c.send(:cell_type_from_value, false), :boolean) end - def test_cast_value + def test_cast_value @c.type = :string assert_equal(@c.send(:cast_value, 1.0), "1.0") @c.type = :integer @@ -192,7 +192,7 @@ class TestCell < Test::Unit::TestCase @c.row.add_cell 2 @c.row.add_cell 3 @c.merge "A2" - assert_equal(@c.row.worksheet.merged_cells.last, "A1:A2") + assert_equal(@c.row.worksheet.merged_cells.last, "A1:A2") end def test_merge_with_cell @@ -200,7 +200,7 @@ class TestCell < Test::Unit::TestCase @c.row.add_cell 2 @c.row.add_cell 3 @c.merge @row.cells.last - assert_equal(@c.row.worksheet.merged_cells.last, "A1:C1") + assert_equal(@c.row.worksheet.merged_cells.last, "A1:C1") end def test_equality @@ -220,4 +220,18 @@ class TestCell < Test::Unit::TestCase assert_equal(@c.ssti, 1) end + def test_to_xml + # TODO This could use some much more stringent testing related to the xml content generated! + row = @ws.add_row [Time.now, Date.today, true, 1, 1.0, "text", "=sum(A1:A2)"] + schema = Nokogiri::XML::Schema(File.open(Axlsx::SML_XSD)) + doc = Nokogiri::XML(@ws.to_xml) + errors = [] + schema.validate(doc).each do |error| + errors.push error + puts error.message + end + assert(errors.empty?, "error free validation") + + end + end -- cgit v1.2.3 From 94a78ec80a91fb441947b8b47766a555bee1ae1f Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Wed, 29 Feb 2012 17:36:02 +0900 Subject: altering package validation errors to show the document they occurred in. validates now returns an array of {:entry=>'file_name', :errors=>[error,error]} hashes. --- lib/axlsx/package.rb | 62 ++++++++++++++++++++++++++++------------------------ 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/lib/axlsx/package.rb b/lib/axlsx/package.rb index 5548dd62..440a1b6a 100644 --- a/lib/axlsx/package.rb +++ b/lib/axlsx/package.rb @@ -4,7 +4,7 @@ module Axlsx # xlsx document including valdation and serialization. class Package - + # provides access to the app doc properties for this package # see App attr_reader :app @@ -31,8 +31,8 @@ module Axlsx # Shortcut to specify that the workbook should use shared strings # @see Workbook#use_shared_strings - def use_shared_strings=(v) - Axlsx::validate_boolean(v); + def use_shared_strings=(v) + Axlsx::validate_boolean(v); workbook.use_shared_strings = v end @@ -45,7 +45,7 @@ module Axlsx # The workbook this package will serialize or validate. # @return [Workbook] If no workbook instance has been assigned with this package a new Workbook instance is returned. # @raise ArgumentError if workbook parameter is not a Workbook instance. - # @note As there are multiple ways to instantiate a workbook for the package, + # @note As there are multiple ways to instantiate a workbook for the package, # here are a few examples: # # assign directly during package instanciation # wb = Package.new(:workbook => Workbook.new).workbook @@ -59,13 +59,13 @@ module Axlsx yield @workbook if block_given? @workbook end - + #def self.parse(input, confirm_valid = false) # p = Package.new # z = Zip::ZipFile.open(input) # p.workbook = Workbook.parse z.get_entry(WORKBOOK_PN) # p - #end + #end # @see workbook def workbook=(workbook) DataTypeValidator.validate "Package.workbook", Workbook, workbook; @workbook = workbook; end @@ -77,7 +77,7 @@ module Axlsx # @option options stream indicates if we should be writing to a stream or a file. True for stream, nil for file # @return [Boolean] False if confirm_valid and validation errors exist. True if the package was serialized # @note A tremendous amount of effort has gone into ensuring that you cannot create invalid xlsx documents. - # confirm_valid should be used in the rare case that you cannot open the serialized file. + # confirm_valid should be used in the rare case that you cannot open the serialized file. # @see Package#validate # @example # # This is how easy it is to create a valid xlsx file. Of course you might want to add a sheet or two, and maybe some data, styles and charts. @@ -105,20 +105,20 @@ module Axlsx stream.rewind stream end - + # Encrypt the package into a CFB using the password provided # This is not ready yet - def encrypt(file_name, password) + def encrypt(file_name, password) return false # moc = MsOffCrypto.new(file_name, password) - # moc.save + # moc.save end - - # Validate all parts of the package against xsd schema. + + # Validate all parts of the package against xsd schema. # @return [Array] An array of all validation errors found. # @note This gem includes all schema from OfficeOpenXML-XMLSchema-Transitional.zip and OpenPackagingConventions-XMLSchema.zip # as per ECMA-376, Third edition. opc schema require an internet connection to import remote schema from dublin core for dc, - # dcterms and xml namespaces. Those remote schema are included in this gem, and the original files have been altered to + # dcterms and xml namespaces. Those remote schema are included in this gem, and the original files have been altered to # refer to the local versions. # # If by chance you are able to creat a package that does not validate it indicates that the internal @@ -131,34 +131,38 @@ module Axlsx # p.validate.each { |error| puts error.message } def validate errors = [] - parts.each { |part| errors.concat validate_single_doc(part[:schema], part[:doc]) unless part[:schema].nil? } + parts.each do |part| + next if part[:schema].nil? + e = validate_single_doc(part[:schema], part[:doc]) + errors << { :entry => part[:entry], :errors => e } if e.size > 0 + end errors end - private + private # Writes the package parts to a zip archive. # @param [Zip::ZipOutputStream] zip # @return [Zip::ZipOutputStream] def write_parts(zip) p = parts - p.each do |part| + p.each do |part| unless part[:doc].nil? zip.put_next_entry(part[:entry]); entry = ['1.9.2', '1.9.3'].include?(RUBY_VERSION) ? part[:doc].force_encoding('BINARY') : part[:doc] zip.puts(entry) end unless part[:path].nil? - zip.put_next_entry(part[:entry]); + zip.put_next_entry(part[:entry]); # binread for 1.9.3 zip.write IO.respond_to?(:binread) ? IO.binread(part[:path]) : IO.read(part[:path]) - end + end end zip end # The parts of a package - # @return [Array] An array of hashes that define the entry, document and schema for each part of the package. + # @return [Array] An array of hashes that define the entry, document and schema for each part of the package. # @private def parts @parts = [ @@ -174,10 +178,10 @@ module Axlsx @parts << {:entry => "xl/#{drawing.rels_pn}", :doc => drawing.relationships.to_xml, :schema => RELS_XSD} @parts << {:entry => "xl/#{drawing.pn}", :doc => drawing.to_xml, :schema => DRAWING_XSD} end - - workbook.charts.each do |chart| + + workbook.charts.each do |chart| @parts << {:entry => "xl/#{chart.pn}", :doc => chart.to_xml, :schema => DRAWING_XSD} - end + end workbook.images.each do |image| @parts << {:entry => "xl/#{image.pn}", :path => image.image_src} @@ -187,9 +191,9 @@ module Axlsx @parts << {:entry => "xl/#{SHARED_STRINGS_PN}", :doc => workbook.shared_strings.to_xml, :schema => SML_XSD} end - workbook.worksheets.each do |sheet| + workbook.worksheets.each do |sheet| @parts << {:entry => "xl/#{sheet.rels_pn}", :doc => sheet.relationships.to_xml, :schema => RELS_XSD} - @parts << {:entry => "xl/#{sheet.pn}", :doc => sheet.to_xml, :schema => SML_XSD} + @parts << {:entry => "xl/#{sheet.pn}", :doc => sheet.to_xml, :schema => SML_XSD} end @parts end @@ -217,15 +221,15 @@ module Axlsx def content_types c_types = base_content_types workbook.drawings.each do |drawing| - c_types << Axlsx::Override.new(:PartName => "/xl/#{drawing.pn}", + c_types << Axlsx::Override.new(:PartName => "/xl/#{drawing.pn}", :ContentType => DRAWING_CT) end workbook.charts.each do |chart| - c_types << Axlsx::Override.new(:PartName => "/xl/#{chart.pn}", - :ContentType => CHART_CT) + c_types << Axlsx::Override.new(:PartName => "/xl/#{chart.pn}", + :ContentType => CHART_CT) end workbook.worksheets.each do |sheet| - c_types << Axlsx::Override.new(:PartName => "/xl/#{sheet.pn}", + c_types << Axlsx::Override.new(:PartName => "/xl/#{sheet.pn}", :ContentType => WORKSHEET_CT) end exts = workbook.images.map { |image| image.extname } @@ -256,7 +260,7 @@ module Axlsx 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) - c_types << Axlsx::Override.new(:PartName => "/#{WORKBOOK_PN}", :ContentType => WORKBOOK_CT) + c_types << Axlsx::Override.new(:PartName => "/#{WORKBOOK_PN}", :ContentType => WORKBOOK_CT) c_types.lock c_types end -- cgit v1.2.3 From 0c696d01cfb095efb4d7c749a4c73bca3611f076 Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Thu, 1 Mar 2012 08:46:18 +0900 Subject: adding in email notification from travis-ci --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 9848260f..7f50677e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,4 +10,5 @@ matrix: notifications: irc: "irc.freenode.org#axlsx + email: "digital.ipseity@gmail.com" -- cgit v1.2.3 From 7e22a617d44a94eb82817d76fe4ff02612ad64b1 Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Thu, 1 Mar 2012 09:04:12 +0900 Subject: ....forgot to close me-quotes.... --- .travis.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7f50677e..95e86d19 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,6 +9,5 @@ matrix: - rvm: jruby notifications: - irc: "irc.freenode.org#axlsx - email: "digital.ipseity@gmail.com" - + irc: "irc.freenode.org#axlsx" + email: "digital.ipseity@gmail.com" \ No newline at end of file -- cgit v1.2.3 From d8ee6871dc2e9781e7d763fa7a97d745537b802c Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Thu, 1 Mar 2012 09:07:34 +0900 Subject: adding head builds to the matrix --- .travis.yml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 95e86d19..158f8ad2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,13 +1,17 @@ +language: ruby rvm: - 1.8.7 - 1.9.2 - 1.9.3 - - jruby - + - ruby-head + - jruby-head + - jruby-18mode matrix: allow_failures: - - rvm: jruby - + rvm: + - jruby-18mode + - ruby-head + - jruby-head notifications: irc: "irc.freenode.org#axlsx" email: "digital.ipseity@gmail.com" \ No newline at end of file -- cgit v1.2.3 From ab52af55f35e031780dc3546ad658bbbd3c54ed7 Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Thu, 1 Mar 2012 09:44:35 +0900 Subject: another attempt at multiple allow_failures on travis --- .travis.yml | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 158f8ad2..25b2f33d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,9 @@ language: ruby + +notifications: + irc: "irc.freenode.org#axlsx" + email: "digital.ipseity@gmail.com" + rvm: - 1.8.7 - 1.9.2 @@ -6,12 +11,10 @@ rvm: - ruby-head - jruby-head - jruby-18mode + matrix: allow_failures: - rvm: - - jruby-18mode - - ruby-head - - jruby-head -notifications: - irc: "irc.freenode.org#axlsx" - email: "digital.ipseity@gmail.com" \ No newline at end of file + - rvm: jruby-18mode + - rvm: ruby-head + - rvm: jruby-head + -- cgit v1.2.3 From 4cc2cca443c83647f2a08d43e92a69ec860697c8 Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Thu, 1 Mar 2012 10:08:17 +0900 Subject: another run at travis matrix with multiple failures --- .travis.yml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 25b2f33d..567debb5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,19 +2,18 @@ language: ruby notifications: irc: "irc.freenode.org#axlsx" - email: "digital.ipseity@gmail.com" - + email: "digital.ipeseity@gmail.com" rvm: - 1.8.7 - 1.9.2 - 1.9.3 + - jruby - ruby-head - jruby-head - - jruby-18mode - matrix: allow_failures: - - rvm: jruby-18mode - - rvm: ruby-head - - rvm: jruby-head + rvm: + - jruby + - ruby-head + - jruby-head -- cgit v1.2.3 From 1751da8305cd5e7bcdd081f685ba576bcd00b791 Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Thu, 1 Mar 2012 11:30:03 +0900 Subject: interestingly specifying the language requires that I rvm it in myself? --- .travis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 567debb5..c5e4da8f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,3 @@ -language: ruby - notifications: irc: "irc.freenode.org#axlsx" email: "digital.ipeseity@gmail.com" -- cgit v1.2.3 From b4b240b4f1e7f2762e6a2d230f607733f0701a47 Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Thu, 1 Mar 2012 12:26:25 +0900 Subject: c'mon travis, show us some love! reverting config for incremental changes to identify where my matrix breaks down. --- .travis.yml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index c5e4da8f..5c4588f6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,12 +6,7 @@ rvm: - 1.9.2 - 1.9.3 - jruby - - ruby-head - - jruby-head matrix: allow_failures: - rvm: - - jruby - - ruby-head - - jruby-head + rvm: - jruby -- cgit v1.2.3 From 9ad3ff09d406fd0e87aba66971e8eb04ba9ab38f Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Thu, 1 Mar 2012 13:19:49 +0900 Subject: ping travis rvm 1.9.2 --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 5c4588f6..d5b23533 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,12 +1,13 @@ notifications: irc: "irc.freenode.org#axlsx" email: "digital.ipeseity@gmail.com" + rvm: - 1.8.7 - 1.9.2 - 1.9.3 - jruby + matrix: allow_failures: rvm: - jruby - -- cgit v1.2.3 From 47b88f1744ad816b404f6bd27c90b00e579b15bc Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Thu, 1 Mar 2012 13:25:27 +0900 Subject: travis testing --- .travis.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index d5b23533..c4469d9b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,13 +1,11 @@ notifications: irc: "irc.freenode.org#axlsx" email: "digital.ipeseity@gmail.com" - rvm: - 1.8.7 - 1.9.2 - 1.9.3 - jruby - matrix: allow_failures: - rvm: - jruby + - rvm: jruby -- cgit v1.2.3 From e34e21b36e61c21dcd6ade6a8db37bd47f9da0be Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Thu, 1 Mar 2012 13:34:45 +0900 Subject: MOAR travis! --- .travis.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index c4469d9b..ac6408fb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,4 @@ +language: ruby notifications: irc: "irc.freenode.org#axlsx" email: "digital.ipeseity@gmail.com" @@ -5,7 +6,9 @@ rvm: - 1.8.7 - 1.9.2 - 1.9.3 - - jruby + - jruby-18mode + - ruby-head matrix: allow_failures: - - rvm: jruby + - rvm: jruby-18mode + - rvm: ruby-head \ No newline at end of file -- cgit v1.2.3 From cf550ec678cb4c2c6e9b07102de4739735fac37e Mon Sep 17 00:00:00 2001 From: Jurriaan Pruis Date: Thu, 1 Mar 2012 12:54:53 +0100 Subject: Added << alias for add_row --- lib/axlsx/workbook/worksheet/worksheet.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/axlsx/workbook/worksheet/worksheet.rb b/lib/axlsx/workbook/worksheet/worksheet.rb index cd0c6c97..d1c8e6ac 100644 --- a/lib/axlsx/workbook/worksheet/worksheet.rb +++ b/lib/axlsx/workbook/worksheet/worksheet.rb @@ -234,6 +234,8 @@ module Axlsx yield @rows.last if block_given? @rows.last end + + alias :<< :add_row # Set the style for cells in a specific row # @param [Integer] index or range of indexes in the table -- cgit v1.2.3 From 94f8dfd7645fa50be2a2f9c7f561a4ee22556001 Mon Sep 17 00:00:00 2001 From: Jurriaan Pruis Date: Thu, 1 Mar 2012 13:11:32 +0100 Subject: Accept row numbers in Worksheet#[] --- lib/axlsx/workbook/worksheet/worksheet.rb | 3 ++- test/workbook/worksheet/tc_worksheet.rb | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/axlsx/workbook/worksheet/worksheet.rb b/lib/axlsx/workbook/worksheet/worksheet.rb index d1c8e6ac..68a3e3c6 100644 --- a/lib/axlsx/workbook/worksheet/worksheet.rb +++ b/lib/axlsx/workbook/worksheet/worksheet.rb @@ -112,9 +112,10 @@ module Axlsx # Returns the cell or cells defined using excel style A1:B3 references. - # @param [String] cell_def the string defining the cell or range of cells + # @param [String|Integer] cell_def the string defining the cell or range of cells, or the rownumber # @return [Cell, Array] def [](cell_def) + return rows[cell_def - 1] if cell_def.is_a? Integer parts = cell_def.split(':') first = name_to_cell parts[0] diff --git a/test/workbook/worksheet/tc_worksheet.rb b/test/workbook/worksheet/tc_worksheet.rb index ac71fce3..97845c92 100644 --- a/test/workbook/worksheet/tc_worksheet.rb +++ b/test/workbook/worksheet/tc_worksheet.rb @@ -62,6 +62,10 @@ class TestWorksheet < Test::Unit::TestCase @ws.add_row [1, 2, 3] @ws.add_row [4, 5, 6] range = @ws["A1:C2"] + first_row = @ws[1] + last_row = @ws[2] + assert_equal(@ws.rows[0],first_row) + assert_equal(@ws.rows[1],last_row) assert_equal(range.size, 6) assert_equal(range.first, @ws.rows.first.cells.first) assert_equal(range.last, @ws.rows.last.cells.last) -- cgit v1.2.3 From c2d3314b02b517c61c8d1cbc8c9a331a3806b1e7 Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Thu, 1 Mar 2012 21:47:32 +0900 Subject: touch of documentation for an excellent addition by @jurriaan --- lib/axlsx/workbook/worksheet/worksheet.rb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/axlsx/workbook/worksheet/worksheet.rb b/lib/axlsx/workbook/worksheet/worksheet.rb index 68a3e3c6..cdeb524a 100644 --- a/lib/axlsx/workbook/worksheet/worksheet.rb +++ b/lib/axlsx/workbook/worksheet/worksheet.rb @@ -193,7 +193,7 @@ module Axlsx @drawing || @drawing = Axlsx::Drawing.new(self) end - # Adds a row to the worksheet and updates auto fit data + # Adds a row to the worksheet and updates auto fit data. # @example - put a vanilla row in your spreadsheet # ws.add_row [1, 'fish on my pl', '8'] # @@ -222,6 +222,9 @@ module Axlsx # @example - force the second cell to be a float value # ws.add_row [3, 4, 5], :types => [nil, :float] # + # @example - use << alias + # ws << [3, 4, 5], :types => [nil, :float] + # # @see Worksheet#column_widths # @return [Row] # @option options [Array] values @@ -235,7 +238,7 @@ module Axlsx yield @rows.last if block_given? @rows.last end - + alias :<< :add_row # Set the style for cells in a specific row -- cgit v1.2.3 From bc9ce6886211c359bb2592e2cb9961a6a4067990 Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Thu, 1 Mar 2012 21:49:15 +0900 Subject: credit where credit is due --- README.md | 66 ++++++++++++++++++++++++++++++++------------------------------- 1 file changed, 34 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index bf32b8de..a1236714 100644 --- a/README.md +++ b/README.md @@ -2,15 +2,15 @@ Axlsx: Office Open XML Spreadsheet Generation ==================================== [![Build Status](https://secure.travis-ci.org/randym/axlsx.png)](http://travis-ci.org/randym/axlsx/) -**IRC**: [irc.freenode.net / #axlsx](irc://irc.freenode.net/axlsx) -**Git**: [http://github.com/randym/axlsx](http://github.com/randym/axlsx) -**Author**: Randy Morgan -**Copyright**: 2011 -**License**: MIT License -**Latest Version**: 1.0.17 -**Ruby Version**: 1.8.7, 1.9.2, 1.9.3 +**IRC**: [irc.freenode.net / #axlsx](irc://irc.freenode.net/axlsx) +**Git**: [http://github.com/randym/axlsx](http://github.com/randym/axlsx) +**Author**: Randy Morgan +**Copyright**: 2011 +**License**: MIT License +**Latest Version**: 1.0.17 +**Ruby Version**: 1.8.7, 1.9.2, 1.9.3 -**Release Date**: February 14th 2012 +**Release Date**: February 14th 2012 Synopsis -------- @@ -19,7 +19,7 @@ Axlsx is an Office Open XML Spreadsheet generator for the Ruby programming langu With Axlsx you can create excel worksheets with charts, images (with links), automated and fixed column widths, customizable styles, functions, merged cells, auto filters, file and stream serialization as well as full schema validation. Axlsx excels at helping you generate beautiful Office Open XML Spreadsheet documents without having to understand the entire ECMA specification. If you are working in rails, or with active record see: -http://github.com/randym/acts_as_xlsx +http://github.com/randym/acts_as_xlsx There are guides for using axlsx and acts_as_xlsx here: [http://axlsx.blogspot.com](http://axlsx.blogspot.com) @@ -31,11 +31,11 @@ I'd really like to get rid of the depenency on RMagick in this gem. RMagic is be Feature List ------------ - + **1. Author xlsx documents: Axlsx is made to let you easily and quickly generate profesional xlsx based reports that can be validated before serialiation. **2. Generate 3D Pie, Line and Bar Charts: With Axlsx chart generation and management is as easy as a few lines of code. You can build charts based off data in your worksheet or generate charts without any data in your sheet at all. - + **3. Custom Styles: With guaranteed document validity, you can style borders, alignment, fills, fonts, and number formats in a single line of code. Those styles can be applied to an entire row, or a single cell anywhere in your workbook. **4. Automatic type support: Axlsx will automatically determine the type of data you are generating. In this release Float, Integer, String, Date, Time and Boolean types are automatically identified and serialized to your spreadsheet. @@ -68,7 +68,7 @@ Installing To install Axlsx, use the following command: $ gem install axlsx - + #Usage ------ @@ -112,25 +112,25 @@ To install Axlsx, use the following command: ##Add an Image wb.add_worksheet(:name => "Images") do |sheet| - img = File.expand_path('examples/image1.jpeg') + img = File.expand_path('examples/image1.jpeg') sheet.add_image(:image_src => img, :noSelect => true, :noMove => true) do |image| image.width=720 image.height=666 image.start_at 2, 2 end - end + end ##Add an Image with a hyperlink wb.add_worksheet(:name => "Image with Hyperlink") do |sheet| - img = File.expand_path('examples/image1.jpeg') + img = File.expand_path('examples/image1.jpeg') sheet.add_image(:image_src => img, :noSelect => true, :noMove => true, :hyperlink=>"http://axlsx.blogspot.com") do |image| image.width=720 image.height=666 image.hyperlink.tooltip = "Labeled Link" image.start_at 2, 2 end - end + end ##Asian Language Support @@ -138,7 +138,7 @@ To install Axlsx, use the following command: sheet.add_row ["日本語"] sheet.add_row ["华语/華語"] sheet.add_row ["한국어/조선말"] - end + end ##Styling Columns @@ -177,7 +177,7 @@ To install Axlsx, use the following command: # cell level style overrides via sheet range sheet["A1:D1"].each { |c| c.color = "FF0000"} sheet['A1:D2'].each { |c| c.style = Axlsx::STYLE_THIN_BORDER } - end + end ##Using formula @@ -204,7 +204,7 @@ To install Axlsx, use the following command: sheet.merge_cells("A4:C4") sheet["A1:D1"].each { |c| c.color = "FF0000"} sheet["A1:D4"].each { |c| c.style = Axlsx::STYLE_THIN_BORDER } - end + end ##Generating A Bar Chart @@ -215,7 +215,7 @@ To install Axlsx, use the following command: sheet.add_chart(Axlsx::Bar3DChart, :start_at => "A4", :end_at => "F17") do |chart| chart.add_series :data => sheet["A3:C3"], :labels => sheet["A2:C2"], :title => sheet["A1"] end - end + end ##Generating A Pie Chart @@ -225,7 +225,7 @@ To install Axlsx, use the following command: sheet.add_chart(Axlsx::Pie3DChart, :start_at => [0,2], :end_at => [5, 15], :title => "example 3: Pie Chart") do |chart| chart.add_series :data => sheet["A2:D2"], :labels => sheet["A1:D1"] end - end + end ##Data over time @@ -239,9 +239,9 @@ To install Axlsx, use the following command: sheet.add_chart(Axlsx::Bar3DChart) do |chart| chart.start_at "B7" chart.end_at "H27" - chart.add_series(:data => sheet["B2:B5"], :labels => sheet["A2:A5"], :title => sheet["B1"]) - end - end + chart.add_series(:data => sheet["B2:B5"], :labels => sheet["A2:A5"], :title => sheet["B1"]) + end + end ##Generating A Line Chart @@ -252,9 +252,9 @@ To install Axlsx, use the following command: chart.start_at 0, 2 chart.end_at 10, 15 chart.add_series :data => sheet["B1:E1"], :title => sheet["A1"] - chart.add_series :data => sheet["B2:E2"], :title => sheet["A2"] - end - end + chart.add_series :data => sheet["B2:E2"], :title => sheet["A2"] + end + end ##Auto Filter @@ -265,7 +265,7 @@ To install Axlsx, use the following command: sheet.add_row ["19.2", "1 min 28 sec", "about 10 hours ago", "1.9.2"] sheet.add_row ["19.3", "1 min 35 sec", "about 10 hours ago", "1.9.3"] sheet.auto_filter = "A2:D5" - end + end ##Specifying Column Widths @@ -306,7 +306,7 @@ This gem is 100% documented with YARD, an exceptional documentation library. To #Specs ------ This gem has 100% test coverage using test/unit. To execute tests for this gem, simply run rake in the gem directory. - + #Changelog --------- - ** March.??.12**: 1.0.18 release @@ -331,8 +331,8 @@ This gem has 100% test coverage using test/unit. To execute tests for this gem, - date1904 now automatically set in bsd and mac environments - removed whitespace/indentation from xml outputs - col_style now skips rows that do not contain cells at the column index - - + + Please see the {file:CHANGELOG.md} document for past release information. #Thanks! @@ -349,8 +349,10 @@ Please see the {file:CHANGELOG.md} document for past release information. [noniq](https://github.com/noniq) - for keeping true to the gem's style, and making sure what we put on paper does not get marginalized. +[jurriaan](https://github.com/jurriaan) - for showing there is more than one way to skin a cat, and work with rows while you are at it!keeping true to the gem's style, and making sure what we put on paper does not get marginalize. + #Copyright and License ---------- -Axlsx © 2011 by [Randy Morgan](mailto:digial.ipseity@gmail.com). Axlsx is +Axlsx © 2011 by [Randy Morgan](mailto:digial.ipseity@gmail.com). Axlsx is licensed under the MIT license. Please see the {file:LICENSE} document for more information. -- cgit v1.2.3 From 6766fb699e1f12c7b7421374796b18f98010d6dc Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Thu, 1 Mar 2012 22:02:42 +0900 Subject: adding rake as runtime requirement for ruby 2.0.0 --- axlsx.gemspec | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/axlsx.gemspec b/axlsx.gemspec index d282b138..0cfa52bd 100644 --- a/axlsx.gemspec +++ b/axlsx.gemspec @@ -8,7 +8,7 @@ Gem::Specification.new do |s| s.author = "Randy Morgan" s.email = 'digital.ipseity@gmail.com' s.homepage = 'https://github.com/randym/axlsx' - s.platform = Gem::Platform::RUBY + s.platform = Gem::Platform::RUBY s.date = Time.now.strftime('%Y-%m-%d') s.summary = "excel OOXML (xlsx) with charts, styles, images and autowidth columns." s.has_rdoc = 'axlsx' @@ -23,9 +23,9 @@ Gem::Specification.new do |s| s.add_runtime_dependency 'rmagick4j', '>= 0.3.7' if Object.const_defined? :JRUBY_VERSION s.add_runtime_dependency 'rubyzip', '~> 0.9' - - s.add_development_dependency 'rake', "0.8.7" if RUBY_VERSION == "1.9.2" - s.add_development_dependency 'rake', "~> 0.9" if ["1.9.3", "1.8.7"].include?(RUBY_VERSION) + + s.add_runtime_dependency 'rake', "0.8.7" if RUBY_VERSION == "1.9.2" + s.add_runtime_dependency 'rake', "~> 0.9" if ["1.9.3", "1.8.7"].include?(RUBY_VERSION) s.add_development_dependency 'yard' s.add_development_dependency 'yard' s.add_development_dependency 'rdiscount' -- cgit v1.2.3 From 0ca7f58b7a01a88ddef177a9c911cbe616f91cce Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Fri, 2 Mar 2012 09:46:18 +0900 Subject: readme edits. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a1236714..31c179b2 100644 --- a/README.md +++ b/README.md @@ -349,7 +349,7 @@ Please see the {file:CHANGELOG.md} document for past release information. [noniq](https://github.com/noniq) - for keeping true to the gem's style, and making sure what we put on paper does not get marginalized. -[jurriaan](https://github.com/jurriaan) - for showing there is more than one way to skin a cat, and work with rows while you are at it!keeping true to the gem's style, and making sure what we put on paper does not get marginalize. +[jurriaan](https://github.com/jurriaan) - for showing there is more than one way to skin a cat, and work with rows while you are at it. #Copyright and License ---------- -- cgit v1.2.3 From 786ec2a429010d6a78d6cc5b4257ad367dabbaed Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Fri, 2 Mar 2012 09:47:15 +0900 Subject: adding in additional features for next release changelog notes. --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 31c179b2..37a09854 100644 --- a/README.md +++ b/README.md @@ -309,13 +309,15 @@ This gem has 100% test coverage using test/unit. To execute tests for this gem, #Changelog --------- -- ** March.??.12**: 1.0.18 release +- ** March.5.12**: 1.0.18 release https://github.com/randym/axlsx/compare/1.0.17...1.0.18 - bugfix custom borders are not properly applied when using styles.add_style - interop worksheet names must be 31 characters or less or some versions of office complain about repairs - added type support for :boolean and :date types cell values - iterop added some elements so that rubyXL can parse sheets generated with axlsx - added support for fixed column widths + - added support for page_margins + - added << alias for add_row - ** February.14.12**: 1.0.17 release https://github.com/randym/axlsx/compare/1.0.16...1.0.17 -- cgit v1.2.3 From 6cbd9b4562280b7d187041bcd9bb8c9db5ec067a Mon Sep 17 00:00:00 2001 From: Jurriaan Pruis Date: Fri, 2 Mar 2012 10:19:31 +0100 Subject: Default to 1900 date system Office 2011 for Mac uses the 1900 system by default see http://www.officeformachelp.com/2010/10/excel-2011-defaults-to-1900-date-system/ for more info --- lib/axlsx/workbook/workbook.rb | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/lib/axlsx/workbook/workbook.rb b/lib/axlsx/workbook/workbook.rb index b3b10fac..cbb85349 100644 --- a/lib/axlsx/workbook/workbook.rb +++ b/lib/axlsx/workbook/workbook.rb @@ -99,25 +99,17 @@ require 'axlsx/workbook/shared_strings_table.rb' # Creates a new Workbook # The recomended way to work with workbooks is via Package#workbook - # @option options [Boolean] date1904. If this is not specified, we try to determine if the platform is bsd/darwin and set date1904 to true automatically. + # @option options [Boolean] date1904. If this is not specified, date1904 is set to false. Office 2011 for Mac defaults to false. def initialize(options={}) @styles = Styles.new @worksheets = SimpleTypedList.new Worksheet @drawings = SimpleTypedList.new Drawing @charts = SimpleTypedList.new Chart @images = SimpleTypedList.new Pic - self.date1904= options[:date1904].nil? ? is_bsd? : options[:date1904] + self.date1904= !options[:date1904].nil? && options[:date1904] yield self if block_given? end - # Uses RUBY_PLATFORM constant to determine if the OS is freebsd or darwin - # based on this value we attempt to set date1904. - # @return [Boolean] - def is_bsd? - platform = RUBY_PLATFORM.downcase - platform.include?('freebsd') || platform.include?('darwin') - end - # Instance level access to the class variable 1904 # @return [Boolean] def date1904() @@date1904; end -- cgit v1.2.3 From 516553a4888ab21e1dee3d7f68a6c481134572ed Mon Sep 17 00:00:00 2001 From: Jurriaan Pruis Date: Fri, 2 Mar 2012 10:21:01 +0100 Subject: Updated example.rb Fixed indenting and commented date1904 --- examples/example.rb | 313 ++++++++++++++++++++++++++-------------------------- 1 file changed, 156 insertions(+), 157 deletions(-) diff --git a/examples/example.rb b/examples/example.rb index caafd274..8058b50b 100644 --- a/examples/example.rb +++ b/examples/example.rb @@ -1,225 +1,224 @@ #!/usr/bin/env ruby -w -s # -*- coding: utf-8 -*- - require 'axlsx.rb' +require 'axlsx.rb' - p = Axlsx::Package.new - wb = p.workbook +p = Axlsx::Package.new +wb = p.workbook #A Simple Workbook - wb.add_worksheet(:name => "Basic Worksheet") do |sheet| - sheet.add_row ["First Column", "Second", "Third"] - sheet.add_row [1, 2, 3] - end +wb.add_worksheet(:name => "Basic Worksheet") do |sheet| + sheet.add_row ["First Column", "Second", "Third"] + sheet.add_row [1, 2, 3] +end #Using Custom Styles - wb.styles do |s| - black_cell = s.add_style :bg_color => "00", :fg_color => "FF", :sz => 14, :alignment => { :horizontal=> :center } - blue_cell = s.add_style :bg_color => "0000FF", :fg_color => "FF", :sz => 20, :alignment => { :horizontal=> :center } - wb.add_worksheet(:name => "Custom Styles") do |sheet| - sheet.add_row ["Text Autowidth", "Second", "Third"], :style => [black_cell, blue_cell, black_cell] - sheet.add_row [1, 2, 3], :style => Axlsx::STYLE_THIN_BORDER - end - end +wb.styles do |s| + black_cell = s.add_style :bg_color => "00", :fg_color => "FF", :sz => 14, :alignment => { :horizontal=> :center } + blue_cell = s.add_style :bg_color => "0000FF", :fg_color => "FF", :sz => 20, :alignment => { :horizontal=> :center } + wb.add_worksheet(:name => "Custom Styles") do |sheet| + sheet.add_row ["Text Autowidth", "Second", "Third"], :style => [black_cell, blue_cell, black_cell] + sheet.add_row [1, 2, 3], :style => Axlsx::STYLE_THIN_BORDER + end +end ##Using Custom Formatting and date1904 - require 'date' - wb.styles do |s| - date = s.add_style(:format_code => "yyyy-mm-dd", :border => Axlsx::STYLE_THIN_BORDER) - padded = s.add_style(:format_code => "00#", :border => Axlsx::STYLE_THIN_BORDER) - percent = s.add_style(:format_code => "0000%", :border => Axlsx::STYLE_THIN_BORDER) - wb.date1904 = true # required for generation on mac - wb.add_worksheet(:name => "Formatting Data") do |sheet| - sheet.add_row ["Custom Formatted Date", "Percent Formatted Float", "Padded Numbers"], :style => Axlsx::STYLE_THIN_BORDER - sheet.add_row [Date::strptime('2012-01-19','%Y-%m-%d'), 0.2, 32], :style => [date, percent, padded] - end - end +require 'date' +wb.styles do |s| + date = s.add_style(:format_code => "yyyy-mm-dd", :border => Axlsx::STYLE_THIN_BORDER) + padded = s.add_style(:format_code => "00#", :border => Axlsx::STYLE_THIN_BORDER) + percent = s.add_style(:format_code => "0000%", :border => Axlsx::STYLE_THIN_BORDER) + # wb.date1904 = true # Use the 1904 date system (Used by Excel for Mac < 2011) + wb.add_worksheet(:name => "Formatting Data") do |sheet| + sheet.add_row ["Custom Formatted Date", "Percent Formatted Float", "Padded Numbers"], :style => Axlsx::STYLE_THIN_BORDER + sheet.add_row [Date::strptime('2012-01-19','%Y-%m-%d'), 0.2, 32], :style => [date, percent, padded] + end +end ##Add an Image - wb.add_worksheet(:name => "Images") do |sheet| - img = File.expand_path('examples/image1.jpeg') - sheet.add_image(:image_src => img, :noSelect => true, :noMove => true) do |image| - image.width=720 - image.height=666 - image.start_at 2, 2 - end - end +wb.add_worksheet(:name => "Images") do |sheet| + img = File.expand_path('examples/image1.jpeg') + sheet.add_image(:image_src => img, :noSelect => true, :noMove => true) do |image| + image.width=720 + image.height=666 + image.start_at 2, 2 + end +end ##Add an Image with a hyperlink - wb.add_worksheet(:name => "Image with Hyperlink") do |sheet| - img = File.expand_path('examples/image1.jpeg') - sheet.add_image(:image_src => img, :noSelect => true, :noMove => true, :hyperlink=>"http://axlsx.blogspot.com") do |image| - image.width=720 - image.height=666 - image.hyperlink.tooltip = "Labeled Link" - image.start_at 2, 2 - end - end +wb.add_worksheet(:name => "Image with Hyperlink") do |sheet| + img = File.expand_path('examples/image1.jpeg') + sheet.add_image(:image_src => img, :noSelect => true, :noMove => true, :hyperlink=>"http://axlsx.blogspot.com") do |image| + image.width=720 + image.height=666 + image.hyperlink.tooltip = "Labeled Link" + image.start_at 2, 2 + end +end ##Asian Language Support - wb.add_worksheet(:name => "日本語でのシート名") do |sheet| - sheet.add_row ["日本語"] - sheet.add_row ["华语/華語"] - sheet.add_row ["한국어/조선말"] - end +wb.add_worksheet(:name => "日本語でのシート名") do |sheet| + sheet.add_row ["日本語"] + sheet.add_row ["华语/華語"] + sheet.add_row ["한국어/조선말"] +end ##Styling Columns - wb.styles do |s| - percent = s.add_style :num_fmt => 9 - wb.add_worksheet(:name => "Styling Columns") do |sheet| - sheet.add_row ['col 1', 'col 2', 'col 3', 'col 4'] - sheet.add_row [1, 2, 0.3, 4] - sheet.add_row [1, 2, 0.2, 4] - sheet.add_row [1, 2, 0.1, 4] - sheet.col_style 2, percent, :row_offset => 1 - end - end +wb.styles do |s| + percent = s.add_style :num_fmt => 9 + wb.add_worksheet(:name => "Styling Columns") do |sheet| + sheet.add_row ['col 1', 'col 2', 'col 3', 'col 4'] + sheet.add_row [1, 2, 0.3, 4] + sheet.add_row [1, 2, 0.2, 4] + sheet.add_row [1, 2, 0.1, 4] + sheet.col_style 2, percent, :row_offset => 1 + end +end ##Styling Rows - wb.styles do |s| - head = s.add_style :bg_color => "00", :fg_color => "FF" - percent = s.add_style :num_fmt => 9 - wb.add_worksheet(:name => "Styling Rows") do |sheet| - sheet.add_row ['col 1', 'col 2', 'col 3', 'col 4'] - sheet.add_row [1, 2, 0.3, 4] - sheet.add_row [1, 2, 0.2, 4] - sheet.add_row [1, 2, 0.1, 4] - sheet.col_style 2, percent, :row_offset => 1 - sheet.row_style 0, head - end - end +wb.styles do |s| + head = s.add_style :bg_color => "00", :fg_color => "FF" + percent = s.add_style :num_fmt => 9 + wb.add_worksheet(:name => "Styling Rows") do |sheet| + sheet.add_row ['col 1', 'col 2', 'col 3', 'col 4'] + sheet.add_row [1, 2, 0.3, 4] + sheet.add_row [1, 2, 0.2, 4] + sheet.add_row [1, 2, 0.1, 4] + sheet.col_style 2, percent, :row_offset => 1 + sheet.row_style 0, head + end +end ##Styling Cell Overrides - wb.add_worksheet(:name => "Cell Level Style Overrides") do |sheet| - # cell level style overides when adding cells - sheet.add_row ['col 1', 'col 2', 'col 3', 'col 4'], :sz => 16 - sheet.add_row [1, 2, 3, "=SUM(A2:C2)"] - # cell level style overrides via sheet range - sheet["A1:D1"].each { |c| c.color = "FF0000"} - sheet['A1:D2'].each { |c| c.style = Axlsx::STYLE_THIN_BORDER } - end +wb.add_worksheet(:name => "Cell Level Style Overrides") do |sheet| + # cell level style overides when adding cells + sheet.add_row ['col 1', 'col 2', 'col 3', 'col 4'], :sz => 16 + sheet.add_row [1, 2, 3, "=SUM(A2:C2)"] + # cell level style overrides via sheet range + sheet["A1:D1"].each { |c| c.color = "FF0000"} + sheet['A1:D2'].each { |c| c.style = Axlsx::STYLE_THIN_BORDER } +end ##Using formula - wb.add_worksheet(:name => "Using Formulas") do |sheet| - sheet.add_row ['col 1', 'col 2', 'col 3', 'col 4'] - sheet.add_row [1, 2, 3, "=SUM(A2:C2)"] - end +wb.add_worksheet(:name => "Using Formulas") do |sheet| + sheet.add_row ['col 1', 'col 2', 'col 3', 'col 4'] + sheet.add_row [1, 2, 3, "=SUM(A2:C2)"] +end ##Automatic cell types - wb.add_worksheet(:name => "Automatic cell types") do |sheet| - sheet.add_row ["Date", "Time", "String", "Boolean", "Float", "Integer"] - sheet.add_row [Date.today, Time.now, "value", true, 0.1, 1] - end +wb.add_worksheet(:name => "Automatic cell types") do |sheet| + sheet.add_row ["Date", "Time", "String", "Boolean", "Float", "Integer"] + sheet.add_row [Date.today, Time.now, "value", true, 0.1, 1] +end ##Merging Cells. - wb.add_worksheet(:name => 'Merging Cells') do |sheet| - # cell level style overides when adding cells - sheet.add_row ["col 1", "col 2", "col 3", "col 4"], :sz => 16 - sheet.add_row [1, 2, 3, "=SUM(A2:C2)"] - sheet.add_row [2, 3, 4, "=SUM(A3:C3)"] - sheet.add_row ["total", "", "", "=SUM(D2:D3)"] - sheet.merge_cells("A4:C4") - sheet["A1:D1"].each { |c| c.color = "FF0000"} - sheet["A1:D4"].each { |c| c.style = Axlsx::STYLE_THIN_BORDER } - end +wb.add_worksheet(:name => 'Merging Cells') do |sheet| + # cell level style overides when adding cells + sheet.add_row ["col 1", "col 2", "col 3", "col 4"], :sz => 16 + sheet.add_row [1, 2, 3, "=SUM(A2:C2)"] + sheet.add_row [2, 3, 4, "=SUM(A3:C3)"] + sheet.add_row ["total", "", "", "=SUM(D2:D3)"] + sheet.merge_cells("A4:C4") + sheet["A1:D1"].each { |c| c.color = "FF0000"} + sheet["A1:D4"].each { |c| c.style = Axlsx::STYLE_THIN_BORDER } +end ##Generating A Bar Chart - wb.add_worksheet(:name => "Bar Chart") do |sheet| - sheet.add_row ["A Simple Bar Chart"] - sheet.add_row ["First", "Second", "Third"] - sheet.add_row [1, 2, 3] - sheet.add_chart(Axlsx::Bar3DChart, :start_at => "A4", :end_at => "F17") do |chart| - chart.add_series :data => sheet["A3:C3"], :labels => sheet["A2:C2"], :title => sheet["A1"] - end - end +wb.add_worksheet(:name => "Bar Chart") do |sheet| + sheet.add_row ["A Simple Bar Chart"] + sheet.add_row ["First", "Second", "Third"] + sheet.add_row [1, 2, 3] + sheet.add_chart(Axlsx::Bar3DChart, :start_at => "A4", :end_at => "F17") do |chart| + chart.add_series :data => sheet["A3:C3"], :labels => sheet["A2:C2"], :title => sheet["A1"] + end +end ##Generating A Pie Chart - wb.add_worksheet(:name => "Pie Chart") do |sheet| - sheet.add_row ["First", "Second", "Third", "Fourth"] - sheet.add_row [1, 2, 3, "=PRODUCT(A2:C2)"] - sheet.add_chart(Axlsx::Pie3DChart, :start_at => [0,2], :end_at => [5, 15], :title => "example 3: Pie Chart") do |chart| - chart.add_series :data => sheet["A2:D2"], :labels => sheet["A1:D1"] - end - end +wb.add_worksheet(:name => "Pie Chart") do |sheet| + sheet.add_row ["First", "Second", "Third", "Fourth"] + sheet.add_row [1, 2, 3, "=PRODUCT(A2:C2)"] + sheet.add_chart(Axlsx::Pie3DChart, :start_at => [0,2], :end_at => [5, 15], :title => "example 3: Pie Chart") do |chart| + chart.add_series :data => sheet["A2:D2"], :labels => sheet["A1:D1"] + end +end ##Data over time - wb.add_worksheet(:name=>'Charting Dates') do |sheet| - # cell level style overides when adding cells - sheet.add_row ['Date', 'Value'], :sz => 16 - sheet.add_row [Time.now - (7*60*60*24), 3] - sheet.add_row [Time.now - (6*60*60*24), 7] - sheet.add_row [Time.now - (5*60*60*24), 18] - sheet.add_row [Time.now - (4*60*60*24), 1] - sheet.add_chart(Axlsx::Bar3DChart) do |chart| - chart.start_at "B7" - chart.end_at "H27" - chart.add_series(:data => sheet["B2:B5"], :labels => sheet["A2:A5"], :title => sheet["B1"]) - end - end +wb.add_worksheet(:name=>'Charting Dates') do |sheet| + # cell level style overides when adding cells + sheet.add_row ['Date', 'Value'], :sz => 16 + sheet.add_row [Time.now - (7*60*60*24), 3] + sheet.add_row [Time.now - (6*60*60*24), 7] + sheet.add_row [Time.now - (5*60*60*24), 18] + sheet.add_row [Time.now - (4*60*60*24), 1] + sheet.add_chart(Axlsx::Bar3DChart) do |chart| + chart.start_at "B7" + chart.end_at "H27" + chart.add_series(:data => sheet["B2:B5"], :labels => sheet["A2:A5"], :title => sheet["B1"]) + end +end ##Generating A Line Chart - wb.add_worksheet(:name => "Line Chart") do |sheet| - sheet.add_row ["First", 1, 5, 7, 9] - sheet.add_row ["Second", 5, 2, 14, 9] - sheet.add_chart(Axlsx::Line3DChart, :title => "example 6: Line Chart", :rotX => 30, :rotY => 20) do |chart| - chart.start_at 0, 2 - chart.end_at 10, 15 - chart.add_series :data => sheet["B1:E1"], :title => sheet["A1"] - chart.add_series :data => sheet["B2:E2"], :title => sheet["A2"] - end - end +wb.add_worksheet(:name => "Line Chart") do |sheet| + sheet.add_row ["First", 1, 5, 7, 9] + sheet.add_row ["Second", 5, 2, 14, 9] + sheet.add_chart(Axlsx::Line3DChart, :title => "example 6: Line Chart", :rotX => 30, :rotY => 20) do |chart| + chart.start_at 0, 2 + chart.end_at 10, 15 + chart.add_series :data => sheet["B1:E1"], :title => sheet["A1"] + chart.add_series :data => sheet["B2:E2"], :title => sheet["A2"] + end +end ##Auto Filter - wb.add_worksheet(:name => "Auto Filter") do |sheet| - sheet.add_row ["Build Matrix"] - sheet.add_row ["Build", "Duration", "Finished", "Rvm"] - sheet.add_row ["19.1", "1 min 32 sec", "about 10 hours ago", "1.8.7"] - sheet.add_row ["19.2", "1 min 28 sec", "about 10 hours ago", "1.9.2"] - sheet.add_row ["19.3", "1 min 35 sec", "about 10 hours ago", "1.9.3"] - sheet.auto_filter = "A2:D5" - end +wb.add_worksheet(:name => "Auto Filter") do |sheet| + sheet.add_row ["Build Matrix"] + sheet.add_row ["Build", "Duration", "Finished", "Rvm"] + sheet.add_row ["19.1", "1 min 32 sec", "about 10 hours ago", "1.8.7"] + sheet.add_row ["19.2", "1 min 28 sec", "about 10 hours ago", "1.9.2"] + sheet.add_row ["19.3", "1 min 35 sec", "about 10 hours ago", "1.9.3"] + sheet.auto_filter = "A2:D5" +end ##Specifying Column Widths - wb.add_worksheet(:name => "custom column widths") do |sheet| - sheet.add_row ["I use autowidth and am very wide", "I use a custom width and am narrow"] - sheet.column_widths nil, 3 - end +wb.add_worksheet(:name => "custom column widths") do |sheet| + sheet.add_row ["I use autowidth and am very wide", "I use a custom width and am narrow"] + sheet.column_widths nil, 3 +end ##Specify Page Margins for printing - margins = {:left => 3, :right => 3, :top => 1.2, :bottom => 1.2, :header => 0.7, :footer => 0.7} - wb.add_worksheet(:name => "print margins", :page_margins => margins) do |sheet| - sheet.add_row ["this sheet uses customized page margins for printing"] - end +margins = {:left => 3, :right => 3, :top => 1.2, :bottom => 1.2, :header => 0.7, :footer => 0.7} +wb.add_worksheet(:name => "print margins", :page_margins => margins) do |sheet| + sheet.add_row ["this sheet uses customized page margins for printing"] +end ##Validate and Serialize - p.validate.each { |e| puts e.message } - p.serialize("example.xlsx") +p.validate.each { |e| puts e.message } +p.serialize("example.xlsx") - s = p.to_stream() - File.open('example_streamed.xlsx', 'w') { |f| f.write(s.read) } +s = p.to_stream() +File.open('example_streamed.xlsx', 'w') { |f| f.write(s.read) } ##Using Shared Strings - - p.use_shared_strings = true - p.serialize("shared_strings_example.xlsx") +p.use_shared_strings = true +p.serialize("shared_strings_example.xlsx") -- cgit v1.2.3 From 5b1860121aa20b83033792192617fbe6cf9b455b Mon Sep 17 00:00:00 2001 From: Jurriaan Pruis Date: Fri, 2 Mar 2012 10:23:03 +0100 Subject: epoc => epoch --- README.md | 2 +- lib/axlsx/workbook/worksheet/date_time_converter.rb | 14 +++++++------- test/workbook/worksheet/tc_date_time_converter.rb | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 37a09854..f23bcde7 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ Feature List **5. Automatic and fixed column widths: Axlsx will automatically determine the appropriate width for your columns based on the content in the worksheet, or use any value you specify for the really funky stuff. -**6. Support for automatically formatted 1904 and 1900 epocs configurable in the workbook. +**6. Support for automatically formatted 1904 and 1900 epochs configurable in the workbook. **7. Add jpg, gif and png images to worksheets with hyperlinks diff --git a/lib/axlsx/workbook/worksheet/date_time_converter.rb b/lib/axlsx/workbook/worksheet/date_time_converter.rb index 5a572781..d2d9a014 100644 --- a/lib/axlsx/workbook/worksheet/date_time_converter.rb +++ b/lib/axlsx/workbook/worksheet/date_time_converter.rb @@ -9,8 +9,8 @@ module Axlsx # @param [Date] date the date to be serialized # @return [Numeric] def self.date_to_serial(date) - epoc = Axlsx::Workbook::date1904 ? Date.new(1904) : Date.new(1899, 12, 30) - (date-epoc).to_f + epoch = Axlsx::Workbook::date1904 ? Date.new(1904) : Date.new(1899, 12, 30) + (date-epoch).to_f end # The time_to_serial methond converts a Time object its excel serialized form. @@ -18,12 +18,12 @@ module Axlsx # @return [Numeric] def self.time_to_serial(time) # Using hardcoded offsets here as some operating systems will not except - # a 'negative' offset from the ruby epoc. - epoc1900 = -2209161600 # Time.utc(1899, 12, 30).to_i - epoc1904 = -2082844800 # Time.utc(1904, 1, 1).to_i + # a 'negative' offset from the ruby epoch. + epoch1900 = -2209161600 # Time.utc(1899, 12, 30).to_i + epoch1904 = -2082844800 # Time.utc(1904, 1, 1).to_i seconds_per_day = 86400 # 60*60*24 - epoc = Axlsx::Workbook::date1904 ? epoc1904 : epoc1900 - (time.to_f - epoc)/seconds_per_day + epoch = Axlsx::Workbook::date1904 ? epoch1904 : epoch1900 + (time.to_f - epoch)/seconds_per_day end end end diff --git a/test/workbook/worksheet/tc_date_time_converter.rb b/test/workbook/worksheet/tc_date_time_converter.rb index 529da917..c78e51eb 100644 --- a/test/workbook/worksheet/tc_date_time_converter.rb +++ b/test/workbook/worksheet/tc_date_time_converter.rb @@ -88,7 +88,7 @@ class TestDateTimeConverter < Test::Unit::TestCase def test_time_to_serial_1904 Axlsx::Workbook.date1904 = true - # ruby 1.8.7 cannot parse dates prior to epoc. see http://ruby-doc.org/core-1.8.7/Time.html + # ruby 1.8.7 cannot parse dates prior to epoch. see http://ruby-doc.org/core-1.8.7/Time.html tests = if @extended_time_range { # examples taken straight from the spec -- cgit v1.2.3 From 0a97afe5a57ecb0e2957ce50d707a550cd287e6c Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Sat, 3 Mar 2012 16:49:53 +0900 Subject: adding email notifications for travis and updating readme in preparation for .18 release --- .travis.yml | 5 ++++- README.md | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ac6408fb..b4a356ab 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,10 @@ language: ruby notifications: irc: "irc.freenode.org#axlsx" - email: "digital.ipeseity@gmail.com" + email: + recipients: + - digital.ipseity@gmail.com + on_success: always rvm: - 1.8.7 - 1.9.2 diff --git a/README.md b/README.md index f23bcde7..fff3ee4f 100644 --- a/README.md +++ b/README.md @@ -318,6 +318,7 @@ This gem has 100% test coverage using test/unit. To execute tests for this gem, - added support for fixed column widths - added support for page_margins - added << alias for add_row + - removed presetting of date1904 based on authoring platform. Now defaults to use 1900 epoch (date1904 = false) - ** February.14.12**: 1.0.17 release https://github.com/randym/axlsx/compare/1.0.16...1.0.17 -- cgit v1.2.3 From f8158127cd91595171ce05aa2c2da109f8c36e07 Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Sat, 3 Mar 2012 16:54:56 +0900 Subject: update gitignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index b1cc5c00..1c698903 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,5 @@ coverage *.gem *.xlsx *.*~ -.DS_Store \ No newline at end of file +.DS_Store +tmp \ No newline at end of file -- cgit v1.2.3 From fe900f7c2655f6a3ec0ef2afe9ae202679daecb2 Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Sun, 4 Mar 2012 08:15:15 +0900 Subject: fix typos in docs --- lib/axlsx/content_type/content_type.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/axlsx/content_type/content_type.rb b/lib/axlsx/content_type/content_type.rb index 32182fd5..8b58bf04 100644 --- a/lib/axlsx/content_type/content_type.rb +++ b/lib/axlsx/content_type/content_type.rb @@ -3,13 +3,13 @@ module Axlsx require 'axlsx/content_type/default.rb' require 'axlsx/content_type/override.rb' - # ContentTypes used in the package. This is automatcially managed by the package package. + # ContentTypes used in the package. This is automatically managed by the package package. class ContentType < SimpleTypedList - + def initialize super [Override, Default] end - + # Generates the xml document for [Content_Types].xml # @return [String] The document as a string. def to_xml() -- cgit v1.2.3 From 1d7d0415de8a2888a2eeaf901b4bf5c49a774b87 Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Sun, 4 Mar 2012 08:15:26 +0900 Subject: fix typos in docs --- lib/axlsx/rels/relationship.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/axlsx/rels/relationship.rb b/lib/axlsx/rels/relationship.rb index 23e6428a..3596d808 100644 --- a/lib/axlsx/rels/relationship.rb +++ b/lib/axlsx/rels/relationship.rb @@ -1,7 +1,7 @@ # encoding: UTF-8 module Axlsx # A relationship defines a reference between package parts. - # @note Packages automatcially manage relationships. + # @note Packages automatically manage relationships. class Relationship # The location of the relationship target @@ -32,7 +32,7 @@ module Axlsx # creates a new relationship # @param [String] Type The type of the relationship # @param [String] Target The target for the relationship - # @option [Symbol] target_mode only accepts :external. + # @option [Symbol] target_mode only accepts :external. def initialize(type, target, options={}) self.Target=target self.Type=type @@ -47,7 +47,7 @@ module Axlsx # @see TargetMode def TargetMode=(v) RestrictionValidator.validate 'Relationship.TargetMode', [:External, :Internal], v; @TargetMode = v; end - # Serializes the relationship + # Serializes the relationship # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. # @param [String] rId the reference id of the object. # @return [String] -- cgit v1.2.3 From 3aca1d48383497fdd4c9cfca45761a01ebcb7442 Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Sun, 4 Mar 2012 08:23:58 +0900 Subject: revert changes to validation reporting as it breaks backwards compatability --- lib/axlsx/package.rb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/axlsx/package.rb b/lib/axlsx/package.rb index 440a1b6a..6a8864f4 100644 --- a/lib/axlsx/package.rb +++ b/lib/axlsx/package.rb @@ -131,11 +131,7 @@ module Axlsx # p.validate.each { |error| puts error.message } def validate errors = [] - parts.each do |part| - next if part[:schema].nil? - e = validate_single_doc(part[:schema], part[:doc]) - errors << { :entry => part[:entry], :errors => e } if e.size > 0 - end + parts.each { |part| errors.concat validate_single_doc(part[:schema], part[:doc]) unless part[:schema].nil? } errors end -- cgit v1.2.3 From 1e2b0111da0ff832a94ba340fcbf2a3f63d52647 Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Sun, 4 Mar 2012 08:59:33 +0900 Subject: fix #44 I think one workbook view is enough ;) --- lib/axlsx/workbook/workbook.rb | 34 +++++++++++++++---------------- lib/axlsx/workbook/worksheet/worksheet.rb | 2 +- 2 files changed, 17 insertions(+), 19 deletions(-) diff --git a/lib/axlsx/workbook/workbook.rb b/lib/axlsx/workbook/workbook.rb index cbb85349..a7d830aa 100644 --- a/lib/axlsx/workbook/workbook.rb +++ b/lib/axlsx/workbook/workbook.rb @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -module Axlsx +module Axlsx require 'axlsx/workbook/worksheet/date_time_converter.rb' require 'axlsx/workbook/worksheet/cell.rb' @@ -10,7 +10,7 @@ require 'axlsx/workbook/shared_strings_table.rb' # The Workbook class is an xlsx workbook that manages worksheets, charts, drawings and styles. # The following parts of the Office Open XML spreadsheet specification are not implimented in this version. - # + # # bookViews # calcPr # customWorkbookViews @@ -40,13 +40,13 @@ require 'axlsx/workbook/shared_strings_table.rb' attr_reader :use_shared_strings # @see use_shared_strings - def use_shared_strings=(v) + def use_shared_strings=(v) Axlsx::validate_boolean(v) @use_shared_strings = v end - # A collection of worksheets associated with this workbook. + # A collection of worksheets associated with this workbook. # @note The recommended way to manage worksheets is add_worksheet # @see Workbook#add_worksheet # @see Worksheet @@ -88,12 +88,12 @@ require 'axlsx/workbook/shared_strings_table.rb' # Indicates if the epoc date for serialization should be 1904. If false, 1900 is used. @@date1904 = false - # lets come back to this later when we are ready for parsing. + # lets come back to this later when we are ready for parsing. #def self.parse entry # io = entry.get_input_stream # w = self.new # w.parser_xml = Nokogiri::XML(io.read) - # w.parse_string :date1904, "//xmlns:workbookPr/@date1904" + # w.parse_string :date1904, "//xmlns:workbookPr/@date1904" # w #end @@ -107,12 +107,12 @@ require 'axlsx/workbook/shared_strings_table.rb' @charts = SimpleTypedList.new Chart @images = SimpleTypedList.new Pic self.date1904= !options[:date1904].nil? && options[:date1904] - yield self if block_given? + yield self if block_given? end # Instance level access to the class variable 1904 # @return [Boolean] - def date1904() @@date1904; end + def date1904() @@date1904; end # see @date1904 def date1904=(v) Axlsx::validate_boolean v; @@date1904 = v; end @@ -142,7 +142,7 @@ require 'axlsx/workbook/shared_strings_table.rb' r = Relationships.new @worksheets.each do |sheet| r << Relationship.new(WORKSHEET_R, WORKSHEET_PN % (r.size+1)) - end + end r << Relationship.new(STYLES_R, STYLES_PN) if use_shared_strings r << Relationship.new(SHARED_STRINGS_R, SHARED_STRINGS_PN) @@ -157,13 +157,13 @@ require 'axlsx/workbook/shared_strings_table.rb' end # returns a range of cells in a worksheet - # @param [String] cell_def The excel style reference defining the worksheet and cells. The range must specify the sheet to + # @param [String] cell_def The excel style reference defining the worksheet and cells. The range must specify the sheet to # retrieve the cells from. e.g. range('Sheet1!A1:B2') will return an array of four cells [A1, A2, B1, B2] while range('Sheet1!A1') will return a single Cell. # @return [Cell, Array] def [](cell_def) sheet_name = cell_def.split('!')[0] if cell_def.match('!') worksheet = self.worksheets.select { |s| s.name == sheet_name }.first - raise ArgumentError, 'Unknown Sheet' unless sheet_name && worksheet.is_a?(Worksheet) + raise ArgumentError, 'Unknown Sheet' unless sheet_name && worksheet.is_a?(Worksheet) worksheet[cell_def.gsub(/.+!/,"")] end @@ -171,23 +171,21 @@ require 'axlsx/workbook/shared_strings_table.rb' # @return [String] def to_xml() add_worksheet unless worksheets.size > 0 - builder = Nokogiri::XML::Builder.new(:encoding => ENCODING) do |xml| + builder = Nokogiri::XML::Builder.new(:encoding => ENCODING) do |xml| xml.workbook(:xmlns => XML_NS, :'xmlns:r' => XML_NS_R) { xml.workbookPr(:date1904=>@@date1904) # # Required to support rubyXL parsing as it requires sheetView, which requires this. - xml.bookViews { - worksheets.count.times do - xml.workbookView :activeTab=>0 - end + xml.bookViews { + xml.workbookView :activeTab=>0 } xml.sheets { - @worksheets.each_with_index do |sheet, index| + @worksheets.each_with_index do |sheet, index| xml.sheet(:name=>sheet.name, :sheetId=>index+1, :"r:id"=>sheet.rId) end } } - end + end builder.to_xml(:save_with => 0) end end diff --git a/lib/axlsx/workbook/worksheet/worksheet.rb b/lib/axlsx/workbook/worksheet/worksheet.rb index cdeb524a..135075f4 100644 --- a/lib/axlsx/workbook/worksheet/worksheet.rb +++ b/lib/axlsx/workbook/worksheet/worksheet.rb @@ -337,7 +337,7 @@ module Axlsx xml.dimension :ref=>dimension unless rows.size == 0 # this is required by rubyXL, spec says who cares - but it seems they didnt notice xml.sheetViews { - xml.sheetView(:tabSelected => 1, :workbookViewId => index) { + xml.sheetView(:tabSelected => 1, :workbookViewId => 1) { xml.selection :activeCell=>"A1", :sqref => "A1" } } -- cgit v1.2.3 From 46b53746d467ab6e3d844600e702070fe18b5190 Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Sun, 4 Mar 2012 19:47:08 +0900 Subject: proper workbookview id - should be 0 based index iirc --- lib/axlsx/workbook/worksheet/worksheet.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/axlsx/workbook/worksheet/worksheet.rb b/lib/axlsx/workbook/worksheet/worksheet.rb index 135075f4..672ba9e0 100644 --- a/lib/axlsx/workbook/worksheet/worksheet.rb +++ b/lib/axlsx/workbook/worksheet/worksheet.rb @@ -337,7 +337,7 @@ module Axlsx xml.dimension :ref=>dimension unless rows.size == 0 # this is required by rubyXL, spec says who cares - but it seems they didnt notice xml.sheetViews { - xml.sheetView(:tabSelected => 1, :workbookViewId => 1) { + xml.sheetView(:tabSelected => 1, :workbookViewId => 0) { xml.selection :activeCell=>"A1", :sqref => "A1" } } -- cgit v1.2.3 From 7d1a6097fdee39685b98432525c61e32b22c497e Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Sun, 4 Mar 2012 22:32:44 +0900 Subject: remove rubyXL interop and update readme --- README.md | 5 ++--- lib/axlsx/workbook/workbook.rb | 7 ++++--- lib/axlsx/workbook/worksheet/worksheet.rb | 13 +++++++------ 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index fff3ee4f..69f8a112 100644 --- a/README.md +++ b/README.md @@ -7,10 +7,10 @@ Axlsx: Office Open XML Spreadsheet Generation **Author**: Randy Morgan **Copyright**: 2011 **License**: MIT License -**Latest Version**: 1.0.17 +**Latest Version**: 1.0.18 **Ruby Version**: 1.8.7, 1.9.2, 1.9.3 -**Release Date**: February 14th 2012 +**Release Date**: March 5th 2012 Synopsis -------- @@ -314,7 +314,6 @@ This gem has 100% test coverage using test/unit. To execute tests for this gem, - bugfix custom borders are not properly applied when using styles.add_style - interop worksheet names must be 31 characters or less or some versions of office complain about repairs - added type support for :boolean and :date types cell values - - iterop added some elements so that rubyXL can parse sheets generated with axlsx - added support for fixed column widths - added support for page_margins - added << alias for add_row diff --git a/lib/axlsx/workbook/workbook.rb b/lib/axlsx/workbook/workbook.rb index a7d830aa..3350b3ff 100644 --- a/lib/axlsx/workbook/workbook.rb +++ b/lib/axlsx/workbook/workbook.rb @@ -176,9 +176,10 @@ require 'axlsx/workbook/shared_strings_table.rb' xml.workbookPr(:date1904=>@@date1904) # # Required to support rubyXL parsing as it requires sheetView, which requires this. - xml.bookViews { - xml.workbookView :activeTab=>0 - } + # and removed because it seems to cause some odd [Grouped] behaviour in excel. + # xml.bookViews { + # xml.workbookView :activeTab=>0 + # } xml.sheets { @worksheets.each_with_index do |sheet, index| xml.sheet(:name=>sheet.name, :sheetId=>index+1, :"r:id"=>sheet.rId) diff --git a/lib/axlsx/workbook/worksheet/worksheet.rb b/lib/axlsx/workbook/worksheet/worksheet.rb index 672ba9e0..679817ce 100644 --- a/lib/axlsx/workbook/worksheet/worksheet.rb +++ b/lib/axlsx/workbook/worksheet/worksheet.rb @@ -51,7 +51,6 @@ module Axlsx # end # @see PageMargins#initialize # @return [PageMargins] - # @yeilds self def page_margins @page_margins ||= PageMargins.new yield @page_margins if block_given? @@ -336,11 +335,13 @@ module Axlsx # another patch for the folks at rubyXL as thier parser depends on this optional element. xml.dimension :ref=>dimension unless rows.size == 0 # this is required by rubyXL, spec says who cares - but it seems they didnt notice - xml.sheetViews { - xml.sheetView(:tabSelected => 1, :workbookViewId => 0) { - xml.selection :activeCell=>"A1", :sqref => "A1" - } - } + # however, it also seems to be causing some odd [Grouped] stuff in excel 2011 - so + # removing until I understand it better. + # xml.sheetViews { + # xml.sheetView(:tabSelected => 1, :workbookViewId => 0) { + # xml.selection :activeCell=>"A1", :sqref => "A1" + # } + # } if @auto_fit_data.size > 0 xml.cols { -- cgit v1.2.3 From 645cab50a9dcba603d34b0a2e20be5d2420e1905 Mon Sep 17 00:00:00 2001 From: Jurriaan Pruis Date: Fri, 23 Mar 2012 15:36:02 +0100 Subject: Added to workbook --- lib/axlsx/workbook/workbook.rb | 7 +++++++ lib/axlsx/workbook/worksheet/worksheet.rb | 8 ++++++++ 2 files changed, 15 insertions(+) diff --git a/lib/axlsx/workbook/workbook.rb b/lib/axlsx/workbook/workbook.rb index a8e0a1af..d57cf8a3 100644 --- a/lib/axlsx/workbook/workbook.rb +++ b/lib/axlsx/workbook/workbook.rb @@ -206,6 +206,13 @@ require 'axlsx/workbook/worksheet/table.rb' xml.sheet(:name=>sheet.name, :sheetId=>index+1, :"r:id"=>sheet.rId) end } + xml.definedNames { + @worksheets.each_with_index do |sheet, index| + if sheet.auto_filter + xml.definedName(sheet.abs_auto_filter, :name => '_xlnm._FilterDatabase', :localSheetId => index, :hidden => 1) + end + end + } } end builder.to_xml(:save_with => 0) diff --git a/lib/axlsx/workbook/worksheet/worksheet.rb b/lib/axlsx/workbook/worksheet/worksheet.rb index 5325294f..88d29432 100644 --- a/lib/axlsx/workbook/worksheet/worksheet.rb +++ b/lib/axlsx/workbook/worksheet/worksheet.rb @@ -210,6 +210,14 @@ module Axlsx @name=v end + # The absolute auto filter range + # @see auto_filter + def abs_auto_filter + "'#{@name}'!#{@auto_filter.split(':').collect { |name| + name_to_cell(name).r_abs + }.join(':')}" if @auto_filter + end + # The auto filter range for the worksheet # @param [String] v # @see auto_filter -- cgit v1.2.3 From 5afd30be1774fb5255dad2eb18c700d0d8f4a628 Mon Sep 17 00:00:00 2001 From: Jurriaan Pruis Date: Fri, 23 Mar 2012 16:12:21 +0100 Subject: Use Alxsx.cell_range --- lib/axlsx/workbook/worksheet/worksheet.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/axlsx/workbook/worksheet/worksheet.rb b/lib/axlsx/workbook/worksheet/worksheet.rb index 88d29432..3f651078 100644 --- a/lib/axlsx/workbook/worksheet/worksheet.rb +++ b/lib/axlsx/workbook/worksheet/worksheet.rb @@ -213,9 +213,7 @@ module Axlsx # The absolute auto filter range # @see auto_filter def abs_auto_filter - "'#{@name}'!#{@auto_filter.split(':').collect { |name| - name_to_cell(name).r_abs - }.join(':')}" if @auto_filter + Axlsx.cell_range(@auto_filter.split(':').collect { |name| name_to_cell(name)}) if @auto_filter end # The auto filter range for the worksheet -- cgit v1.2.3 From c0be18875793d20cbb686c384fa1a1a1647fa395 Mon Sep 17 00:00:00 2001 From: Sean Duckett Date: Tue, 27 Mar 2012 14:50:51 -0500 Subject: Fix no-example in rendered docs, comment to match method. --- lib/axlsx/stylesheet/border.rb | 12 ++++++------ lib/axlsx/workbook/worksheet/worksheet.rb | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/axlsx/stylesheet/border.rb b/lib/axlsx/stylesheet/border.rb index f3d329fa..ddf6dc90 100644 --- a/lib/axlsx/stylesheet/border.rb +++ b/lib/axlsx/stylesheet/border.rb @@ -19,12 +19,12 @@ module Axlsx # @option options [Boolean] diagonalUp # @option options [Boolean] diagonalDown # @option options [Boolean] outline - # @example Making a border - # p = Axlsx::Package.new - # red_border = p.workbook.styles.add_style :border => {:style =>: thin, :color => "FFFF0000"} - # ws = p.workbook.add_worksheet - # ws.add_row [1,2,3], :style => red_border - # p.serialize('red_border.xlsx') + # @example - Making a border + # p = Axlsx::Package.new + # red_border = p.workbook.styles.add_style :border => {:style =>: thin, :color => "FFFF0000"} + # ws = p.workbook.add_worksheet + # ws.add_row [1,2,3], :style => red_border + # p.serialize('red_border.xlsx') # # @note The recommended way to manage borders is with Style#add_style # @see Style#add_style diff --git a/lib/axlsx/workbook/worksheet/worksheet.rb b/lib/axlsx/workbook/worksheet/worksheet.rb index 20c13d8b..ede9c0e8 100644 --- a/lib/axlsx/workbook/worksheet/worksheet.rb +++ b/lib/axlsx/workbook/worksheet/worksheet.rb @@ -160,7 +160,7 @@ module Axlsx end - # Indicates if gridlines should be shown in the sheet. + # Indicates if the worksheet should print in a single page. # This is true by default. # @return [Boolean] def fit_to_page=(v) -- cgit v1.2.3 From ef9e0e6bf36cce1f30b8147b794066f1b9762e5c Mon Sep 17 00:00:00 2001 From: Sean Duckett Date: Tue, 27 Mar 2012 14:54:11 -0500 Subject: bug fixed, so useless. --- examples/test_export-repaired.xlsx | Bin 8315 -> 0 bytes examples/test_export.xlsx | Bin 3708 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 examples/test_export-repaired.xlsx delete mode 100644 examples/test_export.xlsx diff --git a/examples/test_export-repaired.xlsx b/examples/test_export-repaired.xlsx deleted file mode 100644 index e71522c4..00000000 Binary files a/examples/test_export-repaired.xlsx and /dev/null differ diff --git a/examples/test_export.xlsx b/examples/test_export.xlsx deleted file mode 100644 index 4e06b644..00000000 Binary files a/examples/test_export.xlsx and /dev/null differ -- cgit v1.2.3 From 30621f2ce9c88b242524929b184dfeebf89181aa Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Wed, 28 Mar 2012 23:31:38 +0900 Subject: doc fix --- lib/axlsx/util/validators.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/axlsx/util/validators.rb b/lib/axlsx/util/validators.rb index ce810e54..d4913074 100644 --- a/lib/axlsx/util/validators.rb +++ b/lib/axlsx/util/validators.rb @@ -5,11 +5,11 @@ module Axlsx # Perform validation # @param [String] name The name of what is being validatied. This is included in the error message # @param [Array] choices The list of choices to validate against - # @param [Any] v The value to be validated + # @param [Any] v The value to be validated # @raise [ArgumentError] Raised if the value provided is not in the list of choices. # @return [Boolean] true if validation succeeds. def self.validate(name, choices, v) - raise ArgumentError, (ERR_RESTRICTION % [v.to_s, name, choices.inspect]) unless choices.include?(v) + raise ArgumentError, (ERR_RESTRICTION % [v.to_s, name, choices.inspect]) unless choices.include?(v) true end end @@ -55,7 +55,7 @@ module Axlsx # Requires that the value is a Fixnum 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 Fixnum or Integer value greater or equal to 0 + # @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 >= 0 }) @@ -68,7 +68,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 Fixnum, 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) @@ -79,13 +79,13 @@ module Axlsx # @param [Any] v The value validated def self.validate_string(v) DataTypeValidator.validate :string, String, v - end + end # Requires that the value is a Float # @param [Any] v The value validated def self.validate_float(v) DataTypeValidator.validate :float, Float, v - end + end # Requires that the value is valid pattern type. # valid pattern types must be one of :none, :solid, :mediumGray, :darkGray, :lightGray, :darkHorizontal, :darkVertical, :darkDown, -- cgit v1.2.3 From da054ee2f47261f70ebc18f133dc303acd810581 Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Wed, 28 Mar 2012 23:44:15 +0900 Subject: implement column object - still needs to be tied in to a rewrite of autofit_data --- lib/axlsx/workbook/workbook.rb | 1 + lib/axlsx/workbook/worksheet/col.rb | 113 ++++++++++++++++++++++++++++++++++++ test/workbook/worksheet/tc_col.rb | 59 +++++++++++++++++++ 3 files changed, 173 insertions(+) create mode 100644 lib/axlsx/workbook/worksheet/col.rb create mode 100644 test/workbook/worksheet/tc_col.rb diff --git a/lib/axlsx/workbook/workbook.rb b/lib/axlsx/workbook/workbook.rb index a8e0a1af..7f557ef7 100644 --- a/lib/axlsx/workbook/workbook.rb +++ b/lib/axlsx/workbook/workbook.rb @@ -5,6 +5,7 @@ require 'axlsx/workbook/worksheet/date_time_converter.rb' require 'axlsx/workbook/worksheet/cell.rb' require 'axlsx/workbook/worksheet/page_margins.rb' require 'axlsx/workbook/worksheet/row.rb' +require 'axlsx/workbook/worksheet/col.rb' require 'axlsx/workbook/worksheet/worksheet.rb' require 'axlsx/workbook/shared_strings_table.rb' require 'axlsx/workbook/worksheet/table.rb' diff --git a/lib/axlsx/workbook/worksheet/col.rb b/lib/axlsx/workbook/worksheet/col.rb new file mode 100644 index 00000000..e9be61a6 --- /dev/null +++ b/lib/axlsx/workbook/worksheet/col.rb @@ -0,0 +1,113 @@ +# encoding: UTF-8 +module Axlsx + + # The Col class defines column attributes for columns in sheets. + class Col + + # First column affected by this 'column info' record. + # @return [Integer] + attr_reader :min + + # Last column affected by this 'column info' record. + # @return [Integer] + attr_reader :max + + # Flag indicating if the specified column(s) is set to 'best fit'. 'Best fit' is set to true under these conditions: + # The column width has never been manually set by the user, AND The column width is not the default width + # 'Best fit' means that when numbers are typed into a cell contained in a 'best fit' column, the column width should + # automatically resize to display the number. [Note: In best fit cases, column width must not be made smaller, only larger. end note] + # @return [Boolean] + attr_reader :bestFit + + # Flag indicating if the outlining of the affected column(s) is in the collapsed state. + # @return [Boolean] + attr_reader :collapsed + + # Flag indicating if the affected column(s) are hidden on this worksheet. + # @return [Boolean] + attr_reader :hidden + + # Outline level of affected column(s). Range is 0 to 7. + # @return [Integer] + attr_reader :outlineLevel + + # Flag indicating if the phonetic information should be displayed by default for the affected column(s) of the worksheet. + # @return [Boolean] + attr_reader :phonetic + + # Default style for the affected column(s). Affects cells not yet allocated in the column(s). In other words, this style applies to new columns. + # @return [Integer] + attr_reader :style + + # The width of the column + # @return [Numeric] + attr_reader :width + + # @return [Boolean] + attr_reader :customWidth + + # @see Col#collapsed + def collapsed=(v) + Axlsx.validate_boolean(v) + @collapsed = v + end + + # @see Col#hidden + def hidden=(v) + Axlsx.validate_boolean(v) + @hidden = v + end + + # @see Col#outline + def outlineLevel=(v) + Axlsx.validate_boolean(v) + @outlineLevel = v + end + + # @see Col#phonetic + def phonetic=(v) + Axlsx.validate_boolean(v) + @phonetic = v + end + + # @see Col#style + def style=(v) + Axlsx.validate_unsigned_int(v) + @style = v + end + + # @see Col#width + def width=(v) + Axlsx.validate_unsigned_numeric(v) + @customWidth = @bestFit = true + @width = v + end + + # Create a new Col objects + # @param min First column affected by this 'column info' record. + # @param max Last column affected by this 'column info' record. + # @option options [Boolean] collapsed see Col#collapsed + # @option options [Boolean] hidden see Col#hidden + # @option options [Boolean] outlineLevel see Col#outlineLevel + # @option options [Boolean] phonetic see Col#phonetic + # @option options [Integer] style see Col#style + # @option options [Numeric] width see Col#width + def initialize(min, max, options={}) + Axlsx.validate_unsigned_int(max) + Axlsx.validate_unsigned_int(min) + @min = min + @max = max + options.each do |o| + self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}=" + end + end + + # Serialize this columns data to an xml string + # @return [String] + def to_xml_string(str = '') + attrs = self.attribute_values.reject{ |key, value| value == nil } + str << '' + end + + end +end diff --git a/test/workbook/worksheet/tc_col.rb b/test/workbook/worksheet/tc_col.rb new file mode 100644 index 00000000..b28e26e9 --- /dev/null +++ b/test/workbook/worksheet/tc_col.rb @@ -0,0 +1,59 @@ +require 'tc_helper.rb' + +class TestCol < Test::Unit::TestCase + + def setup + @col = Axlsx::Col.new 1, 1 + end + + def test_min_max_required + assert_raise(ArgumentError, 'min and max must be specified when creating a new column') { Axlsx::Col.new } + assert_raise(ArgumentError, 'min and max must be specified when creating a new column') { Axlsx::Col.new nil, nil } + assert_nothing_raised { Axlsx::Col.new 1, 1 } + end + + def test_bestFit + assert_equal(@col.bestFit, nil) + assert_raise(NoMethodError, 'bestFit is read only') { @col.bestFit = 'bob' } + @col.width = 1.999 + assert_equal(@col.bestFit, true, 'bestFit should be true when width has been set') + end + + def test_collapsed + assert_equal(@col.collapsed, nil) + assert_raise(ArgumentError, 'collapsed must be boolean(ish)') { @col.collapsed = 'bob' } + assert_nothing_raised('collapsed must be boolean(ish)') { @col.collapsed = true } + end + + def test_customWidth + assert_equal(@col.customWidth, nil) + @col.width = 3 + assert_raise(NoMethodError, 'customWidth is read only') { @col.customWidth = 3 } + assert_equal(@col.customWidth, true, 'customWidth is true when width is set') + end + + def test_hidden + assert_equal(@col.hidden, nil) + assert_raise(ArgumentError, 'hidden must be boolean(ish)') { @col.hidden = 'bob' } + assert_nothing_raised(ArgumentError, 'hidden must be boolean(ish)') { @col.hidden = true } + end + + def test_outlineLevel + assert_equal(@col.outlineLevel, nil) + assert_raise(ArgumentError, 'outline level cannot be negative') { @col.outlineLevel = -1 } + assert_raise(ArgumentError, 'outline level cannot be greater than 7') { @col.outlineLevel = 8 } + assert_nothing_raised('can set outlineLevel') { @col.outlineLevel = 1 } + end + + def test_phonetic + assert_equal(@col.phonetic, nil) + assert_raise(ArgumentError, 'phonetic must be boolean(ish)') { @col.phonetic = 'bob' } + assert_nothing_raised(ArgumentError, 'phonetic must be boolean(ish)') { @col.phonetic = true } + end + + def test_style + assert_equal(@col.style, nil) + #TODO check that the style specified is actually in the styles xfs collection + end + +end -- cgit v1.2.3 From 78095afd0fe199603cf7bc6e33d6ff9e10f906dd Mon Sep 17 00:00:00 2001 From: Jurriaan Pruis Date: Wed, 28 Mar 2012 17:37:10 +0200 Subject: Updated test cases for Auto Filter fix --- test/workbook/worksheet/tc_worksheet.rb | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/test/workbook/worksheet/tc_worksheet.rb b/test/workbook/worksheet/tc_worksheet.rb index d9a89a69..4f66f250 100644 --- a/test/workbook/worksheet/tc_worksheet.rb +++ b/test/workbook/worksheet/tc_worksheet.rb @@ -2,8 +2,9 @@ require 'tc_helper.rb' class TestWorksheet < Test::Unit::TestCase def setup - p = Axlsx::Package.new - @ws = p.workbook.add_worksheet + @p = Axlsx::Package.new + @wb = @p.workbook + @ws = @wb.add_worksheet end @@ -201,6 +202,8 @@ class TestWorksheet < Test::Unit::TestCase @ws.auto_filter = "A1:B1" doc = Nokogiri::XML(@ws.to_xml_string) assert_equal(doc.xpath('//xmlns:worksheet/xmlns:autoFilter[@ref="A1:B1"]').size, 1) + doc2 = Nokogiri::XML(@wb.to_xml) + assert_equal(doc2.xpath('//xmlns:workbook/xmlns:definedNames/xmlns:definedName').inner_text, @ws.abs_auto_filter) end def test_to_xml_string_merge_cells @@ -234,6 +237,13 @@ class TestWorksheet < Test::Unit::TestCase assert_equal(doc.xpath('//xmlns:worksheet/xmlns:tableParts/xmlns:tablePart[@r:id="rId1"]').size, 1) end + def test_abs_auto_filter + @ws.add_row [1, "two", 3] + @ws.auto_filter = "A1:C1" + doc = Nokogiri::XML(@wb.to_xml) + assert_equal(doc.xpath('//xmlns:workbook/xmlns:definedNames/xmlns:definedName').inner_text, "'Sheet1'!$A$1:$C$1") + end + def test_to_xml schema = Nokogiri::XML::Schema(File.open(Axlsx::SML_XSD)) doc = Nokogiri::XML(@ws.to_xml) -- cgit v1.2.3 From 978e998e167452aafe46953746100f8e4a7d7b59 Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Thu, 29 Mar 2012 01:00:43 +0900 Subject: Implement full set of col attributes and improve performance of autowidth two fold. ``` user system total real axlsx_noautowidth 0.810000 0.020000 0.830000 ( 0.836274) axlsx 1.430000 0.160000 1.590000 ( 1.776305) axlsx_shared 9.360000 0.160000 9.520000 ( 9.662113) axlsx_stream 1.320000 0.110000 1.430000 ( 1.429806) csv 0.260000 0.020000 0.280000 ( 0.296828) --- README.md | 17 ++++- examples/example.rb | 14 ++++ lib/axlsx/drawing/chart.rb | 19 +++--- lib/axlsx/workbook/worksheet/cell.rb | 1 - lib/axlsx/workbook/worksheet/col.rb | 6 +- lib/axlsx/workbook/worksheet/row.rb | 9 +-- lib/axlsx/workbook/worksheet/worksheet.rb | 102 ++++++++++-------------------- test/workbook/worksheet/tc_worksheet.rb | 55 ++++++++-------- 8 files changed, 104 insertions(+), 119 deletions(-) diff --git a/README.md b/README.md index a0ab2173..dcef1f23 100644 --- a/README.md +++ b/README.md @@ -161,6 +161,20 @@ To install Axlsx, use the following command: end end +##Hiding Columns + + wb.styles do |s| + percent = s.add_style :num_fmt => 9 + wb.add_worksheet(:name => "Hidden Column") do |sheet| + sheet.add_row ['col 1', 'col 2', 'col 3', 'col 4'] + sheet.add_row [1, 2, 0.3, 4] + sheet.add_row [1, 2, 0.2, 4] + sheet.add_row [1, 2, 0.1, 4] + sheet.col_style 2, percent, :row_offset => 1 + sheet.column_info[1].hidden = true + end + end + ##Styling Rows wb.styles do |s| @@ -369,7 +383,8 @@ This gem has 100% test coverage using test/unit. To execute tests for this gem, - added option to *not* use RMagick - and default all assigned columns to the excel default of 8.43 - added border style specification to styles#add_style - now you can pass in :border => {:style => :thin, :color =>"0000FF"} instead of creating a border object and border parts manually each time. - Support for tables added in - Note: Pre 2011 versions of Mac office do not support this feature. - + - Support for splatter charts added + - Major performance updates. - ** March.5.12**: 1.0.18 release https://github.com/randym/axlsx/compare/1.0.17...1.0.18 - bugfix custom borders are not properly applied when using styles.add_style diff --git a/examples/example.rb b/examples/example.rb index 604ab597..04ad6f4c 100644 --- a/examples/example.rb +++ b/examples/example.rb @@ -95,6 +95,20 @@ wb.styles do |s| end end +##Hiding Columns + +wb.styles do |s| + percent = s.add_style :num_fmt => 9 + wb.add_worksheet(:name => "Hidden Column") do |sheet| + sheet.add_row ['col 1', 'col 2', 'col 3', 'col 4'] + sheet.add_row [1, 2, 0.3, 4] + sheet.add_row [1, 2, 0.2, 4] + sheet.add_row [1, 2, 0.1, 4] + sheet.col_style 2, percent, :row_offset => 1 + sheet.column_info[1].hidden = true + end +end + ##Styling Rows wb.styles do |s| diff --git a/lib/axlsx/drawing/chart.rb b/lib/axlsx/drawing/chart.rb index 0a8068df..b612fbed 100644 --- a/lib/axlsx/drawing/chart.rb +++ b/lib/axlsx/drawing/chart.rb @@ -28,7 +28,7 @@ module Axlsx # @return [Title] attr_reader :title - # The style for the chart. + # The style for the chart. # see ECMA Part 1 §21.2.2.196 # @return [Integer] attr_reader :style @@ -36,13 +36,14 @@ module Axlsx # Show the legend in the chart # @return [Boolean] attr_reader :show_legend - + # Creates a new chart object # @param [GraphicalFrame] frame The frame that holds this chart. # @option options [Cell, String] title # @option options [Boolean] show_legend def initialize(frame, options={}) @style = 2 + @view3D = nil @graphic_frame=frame @graphic_frame.anchor.drawing.worksheet.workbook.charts << self @series = SimpleTypedList.new Series @@ -72,7 +73,7 @@ module Axlsx # The title object for the chart. # @param [String, Cell] v # @return [Title] - def title=(v) + def title=(v) DataTypeValidator.validate "#{self.class}.title", [String, Cell], v if v.is_a?(String) @title.text = v @@ -80,14 +81,14 @@ module Axlsx @title.cell = v end end - + # Show the legend in the chart # @param [Boolean] v # @return [Boolean] def show_legend=(v) Axlsx::validate_boolean(v); @show_legend = v; end - # The style for the chart. + # The style for the chart. # see ECMA Part 1 §21.2.2.196 # @param [Integer] v must be between 1 and 48 def style=(v) DataTypeValidator.validate "Chart.style", Integer, v, lambda { |arg| arg >= 1 && arg <= 48 }; @style = v; end @@ -122,8 +123,8 @@ module Axlsx xml[:c].chart { @title.to_xml(xml) xml.autoTitleDeleted :val=>0 - @view3D.to_xml(xml) unless @view3D.nil? - + @view3D.to_xml(xml) if @view3D + xml.floor { xml.thickness(:val=>0) } xml.sideWall { xml.thickness(:val=>0) } xml.backWall { xml.thickness(:val=>0) } @@ -135,14 +136,14 @@ module Axlsx xml.legend { xml.legendPos :val => "r" xml.layout - xml.overlay :val => 0 + xml.overlay :val => 0 } end xml.plotVisOnly :val => 1 xml.dispBlanksAs :val => :zero xml.showDLblsOverMax :val => 1 } - + } end builder.to_xml(:save_with => 0) diff --git a/lib/axlsx/workbook/worksheet/cell.rb b/lib/axlsx/workbook/worksheet/cell.rb index 24b380cb..bfb7f35f 100644 --- a/lib/axlsx/workbook/worksheet/cell.rb +++ b/lib/axlsx/workbook/worksheet/cell.rb @@ -278,7 +278,6 @@ module Axlsx def run_xml_string(str = '') if is_text_run? - puts 'text run' data = self.instance_values.reject{|key, value| value == nil } keys = data.keys & INLINE_STYLES keys.delete ['value', 'type'] diff --git a/lib/axlsx/workbook/worksheet/col.rb b/lib/axlsx/workbook/worksheet/col.rb index e9be61a6..ccf4dfaf 100644 --- a/lib/axlsx/workbook/worksheet/col.rb +++ b/lib/axlsx/workbook/worksheet/col.rb @@ -78,8 +78,8 @@ module Axlsx # @see Col#width def width=(v) - Axlsx.validate_unsigned_numeric(v) - @customWidth = @bestFit = true + Axlsx.validate_unsigned_numeric(v) unless v == nil + @customWidth = @bestFit = v != nil @width = v end @@ -105,7 +105,7 @@ module Axlsx # Serialize this columns data to an xml string # @return [String] def to_xml_string(str = '') - attrs = self.attribute_values.reject{ |key, value| value == nil } + attrs = self.instance_values.reject{ |key, value| value == nil } str << '' end diff --git a/lib/axlsx/workbook/worksheet/row.rb b/lib/axlsx/workbook/worksheet/row.rb index ac251ed8..58171fea 100644 --- a/lib/axlsx/workbook/worksheet/row.rb +++ b/lib/axlsx/workbook/worksheet/row.rb @@ -83,7 +83,7 @@ module Axlsx # @return [Cell] def add_cell(value="", options={}) c = Cell.new(self, value, options) - update_auto_fit_data + worksheet.send(:update_column_info, self.cells, self.cells.map(&:style)) c end @@ -117,13 +117,6 @@ module Axlsx # assigns the owning worksheet for this row def worksheet=(v) DataTypeValidator.validate "Row.worksheet", Worksheet, v; @worksheet=v; end - # Tell the worksheet to update autofit data for the columns based on this row's cells. - # @return [SimpleTypedList] - def update_auto_fit_data - worksheet.send(:update_auto_fit_data, self.cells) - 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. # If value option is defined and is a symbol it is applied to all the cells created. diff --git a/lib/axlsx/workbook/worksheet/worksheet.rb b/lib/axlsx/workbook/worksheet/worksheet.rb index 20c13d8b..7678f6f9 100644 --- a/lib/axlsx/workbook/worksheet/worksheet.rb +++ b/lib/axlsx/workbook/worksheet/worksheet.rb @@ -53,6 +53,11 @@ module Axlsx # @return Boolean attr_reader :fit_to_page + + # Column info for the sheet + # @return [SimpleTypedList] + attr_reader :column_info + # Page margins for printing the worksheet. # @example # wb = Axlsx::Package.new.workbook @@ -96,7 +101,8 @@ module Axlsx @page_margins = PageMargins.new options[:page_margins] if options[:page_margins] @rows = SimpleTypedList.new Row - @cols = SimpleTypedList.new Cell + @column_info = SimpleTypedList.new Col + # @cols = SimpleTypedList.new Cell @tables = SimpleTypedList.new Table if self.workbook.use_autowidth @@ -270,7 +276,8 @@ module Axlsx # @option options [Float] height the row's height (in points) def add_row(values=[], options={}) Row.new(self, values, options) - update_auto_fit_data @rows.last.cells, options.delete(:widths) || [] + update_column_info @rows.last.cells, options.delete(:widths) ||[], options.delete(:style) || [] + # update_auto_fit_data @rows.last.cells, options.delete(:widths) || [] yield @rows.last if block_given? @rows.last end @@ -329,9 +336,9 @@ module Axlsx # @param [Integer|Float|Fixnum|nil] values def column_widths(*args) args.each_with_index do |value, index| - raise ArgumentError, "Invalid column specification" unless index < @auto_fit_data.size + raise ArgumentError, "Invalid column specification" unless index < @column_info.size Axlsx::validate_unsigned_numeric(value) unless value == nil - @auto_fit_data[index][:fixed] = value + @column_info[index].width = value end end @@ -377,15 +384,16 @@ module Axlsx str.concat "" % dimension unless rows.size == 0 str.concat "" % [@selected, show_gridlines] - if @auto_fit_data.size > 0 - str.concat "" - @auto_fit_data.each_with_index do |col, index| - min_max = index+1 - str.concat "" % [min_max, min_max, auto_width(col)] - end + if @column_info.size > 0 + str << "" + @column_info.each { |col| col.to_xml_string(str) } + + # @auto_fit_data.each_with_index do |col, index| + # min_max = index+1 + # str.concat "" % [min_max, min_max, auto_width(col)] + # end str.concat '' end - str.concat '' @rows.each_with_index { |row, index| row.to_xml_string(index, str) } str.concat '' @@ -486,74 +494,34 @@ module Axlsx # assigns the owner workbook for this worksheet def workbook=(v) DataTypeValidator.validate "Worksheet.workbook", Workbook, v; @workbook = v; end - # Updates auto fit data. - # We store an auto_fit_data item for each column. when a row is added we multiple the font size by the length of the text to - # attempt to identify the longest cell in the column. This is not 100% accurate as it needs to take into account - # any formatting that will be applied to the data, as well as the actual rendering size when the length and size is equal - # for two cells. - - # @return [Array] of Cell objects - # @param [Array] cells an array of cells - # @param [Array] widths an array of cell widths @see Worksheet#add_row - def update_auto_fit_data(cells, widths=[]) - # TODO delay this until rendering. too much work when we dont know what they are going to do to the sheet. + + def update_column_info(cells, widths=[], style=[]) styles = self.workbook.styles cellXfs, fonts = styles.cellXfs, styles.fonts sz = 11 - cells.each_with_index do |item, index| - col = @auto_fit_data[index] ||= {:longest=>"", :sz=>sz, :fixed=>nil} + cells.each_with_index do |cell, index| + @column_info[index] ||= Col.new index+1, index+1 + col = @column_info[index] width = widths[index] - # set fixed width and skip if numeric width is given - col[:fixed] = width if [Integer, Float, Fixnum].include?(width.class) - # ignore default column widths and formula - next if width == :ignore || (item.value.is_a?(String) && item.value.start_with?('=')) - # make sure we can turn that fixed with off! - col[:fixed] = nil if width == :auto - next unless self.workbook.use_autowidth - - cell_xf = cellXfs[item.style] - font = fonts[cell_xf.fontId || 0] - sz = item.sz || font.sz || fonts[0].sz - if (col[:longest].scan(/./mu).size * col[:sz]) < (item.value.to_s.scan(/./mu).size * sz) - col[:sz] = sz - col[:longest] = item.value.to_s + col.width = width if [Integer, Float, Fixnum].include?(width.class) + c_style = style[index] if [Integer, Fixnum].include?(style[index].class) + next if width == :ignore || col.width || (cell.value.is_a?(String) && cell.value.start_with?('=')) + if self.workbook.use_autowidth + cell_xf = cellXfs[(c_style || 0)] + font = fonts[(cell_xf.fontId || 0)] + sz = cell.sz || font.sz || sz + col.width = [(col.width || 0), calculate_width(cell.value.to_s, sz)].max end end - cells end - # Determines the proper width for a column based on content. - # @note - # width = Truncate([!{Number of Characters} * !{Maximum Digit Width} + !{5 pixel padding}]/!{Maximum Digit Width}*256)/256 - # @return [Float] - # @param [Hash] A hash of auto_fit_data - def auto_width(col) - return col[:fixed] unless col[:fixed] == nil - return Axlsx::FIXED_COL_WIDTH unless self.workbook.use_autowidth - mdw_count, font_scale, mdw = 0, col[:sz]/11.0, 6.0 - mdw_count = col[:longest].scan(/./mu).reduce(0) do | count, char | + def calculate_width(text, sz) + mdw_count, font_scale, mdw = 0, sz/11.0, 6.0 + mdw_count = text.scan(/./mu).reduce(0) do | count, char | count +=1 if @magick_draw.get_type_metrics(char).max_advance >= mdw count end ((mdw_count * mdw + 5) / mdw * 256) / 256.0 * font_scale end - - # Something to look into: - # width calculation actually needs to be done agains the formatted value for items that apply a - # format - # def excel_format(cell) - # # The most common case. - # return time.value.to_s if cell.style == 0 - # - # # The second most common case - # num_fmt = workbook.styles.cellXfs[items.style].numFmtId - # return value.to_s if num_fmt == 0 - # - # format_code = workbook.styles.numFmts[num_fmt] - # # need to find some exceptionally fast way of parsing value according to - # # an excel format_code - # item.value.to_s - # end - end end diff --git a/test/workbook/worksheet/tc_worksheet.rb b/test/workbook/worksheet/tc_worksheet.rb index d9a89a69..603b5314 100644 --- a/test/workbook/worksheet/tc_worksheet.rb +++ b/test/workbook/worksheet/tc_worksheet.rb @@ -27,7 +27,7 @@ class TestWorksheet < Test::Unit::TestCase def test_no_autowidth @ws.workbook.use_autowidth = false @ws.add_row [1,2,3,4] - assert_equal(@ws.send(:auto_width, @ws.auto_fit_data[0]), Axlsx::FIXED_COL_WIDTH) + assert_equal(@ws.column_info[0].width, nil) end def test_initialization_options @@ -277,51 +277,47 @@ class TestWorksheet < Test::Unit::TestCase end def test_update_auto_with_data - small = @ws.workbook.styles.add_style(:sz=>2) - big = @ws.workbook.styles.add_style(:sz=>10) + # small = @ws.workbook.styles.add_style(:sz=>2) + # big = @ws.workbook.styles.add_style(:sz=>10) - @ws.add_row ["chasing windmills", "penut"], :style=>small - assert(@ws.auto_fit_data.size == 2, "a data item for each column") + # @ws.add_row ["chasing windmills", "penut"], :style=>small + # assert(@ws.auto_fit_data.size == 2, "a data item for each column") - assert_equal(@ws.auto_fit_data[0], {:sz => 2, :longest => "chasing windmills", :fixed=>nil}, "adding a row updates auto_fit_data if the product of the string length and font is greater for the column") + # assert_equal(@ws.auto_fit_data[0], {:sz => 2, :longest => "chasing windmills", :fixed=>nil}, "adding a row updates auto_fit_data if the product of the string length and font is greater for the column") - @ws.add_row ["mule"], :style=>big - assert_equal(@ws.auto_fit_data[0], {:sz=>10,:longest=>"mule", :fixed=>nil}, "adding a row updates auto_fit_data if the product of the string length and font is greater for the column") + # @ws.add_row ["mule"], :style=>big + # assert_equal(@ws.auto_fit_data[0], {:sz=>10,:longest=>"mule", :fixed=>nil}, "adding a row updates auto_fit_data if the product of the string length and font is greater for the column") end def test_set_fixed_width_column @ws.add_row ["mule", "donkey", "horse"], :widths => [20, :ignore, nil] - assert(@ws.auto_fit_data.size == 3, "a data item for each column") - assert_equal({:sz=>11, :longest=>"mule", :fixed=>20 }, @ws.auto_fit_data[0], "adding a row with fixed width updates :fixed attribute") - assert_equal({:sz=>11, :longest=>"", :fixed=>nil}, @ws.auto_fit_data[1], ":ignore does not set any data") - assert_equal({:sz=>11, :longest=>"horse", :fixed=>nil}, @ws.auto_fit_data[2], "nil, well really anything else just works as normal") - @ws.add_row ["mule", "donkey", "horse"] - assert_equal({:sz=>11, :longest=>"donkey", :fixed=>nil}, @ws.auto_fit_data[1]) - + assert(@ws.column_info.size == 3, "a data item for each column") + assert_equal(@ws.column_info[0].width, 20, "adding a row with fixed width updates :fixed attribute") + assert_equal(@ws.column_info[1].width, nil, ":ignore does not set any data") end def test_fixed_widths_with_merged_cells - @ws.add_row ["hey, I'm like really long and stuff so I think you will merge me."] - @ws.merge_cells "A1:C1" - @ws.add_row ["but Im Short!"], :widths=> [14.8] - assert_equal(@ws.send(:auto_width, @ws.auto_fit_data[0]), 14.8) + # @ws.add_row ["hey, I'm like really long and stuff so I think you will merge me."] + # @ws.merge_cells "A1:C1" + # @ws.add_row ["but Im Short!"], :widths=> [14.8] + # assert_equal(@ws.send(:auto_width, @ws.auto_fit_data[0]), 14.8) end def test_fixed_width_to_auto - @ws.add_row ["hey, I'm like really long and stuff so I think you will merge me."] - @ws.merge_cells "A1:C1" - @ws.add_row ["but Im Short!"], :widths=> [14.8] - assert_equal(@ws.send(:auto_width, @ws.auto_fit_data[0]), 14.8) - @ws.add_row ["no, I like auto!"], :widths=>[:auto] - assert_equal(@ws.auto_fit_data[0][:fixed], nil) + # @ws.add_row ["hey, I'm like really long and stuff so I think you will merge me."] + # @ws.merge_cells "A1:C1" + # @ws.add_row ["but Im Short!"], :widths=> [14.8] + # assert_equal(@ws.send(:auto_width, @ws.auto_fit_data[0]), 14.8) + # @ws.add_row ["no, I like auto!"], :widths=>[:auto] + # assert_equal(@ws.auto_fit_data[0][:fixed], nil) end def test_auto_width - assert(@ws.send(:auto_width, {:sz=>11, :longest=>"fisheries"}) > @ws.send(:auto_width, {:sz=>11, :longest=>"fish"}), "longer strings get a longer auto_width at the same font size") + # assert(@ws.send(:auto_width, {:sz=>11, :longest=>"fisheries"}) > @ws.send(:auto_width, {:sz=>11, :longest=>"fish"}), "longer strings get a longer auto_width at the same font size") - assert(@ws.send(:auto_width, {:sz=>11, :longest=>"fish"}) < @ws.send(:auto_width, {:sz=>12, :longest=>"fish"}), "larger fonts produce longer with with same string") - assert_equal(@ws.send(:auto_width, {:sz=>11, :longest => "This is a really long string", :fixed=>0.2}), 0.2, "fixed rules!") + # assert(@ws.send(:auto_width, {:sz=>11, :longest=>"fish"}) < @ws.send(:auto_width, {:sz=>12, :longest=>"fish"}), "larger fonts produce longer with with same string") + # assert_equal(@ws.send(:auto_width, {:sz=>11, :longest => "This is a really long string", :fixed=>0.2}), 0.2, "fixed rules!") end def test_fixed_height @@ -332,9 +328,8 @@ class TestWorksheet < Test::Unit::TestCase def test_set_column_width @ws.add_row ["chasing windmills", "penut"] - assert_equal(@ws.auto_fit_data[0][:fixed], nil, 'no fixed by default') @ws.column_widths nil, 0.5 - assert_equal(@ws.auto_fit_data[1][:fixed], 0.5, 'eat my width') + assert_equal(@ws.column_info[1].width, 0.5, 'eat my width') assert_raise(ArgumentError, 'reject invalid columns') { @ws.column_widths 2, 7, nil } 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" } -- cgit v1.2.3 From a276aaebab11117a9c6c78f8bd9b2d44d07c3772 Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Thu, 29 Mar 2012 01:12:42 +0900 Subject: fix example for border add_style --- lib/axlsx/stylesheet/border.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/axlsx/stylesheet/border.rb b/lib/axlsx/stylesheet/border.rb index ddf6dc90..43acbdca 100644 --- a/lib/axlsx/stylesheet/border.rb +++ b/lib/axlsx/stylesheet/border.rb @@ -21,7 +21,7 @@ module Axlsx # @option options [Boolean] outline # @example - Making a border # p = Axlsx::Package.new - # red_border = p.workbook.styles.add_style :border => {:style =>: thin, :color => "FFFF0000"} + # red_border = p.workbook.styles.add_style :border => { :style => :thin, :color => "FFFF0000" } # ws = p.workbook.add_worksheet # ws.add_row [1,2,3], :style => red_border # p.serialize('red_border.xlsx') -- cgit v1.2.3 From bb2117ba17297e02a0fc6d5ad5a22462e72a9a79 Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Sat, 31 Mar 2012 18:23:59 +0900 Subject: post build status to googlegroup --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b4a356ab..cd3e8091 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ notifications: irc: "irc.freenode.org#axlsx" email: recipients: - - digital.ipseity@gmail.com + - axlsx@googlegroups.com on_success: always rvm: - 1.8.7 -- cgit v1.2.3 From 22a341841f191a5aa00e87b1f166b4f25cc67f0a Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Sun, 1 Apr 2012 00:35:26 +0900 Subject: part way through changing all serialization to use string concatenation prior to dropping Nokogiri dep in production. --- lib/axlsx.rb | 4 +- lib/axlsx/content_type/content_type.rb | 17 +++--- lib/axlsx/content_type/default.rb | 14 ++--- lib/axlsx/content_type/override.rb | 18 ++++--- lib/axlsx/doc_props/app.rb | 77 +++++++++++++--------------- lib/axlsx/doc_props/core.rb | 28 ++++------ lib/axlsx/drawing/axis.rb | 23 +++++++++ lib/axlsx/drawing/bar_3D_chart.rb | 44 ++++++++++++---- lib/axlsx/drawing/bar_series.rb | 22 +++++--- lib/axlsx/drawing/cat_axis.rb | 18 +++++-- lib/axlsx/drawing/cat_axis_data.rb | 20 +++++++- lib/axlsx/drawing/chart.rb | 33 +++++++++++- lib/axlsx/drawing/drawing.rb | 17 ++++-- lib/axlsx/drawing/graphic_frame.rb | 18 +++++++ lib/axlsx/drawing/hyperlink.rb | 22 +++++--- lib/axlsx/drawing/line_3D_chart.rb | 37 ++++++++++--- lib/axlsx/drawing/line_series.rb | 17 ++++-- lib/axlsx/drawing/marker.rb | 15 ++++-- lib/axlsx/drawing/named_axis_data.rb | 17 ++++++ lib/axlsx/drawing/one_cell_anchor.rb | 22 ++++++-- lib/axlsx/drawing/pic.rb | 18 ++++--- lib/axlsx/drawing/scaling.rb | 11 +++- lib/axlsx/drawing/ser_axis.rb | 11 +++- lib/axlsx/drawing/series.rb | 21 +++++--- lib/axlsx/drawing/title.rb | 32 +++++++++--- lib/axlsx/drawing/val_axis.rb | 7 +++ lib/axlsx/drawing/val_axis_data.rb | 20 +++++++- lib/axlsx/drawing/view_3D.rb | 30 +++++++---- lib/axlsx/package.rb | 18 +++---- lib/axlsx/rels/relationship.rb | 15 +++--- lib/axlsx/rels/relationships.rb | 8 ++- lib/axlsx/workbook/shared_strings_table.rb | 2 +- lib/axlsx/workbook/workbook.rb | 45 ++++++++-------- lib/axlsx/workbook/worksheet/cell.rb | 77 ++++------------------------ lib/axlsx/workbook/worksheet/col.rb | 9 ++-- lib/axlsx/workbook/worksheet/page_margins.rb | 12 ++--- lib/axlsx/workbook/worksheet/row.rb | 12 ++--- lib/axlsx/workbook/worksheet/table.rb | 32 +++++------- lib/axlsx/workbook/worksheet/worksheet.rb | 10 ++-- test/content_type/tc_content_type.rb | 10 ++-- test/content_type/tc_default.rb | 23 ++------- test/content_type/tc_override.rb | 21 ++------ test/doc_props/tc_app.rb | 7 +-- test/doc_props/tc_core.rb | 4 +- test/rels/tc_relationships.rb | 4 +- test/workbook/tc_workbook.rb | 14 ++++- test/workbook/worksheet/table/tc_table.rb | 4 +- test/workbook/worksheet/tc_cell.rb | 7 +-- test/workbook/worksheet/tc_page_margins.rb | 4 +- test/workbook/worksheet/tc_row.rb | 12 +---- test/workbook/worksheet/tc_worksheet.rb | 49 ++---------------- 51 files changed, 588 insertions(+), 444 deletions(-) diff --git a/lib/axlsx.rb b/lib/axlsx.rb index 09f351fc..dd628562 100644 --- a/lib/axlsx.rb +++ b/lib/axlsx.rb @@ -81,7 +81,7 @@ module Axlsx # @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 - end + Axlsx::col_ref(c_index).to_s << (r_index+1).to_s + end end diff --git a/lib/axlsx/content_type/content_type.rb b/lib/axlsx/content_type/content_type.rb index 8b58bf04..6b4facd0 100644 --- a/lib/axlsx/content_type/content_type.rb +++ b/lib/axlsx/content_type/content_type.rb @@ -10,15 +10,14 @@ module Axlsx super [Override, Default] end - # Generates the xml document for [Content_Types].xml - # @return [String] The document as a string. - def to_xml() - builder = Nokogiri::XML::Builder.new(:encoding => ENCODING) do |xml| - xml.Types(:xmlns => Axlsx::XML_NS_T) { - each { |type| type.to_xml(xml) } - } - end - builder.to_xml(:save_with => 0) + # serialize the content types + # @return [String] str + def to_xml_string(str = '') + str << '' + str << '' + each { |type| type.to_xml_string(str) } + str << '' end + end end diff --git a/lib/axlsx/content_type/default.rb b/lib/axlsx/content_type/default.rb index bd572b14..2ff24527 100644 --- a/lib/axlsx/content_type/default.rb +++ b/lib/axlsx/content_type/default.rb @@ -8,7 +8,7 @@ module Axlsx attr_reader :Extension # The type of content. - # @return [String] + # @return [String] attr_reader :ContentType #Creates a new Default object @@ -19,7 +19,7 @@ module Axlsx raise ArgumentError, "Extension and ContentType are required" unless options[:Extension] && options[:ContentType] options.each do |o| self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}=" - end + end end # Sets the file extension for this content type. def Extension=(v) Axlsx::validate_string v; @Extension = v end @@ -28,11 +28,11 @@ module Axlsx # @see Axlsx#validate_content_type def ContentType=(v) Axlsx::validate_content_type v; @ContentType = v end - # Serializes the object to xml - # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. - # @return [String] - def to_xml(xml) - xml.Default(self.instance_values) + def to_xml_string(str = '') + str << '' end + end end diff --git a/lib/axlsx/content_type/override.rb b/lib/axlsx/content_type/override.rb index 2513b8ff..665a538a 100644 --- a/lib/axlsx/content_type/override.rb +++ b/lib/axlsx/content_type/override.rb @@ -4,11 +4,11 @@ module Axlsx class Override # The type of content. - # @return [String] + # @return [String] attr_reader :ContentType # The name and location of the part. - # @return [String] + # @return [String] attr_reader :PartName #Creates a new Override object @@ -19,20 +19,22 @@ module Axlsx raise ArgumentError, "PartName and ContentType are required" unless options[:PartName] && options[:ContentType] options.each do |o| self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}=" - end + end end # The name and location of the part. def PartName=(v) Axlsx::validate_string v; @PartName = v end - # The content type. + # The content type. # @see Axlsx#validate_content_type def ContentType=(v) Axlsx::validate_content_type v; @ContentType = v end - # Serializes the Override object to xml - # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. - def to_xml(xml) - xml.Override(self.instance_values) + # Serialize the Override + def to_xml_string(str = '') + str << '' end + end end diff --git a/lib/axlsx/doc_props/app.rb b/lib/axlsx/doc_props/app.rb index 16966da4..1b5fc2ad 100644 --- a/lib/axlsx/doc_props/app.rb +++ b/lib/axlsx/doc_props/app.rb @@ -17,7 +17,7 @@ module Axlsx attr_reader :Manager # @return [String] The name of the company generating the document. - attr_reader :Company + attr_reader :Company # @return [Integer] The number of pages in the document. attr_reader :Pages @@ -43,7 +43,7 @@ module Axlsx # @return [Integer] The number of slides that have notes. attr_reader :Notes - # @return [Integer] The total amount of time spent editing. + # @return [Integer] The total amount of time spent editing. attr_reader :TotalTime # @return [Integer] The number of hidden slides. @@ -60,11 +60,11 @@ module Axlsx # @return [Integer] The number of characters in the document including spaces. attr_reader :CharactersWithSpaces - + # @return [Boolean] Indicates if the document is shared. attr_reader :ShareDoc - # @return [String] The base for hyper links in the document. + # @return [String] The base for hyper links in the document. attr_reader :HyperLinkBase # @return [Boolean] Indicates that the hyper links in the document have been changed. @@ -96,7 +96,7 @@ module Axlsx # @option options [Boolean] ScaleCrop # @option options [Boolean] LinksUpToDate # @option options [Integer] CharactersWithSpaces - # @option options [Boolean] ShareDoc + # @option options [Boolean] ShareDoc # @option options [String] HyperLinkBase # @option options [String] HyperlinksChanged # @option options [String] Application @@ -109,70 +109,67 @@ module Axlsx end # Sets the Template property of your app.xml file - def Template=(v) Axlsx::validate_string v; @Template = v; end + def Template=(v) Axlsx::validate_string v; @Template = v; end # Sets the Manager property of your app.xml file - def Manager=(v) Axlsx::validate_string v; @Manager = v; end + def Manager=(v) Axlsx::validate_string v; @Manager = v; end # Sets the Company property of your app.xml file - def Company=(v) Axlsx::validate_string v; @Company = v; end + def Company=(v) Axlsx::validate_string v; @Company = v; end # Sets the Pages property of your app.xml file - def Pages=(v) Axlsx::validate_int v; @Pages = v; end + def Pages=(v) Axlsx::validate_int v; @Pages = v; end # Sets the Words property of your app.xml file - def Words=(v) Axlsx::validate_int v; @Words = v; end + def Words=(v) Axlsx::validate_int v; @Words = v; end # Sets the Characters property of your app.xml file - def Characters=(v) Axlsx::validate_int v; @Characters = v; end + def Characters=(v) Axlsx::validate_int v; @Characters = v; end # Sets the PresentationFormat property of your app.xml file - def PresentationFormat=(v) Axlsx::validate_string v; @PresentationFormat = v; end + def PresentationFormat=(v) Axlsx::validate_string v; @PresentationFormat = v; end # Sets the Lines property of your app.xml file - def Lines=(v) Axlsx::validate_int v; @Lines = v; end + def Lines=(v) Axlsx::validate_int v; @Lines = v; end # Sets the Paragraphs property of your app.xml file - def Paragraphs=(v) Axlsx::validate_int v; @Paragraphs = v; end + def Paragraphs=(v) Axlsx::validate_int v; @Paragraphs = v; end # Sets the Slides property of your app.xml file - def Slides=(v) Axlsx::validate_int v; @Slides = v; end + def Slides=(v) Axlsx::validate_int v; @Slides = v; end # Sets the Notes property of your app.xml file - def Notes=(v) Axlsx::validate_int v; @Notes = v; end + def Notes=(v) Axlsx::validate_int v; @Notes = v; end # Sets the TotalTime property of your app.xml file - def TotalTime=(v) Axlsx::validate_int v; @TotalTime = v; end + def TotalTime=(v) Axlsx::validate_int v; @TotalTime = v; end # Sets the HiddenSlides property of your app.xml file - def HiddenSlides=(v) Axlsx::validate_int v; @HiddenSlides = v; end + def HiddenSlides=(v) Axlsx::validate_int v; @HiddenSlides = v; end # Sets the MMClips property of your app.xml file - def MMClips=(v) Axlsx::validate_int v; @MMClips = v; end + def MMClips=(v) Axlsx::validate_int v; @MMClips = v; end # Sets the ScaleCrop property of your app.xml file - def ScaleCrop=(v) Axlsx::validate_boolean v; @ScaleCrop = v; end + def ScaleCrop=(v) Axlsx::validate_boolean v; @ScaleCrop = v; end # Sets the LinksUpToDate property of your app.xml file - def LinksUpToDate=(v) Axlsx::validate_boolean v; @LinksUpToDate = v; end + def LinksUpToDate=(v) Axlsx::validate_boolean v; @LinksUpToDate = v; end # Sets the CharactersWithSpaces property of your app.xml file - def CharactersWithSpaces=(v) Axlsx::validate_int v; @CharactersWithSpaces = v; end + def CharactersWithSpaces=(v) Axlsx::validate_int v; @CharactersWithSpaces = v; end # Sets the ShareDoc property of your app.xml file - def ShareDoc=(v) Axlsx::validate_boolean v; @ShareDoc = v; end + def ShareDoc=(v) Axlsx::validate_boolean v; @ShareDoc = v; end # Sets the HyperLinkBase property of your app.xml file - def HyperLinkBase=(v) Axlsx::validate_string v; @HyperLinkBase = v; end + def HyperLinkBase=(v) Axlsx::validate_string v; @HyperLinkBase = v; end # Sets the HyperLinksChanged property of your app.xml file - def HyperlinksChanged=(v) Axlsx::validate_boolean v; @HyperlinksChanged = v; end + def HyperlinksChanged=(v) Axlsx::validate_boolean v; @HyperlinksChanged = v; end # Sets the Application property of your app.xml file - def Application=(v) Axlsx::validate_string v; @Application = v; end + def Application=(v) Axlsx::validate_string v; @Application = v; end # Sets the AppVersion property of your app.xml file - def AppVersion=(v) Axlsx::validate_string v; @AppVersion = v; end + def AppVersion=(v) Axlsx::validate_string v; @AppVersion = v; end # Sets the DocSecurity property of your app.xml file - def DocSecurity=(v) Axlsx::validate_int v; @DocSecurity = v; end - - # Generate an app.xml document - # @return [String] The document as a string - def to_xml() - builder = Nokogiri::XML::Builder.new(:encoding => ENCODING) do |xml| - xml.send(:Properties, :xmlns => APP_NS, :'xmlns:vt' => APP_NS_VT) { - self.instance_values.each do |name, value| - xml.send(name, value) - end - } - end - builder.to_xml(:save_with => 0) + def DocSecurity=(v) Axlsx::validate_int v; @DocSecurity = v; end + + # Serialize the app.xml document + # @return [String] + def to_xml_string(str = '') + str << '' + str << '' + str << instance_values.map { |key, value| '<' << key.to_s << '>' << value.to_s << '' }.join + str << '' end + end end diff --git a/lib/axlsx/doc_props/core.rb b/lib/axlsx/doc_props/core.rb index 96716a6b..7d9ba291 100644 --- a/lib/axlsx/doc_props/core.rb +++ b/lib/axlsx/doc_props/core.rb @@ -7,29 +7,23 @@ module Axlsx # The author of the document. By default this is 'axlsx' # @return [String] attr_accessor :creator - + # Creates a new Core object. # @option options [String] creator def initialize(options={}) - @creator = options[:creator] || 'axlsx' + @creator = options[:creator] || 'axlsx' end - # Serializes the core object. The created dcterms item is set to the current time when this method is called. + # serializes the core.xml document # @return [String] - def to_xml() - builder = Nokogiri::XML::Builder.new(:encoding => ENCODING) do |xml| - xml.send('cp:coreProperties', - :"xmlns:cp" => CORE_NS, - :'xmlns:dc' => CORE_NS_DC, - :'xmlns:dcmitype'=>CORE_NS_DCMIT, - :'xmlns:dcterms'=>CORE_NS_DCT, - :'xmlns:xsi'=>CORE_NS_XSI) { - xml['dc'].creator self.creator - xml['dcterms'].created Time.now.strftime('%Y-%m-%dT%H:%M:%S'), :'xsi:type'=>"dcterms:W3CDTF" - xml['cp'].revision 0 - } - end - builder.to_xml(:save_with => 0) + def to_xml_string(str = '') + str << '' + str << '' + str << '' << self.creator << '' + str << '' << Time.now.strftime('%Y-%m-%dT%H:%M:%S') << '' + str << '0' end end end diff --git a/lib/axlsx/drawing/axis.rb b/lib/axlsx/drawing/axis.rb index 183cbcad..8fbc3612 100644 --- a/lib/axlsx/drawing/axis.rb +++ b/lib/axlsx/drawing/axis.rb @@ -83,6 +83,29 @@ module Axlsx # must be one of [:autoZero, :min, :max] def crosses=(v) RestrictionValidator.validate "#{self.class}.crosses", [:autoZero, :min, :max], v; @crosses = v; end + + def to_xml_string(str = '') + str << '' + @scaling.to_xml_string str + str << '' + str << '' + str << '' + if self.gridlines == false + str << '' + str << '' + str << '' + str << '' + str << '' + end + str << '' + str << '' + str << '' + str << '' + str << '' + str << '' + str << '' + end + # Serializes the common axis # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. # @return [String] diff --git a/lib/axlsx/drawing/bar_3D_chart.rb b/lib/axlsx/drawing/bar_3D_chart.rb index de179cb6..dbed026a 100644 --- a/lib/axlsx/drawing/bar_3D_chart.rb +++ b/lib/axlsx/drawing/bar_3D_chart.rb @@ -41,7 +41,7 @@ module Axlsx # validation regex for gap amount percent GAP_AMOUNT_PERCENT = /0*(([0-9])|([1-9][0-9])|([1-4][0-9][0-9])|500)%/ - + # Creates a new bar chart object # @param [GraphicFrame] frame The workbook that owns this chart. # @option options [Cell, String] title @@ -67,14 +67,14 @@ module Axlsx @valAxId = rand(8 ** 8) @catAxis = CatAxis.new(@catAxId, @valAxId) @valAxis = ValAxis.new(@valAxId, @catAxId, :tickLblPos => :low) - super(frame, options) + super(frame, options) @series_type = BarSeries @view3D = View3D.new({:rAngAx=>1}.merge(options)) end # The direction of the bars in the chart # must be one of [:bar, :col] - def barDir=(v) + def barDir=(v) RestrictionValidator.validate "Bar3DChart.barDir", [:bar, :col], v @barDir = v end @@ -100,11 +100,37 @@ module Axlsx # The shabe of the bars or columns # must be one of [:cone, :coneToMax, :box, :cylinder, :pyramid, :pyramidToMax] - def shape=(v) + def shape=(v) RestrictionValidator.validate "Bar3DChart.shape", [:cone, :coneToMax, :box, :cylinder, :pyramid, :pyramidToMax], v @shape = v end - + + def to_xml_string(str = '') + super do |str| + str << '' + str << '' + str << '' + str << '' + @series.each { |ser| ser.to_xml_str(str) } + str << '' + str << '' + str << '' + str << '' + str << '' + str << '' + str << '' + str << '' + str << '' unless @gapWidth.nil? + str << '' unless @gapDepth.nil? + str << '' + str << '' + str << '' + str << '' + str << '' + @catAxis.to_xml_str str + @valAxis.to_xml_str str + end + end # Serializes the bar chart # @return [String] def to_xml @@ -120,7 +146,7 @@ module Axlsx xml.showCatName :val=>0 xml.showSerName :val=>0 xml.showPercent :val=>0 - xml.showBubbleSize :val=>0 + xml.showBubbleSize :val=>0 } xml.gapWidth :val=>@gapWidth unless @gapWidth.nil? xml.gapDepth :val=>@gapDepth unless @gapDepth.nil? @@ -130,8 +156,8 @@ module Axlsx xml.axId :val=>0 } @catAxis.to_xml(xml) - @valAxis.to_xml(xml) + @valAxis.to_xml(xml) end - end - end + end + end end diff --git a/lib/axlsx/drawing/bar_series.rb b/lib/axlsx/drawing/bar_series.rb index 5be8fabc..3a3ea6fa 100644 --- a/lib/axlsx/drawing/bar_series.rb +++ b/lib/axlsx/drawing/bar_series.rb @@ -6,8 +6,8 @@ module Axlsx # @see Chart#add_series class BarSeries < Series - - # The data for this series. + + # The data for this series. # @return [Array, SimpleTypedList] attr_reader :data @@ -31,15 +31,23 @@ module Axlsx super(chart, options) self.labels = CatAxisData.new(options[:labels]) unless options[:labels].nil? self.data = ValAxisData.new(options[:data]) unless options[:data].nil? - end + end # The shabe of the bars or columns # must be one of [:percentStacked, :clustered, :standard, :stacked] - def shape=(v) + def shape=(v) RestrictionValidator.validate "BarSeries.shape", [:cone, :coneToMax, :box, :cylinder, :pyramid, :pyramidToMax], v @shape = v end + def to_xml_string(str = '') + super(str) do + @labels.to_xml_string(str) unless @labels.nil? + @data.to_xml_string(str) unless @data.nil? + str << '' + end + end + # Serializes the series # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. # @return [String] @@ -48,11 +56,11 @@ module Axlsx @labels.to_xml(xml_inner) unless @labels.nil? @data.to_xml(xml_inner) unless @data.nil? xml_inner.shape :val=>@shape - end + end end - - private + + private # assigns the data for this series def data=(v) DataTypeValidator.validate "Series.data", [SimpleTypedList], v; @data = v; end diff --git a/lib/axlsx/drawing/cat_axis.rb b/lib/axlsx/drawing/cat_axis.rb index ee408c56..242ae698 100644 --- a/lib/axlsx/drawing/cat_axis.rb +++ b/lib/axlsx/drawing/cat_axis.rb @@ -10,7 +10,7 @@ module Axlsx # specifies how the perpendicular axis is crossed # must be one of [:ctr, :l, :r] # @return [Symbol] - attr_reader :lblAlgn + attr_reader :lblAlgn # The offset of the labels # must be between a string between 0 and 1000 @@ -20,7 +20,7 @@ module Axlsx # regex for validating label offset LBL_OFFSET_REGEX = /0*(([0-9])|([1-9][0-9])|([1-9][0-9][0-9])|1000)%/ - # Creates a new CatAxis object + # Creates a new CatAxis object # @param [Integer] axId the id of this axis. Inherited # @param [Integer] crossAx the id of the perpendicular axis. Inherited # @option options [Symbol] axPos. Inherited @@ -28,13 +28,13 @@ module Axlsx # @option options [Symbol] crosses. Inherited # @option options [Boolean] auto # @option options [Symbol] lblAlgn - # @option options [Integer] lblOffset + # @option options [Integer] lblOffset def initialize(axId, crossAx, options={}) self.auto = 1 self.lblAlgn = :ctr self.lblOffset = "100%" super(axId, crossAx, options) - end + end # From the docs: This element specifies that this axis is a date or text axis based on the data that is used for the axis labels, not a specific choice. def auto=(v) Axlsx::validate_boolean(v); @auto = v; end @@ -47,6 +47,14 @@ module Axlsx # must be between a string between 0 and 1000 def lblOffset=(v) RegexValidator.validate "#{self.class}.lblOffset", LBL_OFFSET_REGEX, v; @lblOffset = v; end + + def to_xml_string(str = '') + str << '' + super(str) + str << '' + each_with_index do |item, index| + v = item.is_a?(Cell) ? item.value.to_s : item + str << '' << v << '' + end + str << '' + str << '' + str << '' + end + # Serializes the category axis data # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. # @return [String] @@ -24,7 +40,7 @@ module Axlsx v = item.is_a?(Cell) ? item.value : item xml.pt(:idx=>index) { xml.v v - } + } end } } @@ -32,5 +48,5 @@ module Axlsx end end - + end diff --git a/lib/axlsx/drawing/chart.rb b/lib/axlsx/drawing/chart.rb index b612fbed..a0bc75ba 100644 --- a/lib/axlsx/drawing/chart.rb +++ b/lib/axlsx/drawing/chart.rb @@ -113,6 +113,37 @@ module Axlsx @series.last end + + def to_xml_string + str << '' + str << '' + str << '' + str << '' + str << '' + @title.to_xml_string str + # do these need the c: namespace as well??? + str << '' + @view3D.to_xml_string(str) if @view3D + str << '' + str << '' + str << '' + str << '' + str << '' + yield str if block_given? + str << '' + if @show_legend + str << '' + str << '' + str << '' + str << '' + str << '' + end + str << '' + str << '' + str << '' + str << '' + str << '' + end # Chart Serialization # serializes the chart def to_xml @@ -133,7 +164,7 @@ module Axlsx yield xml if block_given? } if @show_legend - xml.legend { + xml.legend { xml.legendPos :val => "r" xml.layout xml.overlay :val => 0 diff --git a/lib/axlsx/drawing/drawing.rb b/lib/axlsx/drawing/drawing.rb index 93068a23..08b8531a 100644 --- a/lib/axlsx/drawing/drawing.rb +++ b/lib/axlsx/drawing/drawing.rb @@ -4,8 +4,8 @@ module Axlsx require 'axlsx/drawing/series_title.rb' require 'axlsx/drawing/series.rb' require 'axlsx/drawing/pie_series.rb' - require 'axlsx/drawing/bar_series.rb' - require 'axlsx/drawing/line_series.rb' + require 'axlsx/drawing/bar_series.rb' + require 'axlsx/drawing/line_series.rb' require 'axlsx/drawing/scatter_series.rb' require 'axlsx/drawing/scaling.rb' @@ -19,7 +19,7 @@ module Axlsx require 'axlsx/drawing/named_axis_data.rb' require 'axlsx/drawing/marker.rb' - + require 'axlsx/drawing/one_cell_anchor.rb' require 'axlsx/drawing/two_cell_anchor.rb' require 'axlsx/drawing/graphic_frame.rb' @@ -46,7 +46,7 @@ module Axlsx # The worksheet that owns the drawing # @return [Worksheet] attr_reader :worksheet - + # A collection of anchors for this drawing # only TwoCellAnchors are supported in this version # @return [SimpleTypedList] @@ -138,13 +138,20 @@ module Axlsx r end + def to_xml_string(str = '') + str << '' + str << '' + anchors.each { |anchor| anchor.to_xml_string(str) } + str << '' + end + # Serializes the drawing # @return [String] def to_xml builder = Nokogiri::XML::Builder.new(:encoding => ENCODING) do |xml| xml.send('xdr:wsDr', :'xmlns:xdr'=>XML_NS_XDR, :'xmlns:a'=>XML_NS_A, :'xmlns:c'=>XML_NS_C) { anchors.each {|anchor| anchor.to_xml(xml) } - } + } end builder.to_xml(:save_with => 0) end diff --git a/lib/axlsx/drawing/graphic_frame.rb b/lib/axlsx/drawing/graphic_frame.rb index 178e0ea8..7502dfba 100644 --- a/lib/axlsx/drawing/graphic_frame.rb +++ b/lib/axlsx/drawing/graphic_frame.rb @@ -28,6 +28,24 @@ module Axlsx "rId#{@anchor.index+1}" end + def to_xml_string(str = '') + str << '' + str << '' + str << '' + str << '' + str << '' + str << '' + str << '' + str << '' + str << '' + str << '' + str << '' + str << '' + str << '' + str << '' + str << '' + end + # Serializes the graphic frame # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. # @return [String] diff --git a/lib/axlsx/drawing/hyperlink.rb b/lib/axlsx/drawing/hyperlink.rb index 67b08f29..9cfdf705 100644 --- a/lib/axlsx/drawing/hyperlink.rb +++ b/lib/axlsx/drawing/hyperlink.rb @@ -31,12 +31,12 @@ module Axlsx # indicates that the link has already been clicked. # @return [Boolean] attr_reader :highlightClick - + # @see highlightClick # @param [Boolean] v The value to assign def highlightClick=(v) Axlsx::validate_boolean(v); @highlightClick = v end - # From the specs: Specifies whether to add this URI to the history when navigating to it. This allows for the viewing of this presentation without the storing of history information on the viewing machine. If this attribute is omitted, then a value of 1 or true is assumed. + # From the specs: Specifies whether to add this URI to the history when navigating to it. This allows for the viewing of this presentation without the storing of history information on the viewing machine. If this attribute is omitted, then a value of 1 or true is assumed. # @return [Boolean] attr_reader :history @@ -52,12 +52,12 @@ module Axlsx # @return [String] attr_accessor :tooltip - #Creates a hyperlink object + #Creates a hyperlink object # parent must be a Pic for now, although I expect that other object support this tag and its cNvPr parent # @param [Pic] parent # @option options [String] tooltip message shown when hyperlinked object is hovered over with mouse. # @option options [String] tgtFrame Target frame for opening hyperlink - # @option options [String] invalidUrl supposedly use to store the href when we know it is an invalid resource. + # @option options [String] invalidUrl supposedly use to store the href when we know it is an invalid resource. # @option options [String] href the target resource this hyperlink links to. # @option options [String] action A string that can be used to perform specific actions. For excel please see this reference: http://msdn.microsoft.com/en-us/library/ff532419%28v=office.12%29.aspx # @option options [Boolean] endSnd terminate any sound events when processing this link @@ -70,14 +70,22 @@ module Axlsx self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}=" end yield self if block_given? - + end + def to_xml_string(str = '') + h = self.instance_values.merge({:'r:id' => "rId#{id}", :'xmlns:r' => XML_NS_R }) + h.delete('href') + h.delete('parent') + str << '' + end # Serializes the hyperlink # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. # @return [String] - def to_xml(xml) + def to_xml(xml) h = self.instance_values.merge({:'r:id' => "rId#{id}", :'xmlns:r' => XML_NS_R }) h.delete('href') h.delete('parent') @@ -85,7 +93,7 @@ module Axlsx end private - # The relational ID for this hyperlink + # The relational ID for this hyperlink # @return [Integer] def id @parent.anchor.drawing.charts.size + @parent.anchor.drawing.images.size + @parent.anchor.drawing.hyperlinks.index(self) + 1 diff --git a/lib/axlsx/drawing/line_3D_chart.rb b/lib/axlsx/drawing/line_3D_chart.rb index 13e42dff..bd587d1b 100644 --- a/lib/axlsx/drawing/line_3D_chart.rb +++ b/lib/axlsx/drawing/line_3D_chart.rb @@ -44,11 +44,11 @@ module Axlsx # validation regex for gap amount percent GAP_AMOUNT_PERCENT = /0*(([0-9])|([1-9][0-9])|([1-4][0-9][0-9])|500)%/ - + # Creates a new line chart object # @param [GraphicFrame] frame The workbook that owns this chart. # @option options [Cell, String] title - # @option options [Boolean] show_legend + # @option options [Boolean] show_legend # @option options [Symbol] grouping # @option options [String] gapDepth # @option options [Integer] rotX @@ -68,7 +68,7 @@ module Axlsx @catAxis = CatAxis.new(@catAxId, @valAxId) @valAxis = ValAxis.new(@valAxId, @catAxId) @serAxis = SerAxis.new(@serAxId, @valAxId) - super(frame, options) + super(frame, options) @series_type = LineSeries @view3D = View3D.new({:perspective=>30}.merge(options)) end @@ -85,6 +85,31 @@ module Axlsx @gapDepth=(v) end + def to_xml_string(str = '') + super do |str| + str << '' + str << '' + str << '' + @series.each { |ser| ser.to_xml_str(str) } + str << '' + str << '' + str << '' + str << '' + str << '' + str << '' + str << '' + str << '' + str << '' unless @gapDepth.nil? + str << '' + str << '' + str << '' + str << '' + @catAxis.to_xml_str str + @valAxis.to_xml_str str + @serAxis.to_xml_str str + end + end + # Serializes the bar chart # @return [String] def to_xml @@ -99,7 +124,7 @@ module Axlsx xml.showCatName :val=>0 xml.showSerName :val=>0 xml.showPercent :val=>0 - xml.showBubbleSize :val=>0 + xml.showBubbleSize :val=>0 } xml.gapDepth :val=>@gapDepth unless @gapDepth.nil? xml.axId :val=>@catAxId @@ -110,6 +135,6 @@ module Axlsx @valAxis.to_xml(xml) @serAxis.to_xml(xml) end - end - end + end + end end diff --git a/lib/axlsx/drawing/line_series.rb b/lib/axlsx/drawing/line_series.rb index a7de888f..c5908f64 100644 --- a/lib/axlsx/drawing/line_series.rb +++ b/lib/axlsx/drawing/line_series.rb @@ -5,8 +5,8 @@ module Axlsx # @see Worksheet#add_chart # @see Chart#add_series class LineSeries < Series - - # The data for this series. + + # The data for this series. # @return [ValAxisData] attr_reader :data @@ -23,7 +23,14 @@ module Axlsx super(chart, options) @labels = CatAxisData.new(options[:labels]) unless options[:labels].nil? @data = ValAxisData.new(options[:data]) unless options[:data].nil? - end + end + + def to_xml_string(str = '') + super(str) do + @labels.to_xml_string(str) unless @labels.nil? + @data.to_xml_string(str) unless @data.nil? + end + end # Serializes the series # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. @@ -32,10 +39,10 @@ module Axlsx super(xml) do |xml_inner| @labels.to_xml(xml_inner) unless @labels.nil? @data.to_xml(xml_inner) unless @data.nil? - end + end end - private + private # assigns the data for this series def data=(v) DataTypeValidator.validate "Series.data", [SimpleTypedList], v; @data = v; end diff --git a/lib/axlsx/drawing/marker.rb b/lib/axlsx/drawing/marker.rb index dac8604e..a2ce4312 100644 --- a/lib/axlsx/drawing/marker.rb +++ b/lib/axlsx/drawing/marker.rb @@ -30,9 +30,9 @@ module Axlsx @col, @colOff, @row, @rowOff = 0, 0, 0, 0 options.each do |o| self.send("#{o[0]}=", o[1]) if self.respond_to? o[0] - end + end end - + # @see col def col=(v) Axlsx::validate_unsigned_int v; @col = v end # @see colOff @@ -41,7 +41,7 @@ module Axlsx def row=(v) Axlsx::validate_unsigned_int v; @row = v end # @see rowOff def rowOff=(v) Axlsx::validate_int v; @rowOff = v end - + # shortcut to set the column, row position for this marker # @param col the column for the marker # @param row the row of the marker @@ -49,13 +49,20 @@ module Axlsx self.col = col self.row = row end + + def to_xml_string(str = '') + [:col, :colOff, :row, :rowOff].each do |k| + str << '<' << k.to_s << '>' << self.send(k).to_s << '' + end + end + # Serializes the marker # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. # @return [String] def to_xml(xml) [:col, :colOff, :row, :rowOff].each do |k| xml.send(k.to_sym, self.send(k)) - end + end end end diff --git a/lib/axlsx/drawing/named_axis_data.rb b/lib/axlsx/drawing/named_axis_data.rb index b249196f..2ec58e8b 100644 --- a/lib/axlsx/drawing/named_axis_data.rb +++ b/lib/axlsx/drawing/named_axis_data.rb @@ -8,6 +8,23 @@ module Axlsx @name = name end + + def to_xml_string(str = '') + str << '<' << @name << '>' + str << '' + str << '' << Axlsx::cell_range(@list) << '' + str << '' + str << 'General' + str << '' + each_with_index do |item, index| + v = item.is_a?(Cell) ? item.value.to_s : item + str << '' << v << '' + end + str << '' + str << '' + str << '' + end + # Serializes the value axis data # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. # @return [String] diff --git a/lib/axlsx/drawing/one_cell_anchor.rb b/lib/axlsx/drawing/one_cell_anchor.rb index 2cd43331..e0574172 100644 --- a/lib/axlsx/drawing/one_cell_anchor.rb +++ b/lib/axlsx/drawing/one_cell_anchor.rb @@ -33,15 +33,15 @@ module Axlsx # @param [Drawing] drawing # @option options [Array] start_at the col, row to start at # @option options [Integer] width - # @option options [Integer] height + # @option options [Integer] height # @option options [String] image_src the file location of the image you will render # @option options [String] name the name attribute for the rendered image - # @option options [String] descr the description of the image rendered + # @option options [String] descr the description of the image rendered def initialize(drawing, options={}) @drawing = drawing @width = 0 @height = 0 - drawing.anchors << self + drawing.anchors << self @from = Marker.new options.each do |o| self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}=" @@ -61,6 +61,18 @@ module Axlsx @drawing.anchors.index(self) end + + def to_xml_string(str = '') + str << '' + str << '' + from.to_xml_string(str) + str << '' + str << '' << ext.to_s << '' + @object.to_xml_string(str) + str << '' + str << '' + end + # Serializes the anchor # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. # @return [String] @@ -73,11 +85,11 @@ module Axlsx @object.to_xml(xml) xml.clientData } - end + end private - # converts the pixel width and height to EMU units and returns a hash of + # converts the pixel width and height to EMU units and returns a hash of # !{:cx=>[Integer], :cy=>[Integer] # @return [Hash] def ext diff --git a/lib/axlsx/drawing/pic.rb b/lib/axlsx/drawing/pic.rb index 754a7e35..1783005a 100644 --- a/lib/axlsx/drawing/pic.rb +++ b/lib/axlsx/drawing/pic.rb @@ -28,7 +28,7 @@ module Axlsx # The picture locking attributes for this picture attr_reader :picture_locking - + # Creates a new Pic(ture) object # @param [Anchor] anchor the anchor that holds this image # @option options [String] name @@ -50,7 +50,7 @@ module Axlsx end attr_reader :hyperlink - + # sets or updates a hyperlink for this image. # @param [String] v The href value for the hyper link # @option options @see Hyperlink#initialize All options available to the Hyperlink class apply - however href will be overridden with the v parameter value. @@ -66,7 +66,7 @@ module Axlsx @hyperlink end - def image_src=(v) + def image_src=(v) Axlsx::validate_string(v) RestrictionValidator.validate 'Pic.image_src', ALLOWED_EXTENSIONS, File.extname(v).delete('.') raise ArgumentError, "File does not exist" unless File.exist?(v) @@ -84,8 +84,8 @@ module Axlsx # @return [String] def file_name File.basename(image_src) unless image_src.nil? - end - + end + # returns the extension of image_src without the preceeding '.' # @return [String] def extname @@ -93,7 +93,7 @@ module Axlsx end # The index of this image in the workbooks images collections - # @return [Index] + # @return [Index] def index @anchor.drawing.worksheet.workbook.images.index(self) end @@ -120,7 +120,7 @@ module Axlsx def width=(v) @anchor.width = v end - + # providing access to update the anchor's height attribute # @param [Integer] v # @see OneCellAnchor.width @@ -144,6 +144,10 @@ module Axlsx @anchor.from.row = y end + def to_xml_string(str = '') + + end + # Serializes the picture # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. # @return [String] diff --git a/lib/axlsx/drawing/scaling.rb b/lib/axlsx/drawing/scaling.rb index 628aa016..c90d0377 100644 --- a/lib/axlsx/drawing/scaling.rb +++ b/lib/axlsx/drawing/scaling.rb @@ -33,7 +33,7 @@ module Axlsx self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}=" end end - + # @see logBase def logBase=(v) DataTypeValidator.validate "Scaling.logBase", [Integer, Fixnum], v, lambda { |arg| arg >= 2 && arg <= 1000}; @logBase = v; end # @see orientation @@ -44,6 +44,15 @@ module Axlsx # @see min def min=(v) DataTypeValidator.validate "Scaling.min", Float, v; @min = v; end + def to_xml_string(str = '') + str << '' + str << '' + str << '' + str << '' + str << '' + str << '' + end + # Serializes the axId # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. # @return [String] diff --git a/lib/axlsx/drawing/ser_axis.rb b/lib/axlsx/drawing/ser_axis.rb index 6fc5fec0..54dde640 100644 --- a/lib/axlsx/drawing/ser_axis.rb +++ b/lib/axlsx/drawing/ser_axis.rb @@ -22,7 +22,7 @@ module Axlsx def initialize(axId, crossAx, options={}) @tickLblSkip, @tickMarkSkip = nil, nil super(axId, crossAx, options) - end + end # @see tickLblSkip def tickLblSkip=(v) Axlsx::validate_unsigned_int(v); @tickLblSkip = v; end @@ -30,6 +30,13 @@ module Axlsx # @see tickMarkSkip def tickMarkSkip=(v) Axlsx::validate_unsigned_int(v); @tickMarkSkip = v; end + def to_xml_string(str = '') + str << '' + super(str) + str << '' unless @tickLblSkip.nil? + str << '' unless @tickMarkSkip.nil? + str << '' + end # Serializes the series axis # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. # @return [String] @@ -41,6 +48,6 @@ module Axlsx } end end - + end diff --git a/lib/axlsx/drawing/series.rb b/lib/axlsx/drawing/series.rb index 1544bc48..5960f508 100644 --- a/lib/axlsx/drawing/series.rb +++ b/lib/axlsx/drawing/series.rb @@ -25,7 +25,7 @@ module Axlsx options.each do |o| self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}=" end - end + end # The index of this series in the chart's series. # @return [Integer] @@ -44,16 +44,25 @@ module Axlsx def order=(v) Axlsx::validate_unsigned_int(v); @order = v; end # @see title - def title=(v) + def title=(v) v = SeriesTitle.new(v) if v.is_a?(String) || v.is_a?(Cell) DataTypeValidator.validate "#{self.class}.title", SeriesTitle, v @title = v end - - private - + + private + # assigns the chart for this series - def chart=(v) DataTypeValidator.validate "Series.chart", Chart, v; @chart = v; end + def chart=(v) DataTypeValidator.validate "Series.chart", Chart, v; @chart = v; end + + def to_xml_string(str = '') + str << '' + str << '' + str << '' + title.to_xml_string(str) unless title.nil? + yeild str if block_given? + str << '' + end # Serializes the series # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. diff --git a/lib/axlsx/drawing/title.rb b/lib/axlsx/drawing/title.rb index cc382205..a7b8e715 100644 --- a/lib/axlsx/drawing/title.rb +++ b/lib/axlsx/drawing/title.rb @@ -2,7 +2,7 @@ module Axlsx # A Title stores information about the title of a chart class Title - + # The text to be shown. Setting this property directly with a string will remove the cell reference. # @return [String] attr_reader :text @@ -17,9 +17,9 @@ module Axlsx self.cell = title if title.is_a?(Cell) self.text = title.to_s unless title.is_a?(Cell) end - + # @see text - def text=(v) + def text=(v) DataTypeValidator.validate 'Title.text', String, v @text = v @cell = nil @@ -30,7 +30,7 @@ module Axlsx def cell=(v) DataTypeValidator.validate 'Title.text', Cell, v @cell = v - @text = v.value.to_s + @text = v.value.to_s v end @@ -38,7 +38,25 @@ module Axlsx #def layout=(v) DataTypeValidator.validate 'Title.layout', Layout, v; @layout = v; end #def overlay=(v) Axlsx::validate_boolean v; @overlay=v; end #def spPr=(v) DataTypeValidator.validate 'Title.spPr', SpPr, v; @spPr = v; end - + + def to_xml_string(str = '') + str << '' + unless @text.empty? + str << '' + str << '' + str << '' << Axlsx::cell_range([@cell]) << '' + str << '' + str << '' + str << '' + str << '' << @text << '' + str << '' + str << '' + str << '' + str << '' + end + str << '' + end + # Serializes the chart title # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. # @return [String] @@ -59,8 +77,8 @@ module Axlsx end xml[:c].layout xml[:c].overlay :val=>0 - } + } end - + end end diff --git a/lib/axlsx/drawing/val_axis.rb b/lib/axlsx/drawing/val_axis.rb index c7091d49..51adc31a 100644 --- a/lib/axlsx/drawing/val_axis.rb +++ b/lib/axlsx/drawing/val_axis.rb @@ -22,6 +22,13 @@ module Axlsx # @see crossBetween def crossBetween=(v) RestrictionValidator.validate "ValAxis.crossBetween", [:between, :midCat], v; @crossBetween = v; end + def to_xml_string(str = '') + str << '' + super(str) + str << '' + str << '' + end + # Serializes the value axis # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. # @return [String] diff --git a/lib/axlsx/drawing/val_axis_data.rb b/lib/axlsx/drawing/val_axis_data.rb index 6b950443..b974b5d1 100644 --- a/lib/axlsx/drawing/val_axis_data.rb +++ b/lib/axlsx/drawing/val_axis_data.rb @@ -3,6 +3,22 @@ module Axlsx # The ValAxisData class manages the values for a chart value series. class ValAxisData < CatAxisData + def to_xml_string(str = '') + str << '' + str << '' + str << '' << Axlsx::cell_range(@list) << '' + str << '' + str << 'General' + str << '' + each_with_index do |item, index| + v = item.is_a?(Cell) ? item.value.to_s : item + str << '' << v << '' + end + str << '' + str << '' + str << '' + end + # Serializes the value axis data # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. # @return [String] @@ -17,11 +33,11 @@ module Axlsx v = item.is_a?(Cell) ? item.value : item xml.pt(:idx=>index) { xml.v v } end - } + } } } end end - + end diff --git a/lib/axlsx/drawing/view_3D.rb b/lib/axlsx/drawing/view_3D.rb index d8a569b1..ee2739b4 100644 --- a/lib/axlsx/drawing/view_3D.rb +++ b/lib/axlsx/drawing/view_3D.rb @@ -5,34 +5,34 @@ module Axlsx # Validation for hPercent H_PERCENT_REGEX = /0*(([5-9])|([1-9][0-9])|([1-4][0-9][0-9])|500)%/ - + # validation for depthPercent DEPTH_PERCENT_REGEX = /0*(([2-9][0-9])|([1-9][0-9][0-9])|(1[0-9][0-9][0-9])|2000)%/ - # x rotation for the chart + # x rotation for the chart # must be between -90 and 90 # @return [Integer] attr_reader :rotX - + # height of chart as % of chart # must be between 5% and 500% # @return [String] attr_reader :hPercent - + # y rotation for the chart # must be between 0 and 360 # @return [Integer] attr_reader :rotY - + # depth or chart as % of chart width # must be between 20% and 2000% # @return [String] attr_reader :depthPercent - + # Chart axis are at right angles # @return [Boolean] attr_reader :rAngAx - + # field of view angle # @return [Integer] attr_reader :perspective @@ -45,10 +45,10 @@ module Axlsx # @option options [Boolean] rAngAx # @option options [Integer] perspective def initialize(options={}) - @rotX, @hPercent, @rotY, @depthPercent, @rAngAx, @perspective = nil, nil, nil, nil, nil, nil + @rotX, @hPercent, @rotY, @depthPercent, @rAngAx, @perspective = nil, nil, nil, nil, nil, nil options.each do |o| self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}=" - end + end end # @see rotX @@ -69,6 +69,18 @@ module Axlsx # @see perspective def perspective=(v) DataTypeValidator.validate "#{self.class}.perspective", [Integer, Fixnum], v, lambda {|arg| arg >= 0 && arg <= 240 }; @perspective = v; end + + def to_xml_string(str = '') + str << '' + str << '' unless @rotX.nil? + str << '' unless @hPercent.nil? + str << '' unless @rotY.nil? + str << '' unless @depthPercent.nil? + str << '' unless @rAngAx.nil? + str << '' unless @perspective.nil? + str << '' + end + # Serializes the view3D properties # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. # @return [String] diff --git a/lib/axlsx/package.rb b/lib/axlsx/package.rb index 35ab181a..9bab4269 100644 --- a/lib/axlsx/package.rb +++ b/lib/axlsx/package.rb @@ -170,21 +170,21 @@ module Axlsx # @private def parts @parts = [ - {:entry => RELS_PN, :doc => relationships.to_xml, :schema => RELS_XSD}, + {:entry => RELS_PN, :doc => relationships.to_xml_string, :schema => RELS_XSD}, {:entry => "xl/#{STYLES_PN}", :doc => workbook.styles.to_xml, :schema => SML_XSD}, - {:entry => CORE_PN, :doc => @core.to_xml, :schema => CORE_XSD}, - {:entry => APP_PN, :doc => @app.to_xml, :schema => APP_XSD}, - {:entry => WORKBOOK_RELS_PN, :doc => workbook.relationships.to_xml, :schema => RELS_XSD}, - {:entry => CONTENT_TYPES_PN, :doc => content_types.to_xml, :schema => CONTENT_TYPES_XSD}, - {:entry => WORKBOOK_PN, :doc => workbook.to_xml, :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} ] workbook.drawings.each do |drawing| - @parts << {:entry => "xl/#{drawing.rels_pn}", :doc => drawing.relationships.to_xml, :schema => RELS_XSD} + @parts << {:entry => "xl/#{drawing.rels_pn}", :doc => drawing.relationships.to_xml_string, :schema => RELS_XSD} @parts << {:entry => "xl/#{drawing.pn}", :doc => drawing.to_xml, :schema => DRAWING_XSD} end workbook.tables.each do |table| - @parts << {:entry => "xl/#{table.pn}", :doc => table.to_xml, :schema => SML_XSD} + @parts << {:entry => "xl/#{table.pn}", :doc => table.to_xml_string, :schema => SML_XSD} end workbook.charts.each do |chart| @@ -200,7 +200,7 @@ module Axlsx end workbook.worksheets.each do |sheet| - @parts << {:entry => "xl/#{sheet.rels_pn}", :doc => sheet.relationships.to_xml, :schema => RELS_XSD} + @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} end @parts diff --git a/lib/axlsx/rels/relationship.rb b/lib/axlsx/rels/relationship.rb index 3596d808..4321c7e1 100644 --- a/lib/axlsx/rels/relationship.rb +++ b/lib/axlsx/rels/relationship.rb @@ -47,14 +47,17 @@ module Axlsx # @see TargetMode def TargetMode=(v) RestrictionValidator.validate 'Relationship.TargetMode', [:External, :Internal], v; @TargetMode = v; end - # Serializes the relationship - # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. - # @param [String] rId the reference id of the object. + # serialize relationship + # @param [String] str + # @param [Integer] rId the id for this relationship # @return [String] - def to_xml(xml, rId) + def to_xml_string(str = '', rId) h = self.instance_values - h[:Id] = rId - xml.Relationship(h) + h[:Id] = 'rId' << rId.to_s + str << '' end + end end diff --git a/lib/axlsx/rels/relationships.rb b/lib/axlsx/rels/relationships.rb index 8516bc69..06bd4934 100644 --- a/lib/axlsx/rels/relationships.rb +++ b/lib/axlsx/rels/relationships.rb @@ -11,6 +11,12 @@ require 'axlsx/rels/relationship.rb' super Relationship end + def to_xml_string(str = '') + str << '' + str << '' + each_with_index { |rel, index| rel.to_xml_string(str, index+1) } + str << '' + end # Serializes the relationships document. # @return [String] def to_xml() @@ -21,6 +27,6 @@ require 'axlsx/rels/relationship.rb' end builder.to_xml(:save_with => 0) end - + end end diff --git a/lib/axlsx/workbook/shared_strings_table.rb b/lib/axlsx/workbook/shared_strings_table.rb index 0bdd7936..dac8221f 100644 --- a/lib/axlsx/workbook/shared_strings_table.rb +++ b/lib/axlsx/workbook/shared_strings_table.rb @@ -37,7 +37,7 @@ module Axlsx end def to_xml_string - '' << @shared_xml_string << '' + '' << @shared_xml_string << '' end # Generate the xml document for the Shared Strings Table diff --git a/lib/axlsx/workbook/workbook.rb b/lib/axlsx/workbook/workbook.rb index 43296611..ce4e161b 100644 --- a/lib/axlsx/workbook/workbook.rb +++ b/lib/axlsx/workbook/workbook.rb @@ -189,34 +189,29 @@ require 'axlsx/workbook/worksheet/table.rb' worksheet[cell_def.gsub(/.+!/,"")] end - # Serializes the workbook document + # Serialize the workbook + # @param [String] str # @return [String] - def to_xml() + def to_xml_string(str='') add_worksheet unless worksheets.size > 0 - builder = Nokogiri::XML::Builder.new(:encoding => ENCODING) do |xml| - xml.workbook(:xmlns => XML_NS, :'xmlns:r' => XML_NS_R) { - xml.workbookPr(:date1904=>@@date1904) - # - # Required to support rubyXL parsing as it requires sheetView, which requires this. - # and removed because it seems to cause some odd [Grouped] behaviour in excel. - # xml.bookViews { - # xml.workbookView :activeTab=>0 - # } - xml.sheets { - @worksheets.each_with_index do |sheet, index| - xml.sheet(:name=>sheet.name, :sheetId=>index+1, :"r:id"=>sheet.rId) - end - } - xml.definedNames { - @worksheets.each_with_index do |sheet, index| - if sheet.auto_filter - xml.definedName(sheet.abs_auto_filter, :name => '_xlnm._FilterDatabase', :localSheetId => index, :hidden => 1) - end - end - } - } + str << '' + str << '' + str << '' + str << '' + @worksheets.each_with_index do |sheet, index| + str << '' end - builder.to_xml(:save_with => 0) + str << '' + str << '' + @worksheets.each_with_index do |sheet, index| + if sheet.auto_filter + str << '' + end + end + str << '' + str << '' end + end end diff --git a/lib/axlsx/workbook/worksheet/cell.rb b/lib/axlsx/workbook/worksheet/cell.rb index bfb7f35f..015c4b91 100644 --- a/lib/axlsx/workbook/worksheet/cell.rb +++ b/lib/axlsx/workbook/worksheet/cell.rb @@ -1,4 +1,5 @@ # encoding: UTF-8 +require 'cgi' module Axlsx # A cell in a worksheet. # Cell stores inforamation requried to serialize a single worksheet cell to xml. You must provde the Row that the cell belongs to and the cells value. The data type will automatically be determed if you do not specify the :type option. The default style will be applied if you do not supply the :style option. Changing the cell's type will recast the value to the type specified. Altering the cell's value via the property accessor will also automatically cast the provided value to the cell's type. @@ -276,6 +277,9 @@ module Axlsx self.row.worksheet.merge_cells "#{self.r}:#{range_end}" unless range_end.nil? end + # builds an xml text run based on this cells attributes. + # @param [String] str The string instance this run will be concated to. + # @return [String] def run_xml_string(str = '') if is_text_run? data = self.instance_values.reject{|key, value| value == nil } @@ -298,40 +302,11 @@ module Axlsx end str end - # builds an xml text run based on this cells attributes. This is extracted from to_xml so that shared strings can use it. - # @param [Nokogiri::XML::Builder] xml The document builder instance this output will be added to. - # @return [String] the xml for this cell's text run - def run_xml(xml) - if (self.instance_values.keys & INLINE_STYLES).size > 0 - xml.r { - xml.rPr { - xml.rFont(:val=>@font_name) if @font_name - xml.charset(:val=>@charset) if @charset - xml.family(:val=>@family) if @family - xml.b(:val=>@b) if @b - xml.i(:val=>@i) if @i - xml.strike(:val=>@strike) if @strike - xml.outline(:val=>@outline) if @outline - xml.shadow(:val=>@shadow) if @shadow - xml.condense(:val=>@condense) if @condense - xml.extend(:val=>@extend) if @extend - @color.to_xml(xml) if @color - xml.sz(:val=>@sz) if @sz - xml.u(:val=>@u) if @u - # :baseline, :subscript, :superscript - xml.vertAlign(:val=>@vertAlign) if @vertAlign - # :none, major, :minor - xml.scheme(:val=>@scheme) if @scheme - } - xml.t @value.to_s - } - else - xml.t @value.to_s - end - end # Serializes the cell - # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. + # @param [Integer] r_index The row index for the cell + # @param [Integer] c_index The cell index in the row. + # @param [String] str The string index the cell content will be appended to. Defaults to empty string. # @return [String] xml text for the cell def to_xml_string(r_index, c_index, str = '') str << '' << ssti << '' + str << 't="s">' << @ssti.to_s << '' else str << 't="inlineStr">' << run_xml_string << '' end @@ -361,40 +336,6 @@ module Axlsx str << '' end - def to_xml(xml) - if @type == :string - #parse formula - if @value.start_with?('=') - xml.c(:r => r, :s=>style, :t=>:str) { - xml.f @value.to_s.gsub('=', '') - } - else - #parse shared - if @ssti - xml.c(:r => r, :s=>style, :t => :s) { xml.v ssti } - else - #parse inline string - xml.c(:r => r, :s=>style, :t => :inlineStr) { - xml.is { - run_xml(xml) - } - } - end - end - elsif @type == :date - # TODO: See if this is subject to the same restriction as Time below - v = DateTimeConverter::date_to_serial @value - xml.c(:r => r, :s => style) { xml.v v } - elsif @type == :time - v = DateTimeConverter::time_to_serial @value - xml.c(:r => r, :s => style) { xml.v v } - elsif @type == :boolean - xml.c(:r => r, :s => style, :t => :b) { xml.v value } - else - xml.c(:r => r, :s => style) { xml.v value } - end - end - private # Utility method for setting inline style attributes @@ -457,7 +398,7 @@ module Axlsx v ? 1 : 0 else @type = :string - v.to_s + ::CGI.escapeHTML(v.to_s) end end end diff --git a/lib/axlsx/workbook/worksheet/col.rb b/lib/axlsx/workbook/worksheet/col.rb index ccf4dfaf..7a34ad40 100644 --- a/lib/axlsx/workbook/worksheet/col.rb +++ b/lib/axlsx/workbook/worksheet/col.rb @@ -64,13 +64,13 @@ module Axlsx @outlineLevel = v end - # @see Col#phonetic - def phonetic=(v) + # @see Col#phonetic + def phonetic=(v) Axlsx.validate_boolean(v) @phonetic = v end - # @see Col#style + # @see Col#style def style=(v) Axlsx.validate_unsigned_int(v) @style = v @@ -103,10 +103,11 @@ module Axlsx end # Serialize this columns data to an xml string + # @param [String] str # @return [String] def to_xml_string(str = '') attrs = self.instance_values.reject{ |key, value| value == nil } - str << '' + str << '' end end diff --git a/lib/axlsx/workbook/worksheet/page_margins.rb b/lib/axlsx/workbook/worksheet/page_margins.rb index 1c456f2a..19402a6d 100644 --- a/lib/axlsx/workbook/worksheet/page_margins.rb +++ b/lib/axlsx/workbook/worksheet/page_margins.rb @@ -83,15 +83,15 @@ module Axlsx # @see footer def footer=(v); Axlsx::validate_unsigned_numeric(v); @footer = v end - def to_xml_string - "" % [left, right, top, bottom, header, footer] - end # Serializes the page margins element # @note For compatibility, this is a noop unless custom margins have been specified. - # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. # @see #custom_margins_specified? - def to_xml(xml) - xml.pageMargins :left => left, :right => right, :top => top, :bottom => bottom, :header => header, :footer => footer + # @param [String] str + # @retrun [String] + def to_xml_string(str = '') + str << '' end end end diff --git a/lib/axlsx/workbook/worksheet/row.rb b/lib/axlsx/workbook/worksheet/row.rb index 58171fea..4e5150da 100644 --- a/lib/axlsx/workbook/worksheet/row.rb +++ b/lib/axlsx/workbook/worksheet/row.rb @@ -59,6 +59,10 @@ module Axlsx worksheet.rows.index(self) end + # Serializes the row + # @param [Integer] r_index The row index, 0 based. + # @param [String] str The string this rows xml will be appended to. + # @return [String] def to_xml_string(r_index, str = '') str << '' str end - # Serializes the row - # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. - # @return [String] - def to_xml(xml) - attrs = {:r => index+1} - attrs.merge!(:customHeight => 1, :ht => height) if custom_height? - xml.row(attrs) { |ixml| @cells.each { |cell| cell.to_xml(ixml) } } - end # Adds a singel sell to the row based on the data provided and updates the worksheet's autofit data. # @return [Cell] diff --git a/lib/axlsx/workbook/worksheet/table.rb b/lib/axlsx/workbook/worksheet/table.rb index 831040f3..0b1dc385 100644 --- a/lib/axlsx/workbook/worksheet/table.rb +++ b/lib/axlsx/workbook/worksheet/table.rb @@ -63,29 +63,25 @@ module Axlsx end end + def to_xml_string(str = '') + str << '' + str << '' + str << '' + str << '' + header_cells.each_with_index do |cell,index| + str << '' + end + str << '' + #TODO implement tableStyleInfo + str << '' + str << '
' + end # The style for the table. # TODO # def style=(v) DataTypeValidator.validate "Table.style", Integer, v, lambda { |arg| arg >= 1 && arg <= 48 }; @style = v; end - # Table Serialization - # serializes the table - def to_xml - builder = Nokogiri::XML::Builder.new(:encoding => ENCODING) do |xml| - xml.table(:xmlns => XML_NS, :id => index+1, :name => @name, :displayName => @name.gsub(/\s/,'_'), :ref => @ref, :totalsRowShown => 0) { - xml.autoFilter :ref=>@ref - xml.tableColumns(:count => header_cells.length) { - header_cells.each_with_index do |cell,index| - xml.tableColumn :id => index+1, :name => cell.value - end - } - xml.tableStyleInfo :showFirstColumn=>"0", :showLastColumn=>"0", :showRowStripes=>"1", :showColumnStripes=>"0", :name=>"TableStyleMedium9" - #TODO implement tableStyleInfo - } - end - builder.to_xml(:save_with => 0) - end - private # get the header cells (hackish) diff --git a/lib/axlsx/workbook/worksheet/worksheet.rb b/lib/axlsx/workbook/worksheet/worksheet.rb index 84f82791..200c8b80 100644 --- a/lib/axlsx/workbook/worksheet/worksheet.rb +++ b/lib/axlsx/workbook/worksheet/worksheet.rb @@ -385,7 +385,8 @@ module Axlsx end def to_xml_string - str = "" % [XML_NS, XML_NS_R] + str = '' + str.concat "" % [XML_NS, XML_NS_R] str.concat "" % fit_to_page if fit_to_page str.concat "" % dimension unless rows.size == 0 str.concat "" % [@selected, show_gridlines] @@ -393,17 +394,12 @@ module Axlsx if @column_info.size > 0 str << "" @column_info.each { |col| col.to_xml_string(str) } - - # @auto_fit_data.each_with_index do |col, index| - # min_max = index+1 - # str.concat "" % [min_max, min_max, auto_width(col)] - # end str.concat '' end str.concat '' @rows.each_with_index { |row, index| row.to_xml_string(index, str) } str.concat '' - str.concat page_margins.to_xml_string if @page_margins + page_margins.to_xml_string(str) if @page_margins str.concat "" % @auto_filter if @auto_filter str.concat "%s" % [@merged_cells.size, @merged_cells.reduce('') { |memo, obj| "" % obj } ] unless @merged_cells.empty? str.concat "" if @drawing diff --git a/test/content_type/tc_content_type.rb b/test/content_type/tc_content_type.rb index 79141748..e353b1bb 100644 --- a/test/content_type/tc_content_type.rb +++ b/test/content_type/tc_content_type.rb @@ -4,7 +4,7 @@ require 'tc_helper.rb' class TestContentType < Test::Unit::TestCase def setup @package = Axlsx::Package.new - @doc = Nokogiri::XML(@package.send(:content_types).to_xml) + @doc = Nokogiri::XML(@package.send(:content_types).to_xml_string) end def test_valid_document @@ -51,12 +51,12 @@ class TestContentType < Test::Unit::TestCase o_path = "//xmlns:Override[@ContentType='%s']" ws = @package.workbook.add_worksheet - doc = Nokogiri::XML(@package.send(:content_types).to_xml) + doc = Nokogiri::XML(@package.send(:content_types).to_xml_string) assert_equal(doc.xpath("//xmlns:Override").size, 5, "adding a worksheet should add another type") assert_equal(doc.xpath(o_path % Axlsx::WORKSHEET_CT).last["PartName"], "/xl/#{ws.pn}", "Worksheet part invalid") ws = @package.workbook.add_worksheet - doc = Nokogiri::XML(@package.send(:content_types).to_xml) + doc = Nokogiri::XML(@package.send(:content_types).to_xml_string) assert_equal(doc.xpath("//xmlns:Override").size, 6, "adding workship should add another type") assert_equal(doc.xpath(o_path % Axlsx::WORKSHEET_CT).last["PartName"], "/xl/#{ws.pn}", "Worksheet part invalid") @@ -67,13 +67,13 @@ class TestContentType < Test::Unit::TestCase ws = @package.workbook.add_worksheet c = ws.add_chart Axlsx::Pie3DChart - doc = Nokogiri::XML(@package.send(:content_types).to_xml) + doc = Nokogiri::XML(@package.send(:content_types).to_xml_string) assert_equal(doc.xpath("//xmlns:Override").size, 7, "expected 7 types got #{doc.css("Types Override").size}") assert_equal(doc.xpath(o_path % Axlsx::DRAWING_CT).first["PartName"], "/xl/#{ws.drawing.pn}", "Drawing part name invlid") assert_equal(doc.xpath(o_path % Axlsx::CHART_CT).last["PartName"], "/xl/#{c.pn}", "Chart part name invlid") c = ws.add_chart Axlsx::Pie3DChart - doc = Nokogiri::XML(@package.send(:content_types).to_xml) + doc = Nokogiri::XML(@package.send(:content_types).to_xml_string) assert_equal(doc.xpath("//xmlns:Override").size, 8, "expected 7 types got #{doc.css("Types Override").size}") assert_equal(doc.xpath(o_path % Axlsx::CHART_CT).last["PartName"], "/xl/#{c.pn}", "Chart part name invlid") end diff --git a/test/content_type/tc_default.rb b/test/content_type/tc_default.rb index e5245b38..2fe0d965 100644 --- a/test/content_type/tc_default.rb +++ b/test/content_type/tc_default.rb @@ -2,10 +2,7 @@ require 'tc_helper.rb' class TestDefault < Test::Unit::TestCase - def setup - end - def teardown - end + def test_initialization_requires_Extension_and_ContentType assert_raise(ArgumentError, "raises argument error if Extension and/or ContentType are not specified") { Axlsx::Default.new } assert_raise(ArgumentError, "raises argument error if Extension and/or ContentType are not specified") { Axlsx::Default.new :Extension=>"xml" } @@ -18,21 +15,11 @@ class TestDefault < Test::Unit::TestCase assert_raise(ArgumentError, "raises argument error if invlalid ContentType is") { Axlsx::Default.new :ContentType=>"asdf" } end - def test_to_xml - schema = Nokogiri::XML::Schema(File.open(Axlsx::CONTENT_TYPES_XSD)) + def test_to_xml_string type = Axlsx::Default.new :Extension=>"xml", :ContentType=>Axlsx::XML_CT - builder = Nokogiri::XML::Builder.new(:encoding => Axlsx::ENCODING) do |xml| - xml.Types(:xmlns => Axlsx::XML_NS_T) { - type.to_xml(xml) - } - end - doc = Nokogiri::XML(builder.to_xml) - errors = [] - schema.validate(doc).each do |error| - puts error.message - errors << error - end - assert_equal(errors.size, 0, "[Content Types].xml Invalid" + errors.map{ |e| e.message }.to_s) + doc = Nokogiri::XML(type.to_xml_string) + assert_equal(doc.xpath("Default[@ContentType='#{Axlsx::XML_CT}']").size, 1) + assert_equal(doc.xpath("Default[@Extension='xml']").size, 1) end diff --git a/test/content_type/tc_override.rb b/test/content_type/tc_override.rb index 5005d12d..920f1667 100644 --- a/test/content_type/tc_override.rb +++ b/test/content_type/tc_override.rb @@ -2,10 +2,7 @@ require 'tc_helper.rb' class TestOverride < Test::Unit::TestCase - def setup - end - def teardown - end + def test_initialization_requires_Extension_and_ContentType err = "requires PartName and ContentType options" assert_raise(ArgumentError, err) { Axlsx::Override.new } @@ -19,20 +16,10 @@ class TestOverride < Test::Unit::TestCase end def test_to_xml - schema = Nokogiri::XML::Schema(File.open(Axlsx::CONTENT_TYPES_XSD)) type = Axlsx::Override.new :PartName=>"somechart.xml", :ContentType=>Axlsx::CHART_CT - builder = Nokogiri::XML::Builder.new(:encoding => Axlsx::ENCODING) do |xml| - xml.Types(:xmlns => Axlsx::XML_NS_T) { - type.to_xml(xml) - } - end - doc = Nokogiri::XML(builder.to_xml) - errors = [] - schema.validate(doc).each do |error| - puts error.message - errors << error - end - assert_equal(errors.size, 0, "Override content type caused invalid content_type doc" + errors.map{ |e| e.message }.to_s) + doc = Nokogiri::XML(type.to_xml_string) + assert_equal(doc.xpath("Override[@ContentType='#{Axlsx::CHART_CT}']").size, 1) + assert_equal(doc.xpath("Override[@PartName='somechart.xml']").size, 1) end diff --git a/test/doc_props/tc_app.rb b/test/doc_props/tc_app.rb index 31c87c41..bff2bb3d 100644 --- a/test/doc_props/tc_app.rb +++ b/test/doc_props/tc_app.rb @@ -1,14 +1,9 @@ require 'tc_helper.rb' class TestApp < Test::Unit::TestCase - def setup - end - def teardown - end - def test_valid_document schema = Nokogiri::XML::Schema(File.open(Axlsx::APP_XSD)) - doc = Nokogiri::XML(Axlsx::App.new.to_xml) + doc = Nokogiri::XML(Axlsx::App.new.to_xml_string) errors = [] schema.validate(doc).each do |error| errors << error diff --git a/test/doc_props/tc_core.rb b/test/doc_props/tc_core.rb index 5e75d812..e26d1236 100644 --- a/test/doc_props/tc_core.rb +++ b/test/doc_props/tc_core.rb @@ -4,7 +4,7 @@ class TestCore < Test::Unit::TestCase def setup @core = Axlsx::Core.new - @doc = Nokogiri::XML(@core.to_xml) + @doc = Nokogiri::XML(@core.to_xml_string) end def test_valid_document @@ -27,7 +27,7 @@ class TestCore < Test::Unit::TestCase def test_creator_as_option c = Axlsx::Core.new :creator => "some guy" - doc = Nokogiri::XML(c.to_xml) + doc = Nokogiri::XML(c.to_xml_string) assert(doc.xpath('//dc:creator').text == "some guy") end end diff --git a/test/rels/tc_relationships.rb b/test/rels/tc_relationships.rb index 9a76d1e5..356e4691 100644 --- a/test/rels/tc_relationships.rb +++ b/test/rels/tc_relationships.rb @@ -5,7 +5,7 @@ class TestRelationships < Test::Unit::TestCase def test_valid_document @rels = Axlsx::Relationships.new schema = Nokogiri::XML::Schema(File.open(Axlsx::RELS_XSD)) - doc = Nokogiri::XML(@rels.to_xml) + doc = Nokogiri::XML(@rels.to_xml_string) errors = [] schema.validate(doc).each do |error| puts error.message @@ -13,7 +13,7 @@ class TestRelationships < Test::Unit::TestCase end @rels << Axlsx::Relationship.new(Axlsx::WORKSHEET_R, "bar") - doc = Nokogiri::XML(@rels.to_xml) + doc = Nokogiri::XML(@rels.to_xml_string) errors = [] schema.validate(doc).each do |error| puts error.message diff --git a/test/workbook/tc_workbook.rb b/test/workbook/tc_workbook.rb index af2a7889..e6bb48a0 100644 --- a/test/workbook/tc_workbook.rb +++ b/test/workbook/tc_workbook.rb @@ -50,7 +50,7 @@ class TestWorkbook < Test::Unit::TestCase def test_to_xml schema = Nokogiri::XML::Schema(File.open(Axlsx::SML_XSD)) - doc = Nokogiri::XML(@wb.to_xml) + doc = Nokogiri::XML(@wb.to_xml_string) errors = [] schema.validate(doc).each do |error| errors.push error @@ -68,9 +68,19 @@ class TestWorkbook < Test::Unit::TestCase def test_to_xml_adds_worksheet_when_worksheets_is_empty assert(@wb.worksheets.empty?) - @wb.to_xml + @wb.to_xml_string assert(@wb.worksheets.size == 1) end + def test_to_xml_string_defined_names + @wb.add_worksheet do |sheet| + sheet.add_row [1, "two"] + sheet.auto_filter = "A1:B1" + end + doc = Nokogiri::XML(@wb.to_xml_string) + assert_equal(doc.xpath('//xmlns:workbook/xmlns:definedNames/xmlns:definedName').inner_text, @wb.worksheets[0].abs_auto_filter) + end + + end diff --git a/test/workbook/worksheet/table/tc_table.rb b/test/workbook/worksheet/table/tc_table.rb index fc29bf66..d4acf39a 100644 --- a/test/workbook/worksheet/table/tc_table.rb +++ b/test/workbook/worksheet/table/tc_table.rb @@ -56,10 +56,10 @@ class TestTable < Test::Unit::TestCase assert_equal(@ws.relationships.size, 2, "adding a table adds a relationship") end - def test_to_xml + def test_to_xml_string table = @ws.add_table("A1:D5") schema = Nokogiri::XML::Schema(File.open(Axlsx::SML_XSD)) - doc = Nokogiri::XML(table.to_xml) + doc = Nokogiri::XML(table.to_xml_string) errors = [] schema.validate(doc).each do |error| errors.push error diff --git a/test/workbook/worksheet/tc_cell.rb b/test/workbook/worksheet/tc_cell.rb index 499f9209..4db0c7be 100644 --- a/test/workbook/worksheet/tc_cell.rb +++ b/test/workbook/worksheet/tc_cell.rb @@ -225,17 +225,14 @@ class TestCell < Test::Unit::TestCase end def test_to_xml_string - builder = Nokogiri::XML::Builder.new(:encoding => Axlsx::ENCODING) do |xml| - @c.to_xml(xml) - end - c_xml = Nokogiri::XML(builder.to_xml(:save_with => 0)) + 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 # TODO This could use some much more stringent testing related to the xml content generated! row = @ws.add_row [Time.now, Date.today, true, 1, 1.0, "text", "=sum(A1:A2)"] schema = Nokogiri::XML::Schema(File.open(Axlsx::SML_XSD)) - doc = Nokogiri::XML(@ws.to_xml) + doc = Nokogiri::XML(@ws.to_xml_string) errors = [] schema.validate(doc).each do |error| errors.push error diff --git a/test/workbook/worksheet/tc_page_margins.rb b/test/workbook/worksheet/tc_page_margins.rb index 4c5e43fa..386f47da 100644 --- a/test/workbook/worksheet/tc_page_margins.rb +++ b/test/workbook/worksheet/tc_page_margins.rb @@ -55,9 +55,7 @@ class TestPageMargins < Test::Unit::TestCase @pm.bottom = 1.4 @pm.header = 0.8 @pm.footer = 0.9 - xml = Nokogiri::XML::Builder.new - @pm.to_xml(xml) - doc = Nokogiri::XML.parse(xml.to_xml) + doc = Nokogiri::XML.parse(@pm.to_xml_string) assert_equal(1, doc.xpath(".//pageMargins[@left=1.1][@right=1.2][@top=1.3][@bottom=1.4][@header=0.8][@footer=0.9]").size) end diff --git a/test/workbook/worksheet/tc_row.rb b/test/workbook/worksheet/tc_row.rb index 47b0f054..d1507aa1 100644 --- a/test/workbook/worksheet/tc_row.rb +++ b/test/workbook/worksheet/tc_row.rb @@ -53,9 +53,7 @@ class TestRow < Test::Unit::TestCase end def test_to_xml_without_custom_height - xml = Nokogiri::XML::Builder.new - @row.to_xml(xml) - doc = Nokogiri::XML.parse(xml.to_xml) + doc = Nokogiri::XML.parse(@row.to_xml_string(0)) assert_equal(0, doc.xpath(".//row[@ht]").size) assert_equal(0, doc.xpath(".//row[@customHeight]").size) end @@ -72,12 +70,4 @@ class TestRow < Test::Unit::TestCase assert_equal(r_s_xml.xpath(".//row[@r=1][@ht=20][@customHeight=1]").size, 1) end - def test_to_xml_with_custom_height - @row.height = 20 - xml = Nokogiri::XML::Builder.new - @row.to_xml(xml) - doc = Nokogiri::XML.parse(xml.to_xml) - assert_equal(1, doc.xpath(".//row[@ht=20][@customHeight=1]").size) - end - end diff --git a/test/workbook/worksheet/tc_worksheet.rb b/test/workbook/worksheet/tc_worksheet.rb index 3a3232fe..499df864 100644 --- a/test/workbook/worksheet/tc_worksheet.rb +++ b/test/workbook/worksheet/tc_worksheet.rb @@ -202,8 +202,6 @@ class TestWorksheet < Test::Unit::TestCase @ws.auto_filter = "A1:B1" doc = Nokogiri::XML(@ws.to_xml_string) assert_equal(doc.xpath('//xmlns:worksheet/xmlns:autoFilter[@ref="A1:B1"]').size, 1) - doc2 = Nokogiri::XML(@wb.to_xml) - assert_equal(doc2.xpath('//xmlns:workbook/xmlns:definedNames/xmlns:definedName').inner_text, @ws.abs_auto_filter) end def test_to_xml_string_merge_cells @@ -240,13 +238,12 @@ class TestWorksheet < Test::Unit::TestCase def test_abs_auto_filter @ws.add_row [1, "two", 3] @ws.auto_filter = "A1:C1" - doc = Nokogiri::XML(@wb.to_xml) - assert_equal(doc.xpath('//xmlns:workbook/xmlns:definedNames/xmlns:definedName').inner_text, "'Sheet1'!$A$1:$C$1") + assert_equal(@ws.abs_auto_filter, "'Sheet1'!$A$1:$C$1") end - def test_to_xml + def test_to_xml_string schema = Nokogiri::XML::Schema(File.open(Axlsx::SML_XSD)) - doc = Nokogiri::XML(@ws.to_xml) + doc = Nokogiri::XML(@ws.to_xml_string) errors = [] schema.validate(doc).each do |error| errors.push error @@ -258,7 +255,7 @@ class TestWorksheet < Test::Unit::TestCase def test_valid_with_page_margins @ws.page_margins.set :left => 9 schema = Nokogiri::XML::Schema(File.open(Axlsx::SML_XSD)) - doc = Nokogiri::XML(@ws.to_xml) + doc = Nokogiri::XML(@ws.to_xml_string) errors = [] schema.validate(doc).each do |error| errors.push error @@ -286,20 +283,6 @@ class TestWorksheet < Test::Unit::TestCase assert_nothing_raised { @ws.name = Array.new(31, "A").join('') } end - def test_update_auto_with_data - # small = @ws.workbook.styles.add_style(:sz=>2) - # big = @ws.workbook.styles.add_style(:sz=>10) - - # @ws.add_row ["chasing windmills", "penut"], :style=>small - # assert(@ws.auto_fit_data.size == 2, "a data item for each column") - - # assert_equal(@ws.auto_fit_data[0], {:sz => 2, :longest => "chasing windmills", :fixed=>nil}, "adding a row updates auto_fit_data if the product of the string length and font is greater for the column") - - - # @ws.add_row ["mule"], :style=>big - # assert_equal(@ws.auto_fit_data[0], {:sz=>10,:longest=>"mule", :fixed=>nil}, "adding a row updates auto_fit_data if the product of the string length and font is greater for the column") - end - def test_set_fixed_width_column @ws.add_row ["mule", "donkey", "horse"], :widths => [20, :ignore, nil] assert(@ws.column_info.size == 3, "a data item for each column") @@ -307,35 +290,11 @@ class TestWorksheet < Test::Unit::TestCase assert_equal(@ws.column_info[1].width, nil, ":ignore does not set any data") end - def test_fixed_widths_with_merged_cells - # @ws.add_row ["hey, I'm like really long and stuff so I think you will merge me."] - # @ws.merge_cells "A1:C1" - # @ws.add_row ["but Im Short!"], :widths=> [14.8] - # assert_equal(@ws.send(:auto_width, @ws.auto_fit_data[0]), 14.8) - end - - def test_fixed_width_to_auto - # @ws.add_row ["hey, I'm like really long and stuff so I think you will merge me."] - # @ws.merge_cells "A1:C1" - # @ws.add_row ["but Im Short!"], :widths=> [14.8] - # assert_equal(@ws.send(:auto_width, @ws.auto_fit_data[0]), 14.8) - # @ws.add_row ["no, I like auto!"], :widths=>[:auto] - # assert_equal(@ws.auto_fit_data[0][:fixed], nil) - end - - def test_auto_width - # assert(@ws.send(:auto_width, {:sz=>11, :longest=>"fisheries"}) > @ws.send(:auto_width, {:sz=>11, :longest=>"fish"}), "longer strings get a longer auto_width at the same font size") - - # assert(@ws.send(:auto_width, {:sz=>11, :longest=>"fish"}) < @ws.send(:auto_width, {:sz=>12, :longest=>"fish"}), "larger fonts produce longer with with same string") - # assert_equal(@ws.send(:auto_width, {:sz=>11, :longest => "This is a really long string", :fixed=>0.2}), 0.2, "fixed rules!") - end - def test_fixed_height @ws.add_row [1, 2, 3], :height => 40 assert_equal(40, @ws.rows[-1].height) end - def test_set_column_width @ws.add_row ["chasing windmills", "penut"] @ws.column_widths nil, 0.5 -- cgit v1.2.3 From 8190b1428774e0dac398d43e9c97e5476126073b Mon Sep 17 00:00:00 2001 From: Joe Kain Date: Sat, 31 Mar 2012 15:57:14 -0700 Subject: Build self_hash up from INLINE_STYLES Iterate over each value in INLINE_STYLES instead of iterating over each value in instances_values and rejecting unwanted items. This version proceses fewer values and runs a little faster. Issue #61 - Axlsx performance --- lib/axlsx/workbook/worksheet/cell.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/axlsx/workbook/worksheet/cell.rb b/lib/axlsx/workbook/worksheet/cell.rb index bfb7f35f..1b042994 100644 --- a/lib/axlsx/workbook/worksheet/cell.rb +++ b/lib/axlsx/workbook/worksheet/cell.rb @@ -225,7 +225,8 @@ module Axlsx # equality comparison to test value, type and inline style attributes # this is how we work out if the cell needs to be added or already exists in the shared strings table def shareable_hash - self_hash = self.instance_values.reject { |key, val| !INLINE_STYLES.include?(key) } + self_hash = {} + INLINE_STYLES.each { |style| self_hash[style] = self.instance_variable_get("@" + style) } self_hash['color'] = self_hash['color'].instance_values if self_hash['color'] self_hash end -- cgit v1.2.3 From 1529fce32449a8454208fded20d83c9ceca810e0 Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Sun, 1 Apr 2012 11:58:09 +0900 Subject: rebuild all serialization to use string concatenation instead of nokogiri. --- lib/axlsx/doc_props/core.rb | 1 + lib/axlsx/drawing/axis.rb | 50 +++++-------------- lib/axlsx/drawing/bar_3D_chart.rb | 74 +++++++++-------------------- lib/axlsx/drawing/bar_series.rb | 20 ++------ lib/axlsx/drawing/cat_axis.rb | 19 ++------ lib/axlsx/drawing/cat_axis_data.rb | 38 ++++----------- lib/axlsx/drawing/chart.rb | 67 +++++++------------------- lib/axlsx/drawing/drawing.rb | 10 ---- lib/axlsx/drawing/graphic_frame.rb | 41 ++++------------ lib/axlsx/drawing/hyperlink.rb | 10 ---- lib/axlsx/drawing/line_3D_chart.rb | 68 ++++++++------------------ lib/axlsx/drawing/line_series.rb | 10 ---- lib/axlsx/drawing/marker.rb | 10 +--- lib/axlsx/drawing/named_axis_data.rb | 38 ++++----------- lib/axlsx/drawing/one_cell_anchor.rb | 22 ++------- lib/axlsx/drawing/pic.rb | 44 +++++------------ lib/axlsx/drawing/picture_locking.rb | 38 +++++++-------- lib/axlsx/drawing/pie_3D_chart.rb | 17 ++++--- lib/axlsx/drawing/pie_series.rb | 25 +++++----- lib/axlsx/drawing/scaling.rb | 20 ++------ lib/axlsx/drawing/scatter_chart.rb | 43 ++++++++--------- lib/axlsx/drawing/scatter_series.rb | 13 ++--- lib/axlsx/drawing/ser_axis.rb | 10 ---- lib/axlsx/drawing/series.rb | 22 ++------- lib/axlsx/drawing/series_title.rb | 27 +++++------ lib/axlsx/drawing/title.rb | 25 +--------- lib/axlsx/drawing/two_cell_anchor.rb | 35 ++++++-------- lib/axlsx/drawing/val_axis.rb | 15 ++---- lib/axlsx/drawing/val_axis_data.rb | 39 ++++----------- lib/axlsx/drawing/view_3D.rb | 25 +++------- lib/axlsx/package.rb | 11 +++-- lib/axlsx/rels/relationship.rb | 2 +- lib/axlsx/rels/relationships.rb | 2 +- lib/axlsx/stylesheet/border.rb | 13 +++++ lib/axlsx/stylesheet/border_pr.rb | 26 ++++++---- lib/axlsx/stylesheet/cell_alignment.rb | 41 +++++++++------- lib/axlsx/stylesheet/cell_protection.rb | 12 +++-- lib/axlsx/stylesheet/cell_style.rb | 9 +++- lib/axlsx/stylesheet/color.rb | 6 +-- lib/axlsx/stylesheet/fill.rb | 8 +++- lib/axlsx/stylesheet/font.rb | 23 ++++++--- lib/axlsx/stylesheet/gradient_fill.rb | 29 +++++++---- lib/axlsx/stylesheet/gradient_stop.rb | 9 +++- lib/axlsx/stylesheet/num_fmt.rb | 14 ++++-- lib/axlsx/stylesheet/pattern_fill.rb | 34 ++++++++++--- lib/axlsx/stylesheet/styles.rb | 8 ++++ lib/axlsx/stylesheet/table_style.rb | 11 +++++ lib/axlsx/stylesheet/table_style_element.rb | 12 +++-- lib/axlsx/stylesheet/table_styles.rb | 15 +++++- lib/axlsx/stylesheet/xf.rb | 46 +++++++++++------- lib/axlsx/util/simple_typed_list.rb | 27 +++++++---- lib/schema/dc.xsd | 10 ++-- lib/schema/dcmitype.xsd | 8 ++-- lib/schema/dcterms.xsd | 30 ++++++------ lib/schema/opc-coreProperties.xsd | 8 +++- lib/schema/xml.xsd | 15 +++--- test/drawing/tc_axis.rb | 5 ++ test/drawing/tc_bar_3D_chart.rb | 4 +- test/drawing/tc_chart.rb | 4 +- test/drawing/tc_drawing.rb | 2 +- test/drawing/tc_line_3d_chart.rb | 2 +- test/drawing/tc_pic.rb | 2 +- test/drawing/tc_pie_3D_chart.rb | 2 +- test/drawing/tc_scatter_chart.rb | 21 ++++++-- test/stylesheet/tc_styles.rb | 2 +- 65 files changed, 571 insertions(+), 778 deletions(-) diff --git a/lib/axlsx/doc_props/core.rb b/lib/axlsx/doc_props/core.rb index 7d9ba291..b3c80991 100644 --- a/lib/axlsx/doc_props/core.rb +++ b/lib/axlsx/doc_props/core.rb @@ -24,6 +24,7 @@ module Axlsx str << '' << self.creator << '' str << '' << Time.now.strftime('%Y-%m-%dT%H:%M:%S') << '' str << '0' + str << '
' end end end diff --git a/lib/axlsx/drawing/axis.rb b/lib/axlsx/drawing/axis.rb index 8fbc3612..e686314c 100644 --- a/lib/axlsx/drawing/axis.rb +++ b/lib/axlsx/drawing/axis.rb @@ -85,50 +85,26 @@ module Axlsx def to_xml_string(str = '') - str << '' + str << '' @scaling.to_xml_string str - str << '' - str << '' - str << '' + str << '' + str << '' + str << '' if self.gridlines == false - str << '' + str << '' str << '' str << '' str << '' - str << '' + str << '' end - str << '' - str << '' - str << '' - str << '' - str << '' - str << '' - str << '' + str << '' + str << '' + str << '' + str << '' + str << '' + str << '' + str << '' end - # Serializes the common axis - # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. - # @return [String] - def to_xml(xml) - xml.axId :val=>@axId - @scaling.to_xml(xml) - xml.delete :val=>0 - xml.axPos :val=>@axPos - xml.majorGridlines { - if self.gridlines == false - xml.spPr { - xml[:a].ln { - xml[:a].noFill - } - } - end - } - xml.numFmt :formatCode => @format_code, :sourceLinked=>"1" - xml.majorTickMark :val=>"none" - xml.minorTickMark :val=>"none" - xml.tickLblPos :val=>@tickLblPos - xml.crossAx :val=>@crossAx - xml.crosses :val=>@crosses - end end end diff --git a/lib/axlsx/drawing/bar_3D_chart.rb b/lib/axlsx/drawing/bar_3D_chart.rb index dbed026a..f623ab9f 100644 --- a/lib/axlsx/drawing/bar_3D_chart.rb +++ b/lib/axlsx/drawing/bar_3D_chart.rb @@ -106,57 +106,29 @@ module Axlsx end def to_xml_string(str = '') - super do |str| - str << '' - str << '' - str << '' - str << '' - @series.each { |ser| ser.to_xml_str(str) } - str << '' - str << '' - str << '' - str << '' - str << '' - str << '' - str << '' - str << '' - str << '' unless @gapWidth.nil? - str << '' unless @gapDepth.nil? - str << '' - str << '' - str << '' - str << '' - str << '' - @catAxis.to_xml_str str - @valAxis.to_xml_str str - end - end - # Serializes the bar chart - # @return [String] - def to_xml - super() do |xml| - xml.bar3DChart { - xml.barDir :val => barDir - xml.grouping :val=>grouping - xml.varyColors :val=>1 - @series.each { |ser| ser.to_xml(xml) } - xml.dLbls { - xml.showLegendKey :val=>0 - xml.showVal :val=>0 - xml.showCatName :val=>0 - xml.showSerName :val=>0 - xml.showPercent :val=>0 - xml.showBubbleSize :val=>0 - } - xml.gapWidth :val=>@gapWidth unless @gapWidth.nil? - xml.gapDepth :val=>@gapDepth unless @gapDepth.nil? - xml.shape :val=>@shape unless @shape.nil? - xml.axId :val=>@catAxId - xml.axId :val=>@valAxId - xml.axId :val=>0 - } - @catAxis.to_xml(xml) - @valAxis.to_xml(xml) + super(str) do |str_inner| + str_inner << '' + str_inner << '' + str_inner << '' + str_inner << '' + @series.each { |ser| ser.to_xml_string(str_inner) } + str_inner << '' + str_inner << '' + str_inner << '' + str_inner << '' + str_inner << '' + str_inner << '' + str_inner << '' + str_inner << '' + str_inner << '' unless @gapWidth.nil? + str_inner << '' unless @gapDepth.nil? + str_inner << '' unless @shape.nil? + str_inner << '' + str_inner << '' + str_inner << '' + str_inner << '' + @catAxis.to_xml_string str_inner + @valAxis.to_xml_string str_inner end end end diff --git a/lib/axlsx/drawing/bar_series.rb b/lib/axlsx/drawing/bar_series.rb index 3a3ea6fa..65cd87d9 100644 --- a/lib/axlsx/drawing/bar_series.rb +++ b/lib/axlsx/drawing/bar_series.rb @@ -41,25 +41,13 @@ module Axlsx end def to_xml_string(str = '') - super(str) do - @labels.to_xml_string(str) unless @labels.nil? - @data.to_xml_string(str) unless @data.nil? - str << '' + super(str) do |str_inner| + @labels.to_xml_string(str_inner) unless @labels.nil? + @data.to_xml_string(str_inner) unless @data.nil? + str_inner << '' end end - # Serializes the series - # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. - # @return [String] - def to_xml(xml) - super(xml) do |xml_inner| - @labels.to_xml(xml_inner) unless @labels.nil? - @data.to_xml(xml_inner) unless @data.nil? - xml_inner.shape :val=>@shape - end - end - - private # assigns the data for this series diff --git a/lib/axlsx/drawing/cat_axis.rb b/lib/axlsx/drawing/cat_axis.rb index 242ae698..66f21943 100644 --- a/lib/axlsx/drawing/cat_axis.rb +++ b/lib/axlsx/drawing/cat_axis.rb @@ -49,23 +49,14 @@ module Axlsx def to_xml_string(str = '') - str << '' + str << '' super(str) - str << '' + str << '' + str << '' + str << '' end - # Serializes the category axis - # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. - # @return [String] - def to_xml(xml) - xml.catAx { - super(xml) - xml.auto :val=>@auto - xml.lblAlgn :val=>@lblAlgn - xml.lblOffset :val=>@lblOffset - } - end end diff --git a/lib/axlsx/drawing/cat_axis_data.rb b/lib/axlsx/drawing/cat_axis_data.rb index a119282e..ced5a305 100644 --- a/lib/axlsx/drawing/cat_axis_data.rb +++ b/lib/axlsx/drawing/cat_axis_data.rb @@ -13,38 +13,18 @@ module Axlsx def to_xml_string(str = '') - str << '' - str << '' - str << '' << Axlsx::cell_range(@list) << '' - str << '' - str << '' + str << '' + str << '' + str << '' << Axlsx::cell_range(@list) << '' + str << '' + str << '' each_with_index do |item, index| v = item.is_a?(Cell) ? item.value.to_s : item - str << '' << v << '' + str << '' << v << '' end - str << '' - str << '' - str << '' - end - - # Serializes the category axis data - # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. - # @return [String] - def to_xml(xml) - xml.cat { - xml.strRef { - xml.f Axlsx::cell_range(@list) - xml.strCache { - xml.ptCount :val=>size - each_with_index do |item, index| - v = item.is_a?(Cell) ? item.value : item - xml.pt(:idx=>index) { - xml.v v - } - end - } - } - } + str << '' + str << '' + str << '' end end diff --git a/lib/axlsx/drawing/chart.rb b/lib/axlsx/drawing/chart.rb index a0bc75ba..65140d66 100644 --- a/lib/axlsx/drawing/chart.rb +++ b/lib/axlsx/drawing/chart.rb @@ -114,7 +114,7 @@ module Axlsx end - def to_xml_string + def to_xml_string(str = '') str << '' str << '' str << '' @@ -122,63 +122,28 @@ module Axlsx str << '' @title.to_xml_string str # do these need the c: namespace as well??? - str << '' + str << '' @view3D.to_xml_string(str) if @view3D - str << '' - str << '' - str << '' - str << '' - str << '' + str << '' + str << '' + str << '' + str << '' + str << '' yield str if block_given? - str << '' + str << '' if @show_legend - str << '' - str << '' - str << '' - str << '' - str << '' + str << '' + str << '' + str << '' + str << '' + str << '' end - str << '' - str << '' - str << '' + str << '' + str << '' + str << '' str << '' str << '' end - # Chart Serialization - # serializes the chart - def to_xml - builder = Nokogiri::XML::Builder.new(:encoding => ENCODING) do |xml| - xml.send('c:chartSpace', :'xmlns:c' => XML_NS_C, :'xmlns:a' => XML_NS_A) { - xml[:c].date1904 :val => Axlsx::Workbook.date1904 - xml[:c].style :val=>style - xml[:c].chart { - @title.to_xml(xml) - xml.autoTitleDeleted :val=>0 - @view3D.to_xml(xml) if @view3D - - xml.floor { xml.thickness(:val=>0) } - xml.sideWall { xml.thickness(:val=>0) } - xml.backWall { xml.thickness(:val=>0) } - xml.plotArea { - xml.layout - yield xml if block_given? - } - if @show_legend - xml.legend { - xml.legendPos :val => "r" - xml.layout - xml.overlay :val => 0 - } - end - xml.plotVisOnly :val => 1 - xml.dispBlanksAs :val => :zero - xml.showDLblsOverMax :val => 1 - } - - } - end - builder.to_xml(:save_with => 0) - end # This is a short cut method to set the start anchor position # If you need finer granularity in positioning use diff --git a/lib/axlsx/drawing/drawing.rb b/lib/axlsx/drawing/drawing.rb index 08b8531a..d9241f29 100644 --- a/lib/axlsx/drawing/drawing.rb +++ b/lib/axlsx/drawing/drawing.rb @@ -145,15 +145,5 @@ module Axlsx str << '' end - # Serializes the drawing - # @return [String] - def to_xml - builder = Nokogiri::XML::Builder.new(:encoding => ENCODING) do |xml| - xml.send('xdr:wsDr', :'xmlns:xdr'=>XML_NS_XDR, :'xmlns:a'=>XML_NS_A, :'xmlns:c'=>XML_NS_C) { - anchors.each {|anchor| anchor.to_xml(xml) } - } - end - builder.to_xml(:save_with => 0) - end end end diff --git a/lib/axlsx/drawing/graphic_frame.rb b/lib/axlsx/drawing/graphic_frame.rb index 7502dfba..d123e58a 100644 --- a/lib/axlsx/drawing/graphic_frame.rb +++ b/lib/axlsx/drawing/graphic_frame.rb @@ -29,43 +29,22 @@ module Axlsx end def to_xml_string(str = '') - str << '' - str << '' - str << '' - str << '' - str << '' - str << '' + str << '' + str << '' + str << '' + str << '' + str << '' + str << '' str << '' str << '' - str << '' + str << '' str << '' - str << '' + str << '' str << '' - str << '' + str << '' str << '' - str << '' + str << '' end - # Serializes the graphic frame - # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. - # @return [String] - def to_xml(xml) - xml.graphicFrame { - xml.nvGraphicFramePr { - xml.cNvPr :id=>2, :name=>chart.title.text - xml.cNvGraphicFramePr - } - xml.xfrm { - xml[:a].off(:x=>0, :y=>0) - xml[:a].ext :cx=>0, :cy=>0 - } - xml[:a].graphic { - xml.graphicData(:uri=>XML_NS_C) { - xml[:c].chart :'xmlns:c'=>XML_NS_C, :'xmlns:r'=>XML_NS_R, :'r:id'=>rId - } - } - } - - end end end diff --git a/lib/axlsx/drawing/hyperlink.rb b/lib/axlsx/drawing/hyperlink.rb index 9cfdf705..ae217f31 100644 --- a/lib/axlsx/drawing/hyperlink.rb +++ b/lib/axlsx/drawing/hyperlink.rb @@ -82,16 +82,6 @@ module Axlsx str << '/>' end - # Serializes the hyperlink - # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. - # @return [String] - def to_xml(xml) - h = self.instance_values.merge({:'r:id' => "rId#{id}", :'xmlns:r' => XML_NS_R }) - h.delete('href') - h.delete('parent') - xml[:a].hlinkClick h - end - private # The relational ID for this hyperlink # @return [Integer] diff --git a/lib/axlsx/drawing/line_3D_chart.rb b/lib/axlsx/drawing/line_3D_chart.rb index bd587d1b..74c10850 100644 --- a/lib/axlsx/drawing/line_3D_chart.rb +++ b/lib/axlsx/drawing/line_3D_chart.rb @@ -86,55 +86,29 @@ module Axlsx end def to_xml_string(str = '') - super do |str| - str << '' - str << '' - str << '' - @series.each { |ser| ser.to_xml_str(str) } - str << '' - str << '' - str << '' - str << '' - str << '' - str << '' - str << '' - str << '' - str << '' unless @gapDepth.nil? - str << '' - str << '' - str << '' - str << '' - @catAxis.to_xml_str str - @valAxis.to_xml_str str - @serAxis.to_xml_str str + super(str) do |str_inner| + str_inner << '' + str_inner << '' + str_inner << '' + @series.each { |ser| ser.to_xml_string(str_inner) } + str_inner << '' + str_inner << '' + str_inner << '' + str_inner << '' + str_inner << '' + str_inner << '' + str_inner << '' + str_inner << '' + str_inner << '' unless @gapDepth.nil? + str_inner << '' + str_inner << '' + str_inner << '' + str_inner << '' + @catAxis.to_xml_string str_inner + @valAxis.to_xml_string str_inner + @serAxis.to_xml_string str_inner end end - # Serializes the bar chart - # @return [String] - def to_xml - super() do |xml| - xml.line3DChart { - xml.grouping :val=>grouping - xml.varyColors :val=>1 - @series.each { |ser| ser.to_xml(xml) } - xml.dLbls { - xml.showLegendKey :val=>0 - xml.showVal :val=>0 - xml.showCatName :val=>0 - xml.showSerName :val=>0 - xml.showPercent :val=>0 - xml.showBubbleSize :val=>0 - } - xml.gapDepth :val=>@gapDepth unless @gapDepth.nil? - xml.axId :val=>@catAxId - xml.axId :val=>@valAxId - xml.axId :val=>@serAxId - } - @catAxis.to_xml(xml) - @valAxis.to_xml(xml) - @serAxis.to_xml(xml) - end - end end end diff --git a/lib/axlsx/drawing/line_series.rb b/lib/axlsx/drawing/line_series.rb index c5908f64..136408dd 100644 --- a/lib/axlsx/drawing/line_series.rb +++ b/lib/axlsx/drawing/line_series.rb @@ -32,16 +32,6 @@ module Axlsx end end - # Serializes the series - # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. - # @return [String] - def to_xml(xml) - super(xml) do |xml_inner| - @labels.to_xml(xml_inner) unless @labels.nil? - @data.to_xml(xml_inner) unless @data.nil? - end - end - private # assigns the data for this series diff --git a/lib/axlsx/drawing/marker.rb b/lib/axlsx/drawing/marker.rb index a2ce4312..985cf321 100644 --- a/lib/axlsx/drawing/marker.rb +++ b/lib/axlsx/drawing/marker.rb @@ -52,18 +52,10 @@ module Axlsx def to_xml_string(str = '') [:col, :colOff, :row, :rowOff].each do |k| - str << '<' << k.to_s << '>' << self.send(k).to_s << '' + str << '' << self.send(k).to_s << '' end end - # Serializes the marker - # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. - # @return [String] - def to_xml(xml) - [:col, :colOff, :row, :rowOff].each do |k| - xml.send(k.to_sym, self.send(k)) - end - end end end diff --git a/lib/axlsx/drawing/named_axis_data.rb b/lib/axlsx/drawing/named_axis_data.rb index 2ec58e8b..952dc10e 100644 --- a/lib/axlsx/drawing/named_axis_data.rb +++ b/lib/axlsx/drawing/named_axis_data.rb @@ -10,39 +10,21 @@ module Axlsx def to_xml_string(str = '') - str << '<' << @name << '>' - str << '' - str << '' << Axlsx::cell_range(@list) << '' - str << '' - str << 'General' - str << '' + str << '' + str << '' + str << '' << Axlsx::cell_range(@list) << '' + str << '' + str << 'General' + str << '' each_with_index do |item, index| v = item.is_a?(Cell) ? item.value.to_s : item - str << '' << v << '' + str << '' << v << '' end - str << '' - str << '' - str << '' + str << '' + str << '' + str << '' end - # Serializes the value axis data - # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. - # @return [String] - def to_xml(xml) - xml.send(@name) { - xml.numRef { - xml.f Axlsx::cell_range(@list) - xml.numCache { - xml.formatCode 'General' - xml.ptCount :val=>size - each_with_index do |item, index| - v = item.is_a?(Cell) ? item.value : item - xml.pt(:idx=>index) { xml.v v } - end - } - } - } - end end end diff --git a/lib/axlsx/drawing/one_cell_anchor.rb b/lib/axlsx/drawing/one_cell_anchor.rb index e0574172..fd33892c 100644 --- a/lib/axlsx/drawing/one_cell_anchor.rb +++ b/lib/axlsx/drawing/one_cell_anchor.rb @@ -64,29 +64,15 @@ module Axlsx def to_xml_string(str = '') str << '' - str << '' + str << '' from.to_xml_string(str) - str << '' - str << '' << ext.to_s << '' + str << '' + str << '' @object.to_xml_string(str) - str << '' + str << '' str << '' end - # Serializes the anchor - # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. - # @return [String] - def to_xml(xml) - xml[:xdr].oneCellAnchor { - xml.from { - from.to_xml(xml) - } - xml.ext ext - @object.to_xml(xml) - xml.clientData - } - end - private # converts the pixel width and height to EMU units and returns a hash of diff --git a/lib/axlsx/drawing/pic.rb b/lib/axlsx/drawing/pic.rb index 1783005a..733dc1df 100644 --- a/lib/axlsx/drawing/pic.rb +++ b/lib/axlsx/drawing/pic.rb @@ -145,40 +145,20 @@ module Axlsx end def to_xml_string(str = '') + str << '' + str << '' + str << '' + @hyperlink.to_xml_string(str) if @hyperlink.is_a?(Hyperlink) + str << '' + picture_locking.to_xml_string(str) + str << '' + str << '' + str << '' + str << '' + str << '' + str << '' end - # Serializes the picture - # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. - # @return [String] - def to_xml(xml) - xml.pic { - xml.nvPicPr { - xml.cNvPr(:id=>"2", :name=>name, :descr=>descr) { - if @hyperlink.is_a?(Hyperlink) - @hyperlink.to_xml(xml) - end - } - xml.cNvPicPr { - picture_locking.to_xml(xml) - } - } - xml.blipFill { - xml[:a].blip :'xmlns:r' => XML_NS_R, :'r:embed'=>"rId#{id}" - xml[:a].stretch { - xml.fillRect - } - } - xml.spPr { - xml[:a].xfrm { - xml.off :x=>0, :y=>0 - xml.ext :cx=>2336800, :cy=>2161540 - } - xml[:a].prstGeom(:prst=>:rect) { - xml.avLst - } - } - } - end end end diff --git a/lib/axlsx/drawing/picture_locking.rb b/lib/axlsx/drawing/picture_locking.rb index c05f1641..867e32b4 100644 --- a/lib/axlsx/drawing/picture_locking.rb +++ b/lib/axlsx/drawing/picture_locking.rb @@ -1,9 +1,9 @@ # encoding: UTF-8 module Axlsx - # The picture locking class defines the locking properties for pictures in your workbook. + # The picture locking class defines the locking properties for pictures in your workbook. class PictureLocking - - + + attr_reader :noGrp attr_reader :noSelect attr_reader :noRot @@ -31,43 +31,43 @@ module Axlsx options.each do |o| self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}=" end - end + end # @see noGrp - def noGrp=(v) Axlsx::validate_boolean v; @noGrp = v end + def noGrp=(v) Axlsx::validate_boolean v; @noGrp = v end # @see noSelect - def noSelect=(v) Axlsx::validate_boolean v; @noSelect = v end + def noSelect=(v) Axlsx::validate_boolean v; @noSelect = v end # @see noRot - def noRot=(v) Axlsx::validate_boolean v; @noRot = v end + def noRot=(v) Axlsx::validate_boolean v; @noRot = v end # @see noChangeAspect - def noChangeAspect=(v) Axlsx::validate_boolean v; @noChangeAspect = v end + def noChangeAspect=(v) Axlsx::validate_boolean v; @noChangeAspect = v end # @see noMove - def noMove=(v) Axlsx::validate_boolean v; @noMove = v end + def noMove=(v) Axlsx::validate_boolean v; @noMove = v end # @see noResize - def noResize=(v) Axlsx::validate_boolean v; @noResize = v end + def noResize=(v) Axlsx::validate_boolean v; @noResize = v end # @see noEditPoints - def noEditPoints=(v) Axlsx::validate_boolean v; @noEditPoints = v end + def noEditPoints=(v) Axlsx::validate_boolean v; @noEditPoints = v end # @see noAdjustHandles - def noAdjustHandles=(v) Axlsx::validate_boolean v; @noAdjustHandles = v end + def noAdjustHandles=(v) Axlsx::validate_boolean v; @noAdjustHandles = v end # @see noChangeArrowheads - def noChangeArrowheads=(v) Axlsx::validate_boolean v; @noChangeArrowheads = v end + def noChangeArrowheads=(v) Axlsx::validate_boolean v; @noChangeArrowheads = v end # @see noChangeShapeType - def noChangeShapeType=(v) Axlsx::validate_boolean v; @noChangeShapeType = v end + def noChangeShapeType=(v) Axlsx::validate_boolean v; @noChangeShapeType = v end - # Serializes the picture locking - # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. - # @return [String] - def to_xml(xml) - xml[:a].picLocks(self.instance_values) + def to_xml_string(str = '') + str << '' end + end end diff --git a/lib/axlsx/drawing/pie_3D_chart.rb b/lib/axlsx/drawing/pie_3D_chart.rb index cb36e4f5..67ae791b 100644 --- a/lib/axlsx/drawing/pie_3D_chart.rb +++ b/lib/axlsx/drawing/pie_3D_chart.rb @@ -11,7 +11,7 @@ module Axlsx # Creates a new pie chart object # @param [GraphicFrame] frame The workbook that owns this chart. # @option options [Cell, String] title - # @option options [Boolean] show_legend + # @option options [Boolean] show_legend # @option options [Symbol] grouping # @option options [String] gapDepth # @option options [Integer] rotX @@ -28,15 +28,14 @@ module Axlsx @view3D = View3D.new({:rotX=>30, :perspective=>30}.merge(options)) end - # Serializes the pie chart - # @return [String] - def to_xml - super() do |xml| - xml[:c].pie3DChart { - xml[:c].varyColors :val=>1 - @series.each { |ser| ser.to_xml(xml) } - } + def to_xml_string(str = '') + super(str) do |str_inner| + str_inner << '' + str_inner << '' + @series.each { |ser| ser.to_xml_string(str_inner) } + str_inner << '' end end + end end diff --git a/lib/axlsx/drawing/pie_series.rb b/lib/axlsx/drawing/pie_series.rb index 8e583806..bf61c9ab 100644 --- a/lib/axlsx/drawing/pie_series.rb +++ b/lib/axlsx/drawing/pie_series.rb @@ -6,7 +6,7 @@ module Axlsx # @see Chart#add_series class PieSeries < Series - # The data for this series. + # The data for this series. # @return [SimpleTypedList] attr_reader :data @@ -29,22 +29,21 @@ module Axlsx super(chart, options) self.labels = CatAxisData.new(options[:labels]) unless options[:labels].nil? self.data = ValAxisData.new(options[:data]) unless options[:data].nil? - end - + end + # @see explosion def explosion=(v) Axlsx::validate_unsigned_int(v); @explosion = v; end - # Serializes the series - # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. - # @return [String] - def to_xml(xml) - super(xml) do |xml_inner| - xml_inner.explosion :val=>@explosion unless @explosion.nil? - @labels.to_xml(xml_inner) unless @labels.nil? - @data.to_xml(xml_inner) unless @data.nil? - end + def to_xml_string(str = '') + super(str) do |str_inner| + str_inner << '' unless @explosion.nil? + @labels.to_xml_string str_inner unless @labels.nil? + @data.to_xml_string str_inner unless @data.nil? + end + str end - private + + private # assigns the data for this series def data=(v) DataTypeValidator.validate "Series.data", [SimpleTypedList], v; @data = v; end diff --git a/lib/axlsx/drawing/scaling.rb b/lib/axlsx/drawing/scaling.rb index c90d0377..af9cf2aa 100644 --- a/lib/axlsx/drawing/scaling.rb +++ b/lib/axlsx/drawing/scaling.rb @@ -46,24 +46,12 @@ module Axlsx def to_xml_string(str = '') str << '' - str << '' - str << '' - str << '' - str << '' + str << '' unless @logBase.nil? + str << '' unless @orientation.nil? + str << '' unless @min.nil? + str << '' unless @max.nil? str << '' end - # Serializes the axId - # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. - # @return [String] - def to_xml(xml) - xml[:c].scaling { - xml[:c].logBase :val=> @logBase unless @logBase.nil? - xml[:c].orientation :val=> @orientation unless @orientation.nil? - xml[:c].min :val => @min unless @min.nil? - xml[:c].max :val => @max unless @max.nil? - } - end - end end diff --git a/lib/axlsx/drawing/scatter_chart.rb b/lib/axlsx/drawing/scatter_chart.rb index f257303a..d8d7bb6d 100644 --- a/lib/axlsx/drawing/scatter_chart.rb +++ b/lib/axlsx/drawing/scatter_chart.rb @@ -21,30 +21,27 @@ module Axlsx @series_type = ScatterSeries end - # Serializes the bar chart - # @return [String] - def to_xml - super() do |xml| - xml.scatterChart { - xml.scatterStyle :val=>scatterStyle - - # This is all repeated from line_3D_chart.rb! - xml.varyColors :val=>1 - @series.each { |ser| ser.to_xml(xml) } - xml.dLbls { - xml.showLegendKey :val=>0 - xml.showVal :val=>0 - xml.showCatName :val=>0 - xml.showSerName :val=>0 - xml.showPercent :val=>0 - xml.showBubbleSize :val=>0 - } - xml.axId :val=>@xValAxId - xml.axId :val=>@yValAxId - } - @xValAxis.to_xml(xml) - @yValAxis.to_xml(xml) + def to_xml_string(str = '') + super do |str| + str << '' + str << '' + str << '' + @series.each { |ser| ser.to_xml_string(str) } + str << '' + str << '' + str << '' + str << '' + str << '' + str << '' + str << '' + str << '' + str << '' + str << '' + str << '' + @xValAxis.to_xml_string str + @yValAxis.to_xml_string str end + str end end end diff --git a/lib/axlsx/drawing/scatter_series.rb b/lib/axlsx/drawing/scatter_series.rb index 52145cd1..03b2cbdd 100644 --- a/lib/axlsx/drawing/scatter_series.rb +++ b/lib/axlsx/drawing/scatter_series.rb @@ -17,15 +17,12 @@ module Axlsx @yData = NamedAxisData.new("yVal", options[:yData]) unless options[:yData].nil? end - # Serializes the series - # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. - # @return [String] - def to_xml(xml) - super(xml) do |xml_inner| - @xData.to_xml(xml_inner) unless @xData.nil? - @yData.to_xml(xml_inner) unless @yData.nil? + def to_xml_string(str = '') + super(str) do |inner_str| + @xData.to_xml_string(inner_str) unless @xData.nil? + @yData.to_xml_string(inner_str) unless @yData.nil? end + str end - end end diff --git a/lib/axlsx/drawing/ser_axis.rb b/lib/axlsx/drawing/ser_axis.rb index 54dde640..fdc0d43d 100644 --- a/lib/axlsx/drawing/ser_axis.rb +++ b/lib/axlsx/drawing/ser_axis.rb @@ -37,16 +37,6 @@ module Axlsx str << '' unless @tickMarkSkip.nil? str << '' end - # Serializes the series axis - # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. - # @return [String] - def to_xml(xml) - xml[:c].serAx { - super(xml) - xml[:c].tickLblSkip :val=>@tickLblSkip unless @tickLblSkip.nil? - xml[:c].tickMarkSkip :val=>@tickMarkSkip unless @tickMarkSkip.nil? - } - end end diff --git a/lib/axlsx/drawing/series.rb b/lib/axlsx/drawing/series.rb index 5960f508..9ab2db13 100644 --- a/lib/axlsx/drawing/series.rb +++ b/lib/axlsx/drawing/series.rb @@ -56,24 +56,12 @@ module Axlsx def chart=(v) DataTypeValidator.validate "Series.chart", Chart, v; @chart = v; end def to_xml_string(str = '') - str << '' - str << '' - str << '' + str << '' + str << '' + str << '' title.to_xml_string(str) unless title.nil? - yeild str if block_given? - str << '' - end - - # Serializes the series - # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. - # @return [String] - def to_xml(xml) - xml.ser { - xml.idx :val=>index - xml.order :val=>order || index - title.to_xml(xml) unless title.nil? - yield xml if block_given? - } + yield str if block_given? + str << '' end end diff --git a/lib/axlsx/drawing/series_title.rb b/lib/axlsx/drawing/series_title.rb index b13cec89..39ec10d5 100644 --- a/lib/axlsx/drawing/series_title.rb +++ b/lib/axlsx/drawing/series_title.rb @@ -3,21 +3,18 @@ module Axlsx # A series title is a Title with a slightly different serialization than chart titles. class SeriesTitle < Title - # Serializes the series title - # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. - # @return [String] - def to_xml(xml) - xml[:c].tx { - xml[:c].strRef { - xml[:c].f Axlsx::cell_range([@cell]) - xml[:c].strCache { - xml[:c].ptCount :val=>1 - xml[:c].pt(:idx=>0) { - xml[:c].v @text - } - } - } - } + def to_xml_string(str = '') + str << '' + str << '' + str << '' << Axlsx::cell_range([@cell]) << '' + str << '' + str << '' + str << '' + str << '' << @text << '' + str << '' + str << '' + str << '' + str << '' end end end diff --git a/lib/axlsx/drawing/title.rb b/lib/axlsx/drawing/title.rb index a7b8e715..a9c253c8 100644 --- a/lib/axlsx/drawing/title.rb +++ b/lib/axlsx/drawing/title.rb @@ -54,31 +54,10 @@ module Axlsx str << '' str << '' end + str << '' + str << '' str << '' end - # Serializes the chart title - # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. - # @return [String] - def to_xml(xml) - xml[:c].title { - unless @text.empty? - xml[:c].tx { - xml[:c].strRef { - xml[:c].f Axlsx::cell_range([@cell]) - xml[:c].strCache { - xml[:c].ptCount :val=>1 - xml[:c].pt(:idx=>0) { - xml[:c].v @text - } - } - } - } - end - xml[:c].layout - xml[:c].overlay :val=>0 - } - end - end end diff --git a/lib/axlsx/drawing/two_cell_anchor.rb b/lib/axlsx/drawing/two_cell_anchor.rb index 436f2e7a..cfa102ae 100644 --- a/lib/axlsx/drawing/two_cell_anchor.rb +++ b/lib/axlsx/drawing/two_cell_anchor.rb @@ -26,7 +26,7 @@ module Axlsx attr_reader :drawing - # Creates a new TwoCellAnchor object and sets up a reference to the from and to markers in the + # Creates a new TwoCellAnchor object and sets up a reference to the from and to markers in the # graphic_frame's chart. That means that you can do stuff like # c = worksheet.add_chart Axlsx::Chart # c.start_at 5, 9 @@ -38,13 +38,13 @@ module Axlsx # @option options [Array] end_at the col, row to end at def initialize(drawing, options={}) @drawing = drawing - drawing.anchors << self + drawing.anchors << self @from, @to = Marker.new, Marker.new(:col => 5, :row=>10) end # Creates a graphic frame and chart object associated with this anchor # @return [Chart] - def add_chart(chart_type, options) + def add_chart(chart_type, options) @object = GraphicFrame.new(self, chart_type, options) @object.chart end @@ -54,24 +54,19 @@ module Axlsx def index @drawing.anchors.index(self) end - # Serializes the two cell anchor - # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. - # @return [String] - def to_xml(xml) - #build it for now, break it down later! - xml[:xdr].twoCellAnchor { - xml.from { - from.to_xml(xml) - } - xml.to { - to.to_xml(xml) - } - @object.to_xml(xml) - xml.clientData - } - end - private + def to_xml_string(str = '') + str << '' + str << '' + from.to_xml_string str + str << '' + str << '' + to.to_xml_string str + str << '' + object.to_xml_string(str) + str << '' + str << '' + end end end diff --git a/lib/axlsx/drawing/val_axis.rb b/lib/axlsx/drawing/val_axis.rb index 51adc31a..f2675733 100644 --- a/lib/axlsx/drawing/val_axis.rb +++ b/lib/axlsx/drawing/val_axis.rb @@ -23,20 +23,11 @@ module Axlsx def crossBetween=(v) RestrictionValidator.validate "ValAxis.crossBetween", [:between, :midCat], v; @crossBetween = v; end def to_xml_string(str = '') - str << '' + str << '' super(str) - str << '' - str << '' + str << '' + str << '' end - # Serializes the value axis - # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. - # @return [String] - def to_xml(xml) - xml.valAx { - super(xml) - xml.crossBetween :val=>@crossBetween - } - end end end diff --git a/lib/axlsx/drawing/val_axis_data.rb b/lib/axlsx/drawing/val_axis_data.rb index b974b5d1..c28e8a58 100644 --- a/lib/axlsx/drawing/val_axis_data.rb +++ b/lib/axlsx/drawing/val_axis_data.rb @@ -4,38 +4,19 @@ module Axlsx class ValAxisData < CatAxisData def to_xml_string(str = '') - str << '' - str << '' - str << '' << Axlsx::cell_range(@list) << '' - str << '' - str << 'General' - str << '' + str << '' + str << '' + str << '' << Axlsx::cell_range(@list) << '' + str << '' + str << 'General' + str << '' each_with_index do |item, index| v = item.is_a?(Cell) ? item.value.to_s : item - str << '' << v << '' + str << '' << v << '' end - str << '' - str << '' - str << '' - end - - # Serializes the value axis data - # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. - # @return [String] - def to_xml(xml) - xml.val { - xml.numRef { - xml.f Axlsx::cell_range(@list) - xml.numCache { - xml.formatCode 'General' - xml.ptCount :val=>size - each_with_index do |item, index| - v = item.is_a?(Cell) ? item.value : item - xml.pt(:idx=>index) { xml.v v } - end - } - } - } + str << '' + str << '' + str << '' end end diff --git a/lib/axlsx/drawing/view_3D.rb b/lib/axlsx/drawing/view_3D.rb index ee2739b4..c2af0953 100644 --- a/lib/axlsx/drawing/view_3D.rb +++ b/lib/axlsx/drawing/view_3D.rb @@ -72,27 +72,14 @@ module Axlsx def to_xml_string(str = '') str << '' - str << '' unless @rotX.nil? - str << '' unless @hPercent.nil? - str << '' unless @rotY.nil? - str << '' unless @depthPercent.nil? - str << '' unless @rAngAx.nil? - str << '' unless @perspective.nil? + str << '' unless @rotX.nil? + str << '' unless @hPercent.nil? + str << '' unless @rotY.nil? + str << '' unless @depthPercent.nil? + str << '' unless @rAngAx.nil? + str << '' unless @perspective.nil? str << '' end - # Serializes the view3D properties - # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. - # @return [String] - def to_xml(xml) - xml[:c].view3D { - xml[:c].rotX :val=>@rotX unless @rotX.nil? - xml[:c].hPercent :val=>@hPercent unless @hPercent.nil? - xml[:c].rotY :val=>@rotY unless @rotY.nil? - xml[:c].depthPercent :val=>@depthPercent unless @depthPercent.nil? - xml[:c].rAngAx :val=>@rAngAx unless @rAngAx.nil? - xml[:c].perspective :val=>@perspective unless @perspective.nil? - } - end end end diff --git a/lib/axlsx/package.rb b/lib/axlsx/package.rb index 9bab4269..3ab7b99a 100644 --- a/lib/axlsx/package.rb +++ b/lib/axlsx/package.rb @@ -139,7 +139,9 @@ module Axlsx # p.validate.each { |error| puts error.message } def validate errors = [] - parts.each { |part| errors.concat validate_single_doc(part[:schema], part[:doc]) unless part[:schema].nil? } + parts.each do |part| + errors.concat validate_single_doc(part[:schema], part[:doc]) unless part[:schema].nil? + end errors end @@ -171,7 +173,7 @@ module Axlsx def parts @parts = [ {:entry => RELS_PN, :doc => relationships.to_xml_string, :schema => RELS_XSD}, - {:entry => "xl/#{STYLES_PN}", :doc => workbook.styles.to_xml, :schema => SML_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}, @@ -180,7 +182,7 @@ module Axlsx ] 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, :schema => DRAWING_XSD} + @parts << {:entry => "xl/#{drawing.pn}", :doc => drawing.to_xml_string, :schema => DRAWING_XSD} end workbook.tables.each do |table| @@ -188,7 +190,7 @@ module Axlsx end workbook.charts.each do |chart| - @parts << {:entry => "xl/#{chart.pn}", :doc => chart.to_xml, :schema => DRAWING_XSD} + @parts << {:entry => "xl/#{chart.pn}", :doc => chart.to_xml_string, :schema => DRAWING_XSD} end workbook.images.each do |image| @@ -215,7 +217,6 @@ module Axlsx def validate_single_doc(schema, doc) schema = Nokogiri::XML::Schema(File.open(schema)) doc = Nokogiri::XML(doc) - errors = [] schema.validate(doc).each do |error| errors << error diff --git a/lib/axlsx/rels/relationship.rb b/lib/axlsx/rels/relationship.rb index 4321c7e1..89a09ce1 100644 --- a/lib/axlsx/rels/relationship.rb +++ b/lib/axlsx/rels/relationship.rb @@ -51,7 +51,7 @@ module Axlsx # @param [String] str # @param [Integer] rId the id for this relationship # @return [String] - def to_xml_string(str = '', rId) + def to_xml_string(rId, str = '') h = self.instance_values h[:Id] = 'rId' << rId.to_s str << '' str << '' - each_with_index { |rel, index| rel.to_xml_string(str, index+1) } + each_with_index { |rel, index| rel.to_xml_string(index+1, str) } str << '' end # Serializes the relationships document. diff --git a/lib/axlsx/stylesheet/border.rb b/lib/axlsx/stylesheet/border.rb index 43acbdca..99bd410a 100644 --- a/lib/axlsx/stylesheet/border.rb +++ b/lib/axlsx/stylesheet/border.rb @@ -42,6 +42,19 @@ module Axlsx # @see outline def outline=(v) Axlsx::validate_boolean v; @outline = v end + def to_xml_string(str = '') + str << '' + [:start, :end, :left, :right, :top, :bottom, :diagonal, :vertical, :horizontal].each do |k| + @prs.select { |pr| pr.name == k }.each do |part| + part.to_xml_string(str) + end + end + str << '' + end + # Serializes the border element # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. def to_xml(xml) diff --git a/lib/axlsx/stylesheet/border_pr.rb b/lib/axlsx/stylesheet/border_pr.rb index 62fe3bab..b15e3918 100644 --- a/lib/axlsx/stylesheet/border_pr.rb +++ b/lib/axlsx/stylesheet/border_pr.rb @@ -1,22 +1,22 @@ # encoding: UTF-8 module Axlsx - # A border part. + # A border part. class BorderPr - + # @return [Color] The color of this border part. attr_reader :color - # @return [Symbol] The syle of this border part. - # @note + # @return [Symbol] The syle of this border part. + # @note # The following are allowed - # :none + # :none # :thin # :medium # :dashed # :dotted # :thick # :double - # :hair + # :hair # :mediumDashed # :dashDot # :mediumDashDot @@ -26,7 +26,7 @@ module Axlsx attr_reader :style # @return [Symbol] The name of this border part - # @note + # @note # The following are allowed # :start # :end @@ -38,7 +38,7 @@ module Axlsx # :vertical # :horizontal attr_reader :name - + # Creates a new Border Part Object # @option options [Color] color # @option options [Symbol] name @@ -53,17 +53,23 @@ module Axlsx # @see name def name=(v) RestrictionValidator.validate "BorderPr.name", [:start, :end, :left, :right, :top, :bottom, :diagonal, :vertical, :horizontal], v; @name = v end # @see color - def color=(v) DataTypeValidator.validate(:color, Color, v); @color = v end + def color=(v) DataTypeValidator.validate(:color, Color, v); @color = v end # @see style def style=(v) RestrictionValidator.validate "BorderPr.style", [:none, :thin, :medium, :dashed, :dotted, :thick, :double, :hair, :mediumDashed, :dashDot, :mediumDashDot, :dashDotDot, :mediumDashDotDot, :slantDashDot], v; @style = v end + def to_xml_string(str = '') + str << '<' << @name.to_s << ' style="' << @style.to_s << '">' + @color.to_xml_string(str) if @color.is_a?(Color) + str << '' + end + # Serializes the border part # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. # @return [String] def to_xml(xml) xml.send(@name, :style => @style) { @color.to_xml(xml) if @color.is_a? Color - } + } end end end diff --git a/lib/axlsx/stylesheet/cell_alignment.rb b/lib/axlsx/stylesheet/cell_alignment.rb index 0a1ce60a..50b0e2d4 100644 --- a/lib/axlsx/stylesheet/cell_alignment.rb +++ b/lib/axlsx/stylesheet/cell_alignment.rb @@ -1,11 +1,11 @@ # encoding: UTF-8 module Axlsx # CellAlignment stores information about the cell alignment of a style Xf Object. - # @note Using Styles#add_style is the recommended way to manage cell alignment. + # @note Using Styles#add_style is the recommended way to manage cell alignment. # @see Styles#add_style class CellAlignment # The horizontal alignment of the cell. - # @note + # @note # The horizontal cell alignement style must be one of # :general # :left @@ -36,7 +36,7 @@ module Axlsx # Indicate if the text of the cell should wrap # @return [Boolean] attr_reader :wrapText - + # The amount of indent # @return [Integer] attr_reader :indent @@ -54,12 +54,12 @@ module Axlsx attr_reader :shrinkToFit # The reading order of the text - # 0 Context Dependent + # 0 Context Dependent # 1 Left-to-Right # 2 Right-to-Left # @return [Integer] attr_reader :readingOrder - + # Create a new cell_alignment object # @option options [Symbol] horizontal # @option options [Symbol] vertical @@ -74,33 +74,38 @@ module Axlsx options.each do |o| self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}=" end - end - + end + # @see horizontal - def horizontal=(v) Axlsx::validate_horizontal_alignment v; @horizontal = v end + def horizontal=(v) Axlsx::validate_horizontal_alignment v; @horizontal = v end # @see vertical - def vertical=(v) Axlsx::validate_vertical_alignment v; @vertical = v end + def vertical=(v) Axlsx::validate_vertical_alignment v; @vertical = v end # @see textRotation - def textRotation=(v) Axlsx::validate_unsigned_int v; @textRotation = v end + def textRotation=(v) Axlsx::validate_unsigned_int v; @textRotation = v end # @see wrapText - def wrapText=(v) Axlsx::validate_boolean v; @wrapText = v end + def wrapText=(v) Axlsx::validate_boolean v; @wrapText = v end # @see indent - def indent=(v) Axlsx::validate_unsigned_int v; @indent = v end + def indent=(v) Axlsx::validate_unsigned_int v; @indent = v end # @see relativeIndent - def relativeIndent=(v) Axlsx::validate_int v; @relativeIndent = v end + def relativeIndent=(v) Axlsx::validate_int v; @relativeIndent = v end # @see justifyLastLine - def justifyLastLine=(v) Axlsx::validate_boolean v; @justifyLastLine = v end + def justifyLastLine=(v) Axlsx::validate_boolean v; @justifyLastLine = v end # @see shrinkToFit - def shrinkToFit=(v) Axlsx::validate_boolean v; @shrinkToFit = v end + def shrinkToFit=(v) Axlsx::validate_boolean v; @shrinkToFit = v end # @see readingOrder - def readingOrder=(v) Axlsx::validate_unsigned_int v; @readingOrder = v end + def readingOrder=(v) Axlsx::validate_unsigned_int v; @readingOrder = v end + def to_xml_string(str = '') + str << '' + end # Serializes the cell alignment # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. # @return [String] def to_xml(xml) - xml.alignment(self.instance_values) + xml.alignment(self.instance_values) end - + end end diff --git a/lib/axlsx/stylesheet/cell_protection.rb b/lib/axlsx/stylesheet/cell_protection.rb index 89d85289..b874b214 100644 --- a/lib/axlsx/stylesheet/cell_protection.rb +++ b/lib/axlsx/stylesheet/cell_protection.rb @@ -4,7 +4,7 @@ module Axlsx # @note Using Styles#add_style is the recommended way to manage cell protection. # @see Styles#add_style class CellProtection - + # specifies locking for cells that have the style containing this protection # @return [Boolean] attr_reader :hidden @@ -23,9 +23,15 @@ module Axlsx end # @see hidden - def hidden=(v) Axlsx::validate_boolean v; @hidden = v end + def hidden=(v) Axlsx::validate_boolean v; @hidden = v end # @see locked - def locked=(v) Axlsx::validate_boolean v; @locked = v end + def locked=(v) Axlsx::validate_boolean v; @locked = v end + + def to_xml_string(str = '') + str << '' + end # Serializes the cell protection # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. diff --git a/lib/axlsx/stylesheet/cell_style.rb b/lib/axlsx/stylesheet/cell_style.rb index 0a40ab13..22694ae1 100644 --- a/lib/axlsx/stylesheet/cell_style.rb +++ b/lib/axlsx/stylesheet/cell_style.rb @@ -7,7 +7,7 @@ module Axlsx # The name of this cell style # @return [String] attr_reader :name - + # The formatting record id this named style utilizes # @return [Integer] # @see Axlsx::Xf @@ -55,6 +55,13 @@ module Axlsx # @see customBuiltin def customBuiltin=(v) Axlsx::validate_boolean v; @customBuiltin = v end + + def to_xml_string(str = '') + str << '' + end + # Serializes the cell style # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. # @return [String] diff --git a/lib/axlsx/stylesheet/color.rb b/lib/axlsx/stylesheet/color.rb index 2a08fd3c..daedc9ed 100644 --- a/lib/axlsx/stylesheet/color.rb +++ b/lib/axlsx/stylesheet/color.rb @@ -61,10 +61,10 @@ module Axlsx # Indexed colors are for backward compatability which I am choosing not to support # def indexed=(v) Axlsx::validate_unsigned_integer v; @indexed = v end - def to_xml_string - str = "" end diff --git a/lib/axlsx/stylesheet/fill.rb b/lib/axlsx/stylesheet/fill.rb index 4dccaa8a..d6fde1c7 100644 --- a/lib/axlsx/stylesheet/fill.rb +++ b/lib/axlsx/stylesheet/fill.rb @@ -12,12 +12,18 @@ module Axlsx attr_reader :fill_type # Creates a new Fill object - # @param [PatternFill, GradientFill] fill_type + # @param [PatternFill, GradientFill] fill_type # @raise [ArgumentError] if the fill_type parameter is not a PatternFill or a GradientFill instance def initialize(fill_type) self.fill_type = fill_type end + + def to_xml_string(str = '') + str << '' + @fill_type.to_xml_string(str) + str << '' + end # Serializes the fill # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. # @return [String] diff --git a/lib/axlsx/stylesheet/font.rb b/lib/axlsx/stylesheet/font.rb index 1d9bc5d4..4bbcb487 100644 --- a/lib/axlsx/stylesheet/font.rb +++ b/lib/axlsx/stylesheet/font.rb @@ -7,7 +7,7 @@ module Axlsx # The name of the font # @return [String] attr_reader :name - + # The charset of the font # @return [Integer] # @note @@ -32,9 +32,9 @@ module Axlsx # 238 EASTEUROPE_CHARSET # 255 OEM_CHARSET attr_reader :charset - + # The font's family - # @note + # @note # The following are defined OOXML specification # 0 Not applicable. # 1 Roman @@ -107,13 +107,13 @@ module Axlsx end end # @see name - def name=(v) Axlsx::validate_string v; @name = v end + def name=(v) Axlsx::validate_string v; @name = v end # @see charset def charset=(v) Axlsx::validate_unsigned_int v; @charset = v end # @see family def family=(v) Axlsx::validate_unsigned_int v; @family = v end # @see b - def b=(v) Axlsx::validate_boolean v; @b = v end + def b=(v) Axlsx::validate_boolean v; @b = v end # @see i def i=(v) Axlsx::validate_boolean v; @i = v end # @see u @@ -123,7 +123,7 @@ module Axlsx # @see outline def outline=(v) Axlsx::validate_boolean v; @outline = v end # @see shadow - def shadow=(v) Axlsx::validate_boolean v; @shadow = v end + def shadow=(v) Axlsx::validate_boolean v; @shadow = v end # @see condense def condense=(v) Axlsx::validate_boolean v; @condense = v end # @see extend @@ -133,13 +133,22 @@ module Axlsx # @see sz def sz=(v) Axlsx::validate_unsigned_int v; @sz=v end + + def to_xml_string(str = '') + str << '' + instance_values.each do |k, v| + v.is_a?(Color) ? v.to_xml_string(str) : (str << '<' << k.to_s << ' val="' << v.to_s << '"/>') + end + str << '' + end + # Serializes the fill # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. # @return [String] def to_xml(xml) xml.font { self.instance_values.each do |k, v| - v.is_a?(Color) ? v.to_xml(xml) : xml.send(k, {:val => v}) + v.is_a?(Color) ? v.to_xml(xml) : xml.send(k, {:val => v}) end } end diff --git a/lib/axlsx/stylesheet/gradient_fill.rb b/lib/axlsx/stylesheet/gradient_fill.rb index 6090b570..2a789c6f 100644 --- a/lib/axlsx/stylesheet/gradient_fill.rb +++ b/lib/axlsx/stylesheet/gradient_fill.rb @@ -1,11 +1,11 @@ # encoding: UTF-8 module Axlsx # A GradientFill defines the color and positioning for gradiant cell fill. - # @see Open Office XML Part 1 §18.8.24 + # @see Open Office XML Part 1 §18.8.24 class GradientFill # The type of gradient. - # @note + # @note # valid options are # :linear # :path @@ -26,7 +26,7 @@ module Axlsx # Percentage format top # @return [Float] - attr_reader :top + attr_reader :top # Percentage format bottom # @return [Float] @@ -35,7 +35,7 @@ module Axlsx # Collection of stop objects # @return [SimpleTypedList] attr_reader :stop - + # Creates a new GradientFill object # @option options [Symbol] type # @option options [Float] degree @@ -52,18 +52,27 @@ module Axlsx end # @see type - def type=(v) Axlsx::validate_gradient_type v; @type = v end + def type=(v) Axlsx::validate_gradient_type v; @type = v end # @see degree - def degree=(v) Axlsx::validate_float v; @degree = v end + def degree=(v) Axlsx::validate_float v; @degree = v end # @see left - def left=(v) DataTypeValidator.validate "GradientFill.left", Float, v, lambda { |arg| arg >= 0.0 && arg <= 1.0}; @left = v end + def left=(v) DataTypeValidator.validate "GradientFill.left", Float, v, lambda { |arg| arg >= 0.0 && arg <= 1.0}; @left = v end # @see right - def right=(v) DataTypeValidator.validate "GradientFill.right", Float, v, lambda { |arg| arg >= 0.0 && arg <= 1.0}; @right = v end + def right=(v) DataTypeValidator.validate "GradientFill.right", Float, v, lambda { |arg| arg >= 0.0 && arg <= 1.0}; @right = v end # @see top - def top=(v) DataTypeValidator.validate "GradientFill.top", Float, v, lambda { |arg| arg >= 0.0 && arg <= 1.0}; @top = v end + def top=(v) DataTypeValidator.validate "GradientFill.top", Float, v, lambda { |arg| arg >= 0.0 && arg <= 1.0}; @top = v end # @see bottom - def bottom=(v) DataTypeValidator.validate "GradientFill.bottom", Float, v, lambda { |arg| arg >= 0.0 && arg <= 1.0}; @bottom= v end + def bottom=(v) DataTypeValidator.validate "GradientFill.bottom", Float, v, lambda { |arg| arg >= 0.0 && arg <= 1.0}; @bottom= v end + + def to_xml_string(str = '') + str << '' + @stop.each { |s| s.to_xml_string(str) } + str << '' + end # Serializes the gradientFill # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. # @return [String] diff --git a/lib/axlsx/stylesheet/gradient_stop.rb b/lib/axlsx/stylesheet/gradient_stop.rb index a05e6d33..aca26b79 100644 --- a/lib/axlsx/stylesheet/gradient_stop.rb +++ b/lib/axlsx/stylesheet/gradient_stop.rb @@ -1,7 +1,7 @@ # encoding: UTF-8 module Axlsx # The GradientStop object represents a color point in a gradient. - # @see Open Office XML Part 1 §18.8.24 + # @see Open Office XML Part 1 §18.8.24 class GradientStop # The color for this gradient stop # @return [Color] @@ -23,8 +23,13 @@ module Axlsx # @see color def color=(v) DataTypeValidator.validate "GradientStop.color", Color, v; @color=v end # @see position - def position=(v) DataTypeValidator.validate "GradientStop.position", Float, v, lambda { |arg| arg >= 0 && arg <= 1}; @position = v end + def position=(v) DataTypeValidator.validate "GradientStop.position", Float, v, lambda { |arg| arg >= 0 && arg <= 1}; @position = v end + def to_xml_string(str = '') + str << '' + self.color.to_xml_string(str) + str << '' + end # Serializes the gradientStop # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. # @return [String] diff --git a/lib/axlsx/stylesheet/num_fmt.rb b/lib/axlsx/stylesheet/num_fmt.rb index 261d5bb3..8c74382f 100644 --- a/lib/axlsx/stylesheet/num_fmt.rb +++ b/lib/axlsx/stylesheet/num_fmt.rb @@ -1,11 +1,11 @@ # encoding: UTF-8 module Axlsx - # A NumFmt object defines an identifier and formatting code for data in cells. + # A NumFmt object defines an identifier and formatting code for data in cells. # @note The recommended way to manage styles is Styles#add_style class NumFmt # @return [Integer] An unsinged integer referencing a standard or custom number format. # @note - # These are the known formats I can dig up. The constant NUM_FMT_PERCENT is 9, and uses the default % formatting. Axlsx also defines a few formats for date and time that are commonly used in asia as NUM_FMT_YYYYMMDD and NUM_FRM_YYYYMMDDHHMMSS. + # These are the known formats I can dig up. The constant NUM_FMT_PERCENT is 9, and uses the default % formatting. Axlsx also defines a few formats for date and time that are commonly used in asia as NUM_FMT_YYYYMMDD and NUM_FRM_YYYYMMDDHHMMSS. # 1 0 # 2 0.00 # 3 #,##0 @@ -40,7 +40,7 @@ module Axlsx # @see Axlsx attr_reader :numFmtId - # @return [String] The formatting to use for this number format. + # @return [String] The formatting to use for this number format. # @see http://support.microsoft.com/kb/264372 attr_reader :formatCode def initialize(options={}) @@ -56,9 +56,15 @@ module Axlsx # @see formatCode def formatCode=(v) Axlsx::validate_string v; @formatCode = v end + def to_xml_string(str = '') + str << '' + end + # Creates a numFmt element applying the instance values of this object as attributes. # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. - def to_xml(xml) xml.numFmt(self.instance_values) end + def to_xml(xml) xml.numFmt(self.instance_values) end end end diff --git a/lib/axlsx/stylesheet/pattern_fill.rb b/lib/axlsx/stylesheet/pattern_fill.rb index 79910ede..32d54d83 100644 --- a/lib/axlsx/stylesheet/pattern_fill.rb +++ b/lib/axlsx/stylesheet/pattern_fill.rb @@ -7,15 +7,15 @@ module Axlsx # The color to use for the the background in solid fills. # @return [Color] - attr_reader :fgColor + attr_reader :fgColor # The color to use for the background of the fill when the type is not solid. # @return [Color] attr_reader :bgColor # The pattern type to use - # @note - # patternType must be one of + # @note + # patternType must be one of # :none # :solid # :mediumGray @@ -53,14 +53,34 @@ module Axlsx # @see bgColor def bgColor=(v) DataTypeValidator.validate "PatternFill.bgColor", Color, v; @bgColor=v end # @see patternType - def patternType=(v) Axlsx::validate_pattern_type v; @patternType = v end + def patternType=(v) Axlsx::validate_pattern_type v; @patternType = v end + + def to_xml_string(str = '') + str << '' + if fgColor.is_a?(Color) + str << "" + end + + if bgColor.is_a?(Color) + str << "" + end + str << '' + end # Serializes the pattern fill # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. # @return [String] - def to_xml(xml) - xml.patternFill(:patternType => self.patternType) { - self.instance_values.reject { |k,v| k.to_sym == :patternType }.each { |k,v| xml.send(k, v.instance_values) } + def to_xml(xml) + xml.patternFill(:patternType => self.patternType) { + self.instance_values.reject { |k,v| k.to_sym == :patternType }.each { |k,v| xml.send(k, v.instance_values) } } end end diff --git a/lib/axlsx/stylesheet/styles.rb b/lib/axlsx/stylesheet/styles.rb index a05067cd..d8d33fa1 100644 --- a/lib/axlsx/stylesheet/styles.rb +++ b/lib/axlsx/stylesheet/styles.rb @@ -250,6 +250,14 @@ module Axlsx cellXfs << xf end + def to_xml_string(str = '') + str << '' + [: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 + str << '' + end + # Serializes the styles document # @return [String] def to_xml() diff --git a/lib/axlsx/stylesheet/table_style.rb b/lib/axlsx/stylesheet/table_style.rb index 4397cffb..3184c042 100644 --- a/lib/axlsx/stylesheet/table_style.rb +++ b/lib/axlsx/stylesheet/table_style.rb @@ -36,6 +36,17 @@ module Axlsx # @see table def table=(v) Axlsx::validate_boolean v; @table=v end + + def to_xml_string(str = '') + attr = self.instance_values.select { |k, v| [:name, :pivot, :table].include? k } + attr[:count] = self.size + str << '' + each { |table_style_el| table_style_el.to_xml_string(str) } + str << '' + end + # Serializes the table style # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. # @return [String] diff --git a/lib/axlsx/stylesheet/table_style_element.rb b/lib/axlsx/stylesheet/table_style_element.rb index a8901f0b..a5cf4c48 100644 --- a/lib/axlsx/stylesheet/table_style_element.rb +++ b/lib/axlsx/stylesheet/table_style_element.rb @@ -1,7 +1,7 @@ # encoding: UTF-8 module Axlsx - # an element of style that belongs to a table style. - # @note tables and table styles are not supported in this version. This class exists in preparation for that support. + # an element of style that belongs to a table style. + # @note tables and table styles are not supported in this version. This class exists in preparation for that support. class TableStyleElement # The type of style element. The following type are allowed # :wholeTable @@ -39,7 +39,7 @@ module Axlsx # @return [Integer] attr_reader :size - # The dxfId this style element points to + # The dxfId this style element points to # @return [Integer] attr_reader :dxfId @@ -62,6 +62,12 @@ module Axlsx # @see dxfId def dxfId=(v) Axlsx::validate_unsigned_int v; @dxfId = v end + def to_xml_string(str = '') + str << '' + end + # Serializes the table style element # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. # @return [String] diff --git a/lib/axlsx/stylesheet/table_styles.rb b/lib/axlsx/stylesheet/table_styles.rb index f0e9c904..5474c165 100644 --- a/lib/axlsx/stylesheet/table_styles.rb +++ b/lib/axlsx/stylesheet/table_styles.rb @@ -11,13 +11,13 @@ module Axlsx # The default pivot table style. The default value is 'PivotStyleLight6' # @return [String] attr_reader :defaultPivotStyle - + # Creates a new TableStyles object that is a container for TableStyle objects # @option options [String] defaultTableStyle # @option options [String] defaultPivotStyle def initialize(options={}) @defaultTableStyle = options[:defaultTableStyle] || "TableStyleMedium9" - @defaultPivotStyle = options[:defaultPivotStyle] || "PivotStyleLight16" + @defaultPivotStyle = options[:defaultPivotStyle] || "PivotStyleLight16" super TableStyle end # @see defaultTableStyle @@ -25,6 +25,17 @@ module Axlsx # @see defaultPivotStyle def defaultPivotStyle=(v) Axlsx::validate_string(v); @defaultPivotStyle = v; end + + def to_xml_string(str = '') + attr = self.instance_values.reject {|k, v| ![:defaultTableStyle, :defaultPivotStyle].include?(k.to_sym) } + attr[:count] = self.size + str << '' + each { |table_style| table_style.to_xml_string(str) } + str << '' + end + # Serializes the table styles element # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. # @return [String] diff --git a/lib/axlsx/stylesheet/xf.rb b/lib/axlsx/stylesheet/xf.rb index 7b55336b..e8e36301 100644 --- a/lib/axlsx/stylesheet/xf.rb +++ b/lib/axlsx/stylesheet/xf.rb @@ -22,7 +22,7 @@ module Axlsx # index (0 based) of the font to be used in this style # @return [Integer] attr_reader :fontId - + # index (0 based) of the fill to be used in this style # @return [Integer] attr_reader :fillId @@ -50,7 +50,7 @@ module Axlsx # indicates if the fontId should be applied # @return [Boolean] attr_reader :applyFont - + # indicates if the fillId should be applied # @return [Boolean] attr_reader :applyFill @@ -75,7 +75,7 @@ module Axlsx # @option options [Integer] xfId # @option options [Boolean] quotePrefix # @option options [Boolean] pivotButton - # @option options [Boolean] applyNumberFormat + # @option options [Boolean] applyNumberFormat # @option options [Boolean] applyFont # @option options [Boolean] applyFill # @option options [Boolean] applyBorder @@ -87,8 +87,8 @@ module Axlsx options.each do |o| self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}=" end - end - + end + # @see Xf#alignment def alignment=(v) DataTypeValidator.validate "Xf.alignment", CellAlignment, v; @alignment = v end @@ -96,35 +96,45 @@ module Axlsx def protection=(v) DataTypeValidator.validate "Xf.protection", CellProtection, v; @protection = v end # @see numFmtId - def numFmtId=(v) Axlsx::validate_unsigned_int v; @numFmtId = v end + def numFmtId=(v) Axlsx::validate_unsigned_int v; @numFmtId = v end # @see fontId - def fontId=(v) Axlsx::validate_unsigned_int v; @fontId = v end + def fontId=(v) Axlsx::validate_unsigned_int v; @fontId = v end # @see fillId - def fillId=(v) Axlsx::validate_unsigned_int v; @fillId = v end + def fillId=(v) Axlsx::validate_unsigned_int v; @fillId = v end # @see borderId - def borderId=(v) Axlsx::validate_unsigned_int v; @borderId = v end + def borderId=(v) Axlsx::validate_unsigned_int v; @borderId = v end # @see xfId - def xfId=(v) Axlsx::validate_unsigned_int v; @xfId = v end + def xfId=(v) Axlsx::validate_unsigned_int v; @xfId = v end # @see quotePrefix - def quotePrefix=(v) Axlsx::validate_boolean v; @quotePrefix = v end + def quotePrefix=(v) Axlsx::validate_boolean v; @quotePrefix = v end # @see pivotButton - def pivotButton=(v) Axlsx::validate_boolean v; @pivotButton = v end + def pivotButton=(v) Axlsx::validate_boolean v; @pivotButton = v end # @see applyNumberFormat - def applyNumberFormat=(v) Axlsx::validate_boolean v; @applyNumberFormat = v end + def applyNumberFormat=(v) Axlsx::validate_boolean v; @applyNumberFormat = v end # @see applyFont - def applyFont=(v) Axlsx::validate_boolean v; @applyFont = v end + def applyFont=(v) Axlsx::validate_boolean v; @applyFont = v end # @see applyFill - def applyFill=(v) Axlsx::validate_boolean v; @applyFill = v end + def applyFill=(v) Axlsx::validate_boolean v; @applyFill = v end # @see applyBorder - def applyBorder=(v) Axlsx::validate_boolean v; @applyBorder = v end + def applyBorder=(v) Axlsx::validate_boolean v; @applyBorder = v end # @see applyAlignment - def applyAlignment=(v) Axlsx::validate_boolean v; @applyAlignment = v end + def applyAlignment=(v) Axlsx::validate_boolean v; @applyAlignment = v end # @see applyProtection - def applyProtection=(v) Axlsx::validate_boolean v; @applyProtection = v end + def applyProtection=(v) Axlsx::validate_boolean v; @applyProtection = v end + + def to_xml_string(str = '') + str << '' + alignment.to_xml_string(str) if self.alignment + protection.to_xml_string(str) if self.protection + str << '' + end # Serializes the xf elemen # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. diff --git a/lib/axlsx/util/simple_typed_list.rb b/lib/axlsx/util/simple_typed_list.rb index ce34a9bb..8fc4795a 100644 --- a/lib/axlsx/util/simple_typed_list.rb +++ b/lib/axlsx/util/simple_typed_list.rb @@ -1,6 +1,6 @@ # encoding: UTF-8 module Axlsx - # A SimpleTypedList is a type restrictive collection that allows some of the methods from Array and supports basic xml serialization. + # A SimpleTypedList is a type restrictive collection that allows some of the methods from Array and supports basic xml serialization. # @private class SimpleTypedList # The class constants of allowed types @@ -12,14 +12,14 @@ module Axlsx attr_reader :locked_at # 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. + # 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. # @return [String] attr_reader :serialize_as # Creats a new typed list # @param [Array, Class] type An array of Class objects or a single Class object # @param [String] serialize The tag name to use in serialization - # @raise [ArgumentError] if all members of type are not Class objects + # @raise [ArgumentError] if all members of type are not Class objects def initialize type, serialize_as=nil if type.is_a? Array type.each { |item| raise ArgumentError, "All members of type must be Class objects" unless item.is_a? Class } @@ -39,7 +39,7 @@ module Axlsx @locked_at = @list.size self end - + def to_ary @list end @@ -58,7 +58,7 @@ module Axlsx def <<(v) DataTypeValidator.validate "SimpleTypedList.<<", @allowed_types, v @list << v - @list.size - 1 + @list.size - 1 end # alternate of << method @@ -104,14 +104,14 @@ module Axlsx 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 + # @note # the following methods are not allowed # :replace # :insert @@ -140,15 +140,23 @@ module Axlsx DELEGATES = Array.instance_methods - self.instance_methods - DESTRUCTIVE DELEGATES.each do |method| - class_eval %{ + class_eval %{ def #{method}(*args, &block) @list.send(:#{method}, *args, &block) end } end + def to_xml_string(str = '') + classname = @allowed_types[0].name.split('::').last + el_name = serialize_as || (classname[0,1].downcase + classname[1..-1]) + str << '<' << el_name << ' count="' << @list.size.to_s << '">' + @list.each { |item| item.to_xml_string(str) } + str << '' + end + # Serializes the list - # If the serialize_as property is set, it is used as the parent node name. + # If the serialize_as property is set, it is used as the parent node name. # If the serialize_as property is nil, the first item in the list of allowed_types will be used, having the first letter of the class changed to lower case. # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. # @return [String] @@ -159,6 +167,7 @@ module Axlsx @list.each { |item| item.to_xml(xml) } } end + end diff --git a/lib/schema/dc.xsd b/lib/schema/dc.xsd index b8315e7e..fffd1522 100644 --- a/lib/schema/dc.xsd +++ b/lib/schema/dc.xsd @@ -12,7 +12,7 @@ Created 2003-04-02 - Created by + Created by Tim Cole (t-cole3@uiuc.edu) Tom Habing (thabing@uiuc.edu) @@ -23,14 +23,14 @@ This schema declares XML elements for the 15 DC elements from the http://purl.org/dc/elements/1.1/ namespace. - It defines a complexType SimpleLiteral which permits mixed content + It defines a complexType SimpleLiteral which permits mixed content and makes the xml:lang attribute available. It disallows child elements by use of minOcccurs/maxOccurs. However, this complexType does permit the derivation of other complexTypes which would permit child elements. - All elements are declared as substitutable for the abstract element any, + All elements are declared as substitutable for the abstract element any, which means that the default type for all elements is dc:SimpleLiteral. @@ -49,7 +49,7 @@ It permits text content only with optional xml:lang attribute. Text is allowed because mixed="true", but sub-elements - are disallowed because minOccurs="0" and maxOccurs="0" + are disallowed because minOccurs="0" and maxOccurs="0" are on the xs:any tag. This complexType allows for restriction or extension permitting @@ -89,7 +89,7 @@ This group is included as a convenience for schema authors - who need to refer to all the elements in the + who need to refer to all the elements in the http://purl.org/dc/elements/1.1/ namespace. diff --git a/lib/schema/dcmitype.xsd b/lib/schema/dcmitype.xsd index 54d9da00..69fcb5bd 100644 --- a/lib/schema/dcmitype.xsd +++ b/lib/schema/dcmitype.xsd @@ -5,6 +5,8 @@ elementFormDefault="qualified" attributeFormDefault="unqualified"> + + DCMI Type Vocabulary XML Schema @@ -12,7 +14,7 @@ Created 2003-04-02 - Created by + Created by Tim Cole (t-cole3@uiuc.edu) Tom Habing (thabing@uiuc.edu) @@ -24,7 +26,7 @@ the allowable values for the DCMI Type Vocabulary. - + @@ -43,7 +45,7 @@ - + diff --git a/lib/schema/dcterms.xsd b/lib/schema/dcterms.xsd index 055a6edf..da22580e 100644 --- a/lib/schema/dcterms.xsd +++ b/lib/schema/dcterms.xsd @@ -14,7 +14,7 @@ Created 2003-04-02 - Created by + Created by Tim Cole (t-cole3@uiuc.edu) Tom Habing (thabing@uiuc.edu) @@ -24,7 +24,7 @@ This schema declares XML elements for the DC elements and DC element refinements from the http://purl.org/dc/terms/ namespace. - + It reuses the complexType dc:SimpleLiteral, imported from the dc.xsd schema, which permits simple element content, and makes the xml:lang attribute available. @@ -32,22 +32,22 @@ This complexType permits the derivation of other complexTypes which would permit child elements. - DC elements are declared as substitutable for the abstract element dc:any, and - DC element refinements are defined as substitutable for the base elements + DC elements are declared as substitutable for the abstract element dc:any, and + DC element refinements are defined as substitutable for the base elements which they refine. - This means that the default type for all XML elements (i.e. all DC elements and + This means that the default type for all XML elements (i.e. all DC elements and element refinements) is dc:SimpleLiteral. Encoding schemes are defined as complexTypes which are restrictions - of the dc:SimpleLiteral complexType. These complexTypes restrict + of the dc:SimpleLiteral complexType. These complexTypes restrict values to an appropriates syntax or format using data typing, regular expressions, or enumerated lists. - - In order to specify one of these encodings an xsi:type attribute must + + In order to specify one of these encodings an xsi:type attribute must be used in the instance document. - Also, note that one shortcoming of this approach is that any type can be + Also, note that one shortcoming of this approach is that any type can be applied to any of the elements or refinements. There is no convenient way to restrict types to specific elements using this approach. @@ -184,7 +184,7 @@ - + @@ -217,7 +217,7 @@ - + @@ -300,9 +300,9 @@ This group is included as a convenience for schema authors - who need to refer to all the DC elements and element refinements - in the http://purl.org/dc/elements/1.1/ and - http://purl.org/dc/terms namespaces. + who need to refer to all the DC elements and element refinements + in the http://purl.org/dc/elements/1.1/ and + http://purl.org/dc/terms namespaces. N.B. Refinements available via substitution groups. @@ -312,7 +312,7 @@ - + diff --git a/lib/schema/opc-coreProperties.xsd b/lib/schema/opc-coreProperties.xsd index a2d6cdac..2b7d5c1c 100644 --- a/lib/schema/opc-coreProperties.xsd +++ b/lib/schema/opc-coreProperties.xsd @@ -2,13 +2,17 @@ + xmlns:dcterms="http://purl.org/dc/terms/" + elementFormDefault="qualified" blockDefault="#all"> + - + + diff --git a/lib/schema/xml.xsd b/lib/schema/xml.xsd index d662b423..4f5ecc8b 100644 --- a/lib/schema/xml.xsd +++ b/lib/schema/xml.xsd @@ -1,6 +1,5 @@ - - + @@ -8,7 +7,7 @@ http://www.w3.org/TR/REC-xml for information about this namespace. This schema document describes the XML namespace, in a form - suitable for import by other schema documents. + suitable for import by other schema documents. Note that local names in this namespace are intended to be defined only by the World Wide Web Consortium or its subgroups. The @@ -26,16 +25,16 @@ is a language code for the natural language of the content of any element; its value is inherited. This name is reserved by virtue of its definition in the XML specification. - + space (as an attribute name): denotes an attribute whose value is a keyword indicating what whitespace processing discipline is intended for the content of the element; its value is inherited. This name is reserved by virtue of its definition in the XML specification. - Father (in any context at all): denotes Jon Bosak, the chair of - the original XML Working Group. This name is reserved by - the following decision of the W3C XML Plenary and + Father (in any context at all): denotes Jon Bosak, the chair of + the original XML Working Group. This name is reserved by + the following decision of the W3C XML Plenary and XML Coordination groups: In appreciation for his vision, leadership and dedication @@ -64,7 +63,7 @@ <type . . .> . . . <attributeGroup ref="xml:specialAttrs"/> - + will define a type which will schema-validate an instance element with any of those attributes diff --git a/test/drawing/tc_axis.rb b/test/drawing/tc_axis.rb index 234eba9c..c627b4d1 100644 --- a/test/drawing/tc_axis.rb +++ b/test/drawing/tc_axis.rb @@ -36,4 +36,9 @@ class TestAxis < Test::Unit::TestCase assert_nothing_raised("accepts valid crosses") { @axis.crosses = :min } end + def test_gridlines + assert_raise(ArgumentError, "requires valid gridlines") { @axis.gridlines = 'alice' } + assert_nothing_raised("accepts valid crosses") { @axis.gridlines = false } + end + end diff --git a/test/drawing/tc_bar_3D_chart.rb b/test/drawing/tc_bar_3D_chart.rb index 93997730..1f78fa0b 100644 --- a/test/drawing/tc_bar_3D_chart.rb +++ b/test/drawing/tc_bar_3D_chart.rb @@ -51,9 +51,9 @@ class TestBar3DChart < Test::Unit::TestCase assert(@chart.shape == :cone) end - def test_to_xml + def test_to_xml_string schema = Nokogiri::XML::Schema(File.open(Axlsx::DRAWING_XSD)) - doc = Nokogiri::XML(@chart.to_xml) + doc = Nokogiri::XML(@chart.to_xml_string) errors = [] schema.validate(doc).each do |error| errors.push error diff --git a/test/drawing/tc_chart.rb b/test/drawing/tc_chart.rb index c0e938cd..8047c018 100644 --- a/test/drawing/tc_chart.rb +++ b/test/drawing/tc_chart.rb @@ -58,9 +58,9 @@ class TestChart < Test::Unit::TestCase assert_equal(@chart.pn, "charts/chart1.xml") end - def test_to_xml + def test_to_xml_string schema = Nokogiri::XML::Schema(File.open(Axlsx::DRAWING_XSD)) - doc = Nokogiri::XML(@chart.to_xml) + doc = Nokogiri::XML(@chart.to_xml_string) errors = [] schema.validate(doc).each do |error| errors.push error diff --git a/test/drawing/tc_drawing.rb b/test/drawing/tc_drawing.rb index ac2dddbe..ce77ef9b 100644 --- a/test/drawing/tc_drawing.rb +++ b/test/drawing/tc_drawing.rb @@ -67,7 +67,7 @@ class TestDrawing < Test::Unit::TestCase def test_to_xml schema = Nokogiri::XML::Schema(File.open(Axlsx::DRAWING_XSD)) - doc = Nokogiri::XML(@ws.drawing.to_xml) + doc = Nokogiri::XML(@ws.drawing.to_xml_string) errors = [] schema.validate(doc).each do |error| errors.push error diff --git a/test/drawing/tc_line_3d_chart.rb b/test/drawing/tc_line_3d_chart.rb index 22dd6158..b419e00a 100644 --- a/test/drawing/tc_line_3d_chart.rb +++ b/test/drawing/tc_line_3d_chart.rb @@ -35,7 +35,7 @@ class TestLine3DChart < Test::Unit::TestCase def test_to_xml schema = Nokogiri::XML::Schema(File.open(Axlsx::DRAWING_XSD)) - doc = Nokogiri::XML(@chart.to_xml) + doc = Nokogiri::XML(@chart.to_xml_string) errors = [] schema.validate(doc).each do |error| errors.push error diff --git a/test/drawing/tc_pic.rb b/test/drawing/tc_pic.rb index 83ed4e1d..78750cbd 100644 --- a/test/drawing/tc_pic.rb +++ b/test/drawing/tc_pic.rb @@ -64,7 +64,7 @@ class TestPic < Test::Unit::TestCase def test_to_xml schema = Nokogiri::XML::Schema(File.open(Axlsx::DRAWING_XSD)) - doc = Nokogiri::XML(@image.anchor.drawing.to_xml) + doc = Nokogiri::XML(@image.anchor.drawing.to_xml_string) errors = [] schema.validate(doc).each do |error| errors.push error diff --git a/test/drawing/tc_pie_3D_chart.rb b/test/drawing/tc_pie_3D_chart.rb index 76bf49c5..5ac16e68 100644 --- a/test/drawing/tc_pie_3D_chart.rb +++ b/test/drawing/tc_pie_3D_chart.rb @@ -20,7 +20,7 @@ class TestPie3DChart < Test::Unit::TestCase def test_to_xml schema = Nokogiri::XML::Schema(File.open(Axlsx::DRAWING_XSD)) - doc = Nokogiri::XML(@chart.to_xml) + doc = Nokogiri::XML(@chart.to_xml_string) errors = [] schema.validate(doc).each do |error| errors.push error diff --git a/test/drawing/tc_scatter_chart.rb b/test/drawing/tc_scatter_chart.rb index 367cf56d..30178649 100644 --- a/test/drawing/tc_scatter_chart.rb +++ b/test/drawing/tc_scatter_chart.rb @@ -3,9 +3,20 @@ require 'tc_helper.rb' class TestScatterChart < Test::Unit::TestCase def setup @p = Axlsx::Package.new - ws = @p.workbook.add_worksheet - @row = ws.add_row ["one", 1, Time.now] - @chart = ws.add_chart Axlsx::ScatterChart, :title => "A Title" + @chart = nil + ws = @p.workbook.add_worksheet do |sheet| + sheet.add_row ["First", 1, 5, 7, 9] + sheet.add_row ["", 1, 25, 49, 81] + sheet.add_row ["Second", 5, 2, 14, 9] + sheet.add_row ["", 5, 10, 15, 20] + sheet.add_chart(Axlsx::ScatterChart, :title => "example 7: Scatter Chart") do |chart| + chart.start_at 0, 4 + chart.end_at 10, 19 + chart.add_series :xData => sheet["B1:E1"], :yData => sheet["B2:E2"], :title => sheet["A1"] + chart.add_series :xData => sheet["B3:E3"], :yData => sheet["B4:E4"], :title => sheet["A3"] + @chart = chart + end + end end def teardown @@ -18,9 +29,9 @@ class TestScatterChart < Test::Unit::TestCase assert(@chart.yValAxis.is_a?(Axlsx::ValAxis), "dependant value axis not created") end - def test_to_xml + def test_to_xml_string schema = Nokogiri::XML::Schema(File.open(Axlsx::DRAWING_XSD)) - doc = Nokogiri::XML(@chart.to_xml) + doc = Nokogiri::XML(@chart.to_xml_string) errors = [] schema.validate(doc).each do |error| errors.push error diff --git a/test/stylesheet/tc_styles.rb b/test/stylesheet/tc_styles.rb index 9db37157..ef14e151 100644 --- a/test/stylesheet/tc_styles.rb +++ b/test/stylesheet/tc_styles.rb @@ -9,7 +9,7 @@ class TestStyles < Test::Unit::TestCase def test_valid_document schema = Nokogiri::XML::Schema(File.open(Axlsx::SML_XSD)) - doc = Nokogiri::XML(@styles.to_xml) + doc = Nokogiri::XML(@styles.to_xml_string) errors = [] schema.validate(doc).each do |error| errors.push error -- cgit v1.2.3 From 2bac51473b5b656d7ef4a61052900878b47ec0b1 Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Sun, 1 Apr 2012 12:04:10 +0900 Subject: remove perftools from gemset. --- axlsx.gemspec | 1 - 1 file changed, 1 deletion(-) diff --git a/axlsx.gemspec b/axlsx.gemspec index d67401d3..c8fda02f 100644 --- a/axlsx.gemspec +++ b/axlsx.gemspec @@ -29,7 +29,6 @@ Gem::Specification.new do |s| s.add_development_dependency 'yard' s.add_development_dependency 'yard' s.add_development_dependency 'rdiscount' - s.add_development_dependency 'perftools.rb' s.required_ruby_version = '>= 1.8.7' s.require_path = 'lib' -- cgit v1.2.3 From 2156d67a49cc231201acc7c5526d15e1cd057324 Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Sun, 1 Apr 2012 12:09:31 +0900 Subject: update travis.yml to require 18mode and 19mode for jruby --- .travis.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index cd3e8091..1cb69a4a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,9 +9,11 @@ rvm: - 1.8.7 - 1.9.2 - 1.9.3 + - jruby-1.6.6 + - jruby-1.6.7 - jruby-18mode + - jruby-19mode - ruby-head matrix: allow_failures: - - rvm: jruby-18mode - rvm: ruby-head \ No newline at end of file -- cgit v1.2.3 From 8126297213b209d928911445cdc8ba520da08bb3 Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Sun, 1 Apr 2012 12:14:19 +0900 Subject: more travis matrix changes --- .travis.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1cb69a4a..3da4376a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,11 +9,8 @@ rvm: - 1.8.7 - 1.9.2 - 1.9.3 - - jruby-1.6.6 - jruby-1.6.7 - - jruby-18mode - - jruby-19mode - ruby-head matrix: allow_failures: - - rvm: ruby-head \ No newline at end of file + - rvm: ruby-head -- cgit v1.2.3 From 98235dc38925a2d7d9d496dfd8efe508bc69a132 Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Sun, 1 Apr 2012 12:21:08 +0900 Subject: version bump --- CHANGELOG.md | 14 +++++++++++--- README.md | 15 ++++++--------- lib/axlsx/version.rb | 2 +- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 20b466ce..9962a604 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ CHANGELOG --------- +- ** February.2.12**: 1.0.16 release + https://github.com/randym/axlsx/compare/1.0.15...1.0.16 + - Bug fix for schema file locations when validating in rails + - Added hyperlink to images + - date1904 now automatically set in BSD and mac environments + - removed whitespace/indentation from xml outputs + - col_style now skips rows that do not contain cells at the column index + - **January.6.12**: 1.0.15 release https://github.com/randym/axlsx/compare/1.0.14...1.0.15 - Bug fix add_style specified number formats must be explicity applied for libraOffice @@ -15,7 +23,7 @@ CHANGELOG - Updated examples to output to a single workbook with multiple sheets - Added access to app and core package objects so you can set the creator and other properties of the package - The beginning of password protected xlsx files - roadmapped for January release. - + - **December.8.11**: 1.0.13 release - Fixing .gemspec errors that caused gem to miss the lib directory. Sorry about that. @@ -62,7 +70,7 @@ CHANGELOG ##October.22.11: 1.0.6 release - Bumping version to include docs. Bug in gemspec pointing to incorrect directory. -##October.22.11: 1.05 +##October.22.11: 1.05 - Added support for line charts - Updated examples and readme - Updated series title to be a real title ** NOTE ** If you are accessing titles directly you will need to update text assignation. @@ -70,7 +78,7 @@ CHANGELOG chart.series.first.title.text = 'Your Title' With this change you can assign a cell for the series title chart.series.title = sheet.rows.first.cells.first - If you are using the recommended + If you are using the recommended chart.add_series :data=>[], :labels=>[], :title You do not have to change anything. - BugFix: shape attribute for bar chart is now properly serialized diff --git a/README.md b/README.md index dcef1f23..c489edea 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,9 @@ Axlsx: Office Open XML Spreadsheet Generation **Ruby Version**: 1.8.7, 1.9.2, 1.9.3 -**Release Date**: March 5th 2012 +**JRuby Version**: 1.6.7 + +**Release Date**: April 1st 2012 Synopsis -------- @@ -385,6 +387,8 @@ This gem has 100% test coverage using test/unit. To execute tests for this gem, - Support for tables added in - Note: Pre 2011 versions of Mac office do not support this feature. - Support for splatter charts added - Major performance updates. + - Gem now supports for JRuby 1.6.7 + - ** March.5.12**: 1.0.18 release https://github.com/randym/axlsx/compare/1.0.17...1.0.18 - bugfix custom borders are not properly applied when using styles.add_style @@ -402,13 +406,6 @@ This gem has 100% test coverage using test/unit. To execute tests for this gem, - Added in support for fixed column_widths - Removed unneeded dependencies on active-support and i18n -- ** February.2.12**: 1.0.16 release - https://github.com/randym/axlsx/compare/1.0.15...1.0.16 - - Bug fix for schema file locations when validating in rails - - Added hyperlink to images - - date1904 now automatically set in BSD and mac environments - - removed whitespace/indentation from xml outputs - - col_style now skips rows that do not contain cells at the column index Please see the {file:CHANGELOG.md} document for past release information. @@ -434,5 +431,5 @@ Please see the {file:CHANGELOG.md} document for past release information. #Copyright and License ---------- -Axlsx © 2011 by [Randy Morgan](mailto:digial.ipseity@gmail.com). Axlsx is +Axlsx © 2011-2012 by [Randy Morgan](mailto:digial.ipseity@gmail.com). Axlsx is licensed under the MIT license. Please see the {file:LICENSE} document for more information. diff --git a/lib/axlsx/version.rb b/lib/axlsx/version.rb index fba7c709..175371e8 100644 --- a/lib/axlsx/version.rb +++ b/lib/axlsx/version.rb @@ -5,6 +5,6 @@ module Axlsx # When using bunle exec rake and referencing the gem on github or locally # it will use the gemspec, which preloads this constant for the gem's version. # We check to make sure that it has not already been loaded - VERSION="1.0.18" unless Axlsx.const_defined? :VERSION + VERSION="1.1.0" unless Axlsx.const_defined? :VERSION end -- cgit v1.2.3 From 9590f0b830fa96cbc6f6465c2020adbf835a30f5 Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Sun, 1 Apr 2012 12:29:18 +0900 Subject: patch travis.yml --- .travis.yml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 3da4376a..06016342 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,8 +9,15 @@ rvm: - 1.8.7 - 1.9.2 - 1.9.3 - - jruby-1.6.7 + - jruby-18mode + - jruby-19mode - ruby-head + - jruby-head + - rbx-18mode + - rbx-19mode matrix: allow_failures: - rvm: ruby-head + - rvm: jruby-head + - rvm: rbx-18mode + - rvm: rbx-19mode -- cgit v1.2.3 From d0491f7a02124940d3b5a65de2fac3b6d26fe98c Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Sun, 1 Apr 2012 12:34:23 +0900 Subject: Add in Rubinius to required envs in travis --- .travis.yml | 7 +++---- README.md | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 06016342..e50bc626 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,14 +10,13 @@ rvm: - 1.9.2 - 1.9.3 - jruby-18mode + - rbx-18mode + - rbx-19mode - jruby-19mode - ruby-head - jruby-head - - rbx-18mode - - rbx-19mode matrix: allow_failures: - rvm: ruby-head - rvm: jruby-head - - rvm: rbx-18mode - - rvm: rbx-19mode + - rvm: jruby-19mode diff --git a/README.md b/README.md index c489edea..84ec50b0 100644 --- a/README.md +++ b/README.md @@ -387,7 +387,7 @@ This gem has 100% test coverage using test/unit. To execute tests for this gem, - Support for tables added in - Note: Pre 2011 versions of Mac office do not support this feature. - Support for splatter charts added - Major performance updates. - - Gem now supports for JRuby 1.6.7 + - Gem now supports for JRuby 1.6.7, as well as expirimental support for Rubinius - ** March.5.12**: 1.0.18 release https://github.com/randym/axlsx/compare/1.0.17...1.0.18 -- cgit v1.2.3 From 225edfc837e99167072fdf15e4ee3a5af9cfe96c Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Sun, 1 Apr 2012 12:48:00 +0900 Subject: revert mail notice address in travis.yml as google groups is set up to only allow members to post. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e50bc626..5fa532c1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ notifications: irc: "irc.freenode.org#axlsx" email: recipients: - - axlsx@googlegroups.com + - digital.ipseity@gmail.com on_success: always rvm: - 1.8.7 -- cgit v1.2.3 From bff4c5ecfa730c6f5af35577a5cb83562512866e Mon Sep 17 00:00:00 2001 From: Joe Kain Date: Sat, 31 Mar 2012 19:00:18 -0700 Subject: Test 3+ letter column references and indices. --- test/workbook/worksheet/tc_cell.rb | 40 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/test/workbook/worksheet/tc_cell.rb b/test/workbook/worksheet/tc_cell.rb index 4db0c7be..c35e62bc 100644 --- a/test/workbook/worksheet/tc_cell.rb +++ b/test/workbook/worksheet/tc_cell.rb @@ -13,6 +13,30 @@ class TestCell < Test::Unit::TestCase @cAA = @ws["AA2"] end + def setup_wide + # The wide row makes the test take a long time. Add it only + # in test_large as adding it in setup make all the tests take + # longer. + # + # For even more, but slower, testing use the 20000 cell row and + # uncomment the ABCD3 element below. + data = (0..1000).map { |index| index } + #data = (0..20000).map { |index| index } + @ws.add_row data + + @wide_test_points = { "A3" => 0, + "Z3" => 25, + "B3" => 1, + "AA3" => 1 * 26 + 0, + "AAA3" => 1 * 26**2 + 1 * 26 + 0, + "AAZ3" => 1 * 26**2 + 1 * 26 + 25, + "ABA3" => 1 * 26**2 + 2 * 26 + 0, + + # For additional testing, uncomment this line and uncomment the 20000 cell row above + #"ABCD3" => 1 * 26**3 + 2 * 26**2 + 3 * 26 + 3 + } + end + def test_initialize assert_equal(@row.cells.last, @c, "the cell was added to the row") assert_equal(@c.type, :float, "type option is applied") @@ -41,6 +65,22 @@ class TestCell < Test::Unit::TestCase assert_equal(@c.r, "A1", "calculate cell reference") end + def test_wide_index + setup_wide + @wide_test_points.each_pair do |ref, index| + c = @ws[ref] + assert_equal(c.index, index, "calculate cell index for cell #{ref}") + end + end + + def test_wide_r + setup_wide + @wide_test_points.each_pair do |ref, index| + c = @ws[ref] + assert_equal(c.r, ref, "calculate cell reference for cell at index #{index}") + end + end + def test_r_abs assert_equal(@c.r_abs,"$A$1", "calculate absolute cell reference") assert_equal(@cAA.r_abs,"$AA$2", "needs to accept multi-digit columns") -- cgit v1.2.3 From 44c77ed27b20c4ebe1c9c8faf6ad80701d7f567e Mon Sep 17 00:00:00 2001 From: Joe Kain Date: Sat, 31 Mar 2012 22:04:41 -0700 Subject: Fixes for 3+ letter columns In Axlsx::name_to_indices multiply by the base. In Axlsx::col_ref move the -1 into the loop, it applies to all but the first iteration. --- lib/axlsx.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/axlsx.rb b/lib/axlsx.rb index dd628562..46d1c9bf 100644 --- a/lib/axlsx.rb +++ b/lib/axlsx.rb @@ -57,7 +57,7 @@ module Axlsx def self.name_to_indices(name) raise ArgumentError, 'invalid cell name' unless name.size > 1 v = name[/[A-Z]+/].reverse.chars.reduce({:base=>1, :i=>0}) do |val, c| - val[:i] += ((c.bytes.first - 65) + val[:base]); val[:base] *= 26; val + val[:i] += ((c.bytes.first - 64) * val[:base]); val[:base] *= 26; val end [v[:i]-1, ((name[/[1-9][0-9]*/]).to_i)-1] @@ -71,9 +71,9 @@ module Axlsx chars = [] while index >= 26 do chars << ((index % 26) + 65).chr - index /= 26 + index = index / 26 - 1 end - chars << ((chars.empty? ? index : index-1) + 65).chr + chars << (index + 65).chr chars.reverse.join end -- cgit v1.2.3 From 5a567dd9fad7cb4739c92d2dda3faba8d50225b6 Mon Sep 17 00:00:00 2001 From: Jurriaan Pruis Date: Sun, 1 Apr 2012 15:48:08 +0200 Subject: Fixed formula handling --- lib/axlsx/workbook/worksheet/cell.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/axlsx/workbook/worksheet/cell.rb b/lib/axlsx/workbook/worksheet/cell.rb index 13140786..cb8dd61b 100644 --- a/lib/axlsx/workbook/worksheet/cell.rb +++ b/lib/axlsx/workbook/worksheet/cell.rb @@ -315,7 +315,7 @@ module Axlsx when :string #parse formula if @value.start_with?('=') - str << 't="str">' << value.to_s.gsub('=', '') << '' + str << 't="str">' << @value.to_s.gsub('=', '') << '' else #parse shared if @ssti -- cgit v1.2.3 From 16f19d36a774a578f4a6892caab320dd262b8e71 Mon Sep 17 00:00:00 2001 From: Jurriaan Pruis Date: Sun, 1 Apr 2012 15:48:37 +0200 Subject: String table ignore nil values --- lib/axlsx/workbook/shared_strings_table.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/axlsx/workbook/shared_strings_table.rb b/lib/axlsx/workbook/shared_strings_table.rb index dac8221f..332a4470 100644 --- a/lib/axlsx/workbook/shared_strings_table.rb +++ b/lib/axlsx/workbook/shared_strings_table.rb @@ -29,7 +29,7 @@ module Axlsx # Creates a new Shared Strings Table agains an array of cells # @param [Array] cells This is an array of all of the cells in the workbook def initialize(cells) - cells = cells.flatten.reject { |c| c.type != :string || c.value.start_with?('=') } + cells = cells.flatten.reject { |c| c.type != :string || c.value.nil? || c.value.start_with?('=') } @count = cells.size @unique_cells = [] @shared_xml_string = "" -- cgit v1.2.3 From 24079401c00af3b000644a57b82627556deea596 Mon Sep 17 00:00:00 2001 From: Jurriaan Pruis Date: Sun, 1 Apr 2012 15:49:13 +0200 Subject: Skip cells with nil values --- examples/example.rb | 3 ++- lib/axlsx/workbook/worksheet/cell.rb | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/examples/example.rb b/examples/example.rb index 04ad6f4c..d93f5dcc 100644 --- a/examples/example.rb +++ b/examples/example.rb @@ -266,7 +266,8 @@ end wb.add_worksheet(:name => "custom column widths") do |sheet| sheet.add_row ["I use autowidth and am very wide", "I use a custom width and am narrow"] - sheet.column_widths nil, 3 + sheet.add_row ['abcdefg', 'This is a very long text and should flow into the right cell', nil, 'xxx' ] + sheet.column_widths nil, 3, 5, nil end ##Fit to page printing diff --git a/lib/axlsx/workbook/worksheet/cell.rb b/lib/axlsx/workbook/worksheet/cell.rb index cb8dd61b..48e77e31 100644 --- a/lib/axlsx/workbook/worksheet/cell.rb +++ b/lib/axlsx/workbook/worksheet/cell.rb @@ -310,6 +310,7 @@ module Axlsx # @param [String] str The string index the cell content will be appended to. Defaults to empty string. # @return [String] xml text for the cell def to_xml_string(r_index, c_index, str = '') + return str if @value.nil? str << ' Date: Mon, 2 Apr 2012 20:09:33 +0900 Subject: move axlsx.rb helper methods into separate test suite. --- test/tc_axlsx.rb | 39 ++++++++++++++++++++++++++++++++++++++ test/workbook/worksheet/tc_cell.rb | 38 +------------------------------------ 2 files changed, 40 insertions(+), 37 deletions(-) create mode 100644 test/tc_axlsx.rb diff --git a/test/tc_axlsx.rb b/test/tc_axlsx.rb new file mode 100644 index 00000000..fe3b7edd --- /dev/null +++ b/test/tc_axlsx.rb @@ -0,0 +1,39 @@ +require 'tc_helper.rb' + +class TestAxlsx < Test::Unit::TestCase + + def setup_wide + @wide_test_points = { "A3" => 0, + "Z3" => 25, + "B3" => 1, + "AA3" => 1 * 26 + 0, + "AAA3" => 1 * 26**2 + 1 * 26 + 0, + "AAZ3" => 1 * 26**2 + 1 * 26 + 25, + "ABA3" => 1 * 26**2 + 2 * 26 + 0, + "BZU3" => 2 * 26**2 + 26 * 26 + 20 + } + end + + def test_cell_range + #To do + end + + def test_name_to_indices + setup_wide + @wide_test_points.each do |key, value| + assert_equal(Axlsx.name_to_indices(key), [value,2]) + end + end + + def test_col_ref + setup_wide + @wide_test_points.each do |key, value| + assert_equal(Axlsx.col_ref(value), key.gsub(/\d+/, '')) + end + end + + def test_cell_r + # todo + end + +end diff --git a/test/workbook/worksheet/tc_cell.rb b/test/workbook/worksheet/tc_cell.rb index c35e62bc..2313a8ba 100644 --- a/test/workbook/worksheet/tc_cell.rb +++ b/test/workbook/worksheet/tc_cell.rb @@ -13,30 +13,6 @@ class TestCell < Test::Unit::TestCase @cAA = @ws["AA2"] end - def setup_wide - # The wide row makes the test take a long time. Add it only - # in test_large as adding it in setup make all the tests take - # longer. - # - # For even more, but slower, testing use the 20000 cell row and - # uncomment the ABCD3 element below. - data = (0..1000).map { |index| index } - #data = (0..20000).map { |index| index } - @ws.add_row data - - @wide_test_points = { "A3" => 0, - "Z3" => 25, - "B3" => 1, - "AA3" => 1 * 26 + 0, - "AAA3" => 1 * 26**2 + 1 * 26 + 0, - "AAZ3" => 1 * 26**2 + 1 * 26 + 25, - "ABA3" => 1 * 26**2 + 2 * 26 + 0, - - # For additional testing, uncomment this line and uncomment the 20000 cell row above - #"ABCD3" => 1 * 26**3 + 2 * 26**2 + 3 * 26 + 3 - } - end - def test_initialize assert_equal(@row.cells.last, @c, "the cell was added to the row") assert_equal(@c.type, :float, "type option is applied") @@ -65,20 +41,8 @@ class TestCell < Test::Unit::TestCase assert_equal(@c.r, "A1", "calculate cell reference") end - def test_wide_index - setup_wide - @wide_test_points.each_pair do |ref, index| - c = @ws[ref] - assert_equal(c.index, index, "calculate cell index for cell #{ref}") - end - end - def test_wide_r - setup_wide - @wide_test_points.each_pair do |ref, index| - c = @ws[ref] - assert_equal(c.r, ref, "calculate cell reference for cell at index #{index}") - end + assert_equal(@cAA.r, "AA2", "calculate cell reference") end def test_r_abs -- cgit v1.2.3 From 32c027461698a81142772d60f142996f2fa2e113 Mon Sep 17 00:00:00 2001 From: Jurriaan Pruis Date: Mon, 2 Apr 2012 13:48:14 +0200 Subject: Support nil cells for all types --- lib/axlsx/workbook/worksheet/cell.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/axlsx/workbook/worksheet/cell.rb b/lib/axlsx/workbook/worksheet/cell.rb index 48e77e31..6f90dfa7 100644 --- a/lib/axlsx/workbook/worksheet/cell.rb +++ b/lib/axlsx/workbook/worksheet/cell.rb @@ -386,6 +386,7 @@ module Axlsx # About Time - Time in OOXML is *different* from what you might expect. The history as to why is interesting, but you can safely assume that if you are generating docs on a mac, you will want to specify Workbook.1904 as true when using time typed values. # @see Axlsx#date1904 def cast_value(v) + return nil if v.nil? if @type == :date self.style = STYLE_DATE if self.style == 0 v @@ -399,7 +400,6 @@ module Axlsx elsif @type == :boolean v ? 1 : 0 else - return nil if v.nil? @type = :string ::CGI.escapeHTML(v.to_s) end -- cgit v1.2.3 From d2b1274f7bf6058e484158cfd78b4ba7212f91b2 Mon Sep 17 00:00:00 2001 From: Jurriaan Pruis Date: Mon, 2 Apr 2012 13:48:35 +0200 Subject: Updated tests for nil cells --- test/workbook/worksheet/tc_cell.rb | 4 +++- test/workbook/worksheet/tc_row.rb | 13 +++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/test/workbook/worksheet/tc_cell.rb b/test/workbook/worksheet/tc_cell.rb index 4db0c7be..44cbf20a 100644 --- a/test/workbook/worksheet/tc_cell.rb +++ b/test/workbook/worksheet/tc_cell.rb @@ -94,7 +94,9 @@ class TestCell < Test::Unit::TestCase @c.type = :float assert_equal(@c.send(:cast_value, "1.0"), 1.0) @c.type = :string - assert_equal(@c.send(:cast_value, nil), "") + assert_equal(@c.send(:cast_value, nil), nil) + @c.type = :float + assert_equal(@c.send(:cast_value, nil), nil) @c.type = :boolean assert_equal(@c.send(:cast_value, true), 1) assert_equal(@c.send(:cast_value, false), 0) diff --git a/test/workbook/worksheet/tc_row.rb b/test/workbook/worksheet/tc_row.rb index d1507aa1..a953566e 100644 --- a/test/workbook/worksheet/tc_row.rb +++ b/test/workbook/worksheet/tc_row.rb @@ -27,6 +27,19 @@ class TestRow < Test::Unit::TestCase r.cells.each { |c| assert_equal(c.style,1) } end + def test_nil_cells + row = @ws.add_row([nil,1,2,nil,4,5,nil]) + r_s_xml = Nokogiri::XML(row.to_xml_string(0, '')) + assert_equal(r_s_xml.xpath(".//row/c").size, 4) + end + + def test_nil_cell_r + row = @ws.add_row([nil,1,2,nil,4,5,nil]) + r_s_xml = Nokogiri::XML(row.to_xml_string(0, '')) + assert_equal(r_s_xml.xpath(".//row/c").first['r'], 'B1') + assert_equal(r_s_xml.xpath(".//row/c").last['r'], 'F1') + end + def test_index assert_equal(@row.index, @row.worksheet.rows.index(@row)) end -- cgit v1.2.3 From 7df172a8f3815e1291f41098705650afd5a2b41d Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Tue, 3 Apr 2012 08:38:37 +0900 Subject: pre-release cleanup --- README.md | 14 ++++---- lib/axlsx/content_type/content_type.rb | 5 +-- lib/axlsx/content_type/default.rb | 3 ++ lib/axlsx/content_type/override.rb | 4 ++- lib/axlsx/drawing/axis.rb | 3 ++ lib/axlsx/drawing/bar_3D_chart.rb | 3 ++ lib/axlsx/drawing/bar_series.rb | 3 ++ lib/axlsx/drawing/cat_axis.rb | 4 ++- lib/axlsx/drawing/cat_axis_data.rb | 4 ++- lib/axlsx/drawing/chart.rb | 4 ++- lib/axlsx/drawing/drawing.rb | 3 ++ lib/axlsx/drawing/graphic_frame.rb | 3 ++ lib/axlsx/drawing/hyperlink.rb | 3 ++ lib/axlsx/drawing/line_3D_chart.rb | 3 ++ lib/axlsx/drawing/line_series.rb | 3 ++ lib/axlsx/drawing/marker.rb | 3 ++ lib/axlsx/drawing/named_axis_data.rb | 8 ++++- lib/axlsx/drawing/one_cell_anchor.rb | 3 ++ lib/axlsx/drawing/pic.rb | 3 ++ lib/axlsx/drawing/picture_locking.rb | 3 ++ lib/axlsx/drawing/pie_3D_chart.rb | 3 ++ lib/axlsx/drawing/pie_series.rb | 4 +++ lib/axlsx/drawing/scaling.rb | 3 ++ lib/axlsx/drawing/scatter_chart.rb | 22 ++++++++++++ lib/axlsx/drawing/scatter_series.rb | 11 ++++++ lib/axlsx/drawing/ser_axis.rb | 3 ++ lib/axlsx/drawing/series.rb | 3 ++ lib/axlsx/drawing/series_title.rb | 3 ++ lib/axlsx/drawing/title.rb | 3 ++ lib/axlsx/drawing/two_cell_anchor.rb | 3 ++ lib/axlsx/drawing/val_axis.rb | 3 ++ lib/axlsx/drawing/val_axis_data.rb | 3 ++ lib/axlsx/drawing/view_3D.rb | 3 ++ lib/axlsx/stylesheet/border.rb | 14 ++------ lib/axlsx/stylesheet/border_pr.rb | 11 ++---- lib/axlsx/stylesheet/cell_alignment.rb | 9 ++--- lib/axlsx/stylesheet/cell_protection.rb | 9 ++--- lib/axlsx/stylesheet/cell_style.rb | 10 ++---- lib/axlsx/stylesheet/color.rb | 7 ++-- lib/axlsx/stylesheet/fill.rb | 10 ++---- lib/axlsx/stylesheet/font.rb | 15 ++------ lib/axlsx/stylesheet/gradient_fill.rb | 12 ++----- lib/axlsx/stylesheet/gradient_stop.rb | 7 ++-- lib/axlsx/stylesheet/num_fmt.rb | 8 ++--- lib/axlsx/stylesheet/pattern_fill.rb | 11 ++---- lib/axlsx/stylesheet/styles.rb | 20 +++-------- lib/axlsx/stylesheet/table_style.rb | 12 ++----- lib/axlsx/stylesheet/table_style_element.rb | 9 ++--- lib/axlsx/stylesheet/table_styles.rb | 14 ++------ lib/axlsx/stylesheet/xf.rb | 12 ++----- lib/axlsx/util/constants.rb | 3 +- lib/axlsx/util/validators.rb | 7 ++++ lib/axlsx/version.rb | 2 +- lib/axlsx/workbook/shared_strings_table.rb | 17 ++-------- lib/axlsx/workbook/worksheet/cell.rb | 3 -- lib/axlsx/workbook/worksheet/page_margins.rb | 4 +-- lib/axlsx/workbook/worksheet/table.rb | 3 ++ lib/axlsx/workbook/worksheet/worksheet.rb | 51 ++-------------------------- 58 files changed, 209 insertions(+), 220 deletions(-) diff --git a/README.md b/README.md index 84ec50b0..796be891 100644 --- a/README.md +++ b/README.md @@ -14,13 +14,13 @@ Axlsx: Office Open XML Spreadsheet Generation **License**: MIT License -**Latest Version**: 1.0.18 +**Latest Version**: 1.1.0 **Ruby Version**: 1.8.7, 1.9.2, 1.9.3 **JRuby Version**: 1.6.7 -**Release Date**: April 1st 2012 +**Release Date**: April 2st 2012 Synopsis -------- @@ -374,7 +374,7 @@ This gem has 100% test coverage using test/unit. To execute tests for this gem, #Change log --------- -- ** March.??.12**: 1.0.19 release +- ** April.2.12**: 1.1.0 release - bugfix patch name_to_indecies to properly handle extended ranges. - bugfix properly serialize chart title. - lower rake minimum requirement for 1.8.7 apps that don't want to move on to 0.9 NOTE this will be reverted for 2.0.0 with workbook parsing! @@ -382,11 +382,11 @@ This gem has 100% test coverage using test/unit. To execute tests for this gem, - added support for turning off gridlines in charts. - added support for turning off gridlines in worksheet. - bugfix some apps like libraoffice require apply[x] attributes to be true. applyAlignment is now properly set. - - added option to *not* use RMagick - and default all assigned columns to the excel default of 8.43 - - added border style specification to styles#add_style - now you can pass in :border => {:style => :thin, :color =>"0000FF"} instead of creating a border object and border parts manually each time. - - Support for tables added in - Note: Pre 2011 versions of Mac office do not support this feature. + - added option use_autowidth. When this is false RMagick will not be loaded or used in the stack. However it is still a requirement in the gem. + - added border style specification to styles#add_style. See the example in the readme. + - Support for tables added in - Note: Pre 2011 versions of Mac office do not support this feature and will warn. - Support for splatter charts added - - Major performance updates. + - Major (like 7x faster!) performance updates. - Gem now supports for JRuby 1.6.7, as well as expirimental support for Rubinius - ** March.5.12**: 1.0.18 release diff --git a/lib/axlsx/content_type/content_type.rb b/lib/axlsx/content_type/content_type.rb index 6b4facd0..003991c7 100644 --- a/lib/axlsx/content_type/content_type.rb +++ b/lib/axlsx/content_type/content_type.rb @@ -10,8 +10,9 @@ module Axlsx super [Override, Default] end - # serialize the content types - # @return [String] str + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') str << '' str << '' diff --git a/lib/axlsx/content_type/default.rb b/lib/axlsx/content_type/default.rb index 2ff24527..c7cedd14 100644 --- a/lib/axlsx/content_type/default.rb +++ b/lib/axlsx/content_type/default.rb @@ -28,6 +28,9 @@ module Axlsx # @see Axlsx#validate_content_type def ContentType=(v) Axlsx::validate_content_type v; @ContentType = v end + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') str << '' @scaling.to_xml_string str diff --git a/lib/axlsx/drawing/bar_3D_chart.rb b/lib/axlsx/drawing/bar_3D_chart.rb index f623ab9f..abed702b 100644 --- a/lib/axlsx/drawing/bar_3D_chart.rb +++ b/lib/axlsx/drawing/bar_3D_chart.rb @@ -105,6 +105,9 @@ module Axlsx @shape = v end + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') super(str) do |str_inner| str_inner << '' diff --git a/lib/axlsx/drawing/bar_series.rb b/lib/axlsx/drawing/bar_series.rb index 65cd87d9..86ae6367 100644 --- a/lib/axlsx/drawing/bar_series.rb +++ b/lib/axlsx/drawing/bar_series.rb @@ -40,6 +40,9 @@ module Axlsx @shape = v end + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') super(str) do |str_inner| @labels.to_xml_string(str_inner) unless @labels.nil? diff --git a/lib/axlsx/drawing/cat_axis.rb b/lib/axlsx/drawing/cat_axis.rb index 66f21943..a961d736 100644 --- a/lib/axlsx/drawing/cat_axis.rb +++ b/lib/axlsx/drawing/cat_axis.rb @@ -47,7 +47,9 @@ module Axlsx # must be between a string between 0 and 1000 def lblOffset=(v) RegexValidator.validate "#{self.class}.lblOffset", LBL_OFFSET_REGEX, v; @lblOffset = v; end - + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') str << '' super(str) diff --git a/lib/axlsx/drawing/cat_axis_data.rb b/lib/axlsx/drawing/cat_axis_data.rb index ced5a305..30df1132 100644 --- a/lib/axlsx/drawing/cat_axis_data.rb +++ b/lib/axlsx/drawing/cat_axis_data.rb @@ -11,7 +11,9 @@ module Axlsx data.each { |i| @list << i } if data.is_a?(SimpleTypedList) end - + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') str << '' str << '' diff --git a/lib/axlsx/drawing/chart.rb b/lib/axlsx/drawing/chart.rb index 65140d66..62bff861 100644 --- a/lib/axlsx/drawing/chart.rb +++ b/lib/axlsx/drawing/chart.rb @@ -113,7 +113,9 @@ module Axlsx @series.last end - + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') str << '' str << '' diff --git a/lib/axlsx/drawing/drawing.rb b/lib/axlsx/drawing/drawing.rb index d9241f29..1267d22e 100644 --- a/lib/axlsx/drawing/drawing.rb +++ b/lib/axlsx/drawing/drawing.rb @@ -138,6 +138,9 @@ module Axlsx r end + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') str << '' str << '' diff --git a/lib/axlsx/drawing/graphic_frame.rb b/lib/axlsx/drawing/graphic_frame.rb index d123e58a..6466a656 100644 --- a/lib/axlsx/drawing/graphic_frame.rb +++ b/lib/axlsx/drawing/graphic_frame.rb @@ -28,6 +28,9 @@ module Axlsx "rId#{@anchor.index+1}" end + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') str << '' str << '' diff --git a/lib/axlsx/drawing/hyperlink.rb b/lib/axlsx/drawing/hyperlink.rb index ae217f31..6caebb6e 100644 --- a/lib/axlsx/drawing/hyperlink.rb +++ b/lib/axlsx/drawing/hyperlink.rb @@ -73,6 +73,9 @@ module Axlsx end + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') h = self.instance_values.merge({:'r:id' => "rId#{id}", :'xmlns:r' => XML_NS_R }) h.delete('href') diff --git a/lib/axlsx/drawing/line_3D_chart.rb b/lib/axlsx/drawing/line_3D_chart.rb index 74c10850..0f8a07f8 100644 --- a/lib/axlsx/drawing/line_3D_chart.rb +++ b/lib/axlsx/drawing/line_3D_chart.rb @@ -85,6 +85,9 @@ module Axlsx @gapDepth=(v) end + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') super(str) do |str_inner| str_inner << '' diff --git a/lib/axlsx/drawing/line_series.rb b/lib/axlsx/drawing/line_series.rb index 136408dd..ac3840f1 100644 --- a/lib/axlsx/drawing/line_series.rb +++ b/lib/axlsx/drawing/line_series.rb @@ -25,6 +25,9 @@ module Axlsx @data = ValAxisData.new(options[:data]) unless options[:data].nil? end + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') super(str) do @labels.to_xml_string(str) unless @labels.nil? diff --git a/lib/axlsx/drawing/marker.rb b/lib/axlsx/drawing/marker.rb index 985cf321..8da9477e 100644 --- a/lib/axlsx/drawing/marker.rb +++ b/lib/axlsx/drawing/marker.rb @@ -50,6 +50,9 @@ module Axlsx self.row = row end + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') [:col, :colOff, :row, :rowOff].each do |k| str << '' << self.send(k).to_s << '' diff --git a/lib/axlsx/drawing/named_axis_data.rb b/lib/axlsx/drawing/named_axis_data.rb index 952dc10e..218057ed 100644 --- a/lib/axlsx/drawing/named_axis_data.rb +++ b/lib/axlsx/drawing/named_axis_data.rb @@ -1,14 +1,20 @@ # encoding: UTF-8 +# TODO: review cat, val and named access data to extend this and reduce replicated code. module Axlsx # The ValAxisData class manages the values for a chart value series. class NamedAxisData < CatAxisData + # creates a new NamedAxisData Object + # @param [String] name The serialized node name for the axis data object + # @param [Array] The data to associate with the axis data object def initialize(name, data=[]) super(data) @name = name end - + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') str << '' str << '' diff --git a/lib/axlsx/drawing/one_cell_anchor.rb b/lib/axlsx/drawing/one_cell_anchor.rb index fd33892c..9a202cc1 100644 --- a/lib/axlsx/drawing/one_cell_anchor.rb +++ b/lib/axlsx/drawing/one_cell_anchor.rb @@ -62,6 +62,9 @@ module Axlsx end + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') str << '' str << '' diff --git a/lib/axlsx/drawing/pic.rb b/lib/axlsx/drawing/pic.rb index 733dc1df..e5e005fa 100644 --- a/lib/axlsx/drawing/pic.rb +++ b/lib/axlsx/drawing/pic.rb @@ -144,6 +144,9 @@ module Axlsx @anchor.from.row = y end + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') str << '' str << '' diff --git a/lib/axlsx/drawing/picture_locking.rb b/lib/axlsx/drawing/picture_locking.rb index 867e32b4..0d6f4e54 100644 --- a/lib/axlsx/drawing/picture_locking.rb +++ b/lib/axlsx/drawing/picture_locking.rb @@ -63,6 +63,9 @@ module Axlsx # @see noChangeShapeType def noChangeShapeType=(v) Axlsx::validate_boolean v; @noChangeShapeType = v end + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') str << '30, :perspective=>30}.merge(options)) end + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') super(str) do |str_inner| str_inner << '' diff --git a/lib/axlsx/drawing/pie_series.rb b/lib/axlsx/drawing/pie_series.rb index bf61c9ab..0deac1be 100644 --- a/lib/axlsx/drawing/pie_series.rb +++ b/lib/axlsx/drawing/pie_series.rb @@ -1,5 +1,6 @@ # encoding: UTF-8 module Axlsx + # A PieSeries defines the data and labels and explosion for pie charts series. # @note The recommended way to manage series is to use Chart#add_series # @see Worksheet#add_chart @@ -34,6 +35,9 @@ module Axlsx # @see explosion def explosion=(v) Axlsx::validate_unsigned_int(v); @explosion = v; end + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') super(str) do |str_inner| str_inner << '' unless @explosion.nil? diff --git a/lib/axlsx/drawing/scaling.rb b/lib/axlsx/drawing/scaling.rb index af9cf2aa..29333bc7 100644 --- a/lib/axlsx/drawing/scaling.rb +++ b/lib/axlsx/drawing/scaling.rb @@ -44,6 +44,9 @@ module Axlsx # @see min def min=(v) DataTypeValidator.validate "Scaling.min", Float, v; @min = v; end + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') str << '' str << '' unless @logBase.nil? diff --git a/lib/axlsx/drawing/scatter_chart.rb b/lib/axlsx/drawing/scatter_chart.rb index d8d7bb6d..1495a907 100644 --- a/lib/axlsx/drawing/scatter_chart.rb +++ b/lib/axlsx/drawing/scatter_chart.rb @@ -1,6 +1,15 @@ # encoding: UTF-8 module Axlsx + + # The ScatterChart allows you to insert a scatter chart into your worksheet + # @see Worksheet#add_chart + # @see Chart#add_series + # @see README for an example class ScatterChart < Chart + + # The Style for the scatter chart + # must be one of :none | :line | :lineMarker | :marker | :smooth | :smoothMarker + # return [Symbol] attr_reader :scatterStyle # the x value axis @@ -11,6 +20,7 @@ module Axlsx # @return [ValAxis] attr_reader :yValAxis + # Creates a new scatter chart def initialize(frame, options={}) @scatterStyle = :lineMarker @xValAxId = rand(8 ** 8) @@ -19,8 +29,20 @@ module Axlsx @yValAxis = ValAxis.new(@yValAxId, @xValAxId) super(frame, options) @series_type = ScatterSeries + options.each do |o| + self.send("#{o[0]}=", o[1]) if self.respond_to? "#{o[0]}=" + end + end + + # see #scatterStyle + def scatterStyle=(v) + Axlsx.validate_scatter_style(v) + @scatterStyle = v end + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') super do |str| str << '' diff --git a/lib/axlsx/drawing/scatter_series.rb b/lib/axlsx/drawing/scatter_series.rb index 03b2cbdd..2469e0bf 100644 --- a/lib/axlsx/drawing/scatter_series.rb +++ b/lib/axlsx/drawing/scatter_series.rb @@ -1,6 +1,13 @@ # encoding: UTF-8 module Axlsx + + # A ScatterSeries defines the x and y position of data in the chart + # @note The recommended way to manage series is to use Chart#add_series + # @see Worksheet#add_chart + # @see Chart#add_series + # @see examples/example.rb class ScatterSeries < Series + # The x data for this series. # @return [NamedAxisData] attr_reader :xData @@ -9,6 +16,7 @@ module Axlsx # @return [NamedAxisData] attr_reader :yData + # Creates a new ScatterSeries def initialize(chart, options={}) @xData, @yData = nil super(chart, options) @@ -17,6 +25,9 @@ module Axlsx @yData = NamedAxisData.new("yVal", options[:yData]) unless options[:yData].nil? end + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') super(str) do |inner_str| @xData.to_xml_string(inner_str) unless @xData.nil? diff --git a/lib/axlsx/drawing/ser_axis.rb b/lib/axlsx/drawing/ser_axis.rb index fdc0d43d..703786e5 100644 --- a/lib/axlsx/drawing/ser_axis.rb +++ b/lib/axlsx/drawing/ser_axis.rb @@ -30,6 +30,9 @@ module Axlsx # @see tickMarkSkip def tickMarkSkip=(v) Axlsx::validate_unsigned_int(v); @tickMarkSkip = v; end + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') str << '' super(str) diff --git a/lib/axlsx/drawing/series.rb b/lib/axlsx/drawing/series.rb index 9ab2db13..798919b5 100644 --- a/lib/axlsx/drawing/series.rb +++ b/lib/axlsx/drawing/series.rb @@ -55,6 +55,9 @@ module Axlsx # assigns the chart for this series def chart=(v) DataTypeValidator.validate "Series.chart", Chart, v; @chart = v; end + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') str << '' str << '' diff --git a/lib/axlsx/drawing/series_title.rb b/lib/axlsx/drawing/series_title.rb index 39ec10d5..658be425 100644 --- a/lib/axlsx/drawing/series_title.rb +++ b/lib/axlsx/drawing/series_title.rb @@ -3,6 +3,9 @@ module Axlsx # A series title is a Title with a slightly different serialization than chart titles. class SeriesTitle < Title + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') str << '' str << '' diff --git a/lib/axlsx/drawing/title.rb b/lib/axlsx/drawing/title.rb index a9c253c8..a85d8e11 100644 --- a/lib/axlsx/drawing/title.rb +++ b/lib/axlsx/drawing/title.rb @@ -39,6 +39,9 @@ module Axlsx #def overlay=(v) Axlsx::validate_boolean v; @overlay=v; end #def spPr=(v) DataTypeValidator.validate 'Title.spPr', SpPr, v; @spPr = v; end + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') str << '' unless @text.empty? diff --git a/lib/axlsx/drawing/two_cell_anchor.rb b/lib/axlsx/drawing/two_cell_anchor.rb index cfa102ae..b496bd8a 100644 --- a/lib/axlsx/drawing/two_cell_anchor.rb +++ b/lib/axlsx/drawing/two_cell_anchor.rb @@ -55,6 +55,9 @@ module Axlsx @drawing.anchors.index(self) end + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') str << '' str << '' diff --git a/lib/axlsx/drawing/val_axis.rb b/lib/axlsx/drawing/val_axis.rb index f2675733..6e55c8ea 100644 --- a/lib/axlsx/drawing/val_axis.rb +++ b/lib/axlsx/drawing/val_axis.rb @@ -22,6 +22,9 @@ module Axlsx # @see crossBetween def crossBetween=(v) RestrictionValidator.validate "ValAxis.crossBetween", [:between, :midCat], v; @crossBetween = v; end + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') str << '' super(str) diff --git a/lib/axlsx/drawing/val_axis_data.rb b/lib/axlsx/drawing/val_axis_data.rb index c28e8a58..61044cd6 100644 --- a/lib/axlsx/drawing/val_axis_data.rb +++ b/lib/axlsx/drawing/val_axis_data.rb @@ -3,6 +3,9 @@ module Axlsx # The ValAxisData class manages the values for a chart value series. class ValAxisData < CatAxisData + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') str << '' str << '' diff --git a/lib/axlsx/drawing/view_3D.rb b/lib/axlsx/drawing/view_3D.rb index c2af0953..1090f4a7 100644 --- a/lib/axlsx/drawing/view_3D.rb +++ b/lib/axlsx/drawing/view_3D.rb @@ -70,6 +70,9 @@ module Axlsx def perspective=(v) DataTypeValidator.validate "#{self.class}.perspective", [Integer, Fixnum], v, lambda {|arg| arg >= 0 && arg <= 240 }; @perspective = v; end + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') str << '' str << '' unless @rotX.nil? diff --git a/lib/axlsx/stylesheet/border.rb b/lib/axlsx/stylesheet/border.rb index 99bd410a..d23e5476 100644 --- a/lib/axlsx/stylesheet/border.rb +++ b/lib/axlsx/stylesheet/border.rb @@ -42,6 +42,9 @@ module Axlsx # @see outline def outline=(v) Axlsx::validate_boolean v; @outline = v end + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') str << '' end - # Serializes the border element - # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. - def to_xml(xml) - xml.border(self.instance_values.select{ |k,v| [:diagonalUp, :diagonalDown, :outline].include? k }) { - [:start, :end, :left, :right, :top, :bottom, :diagonal, :vertical, :horizontal].each do |k| - @prs.select { |pr| pr.name == k }.each do |part| - part.to_xml(xml) - end - end - } - end end end diff --git a/lib/axlsx/stylesheet/border_pr.rb b/lib/axlsx/stylesheet/border_pr.rb index b15e3918..eb1ecf4b 100644 --- a/lib/axlsx/stylesheet/border_pr.rb +++ b/lib/axlsx/stylesheet/border_pr.rb @@ -57,19 +57,14 @@ module Axlsx # @see style def style=(v) RestrictionValidator.validate "BorderPr.style", [:none, :thin, :medium, :dashed, :dotted, :thick, :double, :hair, :mediumDashed, :dashDot, :mediumDashDot, :dashDotDot, :mediumDashDotDot, :slantDashDot], v; @style = v end + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') str << '<' << @name.to_s << ' style="' << @style.to_s << '">' @color.to_xml_string(str) if @color.is_a?(Color) str << '' end - # Serializes the border part - # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. - # @return [String] - def to_xml(xml) - xml.send(@name, :style => @style) { - @color.to_xml(xml) if @color.is_a? Color - } - end end end diff --git a/lib/axlsx/stylesheet/cell_alignment.rb b/lib/axlsx/stylesheet/cell_alignment.rb index 50b0e2d4..a38e3829 100644 --- a/lib/axlsx/stylesheet/cell_alignment.rb +++ b/lib/axlsx/stylesheet/cell_alignment.rb @@ -95,17 +95,14 @@ module Axlsx # @see readingOrder def readingOrder=(v) Axlsx::validate_unsigned_int v; @readingOrder = v end + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') str << '' end - # Serializes the cell alignment - # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. - # @return [String] - def to_xml(xml) - xml.alignment(self.instance_values) - end end end diff --git a/lib/axlsx/stylesheet/cell_protection.rb b/lib/axlsx/stylesheet/cell_protection.rb index b874b214..4309b0e8 100644 --- a/lib/axlsx/stylesheet/cell_protection.rb +++ b/lib/axlsx/stylesheet/cell_protection.rb @@ -27,17 +27,14 @@ module Axlsx # @see locked def locked=(v) Axlsx::validate_boolean v; @locked = v end + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') str << '' end - # Serializes the cell protection - # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. - # @return [String] - def to_xml(xml) - xml.protection(self.instance_values) - end end end diff --git a/lib/axlsx/stylesheet/cell_style.rb b/lib/axlsx/stylesheet/cell_style.rb index 22694ae1..ed3aeda9 100644 --- a/lib/axlsx/stylesheet/cell_style.rb +++ b/lib/axlsx/stylesheet/cell_style.rb @@ -55,19 +55,15 @@ module Axlsx # @see customBuiltin def customBuiltin=(v) Axlsx::validate_boolean v; @customBuiltin = v end - + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') str << '' end - # Serializes the cell style - # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. - # @return [String] - def to_xml(xml) - xml.cellStyle(self.instance_values) - end end end diff --git a/lib/axlsx/stylesheet/color.rb b/lib/axlsx/stylesheet/color.rb index daedc9ed..78171607 100644 --- a/lib/axlsx/stylesheet/color.rb +++ b/lib/axlsx/stylesheet/color.rb @@ -61,6 +61,9 @@ module Axlsx # Indexed colors are for backward compatability which I am choosing not to support # def indexed=(v) Axlsx::validate_unsigned_integer v; @indexed = v end + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') str << "" end - # Serializes the color - # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. - # @return [String] - def to_xml(xml) xml.color(self.instance_values) end end end diff --git a/lib/axlsx/stylesheet/fill.rb b/lib/axlsx/stylesheet/fill.rb index d6fde1c7..7bb5a437 100644 --- a/lib/axlsx/stylesheet/fill.rb +++ b/lib/axlsx/stylesheet/fill.rb @@ -18,18 +18,14 @@ module Axlsx self.fill_type = fill_type end - + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') str << '' @fill_type.to_xml_string(str) str << '' end - # Serializes the fill - # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. - # @return [String] - def to_xml(xml) - xml.fill { @fill_type.to_xml(xml) } - end # @see fill_type def fill_type=(v) DataTypeValidator.validate "Fill.fill_type", [PatternFill, GradientFill], v; @fill_type = v; end diff --git a/lib/axlsx/stylesheet/font.rb b/lib/axlsx/stylesheet/font.rb index 4bbcb487..657c4c30 100644 --- a/lib/axlsx/stylesheet/font.rb +++ b/lib/axlsx/stylesheet/font.rb @@ -133,7 +133,9 @@ module Axlsx # @see sz def sz=(v) Axlsx::validate_unsigned_int v; @sz=v end - + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') str << '' instance_values.each do |k, v| @@ -141,16 +143,5 @@ module Axlsx end str << '' end - - # Serializes the fill - # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. - # @return [String] - def to_xml(xml) - xml.font { - self.instance_values.each do |k, v| - v.is_a?(Color) ? v.to_xml(xml) : xml.send(k, {:val => v}) - end - } - end end end diff --git a/lib/axlsx/stylesheet/gradient_fill.rb b/lib/axlsx/stylesheet/gradient_fill.rb index 2a789c6f..514e0cfd 100644 --- a/lib/axlsx/stylesheet/gradient_fill.rb +++ b/lib/axlsx/stylesheet/gradient_fill.rb @@ -64,7 +64,9 @@ module Axlsx # @see bottom def bottom=(v) DataTypeValidator.validate "GradientFill.bottom", Float, v, lambda { |arg| arg >= 0.0 && arg <= 1.0}; @bottom= v end - + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') str << '' end - # Serializes the gradientFill - # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. - # @return [String] - def to_xml(xml) - xml.gradientFill(self.instance_values.reject { |k,v| k.to_sym == :stop }) { - @stop.each { |s| s.to_xml(xml) } - } - end end end diff --git a/lib/axlsx/stylesheet/gradient_stop.rb b/lib/axlsx/stylesheet/gradient_stop.rb index aca26b79..94ca4795 100644 --- a/lib/axlsx/stylesheet/gradient_stop.rb +++ b/lib/axlsx/stylesheet/gradient_stop.rb @@ -25,14 +25,13 @@ module Axlsx # @see position def position=(v) DataTypeValidator.validate "GradientStop.position", Float, v, lambda { |arg| arg >= 0 && arg <= 1}; @position = v end + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') str << '' self.color.to_xml_string(str) str << '' end - # Serializes the gradientStop - # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. - # @return [String] - def to_xml(xml) xml.stop(:position => self.position) {self.color.to_xml(xml)} end end end diff --git a/lib/axlsx/stylesheet/num_fmt.rb b/lib/axlsx/stylesheet/num_fmt.rb index 8c74382f..d5122f7e 100644 --- a/lib/axlsx/stylesheet/num_fmt.rb +++ b/lib/axlsx/stylesheet/num_fmt.rb @@ -56,15 +56,15 @@ module Axlsx # @see formatCode def formatCode=(v) Axlsx::validate_string v; @formatCode = v end + + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') str << '' end - # Creates a numFmt element applying the instance values of this object as attributes. - # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. - def to_xml(xml) xml.numFmt(self.instance_values) end - end end diff --git a/lib/axlsx/stylesheet/pattern_fill.rb b/lib/axlsx/stylesheet/pattern_fill.rb index 32d54d83..0c0a51a6 100644 --- a/lib/axlsx/stylesheet/pattern_fill.rb +++ b/lib/axlsx/stylesheet/pattern_fill.rb @@ -55,6 +55,9 @@ module Axlsx # @see patternType def patternType=(v) Axlsx::validate_pattern_type v; @patternType = v end + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') str << '' if fgColor.is_a?(Color) @@ -75,13 +78,5 @@ module Axlsx str << '' end - # Serializes the pattern fill - # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. - # @return [String] - def to_xml(xml) - xml.patternFill(:patternType => self.patternType) { - self.instance_values.reject { |k,v| k.to_sym == :patternType }.each { |k,v| xml.send(k, v.instance_values) } - } - end end end diff --git a/lib/axlsx/stylesheet/styles.rb b/lib/axlsx/stylesheet/styles.rb index d8d33fa1..1fb2e9b3 100644 --- a/lib/axlsx/stylesheet/styles.rb +++ b/lib/axlsx/stylesheet/styles.rb @@ -133,7 +133,7 @@ module Axlsx # @option options [String] font_name The name of the font to use # @option options [Integer] num_fmt The number format to apply # @option options [String] format_code The formatting to apply. If this is specified, num_fmt is ignored. - # @option options [Integer] border The border style to use. This can be the index of an existing border or a hash like {:style => :thin, :color => "FFFF0000"} to create a new border style + # @option options [Integer] border The border style to use. # @option options [String] bg_color The background color to apply to the cell # @option options [Boolean] hidden Indicates if the cell should be hidden # @option options [Boolean] locked Indicates if the cell should be locked @@ -148,7 +148,7 @@ module Axlsx # ws = p.workbook.add_worksheet # # # black text on a white background at 14pt with thin borders! - # title = ws.style.add_style(:bg_color => "FFFF0000", :fg_color=>"#FF000000", :sz=>14, :border=>Axlsx::STYLE_THIN_BORDER + # title = ws.style.add_style(:bg_color => "FFFF0000", :fg_color=>"#FF000000", :sz=>14, :border=> {:style => :thin, :color => "FFFF0000"} # # ws.add_row :values => ["Least Popular Pets"] # ws.add_row :values => ["", "Dry Skinned Reptiles", "Bald Cats", "Violent Parrots"], :style=>title @@ -250,6 +250,9 @@ module Axlsx cellXfs << xf end + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') str << '' [:numFmts, :fonts, :fills, :borders, :cellStyleXfs, :cellXfs, :cellStyles, :dxfs, :tableStyles].each do |key| @@ -258,19 +261,6 @@ module Axlsx str << '' end - # Serializes the styles document - # @return [String] - def to_xml() - builder = Nokogiri::XML::Builder.new(:encoding => ENCODING) do |xml| - xml.styleSheet(:xmlns => XML_NS) { - [:numFmts, :fonts, :fills, :borders, :cellStyleXfs, :cellXfs, :cellStyles, :dxfs, :tableStyles].each do |key| - self.instance_values[key.to_s].to_xml(xml) unless self.instance_values[key.to_s].nil? - end - } - end - builder.to_xml(:save_with => 0) - end - private # Creates the default set of styles the exel requires to be valid as well as setting up the # Axlsx::STYLE_THIN_BORDER diff --git a/lib/axlsx/stylesheet/table_style.rb b/lib/axlsx/stylesheet/table_style.rb index 3184c042..324f33d6 100644 --- a/lib/axlsx/stylesheet/table_style.rb +++ b/lib/axlsx/stylesheet/table_style.rb @@ -36,7 +36,9 @@ module Axlsx # @see table def table=(v) Axlsx::validate_boolean v; @table=v end - + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') attr = self.instance_values.select { |k, v| [:name, :pivot, :table].include? k } attr[:count] = self.size @@ -47,13 +49,5 @@ module Axlsx str << '' end - # Serializes the table style - # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. - # @return [String] - def to_xml(xml) - attr = self.instance_values.select { |k, v| [:name, :pivot, :table].include? k } - attr[:count] = self.size - xml.tableStyle(attr) { self.each { |table_style_el| table_style_el.to_xml(xml) } } - end end end diff --git a/lib/axlsx/stylesheet/table_style_element.rb b/lib/axlsx/stylesheet/table_style_element.rb index a5cf4c48..1a4c8803 100644 --- a/lib/axlsx/stylesheet/table_style_element.rb +++ b/lib/axlsx/stylesheet/table_style_element.rb @@ -62,17 +62,14 @@ module Axlsx # @see dxfId def dxfId=(v) Axlsx::validate_unsigned_int v; @dxfId = v end + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') str << '' end - # Serializes the table style element - # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. - # @return [String] - def to_xml(xml) - xml.tableStyleElement self.instance_values - end end end diff --git a/lib/axlsx/stylesheet/table_styles.rb b/lib/axlsx/stylesheet/table_styles.rb index 5474c165..a43e7ce5 100644 --- a/lib/axlsx/stylesheet/table_styles.rb +++ b/lib/axlsx/stylesheet/table_styles.rb @@ -25,7 +25,9 @@ module Axlsx # @see defaultPivotStyle def defaultPivotStyle=(v) Axlsx::validate_string(v); @defaultPivotStyle = v; end - + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') attr = self.instance_values.reject {|k, v| ![:defaultTableStyle, :defaultPivotStyle].include?(k.to_sym) } attr[:count] = self.size @@ -36,16 +38,6 @@ module Axlsx str << '' end - # Serializes the table styles element - # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. - # @return [String] - def to_xml(xml) - attr = self.instance_values.reject {|k, v| ![:defaultTableStyle, :defaultPivotStyle].include?(k.to_sym) } - attr[:count] = self.size - xml.tableStyles(attr) { - self.each { |table_style| table_style.to_xml(xml) } - } - end end end diff --git a/lib/axlsx/stylesheet/xf.rb b/lib/axlsx/stylesheet/xf.rb index e8e36301..59329a63 100644 --- a/lib/axlsx/stylesheet/xf.rb +++ b/lib/axlsx/stylesheet/xf.rb @@ -126,6 +126,9 @@ module Axlsx # @see applyProtection def applyProtection=(v) Axlsx::validate_boolean v; @applyProtection = v end + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string(str = '') str << '' end - # Serializes the xf elemen - # @param [Nokogiri::XML::Builder] xml The document builder instance this objects xml will be added to. - # @return [String] - def to_xml(xml) - xml.xf(self.instance_values.reject { |k, v| [:alignment, :protection, :extList, :name].include? k.to_sym}) { - alignment.to_xml(xml) if self.alignment - protection.to_xml(xml) if self.protection - } - end end end diff --git a/lib/axlsx/util/constants.rb b/lib/axlsx/util/constants.rb index 588dada5..c37b596a 100644 --- a/lib/axlsx/util/constants.rb +++ b/lib/axlsx/util/constants.rb @@ -171,7 +171,7 @@ module Axlsx # drawing rels part DRAWING_RELS_PN = "drawings/_rels/drawing%d.xml.rels" - + # drawing part TABLE_PN = "tables/table%d.xml" @@ -232,5 +232,4 @@ module Axlsx # 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" - FIXED_COL_WIDTH = 8.43 end diff --git a/lib/axlsx/util/validators.rb b/lib/axlsx/util/validators.rb index d4913074..54a0aeb4 100644 --- a/lib/axlsx/util/validators.rb +++ b/lib/axlsx/util/validators.rb @@ -103,6 +103,13 @@ module Axlsx RestrictionValidator.validate :gradient_type, [:linear, :path], v end + # Requires that the value is a valid scatterStyle + # must be one of :none | :line | :lineMarker | :marker | :smooth | :smoothMarker + # must be one of "none" | "line" | "lineMarker" | "marker" | "smooth" | "smoothMarker" + # @param [Symbol|String] the value to validate + def self.validate_scatter_style(v) + Axlsx::RestrictionValidator.validate "ScatterChart.scatterStyle", [:none, :line, :lineMarker, :marker, :smooth, :smoothMarker], v.to_sym + end # Requires that the value is a valid horizontal_alignment # :general, :left, :center, :right, :fill, :justify, :centerContinuous, :distributed are allowed # @param [Any] v The value validated diff --git a/lib/axlsx/version.rb b/lib/axlsx/version.rb index 175371e8..3ffa1049 100644 --- a/lib/axlsx/version.rb +++ b/lib/axlsx/version.rb @@ -5,6 +5,6 @@ module Axlsx # When using bunle exec rake and referencing the gem on github or locally # it will use the gemspec, which preloads this constant for the gem's version. # We check to make sure that it has not already been loaded - VERSION="1.1.0" unless Axlsx.const_defined? :VERSION + VERSION="1.1.0" unless defined? VERSION end diff --git a/lib/axlsx/workbook/shared_strings_table.rb b/lib/axlsx/workbook/shared_strings_table.rb index dac8221f..d9a22432 100644 --- a/lib/axlsx/workbook/shared_strings_table.rb +++ b/lib/axlsx/workbook/shared_strings_table.rb @@ -36,24 +36,13 @@ module Axlsx resolve(cells) end + # Serializes the object + # @param [String] str + # @return [String] def to_xml_string '' << @shared_xml_string << '' end - # Generate the xml document for the Shared Strings Table - # @return [String] - def to_xml - - builder = Nokogiri::XML::Builder.new(:encoding => ENCODING) do |xml| - xml.sst(:xmlns => Axlsx::XML_NS, :count => count, :uniqueCount => unique_count) { - @unique_cells.each do |cell| - xml.si { cell.run_xml(xml) } - end - } - end - builder.to_xml(:save_with => 0) - end - private # Interate over all of the cells in the array. diff --git a/lib/axlsx/workbook/worksheet/cell.rb b/lib/axlsx/workbook/worksheet/cell.rb index 13140786..3557a89b 100644 --- a/lib/axlsx/workbook/worksheet/cell.rb +++ b/lib/axlsx/workbook/worksheet/cell.rb @@ -36,9 +36,6 @@ module Axlsx 'shadow', 'condense', 'extend', 'u', 'vertAlign', 'sz', 'color', 'scheme'] - INLINE_ATTR = [:font_name => { :validator=>:validate_string}] - - # The index of the cellXfs item to be applied to this cell. # @return [Integer] # @see Axlsx::Styles diff --git a/lib/axlsx/workbook/worksheet/page_margins.rb b/lib/axlsx/workbook/worksheet/page_margins.rb index 19402a6d..d2349f9e 100644 --- a/lib/axlsx/workbook/worksheet/page_margins.rb +++ b/lib/axlsx/workbook/worksheet/page_margins.rb @@ -84,10 +84,10 @@ module Axlsx def footer=(v); Axlsx::validate_unsigned_numeric(v); @footer = v end # Serializes the page margins element + # @param [String] str + # @return [String] # @note For compatibility, this is a noop unless custom margins have been specified. # @see #custom_margins_specified? - # @param [String] str - # @retrun [String] def to_xml_string(str = '') str << '' str << '" % [XML_NS, XML_NS_R] @@ -409,54 +412,6 @@ module Axlsx str + '' end - # Serializes the worksheet document - # @return [String] - def to_xml - builder = Nokogiri::XML::Builder.new(:encoding => ENCODING) do |xml| - xml.worksheet(:xmlns => XML_NS, - :'xmlns:r' => XML_NS_R) { - xml.sheetPr { - xml.pageSetUpPr :fitToPage => fit_to_page if fit_to_page - } - # another patch for the folks at rubyXL as thier parser depends on this optional element. - xml.dimension :ref=>dimension unless rows.size == 0 - # this is required by rubyXL, spec says who cares - but it seems they didnt notice - # grouping issue resolved by keeping tabSelected set to 0 - xml.sheetViews { - xml.sheetView(:tabSelected => @selected, :workbookViewId => 0, :showGridLines => show_gridlines) { - xml.selection :activeCell=>"A1", :sqref => "A1" - } - } - - if @auto_fit_data.size > 0 - xml.cols { - @auto_fit_data.each_with_index do |col, index| - min_max = index+1 - xml.col(:min=>min_max, :max=>min_max, :width => auto_width(col), :customWidth=>1) - end - } - end - xml.sheetData { - @rows.each do |row| - row.to_xml(xml) - end - } - xml.autoFilter :ref=>@auto_filter if @auto_filter - xml.mergeCells(:count=>@merged_cells.size) { @merged_cells.each { | mc | xml.mergeCell(:ref=>mc) } } unless @merged_cells.empty? - page_margins.to_xml(xml) if @page_margins - xml.drawing :"r:id"=>"rId1" if @drawing - unless @tables.empty? - xml.tableParts(:count => @tables.length) { - @tables.each do |table| - xml.tablePart :'r:id' => table.rId - end - } - end - } - end - builder.to_xml(:save_with => 0) - end - # The worksheet relationships. This is managed automatically by the worksheet # @return [Relationships] def relationships -- cgit v1.2.3 From a7349d8e40d09b6a061d7c80ea8e1325b9ebaf58 Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Tue, 3 Apr 2012 08:43:41 +0900 Subject: patching gemspec --- axlsx.gemspec | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/axlsx.gemspec b/axlsx.gemspec index c8fda02f..1dee3358 100644 --- a/axlsx.gemspec +++ b/axlsx.gemspec @@ -21,14 +21,12 @@ Gem::Specification.new do |s| s.add_runtime_dependency 'nokogiri', '>= 1.4.1' s.add_runtime_dependency 'rmagick', '>= 2.12.2' unless Object.const_defined? :JRUBY_VERSION s.add_runtime_dependency 'rmagick4j', '>= 0.3.7' if Object.const_defined? :JRUBY_VERSION - s.add_runtime_dependency 'rubyzip', '~> 0.9' s.add_runtime_dependency 'rake', '0.8.7' if RUBY_VERSION == "1.9.2" s.add_runtime_dependency 'rake', '>= 0.8.7' if ["1.9.3", "1.8.7"].include?(RUBY_VERSION) s.add_development_dependency 'yard' - s.add_development_dependency 'yard' - s.add_development_dependency 'rdiscount' + # s.add_development_dependency 'rdiscount' s.required_ruby_version = '>= 1.8.7' s.require_path = 'lib' -- cgit v1.2.3 From e845cf837a5d312c5b2af649f2dfade995976c33 Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Tue, 3 Apr 2012 08:46:50 +0900 Subject: patching version contant detection --- lib/axlsx/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/axlsx/version.rb b/lib/axlsx/version.rb index 3ffa1049..4edbc831 100644 --- a/lib/axlsx/version.rb +++ b/lib/axlsx/version.rb @@ -5,6 +5,6 @@ module Axlsx # When using bunle exec rake and referencing the gem on github or locally # it will use the gemspec, which preloads this constant for the gem's version. # We check to make sure that it has not already been loaded - VERSION="1.1.0" unless defined? VERSION + VERSION="1.1.0" unless defined? Axlsx::VERSION end -- cgit v1.2.3 From 02341a99e6dcc9f4bb1c4273fac9c3d3cf6c642d Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Tue, 3 Apr 2012 09:01:33 +0900 Subject: Trying something crazy for jruby1.9 mode --- test/workbook/worksheet/tc_date_time_converter.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/test/workbook/worksheet/tc_date_time_converter.rb b/test/workbook/worksheet/tc_date_time_converter.rb index adeae92b..64b5cf6b 100644 --- a/test/workbook/worksheet/tc_date_time_converter.rb +++ b/test/workbook/worksheet/tc_date_time_converter.rb @@ -113,6 +113,7 @@ class TestDateTimeConverter < Test::Unit::TestCase def test_timezone utc = Time.utc 2012 # January 1st, 2012 at 0:00 UTC local = begin + ENV["TZ"]="GMT+1" Time.new 2012, 1, 1, 1, 0, 0, 3600 # January 1st, 2012 at 1:00 GMT+1 rescue ArgumentError Time.parse "2012-01-01 01:00:00 +0100" -- cgit v1.2.3 From 6a828bfa7e1e101eeab3ac285f22e78c781c0f48 Mon Sep 17 00:00:00 2001 From: Randy Morgan Date: Tue, 3 Apr 2012 20:53:37 +0900 Subject: pre release prep --- README.md | 6 +++--- test/workbook/worksheet/tc_date_time_converter.rb | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 796be891..ad357303 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Axlsx: Office Open XML Spreadsheet Generation **Author**: Randy Morgan -**Copyright**: 2011 +**Copyright**: 2011 - 2012 **License**: MIT License @@ -20,7 +20,7 @@ Axlsx: Office Open XML Spreadsheet Generation **JRuby Version**: 1.6.7 -**Release Date**: April 2st 2012 +**Release Date**: April 3st 2012 Synopsis -------- @@ -374,7 +374,7 @@ This gem has 100% test coverage using test/unit. To execute tests for this gem, #Change log --------- -- ** April.2.12**: 1.1.0 release +- ** April.3.12**: 1.1.0 release - bugfix patch name_to_indecies to properly handle extended ranges. - bugfix properly serialize chart title. - lower rake minimum requirement for 1.8.7 apps that don't want to move on to 0.9 NOTE this will be reverted for 2.0.0 with workbook parsing! diff --git a/test/workbook/worksheet/tc_date_time_converter.rb b/test/workbook/worksheet/tc_date_time_converter.rb index 64b5cf6b..adeae92b 100644 --- a/test/workbook/worksheet/tc_date_time_converter.rb +++ b/test/workbook/worksheet/tc_date_time_converter.rb @@ -113,7 +113,6 @@ class TestDateTimeConverter < Test::Unit::TestCase def test_timezone utc = Time.utc 2012 # January 1st, 2012 at 0:00 UTC local = begin - ENV["TZ"]="GMT+1" Time.new 2012, 1, 1, 1, 0, 0, 3600 # January 1st, 2012 at 1:00 GMT+1 rescue ArgumentError Time.parse "2012-01-01 01:00:00 +0100" -- cgit v1.2.3 From 548cd6c3f22fd56907cf98ee9dcbed8ba4d4298f Mon Sep 17 00:00:00 2001 From: Jurriaan Pruis Date: Tue, 3 Apr 2012 14:45:07 +0200 Subject: updated README --- README.md | 519 +++++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 308 insertions(+), 211 deletions(-) diff --git a/README.md b/README.md index ad357303..a8562670 100644 --- a/README.md +++ b/README.md @@ -2,17 +2,17 @@ Axlsx: Office Open XML Spreadsheet Generation ==================================== [![Build Status](https://secure.travis-ci.org/randym/axlsx.png)](http://travis-ci.org/randym/axlsx/) -**IRC**: [irc.freenode.net / #axlsx](irc://irc.freenode.net/axlsx) +**IRC**:[irc.freenode.net / #axlsx](irc://irc.freenode.net/axlsx) -**Git**: [http://github.com/randym/axlsx](http://github.com/randym/axlsx) +**Git**:[http://github.com/randym/axlsx](http://github.com/randym/axlsx) -**Twitter**: [https://twitter.com/#!/morgan_randy](https://twitter.com/#!/morgan_randy) release announcements and news will be published here +**Twitter**: [https://twitter.com/#!/morgan_randy](https://twitter.com/#!/morgan_randy) release announcements and news will be published here -**Author**: Randy Morgan +**Author**: Randy Morgan **Copyright**: 2011 - 2012 -**License**: MIT License +**License**: MIT License **Latest Version**: 1.1.0 @@ -82,292 +82,389 @@ To install Axlsx, use the following command: #Usage ------ - require 'axlsx' +```ruby +require 'axlsx' - p = Axlsx::Package.new - wb = p.workbook +p = Axlsx::Package.new +wb = p.workbook +``` -##A Simple Workbook +#A Simple Workbook - wb.add_worksheet(:name => "Basic Worksheet") do |sheet| - sheet.add_row ["First Column", "Second", "Third"] - sheet.add_row [1, 2, 3] - end +```ruby +wb.add_worksheet(:name => "Basic Worksheet") do |sheet| + sheet.add_row ["First Column", "Second", "Third"] + sheet.add_row [1, 2, 3] +end +``` -##Using Custom Styles and Row Heights +#Using Custom Styles + +```ruby +wb.styles do |s| + black_cell = s.add_style :bg_color => "00", :fg_color => "FF", :sz => 14, :alignment => { :horizontal=> :center } + blue_cell = s.add_style :bg_color => "0000FF", :fg_color => "FF", :sz => 20, :alignment => { :horizontal=> :center } + wb.add_worksheet(:name => "Custom Styles") do |sheet| + sheet.add_row ["Text Autowidth", "Second", "Third"], :style => [black_cell, blue_cell, black_cell] + sheet.add_row [1, 2, 3], :style => Axlsx::STYLE_THIN_BORDER + end +end +``` + +#Using Custom Border Styles + +```ruby +wb.styles do |s| + red_border = s.add_style :border => {:style=>:thin, :color =>"FFFF0000"} + blue_border = s.add_style :border => {:style=>:thin, :color =>"FF0000FF"} + + wb.add_worksheet(:name => "Custom Borders") do |sheet| + sheet.add_row ["wrap", "me", "Up in Red"], :style => red_border + sheet.add_row [1, 2, 3], :style => blue_border + end +end +``` - wb.styles do |s| - black_cell = s.add_style :bg_color => "00", :fg_color => "FF", :sz => 14, :alignment => { :horizontal=> :center } - blue_cell = s.add_style :bg_color => "0000FF", :fg_color => "FF", :sz => 20, :alignment => { :horizontal=> :center } - wb.add_worksheet(:name => "Custom Styles") do |sheet| - sheet.add_row ["Text Autowidth", "Second", "Third"], :style => [black_cell, blue_cell, black_cell] - sheet.add_row [1, 2, 3], :style => Axlsx::STYLE_THIN_BORDER, :height => 20 - end - end ##Using Custom Formatting and date1904 - require 'date' - wb.styles do |s| - date = s.add_style(:format_code => "yyyy-mm-dd", :border => Axlsx::STYLE_THIN_BORDER) - padded = s.add_style(:format_code => "00#", :border => Axlsx::STYLE_THIN_BORDER) - percent = s.add_style(:format_code => "0000%", :border => Axlsx::STYLE_THIN_BORDER) - wb.date1904 = true # required for generation on mac - wb.add_worksheet(:name => "Formatting Data") do |sheet| - sheet.add_row ["Custom Formatted Date", "Percent Formatted Float", "Padded Numbers"], :style => Axlsx::STYLE_THIN_BORDER - sheet.add_row [Date::strptime('2012-01-19','%Y-%m-%d'), 0.2, 32], :style => [date, percent, padded] - end - end +```ruby +require 'date' +wb.styles do |s| + date = s.add_style(:format_code => "yyyy-mm-dd", :border => Axlsx::STYLE_THIN_BORDER) + padded = s.add_style(:format_code => "00#", :border => Axlsx::STYLE_THIN_BORDER) + percent = s.add_style(:format_code => "0000%", :border => Axlsx::STYLE_THIN_BORDER) + # wb.date1904 = true # Use the 1904 date system (Used by Excel for Mac < 2011) + wb.add_worksheet(:name => "Formatting Data") do |sheet| + sheet.add_row ["Custom Formatted Date", "Percent Formatted Float", "Padded Numbers"], :style => Axlsx::STYLE_THIN_BORDER + sheet.add_row [Date::strptime('2012-01-19','%Y-%m-%d'), 0.2, 32], :style => [date, percent, padded] + end +end +``` + ##Add an Image - wb.add_worksheet(:name => "Images") do |sheet| - img = File.expand_path('examples/image1.jpeg') - sheet.add_image(:image_src => img, :noSelect => true, :noMove => true) do |image| - image.width=720 - image.height=666 - image.start_at 2, 2 - end - end +```ruby +wb.add_worksheet(:name => "Images") do |sheet| + img = File.expand_path('../image1.jpeg', __FILE__) + sheet.add_image(:image_src => img, :noSelect => true, :noMove => true) do |image| + image.width=720 + image.height=666 + image.start_at 2, 2 + end +end +``` ##Add an Image with a hyperlink - wb.add_worksheet(:name => "Image with Hyperlink") do |sheet| - img = File.expand_path('examples/image1.jpeg') - sheet.add_image(:image_src => img, :noSelect => true, :noMove => true, :hyperlink=>"http://axlsx.blogspot.com") do |image| - image.width=720 - image.height=666 - image.hyperlink.tooltip = "Labeled Link" - image.start_at 2, 2 - end - end +```ruby +wb.add_worksheet(:name => "Image with Hyperlink") do |sheet| + img = File.expand_path('../image1.jpeg', __FILE__) + sheet.add_image(:image_src => img, :noSelect => true, :noMove => true, :hyperlink=>"http://axlsx.blogspot.com") do |image| + image.width=720 + image.height=666 + image.hyperlink.tooltip = "Labeled Link" + image.start_at 2, 2 + end +end +``` ##Asian Language Support - wb.add_worksheet(:name => "Unicode Support") do |sheet| - sheet.add_row ["日本語"] - sheet.add_row ["华语/華語"] - sheet.add_row ["한국어/조선말"] - end +```ruby +wb.add_worksheet(:name => "日本語でのシート名") do |sheet| + sheet.add_row ["日本語"] + sheet.add_row ["华语/華語"] + sheet.add_row ["한국어/조선말"] +end +``` ##Styling Columns - wb.styles do |s| - percent = s.add_style :num_fmt => 9 - wb.add_worksheet(:name => "Styling Columns") do |sheet| - sheet.add_row ['col 1', 'col 2', 'col 3', 'col 4'] - sheet.add_row [1, 2, 0.3, 4] - sheet.add_row [1, 2, 0.2, 4] - sheet.add_row [1, 2, 0.1, 4] - sheet.col_style 2, percent, :row_offset => 1 - end - end +```ruby +wb.styles do |s| + percent = s.add_style :num_fmt => 9 + wb.add_worksheet(:name => "Styling Columns") do |sheet| + sheet.add_row ['col 1', 'col 2', 'col 3', 'col 4'] + sheet.add_row [1, 2, 0.3, 4] + sheet.add_row [1, 2, 0.2, 4] + sheet.add_row [1, 2, 0.1, 4] + sheet.col_style 2, percent, :row_offset => 1 + end +end +``` ##Hiding Columns - wb.styles do |s| - percent = s.add_style :num_fmt => 9 - wb.add_worksheet(:name => "Hidden Column") do |sheet| - sheet.add_row ['col 1', 'col 2', 'col 3', 'col 4'] - sheet.add_row [1, 2, 0.3, 4] - sheet.add_row [1, 2, 0.2, 4] - sheet.add_row [1, 2, 0.1, 4] - sheet.col_style 2, percent, :row_offset => 1 - sheet.column_info[1].hidden = true - end - end +```ruby +wb.styles do |s| + percent = s.add_style :num_fmt => 9 + wb.add_worksheet(:name => "Hidden Column") do |sheet| + sheet.add_row ['col 1', 'col 2', 'col 3', 'col 4'] + sheet.add_row [1, 2, 0.3, 4] + sheet.add_row [1, 2, 0.2, 4] + sheet.add_row [1, 2, 0.1, 4] + sheet.col_style 2, percent, :row_offset => 1 + sheet.column_info[1].hidden = true + end +end +``` ##Styling Rows - wb.styles do |s| - head = s.add_style :bg_color => "00", :fg_color => "FF" - percent = s.add_style :num_fmt => 9 - wb.add_worksheet(:name => "Styling Rows") do |sheet| - sheet.add_row ['col 1', 'col 2', 'col 3', 'col 4'] - sheet.add_row [1, 2, 0.3, 4] - sheet.add_row [1, 2, 0.2, 4] - sheet.add_row [1, 2, 0.1, 4] - sheet.col_style 2, percent, :row_offset => 1 - sheet.row_style 0, head - end - end +```ruby +wb.styles do |s| + head = s.add_style :bg_color => "00", :fg_color => "FF" + percent = s.add_style :num_fmt => 9 + wb.add_worksheet(:name => "Styling Rows") do |sheet| + sheet.add_row ['col 1', 'col 2', 'col 3', 'col 4'] + sheet.add_row [1, 2, 0.3, 4] + sheet.add_row [1, 2, 0.2, 4] + sheet.add_row [1, 2, 0.1, 4] + sheet.col_style 2, percent, :row_offset => 1 + sheet.row_style 0, head + end +end +``` ##Styling Cell Overrides - wb.add_worksheet(:name => "Cell Level Style Overrides") do |sheet| - # cell level style overides when adding cells - sheet.add_row ['col 1', 'col 2', 'col 3', 'col 4'], :sz => 16 - sheet.add_row [1, 2, 3, "=SUM(A2:C2)"] - # cell level style overrides via sheet range - sheet["A1:D1"].each { |c| c.color = "FF0000"} - sheet['A1:D2'].each { |c| c.style = Axlsx::STYLE_THIN_BORDER } - end +```ruby +wb.add_worksheet(:name => "Cell Level Style Overrides") do |sheet| + # cell level style overides when adding cells + sheet.add_row ['col 1', 'col 2', 'col 3', 'col 4'], :sz => 16 + sheet.add_row [1, 2, 3, "=SUM(A2:C2)"] + # cell level style overrides via sheet range + sheet["A1:D1"].each { |c| c.color = "FF0000"} + sheet['A1:D2'].each { |c| c.style = Axlsx::STYLE_THIN_BORDER } +end +``` ##Using formula - wb.add_worksheet(:name => "Using Formulas") do |sheet| - sheet.add_row ['col 1', 'col 2', 'col 3', 'col 4'] - sheet.add_row [1, 2, 3, "=SUM(A2:C2)"] - end +```ruby +wb.add_worksheet(:name => "Using Formulas") do |sheet| + sheet.add_row ['col 1', 'col 2', 'col 3', 'col 4'] + sheet.add_row [1, 2, 3, "=SUM(A2:C2)"] +end +``` ##Automatic cell types - wb.add_worksheet(:name => "Automatic cell types") do |sheet| - sheet.add_row ["Date", "Time", "String", "Boolean", "Float", "Integer"] - sheet.add_row [Date.today, Time.now, "value", true, 0.1, 1] - end +```ruby +wb.add_worksheet(:name => "Automatic cell types") do |sheet| + sheet.add_row ["Date", "Time", "String", "Boolean", "Float", "Integer"] + sheet.add_row [Date.today, Time.now, "value", true, 0.1, 1] +end +``` ##Merging Cells. - wb.add_worksheet(:name => 'Merging Cells') do |sheet| - # cell level style overides when adding cells - sheet.add_row ["col 1", "col 2", "col 3", "col 4"], :sz => 16 - sheet.add_row [1, 2, 3, "=SUM(A2:C2)"] - sheet.add_row [2, 3, 4, "=SUM(A3:C3)"] - sheet.add_row ["total", "", "", "=SUM(D2:D3)"] - sheet.merge_cells("A4:C4") - sheet["A1:D1"].each { |c| c.color = "FF0000"} - sheet["A1:D4"].each { |c| c.style = Axlsx::STYLE_THIN_BORDER } - end +```ruby +wb.add_worksheet(:name => 'Merging Cells') do |sheet| + # cell level style overides when adding cells + sheet.add_row ["col 1", "col 2", "col 3", "col 4"], :sz => 16 + sheet.add_row [1, 2, 3, "=SUM(A2:C2)"] + sheet.add_row [2, 3, 4, "=SUM(A3:C3)"] + sheet.add_row ["total", "", "", "=SUM(D2:D3)"] + sheet.merge_cells("A4:C4") + sheet["A1:D1"].each { |c| c.color = "FF0000"} + sheet["A1:D4"].each { |c| c.style = Axlsx::STYLE_THIN_BORDER } +end +``` ##Generating A Bar Chart - wb.add_worksheet(:name => "Bar Chart") do |sheet| - sheet.add_row ["A Simple Bar Chart"] - sheet.add_row ["First", "Second", "Third"] - sheet.add_row [1, 2, 3] - sheet.add_chart(Axlsx::Bar3DChart, :start_at => "A4", :end_at => "F17") do |chart| - chart.add_series :data => sheet["A3:C3"], :labels => sheet["A2:C2"], :title => sheet["A1"] - end - end +```ruby +wb.add_worksheet(:name => "Bar Chart") do |sheet| + sheet.add_row ["A Simple Bar Chart"] + sheet.add_row ["First", "Second", "Third"] + sheet.add_row [1, 2, 3] + sheet.add_chart(Axlsx::Bar3DChart, :start_at => "A4", :end_at => "F17") do |chart| + chart.add_series :data => sheet["A3:C3"], :labels => sheet["A2:C2"], :title => sheet["A1"] + end +end +``` + +##Hide Gridlines in chart + +```ruby +wb.add_worksheet(:name => "Chart With No Gridlines") do |sheet| + sheet.add_row ["A Simple Bar Chart"] + sheet.add_row ["First", "Second", "Third"] + sheet.add_row [1, 2, 3] + sheet.add_chart(Axlsx::Bar3DChart, :start_at => "A4", :end_at => "F17") do |chart| + chart.add_series :data => sheet["A3:C3"], :labels => sheet["A2:C2"], :title => sheet["A1"] + chart.valAxis.gridlines = false + chart.catAxis.gridlines = false + end +end +``` ##Generating A Pie Chart - wb.add_worksheet(:name => "Pie Chart") do |sheet| - sheet.add_row ["First", "Second", "Third", "Fourth"] - sheet.add_row [1, 2, 3, "=PRODUCT(A2:C2)"] - sheet.add_chart(Axlsx::Pie3DChart, :start_at => [0,2], :end_at => [5, 15], :title => "example 3: Pie Chart") do |chart| - chart.add_series :data => sheet["A2:D2"], :labels => sheet["A1:D1"] - end - end +```ruby +wb.add_worksheet(:name => "Pie Chart") do |sheet| + sheet.add_row ["First", "Second", "Third", "Fourth"] + sheet.add_row [1, 2, 3, "=PRODUCT(A2:C2)"] + sheet.add_chart(Axlsx::Pie3DChart, :start_at => [0,2], :end_at => [5, 15], :title => "example 3: Pie Chart") do |chart| + chart.add_series :data => sheet["A2:D2"], :labels => sheet["A1:D1"] + end +end +``` ##Data over time - wb.add_worksheet(:name=>'Charting Dates') do |sheet| - # cell level style overides when adding cells - sheet.add_row ['Date', 'Value'], :sz => 16 - sheet.add_row [Time.now - (7*60*60*24), 3] - sheet.add_row [Time.now - (6*60*60*24), 7] - sheet.add_row [Time.now - (5*60*60*24), 18] - sheet.add_row [Time.now - (4*60*60*24), 1] - sheet.add_chart(Axlsx::Bar3DChart) do |chart| - chart.start_at "B7" - chart.end_at "H27" - chart.add_series(:data => sheet["B2:B5"], :labels => sheet["A2:A5"], :title => sheet["B1"]) - end - end +```ruby +wb.add_worksheet(:name=>'Charting Dates') do |sheet| + # cell level style overides when adding cells + sheet.add_row ['Date', 'Value'], :sz => 16 + sheet.add_row [Time.now - (7*60*60*24), 3] + sheet.add_row [Time.now - (6*60*60*24), 7] + sheet.add_row [Time.now - (5*60*60*24), 18] + sheet.add_row [Time.now - (4*60*60*24), 1] + sheet.add_chart(Axlsx::Bar3DChart) do |chart| + chart.start_at "B7" + chart.end_at "H27" + chart.add_series(:data => sheet["B2:B5"], :labels => sheet["A2:A5"], :title => sheet["B1"]) + end +end +``` ##Generating A Line Chart - wb.add_worksheet(:name => "Line Chart") do |sheet| - sheet.add_row ["First", 1, 5, 7, 9] - sheet.add_row ["Second", 5, 2, 14, 9] - sheet.add_chart(Axlsx::Line3DChart, :title => "example 6: Line Chart", :rotX => 30, :rotY => 20) do |chart| - chart.start_at 0, 2 - chart.end_at 10, 15 - chart.add_series :data => sheet["B1:E1"], :title => sheet["A1"] - chart.add_series :data => sheet["B2:E2"], :title => sheet["A2"] - end - end +```ruby +wb.add_worksheet(:name => "Line Chart") do |sheet| + sheet.add_row ["First", 1, 5, 7, 9] + sheet.add_row ["Second", 5, 2, 14, 9] + sheet.add_chart(Axlsx::Line3DChart, :title => "example 6: Line Chart", :rotX => 30, :rotY => 20) do |chart| + chart.start_at 0, 2 + chart.end_at 10, 15 + chart.add_series :data => sheet["B1:E1"], :title => sheet["A1"] + chart.add_series :data => sheet["B2:E2"], :title => sheet["A2"] + end +end +``` ##Generating A Scatter Chart - wb.add_worksheet(:name => "Scatter Chart") do |sheet| - sheet.add_row ["First", 1, 5, 7, 9] - sheet.add_row ["", 1, 25, 49, 81] - sheet.add_row ["Second", 5, 2, 14, 9] - sheet.add_row ["", 5, 10, 15, 20] - sheet.add_chart(Axlsx::ScatterChart, :title => "example 7: Scatter Chart") do |chart| - chart.start_at 0, 4 - chart.end_at 10, 19 - chart.add_series :xData => sheet["B1:E1"], :yData => sheet["B2:E2"], :title => sheet["A1"] - chart.add_series :xData => sheet["B3:E3"], :yData => sheet["B4:E4"], :title => sheet["A3"] - end - end +```ruby +wb.add_worksheet(:name => "Scatter Chart") do |sheet| + sheet.add_row ["First", 1, 5, 7, 9] + sheet.add_row ["", 1, 25, 49, 81] + sheet.add_row ["Second", 5, 2, 14, 9] + sheet.add_row ["", 5, 10, 15, 20] + sheet.add_chart(Axlsx::ScatterChart, :title => "example 7: Scatter Chart") do |chart| + chart.start_at 0, 4 + chart.end_at 10, 19 + chart.add_series :xData => sheet["B1:E1"], :yData => sheet["B2:E2"], :title => sheet["A1"] + chart.add_series :xData => sheet["B3:E3"], :yData => sheet["B4:E4"], :title => sheet["A3"] + end +end +``` ##Auto Filter - wb.add_worksheet(:name => "Auto Filter") do |sheet| - sheet.add_row ["Build Matrix"] - sheet.add_row ["Build", "Duration", "Finished", "Rvm"] - sheet.add_row ["19.1", "1 min 32 sec", "about 10 hours ago", "1.8.7"] - sheet.add_row ["19.2", "1 min 28 sec", "about 10 hours ago", "1.9.2"] - sheet.add_row ["19.3", "1 min 35 sec", "about 10 hours ago", "1.9.3"] - sheet.auto_filter = "A2:D5" - end +```ruby +wb.add_worksheet(:name => "Auto Filter") do |sheet| + sheet.add_row ["Build Matrix"] + sheet.add_row ["Build", "Duration", "Finished", "Rvm"] + sheet.add_row ["19.1", "1 min 32 sec", "about 10 hours ago", "1.8.7"] + sheet.add_row ["19.2", "1 min 28 sec", "about 10 hours ago", "1.9.2"] + sheet.add_row ["19.3", "1 min 35 sec", "about 10 hours ago", "1.9.3"] + sheet.auto_filter = "A2:D5" +end +``` + +##Tables + +```ruby +wb.add_worksheet(:name => "Table") do |sheet| + sheet.add_row ["Build Matrix"] + sheet.add_row ["Build", "Duration", "Finished", "Rvm"] + sheet.add_row ["19.1", "1 min 32 sec", "about 10 hours ago", "1.8.7"] + sheet.add_row ["19.2", "1 min 28 sec", "about 10 hours ago", "1.9.2"] + sheet.add_row ["19.3", "1 min 35 sec", "about 10 hours ago", "1.9.3"] + sheet.add_table "A2:D5", :name => 'Build Matrix' +end +``` ##Specifying Column Widths - wb.add_worksheet(:name => "custom column widths") do |sheet| - sheet.add_row ["I use auto_fit and am very wide", "I use a custom width and am narrow"] - sheet.column_widths nil, 3 - end - -##Specify Page Margins for printing - - margins = {:left => 3, :right => 3, :top => 1.2, :bottom => 1.2, :header => 0.7, :footer => 0.7} - wb.add_worksheet(:name => "print margins", :page_margins => margins) do |sheet| - sheet.add_row["this sheet uses customized page margins for printing"] - end +```ruby +wb.add_worksheet(:name => "custom column widths") do |sheet| + sheet.add_row ["I use autowidth and am very wide", "I use a custom width and am narrow"] + sheet.add_row ['abcdefg', 'This is a very long text and should flow into the right cell', nil, 'xxx' ] + sheet.column_widths nil, 3, 5, nil +end +``` ##Fit to page printing - wb.add_worksheet(:name => "fit to page") do |sheet| - sheet.add_row ['this all goes on one page'] - sheet.fit_to_page = true - end - +```ruby +wb.add_worksheet(:name => "fit to page") do |sheet| + sheet.add_row ['this all goes on one page'] + sheet.fit_to_page = true +end +``` ##Hide Gridlines in worksheet - wb.add_worksheet(:name => "No Gridlines") do |sheet| - sheet.add_row ["This", "Sheet", "Hides", "Gridlines"] - sheet.show_gridlines = false - end +```ruby +wb.add_worksheet(:name => "No Gridlines") do |sheet| + sheet.add_row ["This", "Sheet", "Hides", "Gridlines"] + sheet.show_gridlines = false +end +``` + +##Specify Page Margins for printing + +```ruby +margins = {:left => 3, :right => 3, :top => 1.2, :bottom => 1.2, :header => 0.7, :footer => 0.7} +wb.add_worksheet(:name => "print margins", :page_margins => margins) do |sheet| + sheet.add_row ["this sheet uses customized page margins for printing"] +end +``` ##Validate and Serialize - p.validate.each { |e| puts e.message } - p.serialize("example.xlsx") +```ruby +p.serialize("example.xlsx") - # alternatively, serialize to StringIO - s = p.to_stream() - File.open('example_streamed.xlsx', 'w') { |f| f.write(s.read) } +s = p.to_stream() +File.open('example_streamed.xlsx', 'w') { |f| f.write(s.read) } +``` ##Using Shared Strings - p.use_shared_strings = true - p.serialize("shared_strings_example.xlsx") +```ruby +p.use_shared_strings = true +p.serialize("shared_strings_example.xlsx") +``` -##Disabling Autowidth - p = Axlsx::Package.new - p.use_autowidth = false - wb = p.workbook - wb.add_worksheet(:name => "No Magick") do | sheet | - sheet.add_row ['oh look! no autowidth - and no magick loaded in your process'] - end - p.validate.each { |e| puts e.message } - p.serialize("no-use_autowidth.xlsx") +##Disabling Autowidth +```ruby +p = Axlsx::Package.new +p.use_autowidth = false +wb = p.workbook +wb.add_worksheet(:name => "No Magick") do | sheet | + sheet.add_row ['oh look! no autowidth - and no magick loaded in your process'] +end +p.validate.each { |e| puts e.message } +p.serialize("no-use_autowidth.xlsx") +``` #Documentation -------------- This gem is 100% documented with YARD, an exceptional documentation library. To see documentation for this, and all the gems installed on your system use: - gem install yard - yard server -g - +```bash +gem install yard +yard server -g +``` #Specs ------ This gem has 100% test coverage using test/unit. To execute tests for this gem, simply run rake in the gem directory. -- cgit v1.2.3