From 07ae860c69b06f937f588d58fe17171bb9ca4813 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 349a8cc81f58398c48ded873abace3c34c800f01 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 e511a47af99813c4b80f5f2dd19507f24a8d6a65 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 65ec495117d22df16ef1c3fc94bdcfe0f2d32d30 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 42b3af1a8b6e6a68c200f40d35e0dbad5b7316c3 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 bde6f651d0a7c0f9661c881bbb1a5e44f3e83c9f 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 d9705fa234819fd640e2e5fdb5422a8d22d8ff3b 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 f93ac348f13b9cdc8df48e7d566aec1bf03b5ddd 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 6bd48b06be03d4b85b4d2cc2db4f540fb1e5e4a9 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 cad457279d6ec32efa5d6c670d99de3e00c9afbd 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 a3f287c6bc810584ff279ae62b955cbe635c5310 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 760492c8c6dd389a9668dac928695c0bb04bcab3 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 4c2ccec3b3553419c2251cc6c53fc53baadab146 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 694af4f58d113c294340246660dbe314764a9bd3 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 568a9005d80021bc2b02fabaa9dbe91080d5cf51 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 dc1f2922b1a546009ce3c4d937e8473939a51959 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 6440dced8ff2da027fd4f60f434262ec60191573 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 cf69408bec13982d6b22cd1c91ec6a52da6c3920 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 1f785558252d8bc35bae6cec721641a26b6978d0 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 57f4162adb1984cc19e41833c32b9dcbf211a4c9 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 f43f801b9e01249dfde0bc8453ecf5376898d3c2 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 b18ac56202a0a33adfe6b226cfd593b5e342ab76 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 4f418b24fd10055c89e50c57dc617225d08875fd 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 1ee8ce1778294d39640f66f02ad52af59c753ea0 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 e8a6a524b8fa7f1ecc63c00cde3e0c07ee79812c 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 14d1ee01951226f9482e711556cfc013ee6f64cb 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 720a34fff84b9423d4052a5432b24d953e947edb 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 09482f71649a454eff7c7aff04d2de864d3826dc 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 9e71b531862f14b971d8b33f7a038e2351586ead 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 91432f53b6da621a9bccba8c1d150b414fe28bb4 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 0d2320f4aeed8d405e645f6d01334b625d0a3590 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 8861dd32d072bf42181d99c30ba406b07cd1e990 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 d06b14cf31eb92bff1895df612e70fd0608c3822 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 bb941417e85935726dc1d462165dfcc1b1f1927b 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 ce4fd4066fa06b57aa645219a71c703e35d4d408 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 dc3f8ef528b86e84043ee9133325e61380a401c9 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 5892ab4c667eacdef6f8a16f2ca0b652aeff715f 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 452226bea54da171cc57f4d5ba21363fd16eb188 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 a5eede3fd70813f0d1c47fca5a17cc6f9130ac17 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 b169cc9d067fb8c195d452768ef4d70414bc25c1 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 223d4baee0f9aeb3485321d6f4128eb34e0dfce3 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 99e0fd6d70b48df1e09b6f234b2512893eae9ff6 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 ca7248353d295c74f3dff7e8e003044849c026e7 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 9b977d94d632eddfbc9c7651ced9932c308752b9 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 37a09854..ebdca767 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 0a0306e249ce68eee4fbb36240aa897d62af66ba 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 2970febe9d3e92cbf45b4be04955a92c52a104ce 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 0dba5eb6689c326a137394a6ff9143badc31d3ae 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 11d26d323b9715f99bc0ef637fbd1a973a45e2b5 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 4f50dd3270e87d2fd69cd10ec97720677921f847 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 b94d041a1f43b3a43024e7d0245e4c14020a4baf 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 07e5a44e95871d483b48354d8996e05b1c6b0439 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