summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md14
-rw-r--r--README.md47
-rw-r--r--Rakefile2
-rw-r--r--axlsx.gemspec6
-rwxr-xr-xexamples/example.rb776
-rw-r--r--examples/extractive.pdfbin64125 -> 0 bytes
-rw-r--r--examples/finance.rb82
-rw-r--r--examples/hyperlinks.rb23
-rw-r--r--examples/scraping_html.rb91
-rw-r--r--examples/sheet_view.rb34
-rw-r--r--examples/skydrive/axlsx.csv1
-rw-r--r--examples/sprk2012/basics.rb11
-rw-r--r--examples/sprk2012/images.rb9
-rw-r--r--examples/sprk2012/styles.rb20
-rw-r--r--examples/two_cell_anchor_image.rb11
-rw-r--r--examples/wrap_text.rb21
-rw-r--r--lib/axlsx/content_type/abstract_content_type.rb32
-rw-r--r--lib/axlsx/content_type/content_type.rb2
-rw-r--r--lib/axlsx/content_type/default.rb43
-rw-r--r--lib/axlsx/content_type/override.rb44
-rw-r--r--lib/axlsx/drawing/chart.rb2
-rw-r--r--lib/axlsx/drawing/drawing.rb6
-rw-r--r--lib/axlsx/drawing/hyperlink.rb3
-rw-r--r--lib/axlsx/drawing/view_3D.rb60
-rw-r--r--lib/axlsx/package.rb24
-rw-r--r--lib/axlsx/rels/relationship.rb2
-rw-r--r--lib/axlsx/stylesheet/color.rb4
-rw-r--r--lib/axlsx/stylesheet/gradient_fill.rb1
-rw-r--r--lib/axlsx/stylesheet/pattern_fill.rb13
-rw-r--r--lib/axlsx/util/accessors.rb23
-rw-r--r--lib/axlsx/util/options_parser.rb6
-rw-r--r--lib/axlsx/util/serialized_attributes.rb49
-rw-r--r--lib/axlsx/util/simple_typed_list.rb20
-rw-r--r--lib/axlsx/util/validators.rb8
-rw-r--r--lib/axlsx/version.rb2
-rw-r--r--lib/axlsx/workbook/defined_name.rb18
-rw-r--r--lib/axlsx/workbook/workbook.rb19
-rw-r--r--lib/axlsx/workbook/worksheet/cell.rb48
-rw-r--r--lib/axlsx/workbook/worksheet/cfvos.rb15
-rw-r--r--lib/axlsx/workbook/worksheet/col.rb10
-rw-r--r--lib/axlsx/workbook/worksheet/color_scale.rb90
-rw-r--r--lib/axlsx/workbook/worksheet/data_bar.rb91
-rw-r--r--lib/axlsx/workbook/worksheet/header_footer.rb54
-rw-r--r--lib/axlsx/workbook/worksheet/pane.rb3
-rw-r--r--lib/axlsx/workbook/worksheet/protected_range.rb1
-rw-r--r--lib/axlsx/workbook/worksheet/row.rb129
-rw-r--r--lib/axlsx/workbook/worksheet/sheet_protection.rb6
-rw-r--r--lib/axlsx/workbook/worksheet/worksheet.rb48
-rw-r--r--lib/axlsx/workbook/worksheet/worksheet_hyperlink.rb2
-rw-r--r--test/benchmark.rb3
-rw-r--r--test/content_type/tc_default.rb11
-rw-r--r--test/content_type/tc_override.rb13
-rw-r--r--test/profile.rb17
-rw-r--r--test/rels/tc_relationship.rb5
-rw-r--r--test/tc_helper.rb6
-rw-r--r--test/util/tc_validators.rb14
-rw-r--r--test/workbook/tc_workbook.rb8
-rw-r--r--test/workbook/worksheet/tc_cell.rb16
-rw-r--r--test/workbook/worksheet/tc_col.rb10
-rw-r--r--test/workbook/worksheet/tc_color_scale.rb33
-rw-r--r--test/workbook/worksheet/tc_data_bar.rb7
-rw-r--r--test/workbook/worksheet/tc_header_footer.rb151
-rw-r--r--test/workbook/worksheet/tc_row.rb8
-rw-r--r--test/workbook/worksheet/tc_worksheet.rb37
-rw-r--r--test/workbook/worksheet/tc_worksheet_hyperlink.rb2
65 files changed, 1398 insertions, 969 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7f8a3571..a1e392ff 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,19 @@
CHANGELOG
---------
+
+- **September.30.12**: 1.3.1
+ - Improved control character handling
+ - Added stored auto filter values and date grouping items
+ - Improved support for autowidth when custom styles are applied
+ - Added support for table style info that lets you take advantage of
+ all the predefined table styles.
+ - Improved style management for fonts so they merge undefined values
+ from the initial master.
+- **September.8.12**: 1.2.3
+ - enhance exponential float/bigdecimal values rendering as strings intead
+ of 'numbers' in excel.
+ - added support for :none option on chart axis labels
+ - added support for paper_size option on worksheet.page_setup
- **August.27.12**: 1.2.2
- minor patch for auto-filters
- minor documentation improvements.
diff --git a/README.md b/README.md
index 9af712a4..061407cb 100644
--- a/README.md
+++ b/README.md
@@ -15,13 +15,13 @@ appreciation for the gem, please don't hesitate to make a donation.
**Google Group**: [https://groups.google.com/forum/?fromgroups#!forum/axlsx](https://groups.google.com/forum/?fromgroups#!forum/axlsx)
-**Author**: Randy Morgan
+**Author**: Randy Morgan
-**Copyright**: 2011 - 2012
+**Copyright**: 2011 - 2012
**License**: MIT License
-**Latest Version**: 1.3.1
+**Latest Version**: 1.3.4
**Ruby Version**: 1.8.7, 1.9.2, 1.9.3
@@ -29,7 +29,7 @@ appreciation for the gem, please don't hesitate to make a donation.
**Rubinius Version**: rubinius 2.0.0dev * lower versions may run, this gem always tests against head.
-**Release Date**: September 30th 2012
+**Release Date**: November ??th 2012
If you are working in rails, or with active record see:
* http://github.com/randym/acts_as_xlsx
@@ -101,6 +101,9 @@ and Numbers
**19. Data labels for charts as well as series color customization.
+**20. Support for sheet headers and footers
+
+
Installing
----------
@@ -149,22 +152,21 @@ This gem has 100% test coverage using test/unit. To execute tests for this gem,
#Change log
---------
-- **October.??.12**: 1.3.2
- - Patched to handle sheet names with apostrophes
- - refactored string and boolean attribute accessors
-- **September.30.12**: 1.3.1
- - Improved control character handling
- - Added stored auto filter values and date grouping items
- - Improved support for autowidth when custom styles are applied
- - Added support for table style info that lets you take advantage of
- all the predefined table styles.
- - Improved style management for fonts so they merge undefined values
- from the initial master.
-- **September.8.12**: 1.2.3
- - enhance exponential float/bigdecimal values rendering as strings intead
- of 'numbers' in excel.
- - added support for :none option on chart axis labels
- - added support for paper_size option on worksheet.page_setup
+- **November.25.12**:1.3.4
+ - Support for headers and footers for worksheets
+ - bug fix: Properly escape hyperlink urls
+ - Improvements in color_scale generation for conditional formatting
+ - Improvements in autowidth calculation.
+- **November.8.12**:1.3.3
+ - Patched cell run styles for u and validation for family
+- **November.5.12**:1.3.2
+ - MASSIVE REFACTORING
+ - Patch for apostrophes in worksheet names
+ - added sheet_by_name for workbook so you can now find your worksheets
+ by name
+ - added insert_worksheet so you can now add a worksheet to an
+ arbitrary position in the worksheets list.
+ - reduced memory consumption for package parts post serialization
Please see the {file:CHANGELOG.md} document for past release information.
@@ -173,7 +175,7 @@ As axslx implements the Office Open XML (ECMA-376 spec) much of the
functionality is interoperable with other spreadsheet software. Below is
a listing of some known issues.
-1. Libra Office
+1. Libre Office
- You must specify colors for your series. see examples/chart_colors.rb
for an example.
- You must use data in your sheet for charts. You cannot use hard coded
@@ -238,6 +240,9 @@ done without the help of the people below.
[ebenoist](https://github.com/ebenoist) - For taking control of control characters and keeping what is between the lines, between the lines.
+[adammathys](https://github.com/adammathys) - Fgr getting our head in the
+air and our feet on the ground.
+
#Copyright and License
----------
diff --git a/Rakefile b/Rakefile
index 01a55527..227ecfc2 100644
--- a/Rakefile
+++ b/Rakefile
@@ -11,7 +11,7 @@ end
task :gendoc do
#puts 'yard doc generation disabled until JRuby build native extensions for redcarpet or yard removes the dependency.'
system "yardoc"
- #system "yard stats --list-undoc"
+ system "yard stats --list-undoc"
end
task :test do
diff --git a/axlsx.gemspec b/axlsx.gemspec
index 81a3ce0a..be46cb6b 100644
--- a/axlsx.gemspec
+++ b/axlsx.gemspec
@@ -1,5 +1,3 @@
-# This will recursively require rake when using rake 0.9.2.2 and bundler
-#require 'rake'
require File.expand_path('../lib/axlsx/version', __FILE__)
Gem::Specification.new do |s|
@@ -15,7 +13,7 @@ Gem::Specification.new do |s|
s.description = <<-eof
xlsx generation with charts, images, automated column width, customizable styles and full schema validation. Axlsx excels at helping you generate beautiful Office Open XML Spreadsheet documents without having to understand the entire ECMA specification. Check out the README for some examples of how easy it is. Best of all, you can validate your xlsx file before serialization so you know for sure that anything generated is going to load on your client's machine.
eof
- s.files = Dir.glob("{lib/**/*,examples/**/*}") + %w{ LICENSE README.md Rakefile CHANGELOG.md .yardopts }
+ s.files = Dir.glob("{lib/**/*,examples/**/*.rb,examples/**/*.jpeg}") + %w{ LICENSE README.md Rakefile CHANGELOG.md .yardopts }
s.test_files = Dir.glob("{test/**/*}")
s.add_runtime_dependency 'nokogiri', '>= 1.4.1'
@@ -25,7 +23,7 @@ Gem::Specification.new do |s|
# This has been removed until JRuby can support the native extensions for redcarpet or yard removes the dependency
s.add_development_dependency 'yard'
s.add_development_dependency 'kramdown'
- s.add_development_dependency 'cover_me' unless RUBY_VERSION == '1.8.7'
+ s.add_development_dependency 'simplecov'
s.required_ruby_version = '>= 1.8.7'
s.require_path = 'lib'
end
diff --git a/examples/example.rb b/examples/example.rb
index 596da6b2..a7eace2a 100755
--- a/examples/example.rb
+++ b/examples/example.rb
@@ -1,20 +1,61 @@
#!/usr/bin/env ruby -w -s
# -*- coding: utf-8 -*-
-# $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib"
+$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib"
#```ruby
require 'axlsx'
+examples = []
+examples << :basic
+examples << :custom_styles
+examples << :wrap_text
+examples << :cell_style_override
+examples << :custom_borders
+examples << :surrounding_border
+examples << :deep_custom_borders
+examples << :row_column_style
+examples << :fixed_column_width
+examples << :merge_cells
+examples << :images
+examples << :format_dates
+examples << :mbcs
+examples << :formula
+examples << :auto_filter
+examples << :data_types
+examples << :hyperlinks
+examples << :number_currency_format
+examples << :venezuela_currency
+examples << :bar_chart
+examples << :chart_gridlines
+examples << :pie_chart
+examples << :line_chart
+examples << :scatter_chart
+examples << :tables
+examples << :fit_to_page
+examples << :hide_gridlines
+examples << :repeated_header
+examples << :defined_name
+examples << :printing
+examples << :header_footer
+examples << :comments
+examples << :panes
+examples << :sheet_view
+examples << :conditional_formatting
+examples << :streaming
+examples << :shared_strings
+examples << :no_autowidth
p = Axlsx::Package.new
wb = p.workbook
#```
-#A Simple Workbook
+## A Simple Workbook
#```ruby
-wb.add_worksheet(:name => "Basic Worksheet") do |sheet|
- sheet.add_row ["First Column", "Second", "Third"]
- sheet.add_row [1, 2, 3]
+if examples.include? :basic
+ wb.add_worksheet(:name => "Basic Worksheet") do |sheet|
+ sheet.add_row ["First Column", "Second", "Third"]
+ sheet.add_row [1, 2, 3]
+ end
end
#```
@@ -24,36 +65,64 @@ end
# Each cell allows a single, predified style.
# When using add_row, the value in the :style array at the same index as the cell's column will be applied to that cell.
# Alternatively, you can apply a style to an entire row by using an integer value for :style.
+if examples.include? :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|
+
+ # Applies the black_cell style to the first and third cell, and the blue_cell style to the second.
+ sheet.add_row ["Text Autowidth", "Second", "Third"], :style => [black_cell, blue_cell, black_cell]
-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|
+ # Applies the thin border to all three cells
+ sheet.add_row [1, 2, 3], :style => Axlsx::STYLE_THIN_BORDER
+ end
+ end
+end
- # Applies the black_cell style to the first and third cell, and the blue_cell style to the second.
- sheet.add_row ["Text Autowidth", "Second", "Third"], :style => [black_cell, blue_cell, black_cell]
- # Applies the thin border to all three cells
- sheet.add_row [1, 2, 3], :style => Axlsx::STYLE_THIN_BORDER
+#```ruby
+# A simple example of wrapping text. Seems this may not be working in Libre Office so here is an example for me to play with.
+if examples.include? :wrap_text
+ wb.styles do |s|
+ wrap_text = s.add_style :fg_color=> "FFFFFF",
+ :b => true,
+ :bg_color => "004586",
+ :sz => 12,
+ :border => { :style => :thin, :color => "00" },
+ :alignment => { :horizontal => :center,
+ :vertical => :center ,
+ :wrap_text => true}
+ wb.add_worksheet(:name => 'wrap text') do |sheet|
+ sheet.add_row ['Torp, White and Cronin'], :style=>wrap_text
+ sheet.column_info.first.width = 5
+ end
end
end
-#```
##Styling Cell Overrides
#```ruby
#Some of the style attributes can also be set at the cell level. Cell level styles take precedence over Custom Styles shown in the previous example.
-
-wb.add_worksheet(:name => "Cell Level Style Overrides") do |sheet|
-
- # this will set the font size for each cell.
- sheet.add_row ['col 1', 'col 2', 'col 3', 'col 4'], :sz => 16
-
- sheet.add_row [1, 2, 3, "=SUM(A2:C2)"]
-
- # You can also apply cell style overrides to a range of cells
- sheet["A1:D1"].each { |c| c.color = "FF0000" }
- sheet['A1:D2'].each { |c| c.style = Axlsx::STYLE_THIN_BORDER }
+if examples.include? :cell_style_override
+ wb.add_worksheet(:name => "Cell Level Style Overrides") do |sheet|
+
+ # this will set the font size for each cell.
+ 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 %w(u shadow sz b i strike outline)
+ sheet.rows.last.cells[0].u = :double
+ sheet.rows.last.cells[1].shadow = true
+ sheet.rows.last.cells[2].sz = 20
+ sheet.rows.last.cells[3].b = true
+ sheet.rows.last.cells[4].i = true
+ sheet.rows.last.cells[5].strike = true
+ sheet.rows.last.cells[6].outline = 1
+ # You can also apply cell style overrides to a range of cells
+ sheet["A1:D1"].each { |c| c.color = "FF0000" }
+ sheet['A1:D2'].each { |c| c.style = Axlsx::STYLE_THIN_BORDER }
+ end
end
##```
@@ -61,65 +130,98 @@ end
#```ruby
#Axlsx defines a thin border style, but you can easily create and use your own.
-wb.styles do |s|
- red_border = s.add_style :border => { :style => :thick, :color =>"FFFF0000", :edges => [:left, :right] }
- blue_border = s.add_style :border => { :style => :thick, :color =>"FF0000FF"}
+if examples.include? :custom_borders
+ wb.styles do |s|
+ red_border = s.add_style :border => { :style => :thick, :color =>"FFFF0000", :edges => [:left, :right] }
+ blue_border = s.add_style :border => { :style => :thick, :color =>"FF0000FF"}
+
+ wb.add_worksheet(:name => "Custom Borders") do |sheet|
+ sheet.add_row ["wrap", "me", "Up in Red"], :style => red_border
+ sheet.add_row [1, 2, 3], :style => blue_border
+ end
+ end
+end
+
+#```ruby
+# More Custom Borders
+if examples.include? :surrounding_border
+
+ # Stuff like this is why I LOVE RUBY
+ # If you dont know about hash default values
+ # LEARN IT! LIVE IT! LOVE IT!
+ defaults = { :style => :thick, :color => "000000" }
+ borders = Hash.new do |hash, key|
+ hash[key] = wb.styles.add_style :border => defaults.merge( { :edges => key.to_s.split('_').map(&:to_sym) } )
+ end
+ top_row = [0, borders[:top_left], borders[:top], borders[:top], borders[:top_right]]
+ middle_row = [0, borders[:left], nil, nil, borders[:right]]
+ bottom_row = [0, borders[:bottom_left], borders[:bottom], borders[:bottom], borders[:bottom_right]]
+
+ wb.add_worksheet(:name => "Surrounding Border") do |ws|
+ ws.add_row []
+ ws.add_row ['', 1,2,3,4], :style => top_row
+ ws.add_row ['', 5,6,7,8], :style => middle_row
+ ws.add_row ['', 9, 10, 11, 12]
+
+ #This works too!
+ ws.rows.last.style = bottom_row
- wb.add_worksheet(:name => "Custom Borders") do |sheet|
- sheet.add_row ["wrap", "me", "Up in Red"], :style => red_border
- sheet.add_row [1, 2, 3], :style => blue_border
end
end
-#```ruby
+#```ruby
# Hacking border styles
- wb.styles do |s|
- top_bottom = s.add_style :border => { :style => :thick, :color =>"FFFF0000", :edges => [:top, :bottom] }
- border = s.borders[s.cellXfs[top_bottom].borderId]
- # edit existing border parts
- border.prs.each do |part|
- case part.name
- when :top
- part.color = Axlsx::Color.new(:rgb => "FFFF0000")
- when :bottom
- part.color = Axlsx::Color.new(:rgb => "FF00FF00")
- end
+if examples.include? :deep_custom_borders
+ wb.styles do |s|
+ top_bottom = s.add_style :border => { :style => :thick, :color =>"FFFF0000", :edges => [:top, :bottom] }
+ border = s.borders[s.cellXfs[top_bottom].borderId]
+ # edit existing border parts
+ border.prs.each do |part|
+ case part.name
+ when :top
+ part.color = Axlsx::Color.new(:rgb => "FFFF0000")
+ when :bottom
+ part.color = Axlsx::Color.new(:rgb => "FF00FF00")
end
+ end
- border.prs << Axlsx::BorderPr.new(:name => :left, :color => Axlsx::Color.new(:rgb => '0000FF'), :style => :mediumDashed)
- wb.add_worksheet(:name => 'hacked borders') do |sheet|
- sheet.add_row [1,2,3], :style=>top_bottom
- end
+ border.prs << Axlsx::BorderPr.new(:name => :left, :color => Axlsx::Color.new(:rgb => '0000FF'), :style => :mediumDashed)
+ wb.add_worksheet(:name => 'hacked borders') do |sheet|
+ sheet.add_row [1,2,3], :style=>top_bottom
end
+ end
+end
##```
##Styling Rows and Columns
#```ruby
-wb.styles do |s|
- head = s.add_style :bg_color => "00", :fg_color => "FF"
- percent = s.add_style :num_fmt => 9
- wb.add_worksheet(:name => "Columns and Rows") do |sheet|
- sheet.add_row ['col 1', 'col 2', 'col 3', 'col 4', 'col5']
- sheet.add_row [1, 2, 0.3, 4, 5.0]
- sheet.add_row [1, 2, 0.2, 4, 5.0]
- sheet.add_row [1, 2, 0.1, 4, 5.0]
-
- #apply the percent style to the column at index 2 skipping the first row.
- sheet.col_style 2, percent, :row_offset => 1
-
- # apply the head style to the first row.
- sheet.row_style 0, head
-
- #Hide the 5th column
- sheet.column_info[4].hidden = true
-
- #Set the second column outline level
- sheet.column_info[1].outlineLevel = 2
-
- sheet.rows[3].hidden = true
- sheet.rows[1].outlineLevel = 2
+if examples.include? :row_column_style
+ 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 => "Columns and Rows") do |sheet|
+ sheet.add_row ['col 1', 'col 2', 'col 3', 'col 4', 'col5']
+ sheet.add_row [1, 2, 0.3, 4, 5.0]
+ sheet.add_row [1, 2, 0.2, 4, 5.0]
+ sheet.add_row [1, 2, 0.1, 4, 5.0]
+
+ #apply the percent style to the column at index 2 skipping the first row.
+ sheet.col_style 2, percent, :row_offset => 1
+
+ # apply the head style to the first row.
+ sheet.row_style 0, head
+
+ #Hide the 5th column
+ sheet.column_info[4].hidden = true
+
+ #Set the second column outline level
+ sheet.column_info[1].outlineLevel = 2
+
+ sheet.rows[3].hidden = true
+ sheet.rows[1].outlineLevel = 2
+ end
end
end
##```
@@ -128,40 +230,46 @@ end
##Specifying Column Widths
#```ruby
-wb.add_worksheet(:name => "custom column widths") do |sheet|
- sheet.add_row ["I use autowidth and am very wide", "I use a custom width and am narrow"]
- sheet.add_row ['abcdefg', 'This is a very long text and should flow into the right cell', nil, 'xxx' ]
- sheet.column_widths nil, 3, 5, nil
+if examples.include? :fixed_column_width
+ wb.add_worksheet(:name => "custom column widths") do |sheet|
+ sheet.add_row ["I use autowidth and am very wide", "I use a custom width and am narrow"]
+ sheet.add_row ['abcdefg', 'This is a very long text and should flow into the right cell', nil, 'xxx' ]
+ sheet.column_widths nil, 3, 5, nil
+ end
end
##```
##Merging Cells.
#```ruby
-wb.add_worksheet(:name => 'Merging Cells') do |sheet|
- # cell level style overides when adding cells
- sheet.add_row ["col 1", "col 2", "col 3", "col 4"], :sz => 16
- sheet.add_row [1, 2, 3, "=SUM(A2:C2)"]
- sheet.add_row [2, 3, 4, "=SUM(A3:C3)"]
- sheet.add_row ["total", "", "", "=SUM(D2:D3)"]
- sheet.merge_cells("A4:C4")
- sheet["A1:D1"].each { |c| c.color = "FF0000"}
- sheet["A1:D4"].each { |c| c.style = Axlsx::STYLE_THIN_BORDER }
+if examples.include? :merge_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
end
##```
##Add an Image with a hyperlink
#```ruby
-wb.add_worksheet(:name => "Image with Hyperlink") do |sheet|
- img = File.expand_path('../image1.jpeg', __FILE__)
- # specifying the :hyperlink option will add a hyper link to your image.
- # @note - Numbers does not support this part of the specification.
- 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
+if examples.include? :images
+ wb.add_worksheet(:name => "Image with Hyperlink") do |sheet|
+ img = File.expand_path('../image1.jpeg', __FILE__)
+ # specifying the :hyperlink option will add a hyper link to your image.
+ # @note - Numbers does not support this part of the specification.
+ 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
#```
@@ -169,15 +277,17 @@ end
##Using Custom Formatting and date1904
#```ruby
-require 'date'
-wb.styles do |s|
- date = s.add_style(:format_code => "yyyy-mm-dd", :border => Axlsx::STYLE_THIN_BORDER)
- padded = s.add_style(:format_code => "00#", :border => Axlsx::STYLE_THIN_BORDER)
- percent = s.add_style(:format_code => "0000%", :border => Axlsx::STYLE_THIN_BORDER)
- # wb.date1904 = true # Use the 1904 date system (Used by Excel for Mac < 2011)
- wb.add_worksheet(:name => "Formatting Data") do |sheet|
- sheet.add_row ["Custom Formatted Date", "Percent Formatted Float", "Padded Numbers"], :style => Axlsx::STYLE_THIN_BORDER
- sheet.add_row [Date::strptime('2012-01-19','%Y-%m-%d'), 0.2, 32], :style => [date, percent, padded]
+if examples.include? :format_dates
+ 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
end
#```
@@ -185,33 +295,39 @@ end
##Asian Language Support
#```ruby
-wb.add_worksheet(:name => "日本語でのシート名") do |sheet|
- sheet.add_row ["日本語"]
- sheet.add_row ["华语/華語"]
- sheet.add_row ["한국어/조선말"]
+if examples.include? :mbcs
+ wb.add_worksheet(:name => "日本語でのシート名") do |sheet|
+ sheet.add_row ["日本語"]
+ sheet.add_row ["华语/華語"]
+ sheet.add_row ["한국어/조선말"]
+ end
end
##```
##Using formula
#```ruby
-wb.add_worksheet(:name => "Using Formulas") do |sheet|
- sheet.add_row ['col 1', 'col 2', 'col 3', 'col 4']
- sheet.add_row [1, 2, 3, "=SUM(A2:C2)"]
+if examples.include? :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
end
##```
##Auto Filter
#```ruby
-wb.add_worksheet(:name => "Auto Filter") do |sheet|
- sheet.add_row ["Build Matrix"]
- sheet.add_row ["Build", "Duration", "Finished", "Rvm"]
- sheet.add_row ["19.1", "1 min 32 sec", "about 10 hours ago", "1.8.7"]
- sheet.add_row ["19.2", "1 min 28 sec", "about 10 hours ago", "1.9.2"]
- sheet.add_row ["19.3", "1 min 35 sec", "about 10 hours ago", "1.9.3"]
- sheet.auto_filter = "A2:D5"
- sheet.auto_filter.add_column 3, :filters, :filter_items => ['1.9.2', '1.8.7']
+if examples.include? :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"
+ sheet.auto_filter.add_column 3, :filters, :filter_items => ['1.9.2', '1.8.7']
+ end
end
#```
@@ -219,61 +335,79 @@ end
#```ruby
-wb.add_worksheet(:name => "Automatic cell types") do |sheet|
- date_format = wb.styles.add_style :format_code => 'YYYY-MM-DD'
- time_format = wb.styles.add_style :format_code => 'hh:mm:ss'
- sheet.add_row ["Date", "Time", "String", "Boolean", "Float", "Integer"]
- sheet.add_row [Date.today, Time.now, "value", true, 0.1, 1], :style => [date_format, time_format]
+if examples.include? :data_types
+ wb.add_worksheet(:name => "Automatic cell types") do |sheet|
+ date_format = wb.styles.add_style :format_code => 'YYYY-MM-DD'
+ time_format = wb.styles.add_style :format_code => 'hh:mm:ss'
+ sheet.add_row ["Date", "Time", "String", "Boolean", "Float", "Integer"]
+ sheet.add_row [Date.today, Time.now, "value", true, 0.1, 1], :style => [date_format, time_format]
+ end
end
-
# Hyperlinks in worksheet
-wb.add_worksheet(:name => 'hyperlinks') do |sheet|
- # external references
- sheet.add_row ['axlsx']
- sheet.add_hyperlink :location => 'https://github.com/randym/axlsx', :ref => sheet.rows.first.cells.first
- # internal references
- sheet.add_hyperlink :location => "'Next Sheet'!A1", :ref => 'A2', :target => :sheet
- sheet.add_row ['next sheet']
-end
+if examples.include? :hyperlinks
+ wb.add_worksheet(:name => 'hyperlinks') do |sheet|
+ # external references
+ sheet.add_row ['axlsx']
+ sheet.add_hyperlink :location => 'https://github.com/randym/axlsx', :ref => sheet.rows.first.cells.first
+ # internal references
+ sheet.add_hyperlink :location => "'Next Sheet'!A1", :ref => 'A2', :target => :sheet
+ sheet.add_row ['next sheet']
+ end
-wb.add_worksheet(:name => 'Next Sheet') do |sheet|
- sheet.add_row ['hello!']
+ wb.add_worksheet(:name => 'Next Sheet') do |sheet|
+ sheet.add_row ['hello!']
+ end
end
###```
##Number formatting and currency
-wb.add_worksheet(:name => "Formats and Currency") do |sheet|
- currency = wb.styles.add_style :num_fmt => 5
- red_negative = wb.styles.add_style :num_fmt => 8
- comma = wb.styles.add_style :num_fmt => 3
- super_funk = wb.styles.add_style :format_code => '[Green]#'
- sheet.add_row %w(Currency RedNegative Comma Custom)
- sheet.add_row [1500, -122.34, 123456789, 594829], :style=> [currency, red_negative, comma, super_funk]
+if examples.include? :number_currency_format
+ wb.add_worksheet(:name => "Formats and Currency") do |sheet|
+ currency = wb.styles.add_style :num_fmt => 5
+ red_negative = wb.styles.add_style :num_fmt => 8
+ comma = wb.styles.add_style :num_fmt => 3
+ super_funk = wb.styles.add_style :format_code => '[Green]#'
+ sheet.add_row %w(Currency RedNegative Comma Custom)
+ sheet.add_row [1500, -122.34, 123456789, 594829], :style=> [currency, red_negative, comma, super_funk]
+ end
+end
+
+## Venezuala currency
+if examples.include? :venezuela_currency
+ wb.add_worksheet(:name => 'Venezuala_currency') do |sheet|
+ number = wb.styles.add_style :format_code => '#.##0\,00'
+ sheet.add_row [2.5] , :style => [number]
+ end
end
##Generating A Bar Chart
#```ruby
-wb.add_worksheet(:name => "Bar Chart") do |sheet|
- sheet.add_row ["A Simple Bar Chart"]
- %w(first second third).each { |label| sheet.add_row [label, rand(24)+1] }
- sheet.add_chart(Axlsx::Bar3DChart, :start_at => "A6", :end_at => "F20") do |chart|
- chart.add_series :data => sheet["B2:B4"], :labels => sheet["A2:A4"], :title => sheet["A1"]
+if examples.include? :bar_chart
+ wb.add_worksheet(:name => "Bar Chart") do |sheet|
+ sheet.add_row ["A Simple Bar Chart"]
+ %w(first second third).each { |label| sheet.add_row [label, rand(24)+1] }
+ sheet.add_chart(Axlsx::Bar3DChart, :start_at => "A6", :end_at => "F20") do |chart|
+ chart.add_series :data => sheet["B2:B4"], :labels => sheet["A2:A4"], :title => sheet["A1"]
+ end
end
end
+
##```
##Hide Gridlines in chart
#```ruby
-wb.add_worksheet(:name => "Chart With No Gridlines") do |sheet|
- sheet.add_row ["Bar Chart without gridlines"]
- %w(first second third).each { |label| sheet.add_row [label, rand(24)+1] }
- sheet.add_chart(Axlsx::Bar3DChart, :start_at => "A6", :end_at => "F20") do |chart|
- chart.add_series :data => sheet["B2:B4"], :labels => sheet["A2:A4"]
- chart.valAxis.gridlines = false
- chart.catAxis.gridlines = false
+if examples.include? :chart_gridlines
+ wb.add_worksheet(:name => "Chart With No Gridlines") do |sheet|
+ sheet.add_row ["Bar Chart without gridlines"]
+ %w(first second third).each { |label| sheet.add_row [label, rand(24)+1] }
+ sheet.add_chart(Axlsx::Bar3DChart, :start_at => "A6", :end_at => "F20") do |chart|
+ chart.add_series :data => sheet["B2:B4"], :labels => sheet["A2:A4"]
+ chart.valAxis.gridlines = false
+ chart.catAxis.gridlines = false
+ end
end
end
#```
@@ -281,11 +415,13 @@ end
##Generating A Pie Chart
#```ruby
-wb.add_worksheet(:name => "Pie Chart") do |sheet|
- sheet.add_row ["Simple Pie Chart"]
- %w(first second third).each { |label| sheet.add_row [label, rand(24)+1] }
- sheet.add_chart(Axlsx::Pie3DChart, :start_at => [0,5], :end_at => [10, 20], :title => "example 3: Pie Chart") do |chart|
- chart.add_series :data => sheet["B2:B4"], :labels => sheet["A2:A4"], :colors => ['FF0000', '00FF00', '0000FF']
+if examples.include? :pie_chart
+ wb.add_worksheet(:name => "Pie Chart") do |sheet|
+ sheet.add_row ["Simple Pie Chart"]
+ %w(first second third).each { |label| sheet.add_row [label, rand(24)+1] }
+ sheet.add_chart(Axlsx::Pie3DChart, :start_at => [0,5], :end_at => [10, 20], :title => "example 3: Pie Chart") do |chart|
+ chart.add_series :data => sheet["B2:B4"], :labels => sheet["A2:A4"], :colors => ['FF0000', '00FF00', '0000FF']
+ end
end
end
#```
@@ -293,19 +429,21 @@ end
##Generating A Line Chart
#```ruby
-wb.add_worksheet(:name => "Line Chart") do |sheet|
- sheet.add_row ["Simple Line Chart"]
- sheet.add_row %w(first second)
- 4.times do
- sheet.add_row [ rand(24)+1, rand(24)+1]
- end
- sheet.add_chart(Axlsx::Line3DChart, :title => "Simple Line Chart", :rotX => 30, :rotY => 20) do |chart|
- chart.start_at 0, 5
- chart.end_at 10, 20
- chart.add_series :data => sheet["A3:A6"], :title => sheet["A2"]
- chart.add_series :data => sheet["B3:B6"], :title => sheet["B2"]
- chart.catAxis.title = 'X Axis'
- chart.valAxis.title = 'Y Axis'
+if examples.include? :line_chart
+ wb.add_worksheet(:name => "Line Chart") do |sheet|
+ sheet.add_row ["Simple Line Chart"]
+ sheet.add_row %w(first second)
+ 4.times do
+ sheet.add_row [ rand(24)+1, rand(24)+1]
+ end
+ sheet.add_chart(Axlsx::Line3DChart, :title => "Simple Line Chart", :rotX => 30, :rotY => 20) do |chart|
+ chart.start_at 0, 5
+ chart.end_at 10, 20
+ chart.add_series :data => sheet["A3:A6"], :title => sheet["A2"]
+ chart.add_series :data => sheet["B3:B6"], :title => sheet["B2"]
+ chart.catAxis.title = 'X Axis'
+ chart.valAxis.title = 'Y Axis'
+ end
end
end
#```
@@ -313,16 +451,18 @@ end
##Generating A Scatter Chart
#```ruby
-wb.add_worksheet(:name => "Scatter Chart") do |sheet|
- sheet.add_row ["First", 1, 5, 7, 9]
- sheet.add_row ["", 1, 25, 49, 81]
- sheet.add_row ["Second", 5, 2, 14, 9]
- sheet.add_row ["", 5, 10, 15, 20]
- sheet.add_chart(Axlsx::ScatterChart, :title => "example 7: Scatter Chart") do |chart|
- chart.start_at 0, 4
- chart.end_at 10, 19
- chart.add_series :xData => sheet["B1:E1"], :yData => sheet["B2:E2"], :title => sheet["A1"]
- chart.add_series :xData => sheet["B3:E3"], :yData => sheet["B4:E4"], :title => sheet["A3"]
+if examples.include? :scatter_chart
+ wb.add_worksheet(:name => "Scatter Chart") do |sheet|
+ sheet.add_row ["First", 1, 5, 7, 9]
+ sheet.add_row ["", 1, 25, 49, 81]
+ sheet.add_row ["Second", 5, 2, 14, 9]
+ sheet.add_row ["", 5, 10, 15, 20]
+ sheet.add_chart(Axlsx::ScatterChart, :title => "example 7: Scatter Chart") do |chart|
+ chart.start_at 0, 4
+ chart.end_at 10, 19
+ chart.add_series :xData => sheet["B1:E1"], :yData => sheet["B2:E2"], :title => sheet["A1"]
+ chart.add_series :xData => sheet["B3:E3"], :yData => sheet["B4:E4"], :title => sheet["A3"]
+ end
end
end
#```
@@ -331,13 +471,15 @@ end
##Tables
#```ruby
-wb.add_worksheet(:name => "Table") do |sheet|
- sheet.add_row ["Build Matrix"]
- sheet.add_row ["Build", "Duration", "Finished", "Rvm"]
- sheet.add_row ["19.1", "1 min 32 sec", "about 10 hours ago", "1.8.7"]
- sheet.add_row ["19.2", "1 min 28 sec", "about 10 hours ago", "1.9.2"]
- sheet.add_row ["19.3", "1 min 35 sec", "about 10 hours ago", "1.9.3"]
- sheet.add_table "A2:D5", :name => 'Build Matrix', :style_info => { :name => "TableStyleMedium23" }
+if examples.include? :tables
+ wb.add_worksheet(:name => "Table") do |sheet|
+ sheet.add_row ["Build Matrix"]
+ sheet.add_row ["Build", "Duration", "Finished", "Rvm"]
+ sheet.add_row ["19.1", "1 min 32 sec", "about 10 hours ago", "1.8.7"]
+ sheet.add_row ["19.2", "1 min 28 sec", "about 10 hours ago", "1.9.2"]
+ sheet.add_row ["19.3", "1 min 35 sec", "about 10 hours ago", "1.9.3"]
+ sheet.add_table "A2:D5", :name => 'Build Matrix', :style_info => { :name => "TableStyleMedium23" }
+ end
end
#```
@@ -345,9 +487,11 @@ end
##Fit to page printing
#```ruby
-wb.add_worksheet(:name => "fit to page") do |sheet|
- sheet.add_row ['this all goes on one page']
- sheet.fit_to_page = true
+if examples.include? :fit_to_page
+ wb.add_worksheet(:name => "fit to page") do |sheet|
+ sheet.add_row ['this all goes on one page']
+ sheet.fit_to_page = true
+ end
end
##```
@@ -355,159 +499,227 @@ end
##Hide Gridlines in worksheet
#```ruby
-wb.add_worksheet(:name => "No Gridlines") do |sheet|
- sheet.add_row ["This", "Sheet", "Hides", "Gridlines"]
- sheet.show_gridlines = false
+if examples.include? :hide_gridlines
+ wb.add_worksheet(:name => "No Gridlines") do |sheet|
+ sheet.add_row ["This", "Sheet", "Hides", "Gridlines"]
+ sheet.show_gridlines = false
+ end
end
##```
+# Repeat printing of header rows.
#```ruby
-wb.add_worksheet(:name => "repeated header") do |sheet|
- sheet.add_row %w(These Column Header Will Render On Every Printed Sheet)
- 200.times { sheet.add_row %w(1 2 3 4 5 6 7 8) }
- wb.add_defined_name("'repeated header'!$1:$1", :local_sheet_id => sheet.index, :name => '_xlnm.Print_Titles')
+if examples.include? :repeated_header
+ wb.add_worksheet(:name => "repeated header") do |sheet|
+ sheet.add_row %w(These Column Header Will Render On Every Printed Sheet)
+ 200.times { sheet.add_row %w(1 2 3 4 5 6 7 8) }
+ wb.add_defined_name("'repeated header'!$1:$1", :local_sheet_id => sheet.index, :name => '_xlnm.Print_Titles')
+ end
end
-# Sheet Protection and excluding cells from locking.
-unlocked = wb.styles.add_style :locked => false
-wb.add_worksheet(:name => 'Sheet Protection') do |sheet|
- sheet.sheet_protection.password = 'fish'
- sheet.add_row [1, 2 ,3] # These cells will be locked
- sheet.add_row [4, 5, 6], :style => unlocked # these cells will not!
+# Defined Names in formula
+if examples.include? :defined_name
+ wb.add_worksheet(:name => 'defined name') do |sheet|
+ sheet.add_row [1, 2, 17, '=FOOBAR']
+ wb.add_defined_name("'defined name'!$C1", :local_sheet_id => sheet.index, :name => 'FOOBAR')
+ end
end
+# Sheet Protection and excluding cells from locking.
+if examples.include? :sheet_protection
+ unlocked = wb.styles.add_style :locked => false
+ wb.add_worksheet(:name => 'Sheet Protection') do |sheet|
+ sheet.sheet_protection.password = 'fish'
+ sheet.add_row [1, 2 ,3] # These cells will be locked
+ sheet.add_row [4, 5, 6], :style => unlocked # these cells will not!
+ end
+end
##Specify page margins and other options for printing
#```ruby
-margins = {:left => 3, :right => 3, :top => 1.2, :bottom => 1.2, :header => 0.7, :footer => 0.7}
-setup = {:fit_to_width => 1, :orientation => :landscape, :paper_width => "297mm", :paper_height => "210mm"}
-options = {:grid_lines => true, :headings => true, :horizontal_centered => true}
-wb.add_worksheet(:name => "print margins", :page_margins => margins, :page_setup => setup, :print_options => options) do |sheet|
- sheet.add_row ["this sheet uses customized print settings"]
+if examples.include? :printing
+ margins = {:left => 3, :right => 3, :top => 1.2, :bottom => 1.2, :header => 0.7, :footer => 0.7}
+ setup = {:fit_to_width => 1, :orientation => :landscape, :paper_width => "297mm", :paper_height => "210mm"}
+ options = {:grid_lines => true, :headings => true, :horizontal_centered => true}
+ wb.add_worksheet(:name => "print margins", :page_margins => margins, :page_setup => setup, :print_options => options) do |sheet|
+ sheet.add_row ["this sheet uses customized print settings"]
+ end
end
#```
-## Add Comments to your spreadsheet
+## Add headers and footers to a worksheet
#``` ruby
-wb.add_worksheet(:name => 'comments') do |sheet|
- sheet.add_row ['Can we build it?']
- sheet.add_comment :ref => 'A1', :author => 'Bob', :text => 'Yes We Can!'
+if examples.include? :header_footer
+ header_footer = {:different_first => false, :odd_header => '&L&F : &A&R&D &T', :odd_footer => '&C&Pof&N'}
+ wb.add_worksheet(:name => "header footer", :header_footer => header_footer) do |sheet|
+ sheet.add_row ["this sheet has a header and a footer"]
+ end
+end
+#```
+
+## Add Comments to your spreadsheet
+#``` ruby
+if examples.include? :comments
+ wb.add_worksheet(:name => 'comments') do |sheet|
+ sheet.add_row ['Can we build it?']
+ sheet.add_comment :ref => 'A1', :author => 'Bob', :text => 'Yes We Can!'
+ end
end
## Frozen/Split panes
## ``` ruby
-wb.add_worksheet(:name => 'fixed headers') do |sheet|
- sheet.add_row(['', (0..99).map { |i| "column header #{i}" }].flatten )
- 100.times.with_index { |index| sheet << ["row header", (0..index).to_a].flatten }
- sheet.sheet_view.pane do |pane|
- pane.top_left_cell = "B2"
- pane.state = :frozen_split
- pane.y_split = 1
- pane.x_split = 1
- pane.active_pane = :bottom_right
+if examples.include? :panes
+ wb.add_worksheet(:name => 'panes') do |sheet|
+ sheet.add_row(['', (0..99).map { |i| "column header #{i}" }].flatten )
+ 100.times.with_index { |index| sheet << ["row header", (0..index).to_a].flatten }
+ sheet.sheet_view.pane do |pane|
+ pane.top_left_cell = "B2"
+ pane.state = :frozen_split
+ pane.y_split = 1
+ pane.x_split = 1
+ pane.active_pane = :bottom_right
+ end
end
end
-# conditional formatting
-#
-percent = wb.styles.add_style(:format_code => "0.00%", :border => Axlsx::STYLE_THIN_BORDER)
-money = wb.styles.add_style(:format_code => '0,000', :border => Axlsx::STYLE_THIN_BORDER)
+if examples.include? :sheet_view
+ ws = wb.add_worksheet(:name => 'SheetView - Split')
+ ws.sheet_view do |vs|
+ vs.pane do |pane|
+ pane.active_pane = :top_right
+ pane.state = :split
+ pane.x_split = 11080
+ pane.y_split = 5000
+ pane.top_left_cell = 'C44'
+ end
+
+ vs.add_selection(:top_left, { :active_cell => 'A2', :sqref => 'A2' })
+ vs.add_selection(:top_right, { :active_cell => 'I10', :sqref => 'I10' })
+ vs.add_selection(:bottom_left, { :active_cell => 'E55', :sqref => 'E55' })
+ vs.add_selection(:bottom_right, { :active_cell => 'I57', :sqref => 'I57' })
+ end
-# define the style for conditional formatting
-profitable = wb.styles.add_style( :fg_color=>"FF428751",
- :type => :dxf)
+ ws = wb.add_worksheet :name => "Sheetview - Frozen"
+ ws.sheet_view do |vs|
+ vs.pane do |pane|
+ pane.state = :frozen
+ pane.x_split = 3
+ pane.y_split = 4
+ end
+ end
+end
-wb.add_worksheet(:name => "Conditional Cell Is") do |ws|
+# conditional formatting
+#
+if examples.include? :conditional_formatting
+ percent = wb.styles.add_style(:format_code => "0.00%", :border => Axlsx::STYLE_THIN_BORDER)
+ money = wb.styles.add_style(:format_code => '0,000', :border => Axlsx::STYLE_THIN_BORDER)
+
+ # define the style for conditional formatting
+ profitable = wb.styles.add_style( :fg_color=>"FF428751",
+ :type => :dxf)
+
+ wb.add_worksheet(:name => "Conditional Cell Is") do |sheet|
+
+ # Generate 20 rosheet of data
+ sheet.add_row ["Previous Year Quarterly Profits (JPY)"]
+ sheet.add_row ["Quarter", "Profit", "% of Total"]
+ offset = 3
+ rosheet = 20
+ offset.upto(rosheet + offset) do |i|
+ sheet.add_row ["Q#{i}", 10000*((rosheet/2-i) * (rosheet/2-i)), "=100*B#{i}/SUM(B3:B#{rosheet+offset})"], :style=>[nil, money, percent]
+ end
- # Generate 20 rows of data
- ws.add_row ["Previous Year Quarterly Profits (JPY)"]
- ws.add_row ["Quarter", "Profit", "% of Total"]
- offset = 3
- rows = 20
- offset.upto(rows + offset) do |i|
- ws.add_row ["Q#{i}", 10000*((rows/2-i) * (rows/2-i)), "=100*B#{i}/SUM(B3:B#{rows+offset})"], :style=>[nil, money, percent]
+ # Apply conditional formatting to range B3:B100 in the worksheet
+ sheet.add_conditional_formatting("B3:B100", { :type => :cellIs, :operator => :greaterThan, :formula => "100000", :dxfId => profitable, :priority => 1 })
end
-# Apply conditional formatting to range B3:B100 in the worksheet
- ws.add_conditional_formatting("B3:B100", { :type => :cellIs, :operator => :greaterThan, :formula => "100000", :dxfId => profitable, :priority => 1 })
-end
+ wb.add_worksheet(:name => "Conditional Color Scale") do |sheet|
+ sheet.add_row ["Previous Year Quarterly Profits (JPY)"]
+ sheet.add_row ["Quarter", "Profit", "% of Total"]
+ offset = 3
+ rosheet = 20
+ offset.upto(rosheet + offset) do |i|
+ sheet.add_row ["Q#{i}", 10000*((rosheet/2-i) * (rosheet/2-i)), "=100*B#{i}/SUM(B3:B#{rosheet+offset})"], :style=>[nil, money, percent]
+ end
+ # color scale has two_tone and three_tone class methods to setup the excel defaults (2011)
+ # alternatively, you can pass in {:type => [:min, :max, :percent], :val => [whatever], :color =>[Some RGB String] to create a customized color scale object
-wb.add_worksheet(:name => "Conditional Color Scale") do |ws|
- ws.add_row ["Previous Year Quarterly Profits (JPY)"]
- ws.add_row ["Quarter", "Profit", "% of Total"]
- offset = 3
- rows = 20
- offset.upto(rows + offset) do |i|
- ws.add_row ["Q#{i}", 10000*((rows/2-i) * (rows/2-i)), "=100*B#{i}/SUM(B3:B#{rows+offset})"], :style=>[nil, money, percent]
+ color_scale = Axlsx::ColorScale.three_tone
+ sheet.add_conditional_formatting("B3:B100", { :type => :colorScale, :operator => :greaterThan, :formula => "100000", :dxfId => profitable, :priority => 1, :color_scale => color_scale })
end
-# Apply conditional formatting to range B3:B100 in the worksheet
- color_scale = Axlsx::ColorScale.new
- ws.add_conditional_formatting("B3:B100", { :type => :colorScale, :operator => :greaterThan, :formula => "100000", :dxfId => profitable, :priority => 1, :color_scale => color_scale })
-end
-wb.add_worksheet(:name => "Conditional Data Bar") do |ws|
- ws.add_row ["Previous Year Quarterly Profits (JPY)"]
- ws.add_row ["Quarter", "Profit", "% of Total"]
- offset = 3
- rows = 20
- offset.upto(rows + offset) do |i|
- ws.add_row ["Q#{i}", 10000*((rows/2-i) * (rows/2-i)), "=100*B#{i}/SUM(B3:B#{rows+offset})"], :style=>[nil, money, percent]
+ wb.add_worksheet(:name => "Conditional Data Bar") do |sheet|
+ sheet.add_row ["Previous Year Quarterly Profits (JPY)"]
+ sheet.add_row ["Quarter", "Profit", "% of Total"]
+ offset = 3
+ rows = 20
+ offset.upto(rows + offset) do |i|
+ sheet.add_row ["Q#{i}", 10000*((rows/2-i) * (rows/2-i)), "=100*B#{i}/SUM(B3:B#{rows+offset})"], :style=>[nil, money, percent]
+ end
+ # Apply conditional formatting to range B3:B100 in the worksheet
+ data_bar = Axlsx::DataBar.new
+ sheet.add_conditional_formatting("B3:B100", { :type => :dataBar, :dxfId => profitable, :priority => 1, :data_bar => data_bar })
end
-# Apply conditional formatting to range B3:B100 in the worksheet
- data_bar = Axlsx::DataBar.new
- ws.add_conditional_formatting("B3:B100", { :type => :dataBar, :dxfId => profitable, :priority => 1, :data_bar => data_bar })
-end
-wb.add_worksheet(:name => "Conditional Format Icon Set") do |ws|
- ws.add_row ["Previous Year Quarterly Profits (JPY)"]
- ws.add_row ["Quarter", "Profit", "% of Total"]
- offset = 3
- rows = 20
- offset.upto(rows + offset) do |i|
- ws.add_row ["Q#{i}", 10000*((rows/2-i) * (rows/2-i)), "=100*B#{i}/SUM(B3:B#{rows+offset})"], :style=>[nil, money, percent]
+ wb.add_worksheet(:name => "Conditional Format Icon Set") do |sheet|
+ sheet.add_row ["Previous Year Quarterly Profits (JPY)"]
+ sheet.add_row ["Quarter", "Profit", "% of Total"]
+ offset = 3
+ rows = 20
+ offset.upto(rows + offset) do |i|
+ sheet.add_row ["Q#{i}", 10000*((rows/2-i) * (rows/2-i)), "=100*B#{i}/SUM(B3:B#{rows+offset})"], :style=>[nil, money, percent]
+ end
+ # Apply conditional formatting to range B3:B100 in the worksheet
+ icon_set = Axlsx::IconSet.new
+ sheet.add_conditional_formatting("B3:B100", { :type => :iconSet, :dxfId => profitable, :priority => 1, :icon_set => icon_set })
end
-# Apply conditional formatting to range B3:B100 in the worksheet
- icon_set = Axlsx::IconSet.new
- ws.add_conditional_formatting("B3:B100", { :type => :iconSet, :dxfId => profitable, :priority => 1, :icon_set => icon_set })
end
##Validate and Serialize
#```ruby
# Serialize directly to file
+
p.serialize("example.xlsx")
# or
#Serialize to a stream
-s = p.to_stream()
-File.open('example_streamed.xlsx', 'w') { |f| f.write(s.read) }
+if examples.include? :streaming
+ s = p.to_stream()
+ File.open('example_streamed.xlsx', 'w') { |f| f.write(s.read) }
+end
#```
##Using Shared Strings
#```ruby
# This is required by Numbers
-p.use_shared_strings = true
-p.serialize("shared_strings_example.xlsx")
+if examples.include? :shared_strings
+ p.use_shared_strings = true
+ p.serialize("shared_strings_example.xlsx")
+end
#```
#p.validate do |er|
- #puts er.inspect
+#puts er.inspect
#end
##Disabling Autowidth
#```ruby
-p = Axlsx::Package.new
-p.use_autowidth = false
-wb = p.workbook
-wb.add_worksheet(:name => "Manual Widths") do | sheet |
- sheet.add_row ['oh look! no autowidth']
+if examples.include? :no_autowidth
+ p = Axlsx::Package.new
+ p.use_autowidth = false
+ wb = p.workbook
+ wb.add_worksheet(:name => "Manual Widths") do | sheet |
+ sheet.add_row ['oh look! no autowidth']
+ end
+ p.validate.each { |e| puts e.message }
+ p.serialize("no-use_autowidth.xlsx")
end
-p.validate.each { |e| puts e.message }
-p.serialize("no-use_autowidth.xlsx")
#```
diff --git a/examples/extractive.pdf b/examples/extractive.pdf
deleted file mode 100644
index e430df96..00000000
--- a/examples/extractive.pdf
+++ /dev/null
Binary files differ
diff --git a/examples/finance.rb b/examples/finance.rb
deleted file mode 100644
index 623773fd..00000000
--- a/examples/finance.rb
+++ /dev/null
@@ -1,82 +0,0 @@
-$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib"
-
-
-require 'axlsx'
-
-# First thing to do is setup our styles. OOXML Style management is unfortunately very different from CSS so we want to use the
-# add_style helper method on the workbook styles object so we dont go insane.
-
-# I find it easier to declare a hash and then feed that in later
-
-class FinancialReport
-
- def initialize(data)
- create_styles
- prepare
- insert_data data
- finalize
- package
- end
-
- def style_hash
-
- sienna = 'A0522D'
- {
- :search_results => { :sz => 10, :b => true },
- :bold_header => { :b => true },
- :grey_bg => { :bg_color => "DEDEDE" },
- :transaction__header => { :fg_color => sienna, :b => true },
- :transaction_currency => { :fb_color => sienna, :num_fmt => 5 },
- :transactin_date => { :fg_color => sienna, :format_code => 'yyyy-mm-dd' }
- }
- end
-
- def styles
- @styles ||= {}
- end
-
- def package
- @package ||= Axlsx::Package.new
- end
-
- # Just a place to put some defualt data for the exercise
- def self.data
- @data = ['baked',
- "American Medical Systems Holdings, Inc.",
- "Endo Pharmaceuticals Holdings, Inc.",
- "4371",
- Date.new,
- 2757001160,
- 2519495160,
- 116,
- 3842,
- "Medical devices for urology disorders"]
- end
-
- # Populates an array of ['style_name'] = style_index
- def create_styles
- package.workbook.styles do |style|
- style_hash.each do |key, value|
- styles[key] = style.add_style(value)
- end
- end
- end
- def prepare
- package.workbook.add_worksheet(:name => 'All Information') do |sheet|
- sheet.add_row [nil, 'Search Results'], :style => [nil, styles['search_results']]
- end
- end
-
-
- def insert_data(data)
- package.workbook.worksheets.first do |sheet|
- sheet.add_row data, style=> [styles[:
- end
- end
-
- def finalize
- # package.serialize 'financial.xlsx'
- end
-end
-f = FinancialReport.new(FinancialReport.data)
-f.package.serialize 'finance.xlsx'
diff --git a/examples/hyperlinks.rb b/examples/hyperlinks.rb
deleted file mode 100644
index 9519f154..00000000
--- a/examples/hyperlinks.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/usr/bin/env ruby -w -s
-# -*- coding: utf-8 -*-
-$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib"
-
-#```ruby
-require 'axlsx'
-
-p = Axlsx::Package.new
-wb = p.workbook
-wb.add_worksheet(:name => 'hyperlinks') do |sheet|
- # external references
- sheet.add_row ['axlsx']
- sheet.add_hyperlink :location => 'https://github.com/randym/axlsx', :ref => sheet.rows.first.cells.first
- # internal references
- sheet.add_row ['next sheet']
- sheet.add_hyperlink :location => "'Next Sheet'!A1", :target => :sheet, :ref => 'A2'
-end
-
-wb.add_worksheet(:name => 'Next Sheet') do |sheet|
- sheet.add_row ['hello!']
-end
-
-p.serialize 'hyperlinks.xlsx'
diff --git a/examples/scraping_html.rb b/examples/scraping_html.rb
deleted file mode 100644
index 7df27c25..00000000
--- a/examples/scraping_html.rb
+++ /dev/null
@@ -1,91 +0,0 @@
- require 'rubygems'
- require 'nokogiri'
- require 'open-uri'
- require 'axlsx'
-
- class Scraper
-
- def initialize(url, selector)
- @url = url
- @selector = selector
- end
-
- def hooks
- @hooks ||= {}
- end
-
- def add_hook(clue, p_roc)
- hooks[clue] = p_roc
- end
-
- def export(file_name)
- Scraper.clues.each do |clue|
- if detail = parse_clue(clue)
- output << [clue, detail.pop]
- detail.each { |datum| output << ['', datum] }
- end
- end
- serialize(file_name)
- end
-
- private
-
- def self.clues
- @clues ||= ['Operating system', 'Processors', 'Chipset', 'Memory type', 'Hard drive', 'Graphics',
- 'Ports', 'Webcam', 'Pointing device', 'Keyboard', 'Network interface', 'Chipset', 'Wireless',
- 'Power supply type', 'Energy efficiency', 'Weight', 'Minimum dimensions (W x D x H)',
- 'Warranty', 'Software included', 'Product color']
- end
-
- def doc
- @doc ||= begin
- Nokogiri::HTML(open(@url))
- rescue
- raise ArgumentError, 'Invalid URL - Nothing to parse'
- end
- end
-
- def output
- @output ||= []
- end
-
- def selector_for_clue(clue)
- @selector % clue
- end
-
- def parse_clue(clue)
- if element = doc.at(selector_for_clue(clue))
- call_hook(clue, element) || element.inner_html.split('<br>').each(&:strip)
- end
- end
-
- def call_hook(clue, element)
- if hooks[clue].is_a? Proc
- value = hooks[clue].call(element)
- value.is_a?(Array) ? value : [value]
- end
- end
-
- def package
- @package ||= Axlsx::Package.new
- end
-
- def serialize(file_name)
- package.workbook.add_worksheet do |sheet|
- output.each { |datum| sheet.add_row datum }
- end
- package.serialize(file_name)
- end
- end
-
- scraper = Scraper.new("http://h10010.www1.hp.com/wwpc/ie/en/ho/WF06b/321957-321957-3329742-89318-89318-5186820-5231694.html?dnr=1", "//td[text()='%s']/following-sibling::td")
-
- # define a custom action to take against any elements found.
- os_parse = Proc.new do |element|
- element.inner_html.split('<br>').each(&:strip!).each(&:upcase!)
- end
-
- scraper.add_hook('Operating system', os_parse)
-
- scraper.export('foo.xlsx')
-
diff --git a/examples/sheet_view.rb b/examples/sheet_view.rb
deleted file mode 100644
index 2cbe680a..00000000
--- a/examples/sheet_view.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/usr/bin/env ruby -w -s
-# -*- coding: utf-8 -*-
-$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib"
-require 'axlsx'
-
-p = Axlsx::Package.new
-ws = p.workbook.add_worksheet :name => "Sheetview - Split"
-ws.sheet_view do |vs|
- vs.pane do |p|
- p.active_pane = :top_right
- p.state = :split
- p.x_split = 11080
- p.y_split = 5000
- p.top_left_cell = 'C44'
- end
-
- vs.add_selection(:top_left, { :active_cell => 'A2', :sqref => 'A2' })
- vs.add_selection(:top_right, { :active_cell => 'I10', :sqref => 'I10' })
- vs.add_selection(:bottom_left, { :active_cell => 'E55', :sqref => 'E55' })
- vs.add_selection(:bottom_right, { :active_cell => 'I57', :sqref => 'I57' })
-end
-
-
-ws = p.workbook.add_worksheet :name => "Sheetview - Frozen"
-ws.sheet_view do |vs|
- vs.pane do |p|
- p.state = :frozen
- p.x_split = 3
- p.y_split = 4
- end
-end
-
-
-p.serialize 'sheet_view.xlsx' \ No newline at end of file
diff --git a/examples/skydrive/axlsx.csv b/examples/skydrive/axlsx.csv
deleted file mode 100644
index b3cea7c1..00000000
--- a/examples/skydrive/axlsx.csv
+++ /dev/null
@@ -1 +0,0 @@
-,,,,, ,College Budget,,,, ,,,,, ,What's coming in this month.,,,How am I doing, ,Item,Amount,,Item,Amount ,Estimated monthly net income,\500,,Monthly income,"\20,600" ,Financial aid,\100,,Monthly expenses,"\2,255" ,Allowance from mom & dad,"\20,000",,Semester expenses,\440 ,Total,"\20,600",,Difference,"\17,905" ,,,,, ,What's going out this month.,,,Semester Costs, ,Item,Amount,,Item,Amount ,Rent,\650,,Tuition,\200 ,Utilities,\120,,Lab fees,\50 ,Cell phone,\100,,Other fees,\10 ,Groceries,\75,,Books,\150 ,Auto expenses,\0,,Deposits,\0 ,Student loans,\0,,Transportation,\30 ,Other loans,\350,,Total,\440 ,Credit cards,\450,,, ,Insurance,\0,,, ,Laundry,\10,,, ,Haircuts,\0,,, ,Medical expenses,\0,,, ,Entertainment,\500,,, ,Miscellaneous,\0,,, ,Total,"\2,255",,, \ No newline at end of file
diff --git a/examples/sprk2012/basics.rb b/examples/sprk2012/basics.rb
deleted file mode 100644
index 82c56a4e..00000000
--- a/examples/sprk2012/basics.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../../lib"
-require 'axlsx'
-
-package = Axlsx::Package.new
-package.workbook.add_worksheet(:name => "Basic Worksheet") do |sheet|
- sheet.add_row ["First Column", "Second", "Third"]
- sheet.add_row [1, 2, 3]
-end
-package.serialize 'basics.xlsx'
-
-
diff --git a/examples/sprk2012/images.rb b/examples/sprk2012/images.rb
deleted file mode 100644
index 6e0b306d..00000000
--- a/examples/sprk2012/images.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../../lib"
-
-require 'axlsx'
-package = Axlsx::Package.new do |package|
- package.workbook.add_worksheet(:name => "imagex") do |sheet|
- img_path = File.expand_path('../../image1.jpeg', __FILE__)
- sheet.add_image(:image_src => img_path, :width => 720, :height => 666, :start_at => [2,2])
- end
-end.serialize 'images.xlsx'
diff --git a/examples/sprk2012/styles.rb b/examples/sprk2012/styles.rb
deleted file mode 100644
index ce1bf2a0..00000000
--- a/examples/sprk2012/styles.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../../lib"
-
-require 'axlsx'
-package = Axlsx::Package.new
-package.workbook do |workbook|
- workbook.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 }
-
- workbook.add_worksheet(:name => "Styles") do |sheet|
- # Applies the black_cell style to the first and third cell, and the blue_cell style to the second.
- sheet.add_row ["Text Autowidth", "Second", "Third"], :style => [black_cell, blue_cell, black_cell]
-
- # Applies the thin border to all three cells
- sheet.add_row [1, 2, 3], :style => Axlsx::STYLE_THIN_BORDER
- end
- end
-end
-package.serialize 'styles.xlsx'
-
diff --git a/examples/two_cell_anchor_image.rb b/examples/two_cell_anchor_image.rb
deleted file mode 100644
index 4fe4b566..00000000
--- a/examples/two_cell_anchor_image.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/usr/bin/env ruby -w -s
-# -*- coding: utf-8 -*-
-$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib"
-require 'axlsx'
-
-p = Axlsx::Package.new
-src = "#{File.dirname(__FILE__)}/image1.png"
-p.workbook.add_worksheet(:name => 'double_anchor') do |ws|
- ws.add_image(:image_src => src, :start_at => [0,0], :end_at => [2,4])
-end
-p.serialize('two_cell_anchor_image.xlsx')
diff --git a/examples/wrap_text.rb b/examples/wrap_text.rb
new file mode 100644
index 00000000..c2e1aeb5
--- /dev/null
+++ b/examples/wrap_text.rb
@@ -0,0 +1,21 @@
+$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib"
+require 'axlsx'
+p = Axlsx::Package.new
+p.workbook do |wb|
+ wb.styles do |s|
+ wrap_text = s.add_style :fg_color=> "FFFFFF",
+ :b => true,
+ :bg_color => "004586",
+ :sz => 12,
+ :border => { :style => :thin, :color => "00" },
+ :alignment => { :horizontal => :center,
+ :vertical => :center ,
+ :wrap_text => true}
+ wb.add_worksheet(:name => 'wrap text') do |sheet|
+ sheet.add_row ['Torp, White and Cronin'], :style => wrap_text
+ # Forcing the column to be a bit narrow so we can see if the text wrap.
+ sheet.column_info.first.width = 5
+ end
+ end
+end
+p.serialize 'wrap_text.xlsx'
diff --git a/lib/axlsx/content_type/abstract_content_type.rb b/lib/axlsx/content_type/abstract_content_type.rb
new file mode 100644
index 00000000..0afaa53f
--- /dev/null
+++ b/lib/axlsx/content_type/abstract_content_type.rb
@@ -0,0 +1,32 @@
+module Axlsx
+
+ # This class extracts the common parts from Default and Override
+ class AbstractContentType
+
+ include Axlsx::OptionsParser
+
+ # Initializes an abstract content type
+ # @see Default, Override
+ def initialize(options={})
+ parse_options options
+ end
+
+ # The type of content.
+ # @return [String]
+ attr_reader :content_type
+ alias :ContentType :content_type
+
+ # The content type.
+ # @see Axlsx#validate_content_type
+ def content_type=(v) Axlsx::validate_content_type v; @content_type = v end
+ alias :ContentType= :content_type=
+
+ # Serialize the contenty type to xml
+ def to_xml_string(node_name = '', str = '')
+ str << "<#{node_name} "
+ str << instance_values.map { |key, value| '' << Axlsx::camel(key) << '="' << value.to_s << '"' }.join(' ')
+ str << '/>'
+ end
+
+ end
+end
diff --git a/lib/axlsx/content_type/content_type.rb b/lib/axlsx/content_type/content_type.rb
index 1d528097..94d65296 100644
--- a/lib/axlsx/content_type/content_type.rb
+++ b/lib/axlsx/content_type/content_type.rb
@@ -1,6 +1,6 @@
# encoding: UTF-8
module Axlsx
-
+ require 'axlsx/content_type/abstract_content_type.rb'
require 'axlsx/content_type/default.rb'
require 'axlsx/content_type/override.rb'
diff --git a/lib/axlsx/content_type/default.rb b/lib/axlsx/content_type/default.rb
index 2b784ebf..3fe15609 100644
--- a/lib/axlsx/content_type/default.rb
+++ b/lib/axlsx/content_type/default.rb
@@ -2,55 +2,24 @@
module Axlsx
# An default content part. These parts are automatically created by for you based on the content of your package.
- class Default
+ class Default < AbstractContentType
- include Axlsx::OptionsParser
-
- #Creates a new Default object
- # @option options [String] extension
- # @option options [String] content_type
- # @raise [ArgumentError] An argument error is raised if both extension and content_type are not specified.
- def initialize(options={})
- raise ArgumentError, INVALID_ARGUMENTS unless validate_options(options)
- parse_options options
- end
-
- # Error string for option validation
- INVALID_ARGUMENTS = "extension and content_type are required"
+ # The serialization node name for this class
+ NODE_NAME = 'Default'
# The extension of the content type.
# @return [String]
attr_reader :extension
alias :Extension :extension
- # The type of content.
- # @return [String]
- attr_reader :content_type
- alias :ContentType :content_type
-
# Sets the file extension for this content type.
def extension=(v) Axlsx::validate_string v; @extension = v end
alias :Extension= :extension=
- # Sets the content type
- # @see Axlsx#validate_content_type
- def content_type=(v) Axlsx::validate_content_type v; @content_type = v end
- alias :ContentType= :content_type=
-
- # Serializes the object
- # @param [String] str
- # @return [String]
- def to_xml_string(str = '')
- str << '<Default '
- str << instance_values.map { |key, value| '' << Axlsx::camel(key) << '="' << value.to_s << '"' }.join(' ')
- str << '/>'
+ # Serializes this object to xml
+ def to_xml_string(str ='')
+ super(NODE_NAME, str)
end
-
- private
- def validate_options(options)
- (options[:Extension] || options[:extension]) && (options[:content_type] || options[:ContentType])
- end
-
end
end
diff --git a/lib/axlsx/content_type/override.rb b/lib/axlsx/content_type/override.rb
index a3947d99..7a8e33fa 100644
--- a/lib/axlsx/content_type/override.rb
+++ b/lib/axlsx/content_type/override.rb
@@ -1,27 +1,12 @@
+
# encoding: UTF-8
module Axlsx
# An override content part. These parts are automatically created by for you based on the content of your package.
- class Override
-
- include Axlsx::OptionsParser
-
- #Creates a new Override object
- # @option options [String] PartName
- # @option options [String] ContentType
- # @raise [ArgumentError] An argument error is raised if both PartName and ContentType are not specified.
- def initialize(options={})
- raise ArgumentError, INVALID_ARGUMENTS unless validate_options(options)
- parse_options options
- end
+ class Override < AbstractContentType
- # Error message for invalid options
- INVALID_ARGUMENTS = 'part_name and content_type are required'
-
- # The type of content.
- # @return [String]
- attr_reader :content_type
- alias :ContentType :content_type
+ # Serialization node name for this object
+ NODE_NAME = 'Override'
# The name and location of the part.
# @return [String]
@@ -32,26 +17,9 @@ module Axlsx
def part_name=(v) Axlsx::validate_string v; @part_name = v end
alias :PartName= :part_name=
- # The content type.
- # @see Axlsx#validate_content_type
- def content_type=(v) Axlsx::validate_content_type v; @content_type = v end
- alias :ContentType= :content_type=
-
- # Serializes the object
- # @param [String] str
- # @return [String]
+ # Serializes this object to xml
def to_xml_string(str = '')
- str << '<Override '
- str << instance_values.map { |key, value| '' << Axlsx::camel(key) << '="' << value.to_s << '"' }.join(' ')
- str << '/>'
- end
-
- private
-
- def validate_options(options)
- (options[:PartName] || options[:part_name]) && (options[:ContentType] || options[:content_type])
+ super(NODE_NAME, str)
end
-
end
-
end
diff --git a/lib/axlsx/drawing/chart.rb b/lib/axlsx/drawing/chart.rb
index 35e2089a..1006f25e 100644
--- a/lib/axlsx/drawing/chart.rb
+++ b/lib/axlsx/drawing/chart.rb
@@ -14,7 +14,7 @@ module Axlsx
# @option options [Array|String|Cell] start_at The X, Y coordinates defining the top left corner of the chart.
# @option options [Array|String|Cell] end_at The X, Y coordinates defining the bottom right corner of the chart.
def initialize(frame, options={})
- @style = 18
+ @style = 18
@view_3D = nil
@graphic_frame=frame
@graphic_frame.anchor.drawing.worksheet.workbook.charts << self
diff --git a/lib/axlsx/drawing/drawing.rb b/lib/axlsx/drawing/drawing.rb
index 48b9320f..769d67c5 100644
--- a/lib/axlsx/drawing/drawing.rb
+++ b/lib/axlsx/drawing/drawing.rb
@@ -137,6 +137,12 @@ module Axlsx
"#{DRAWING_RELS_PN % (index+1)}"
end
+ # The index of a chart, image or hyperlink object this drawing contains
+ def index_of(object)
+ objects = charts + images + hyperlinks
+ objects.index(object)
+ end
+
# The drawing's relationships.
# @return [Relationships]
def relationships
diff --git a/lib/axlsx/drawing/hyperlink.rb b/lib/axlsx/drawing/hyperlink.rb
index 3f4a2e80..aa763e1f 100644
--- a/lib/axlsx/drawing/hyperlink.rb
+++ b/lib/axlsx/drawing/hyperlink.rb
@@ -93,10 +93,11 @@ module Axlsx
end
private
+
# The relational ID for this hyperlink
# @return [Integer]
def id
- @parent.anchor.drawing.charts.size + @parent.anchor.drawing.images.size + @parent.anchor.drawing.hyperlinks.index(self) + 1
+ @parent.anchor.drawing.index_of(self)+1
end
end
diff --git a/lib/axlsx/drawing/view_3D.rb b/lib/axlsx/drawing/view_3D.rb
index 0acba62f..9c320b4a 100644
--- a/lib/axlsx/drawing/view_3D.rb
+++ b/lib/axlsx/drawing/view_3D.rb
@@ -40,7 +40,7 @@ module Axlsx
# @return [Integer]
attr_reader :rot_y
alias :rotY :rot_y
-
+
# depth or chart as % of chart width
# must be between 20% and 2000%
# @return [String]
@@ -56,44 +56,60 @@ module Axlsx
# @return [Integer]
attr_reader :perspective
- # @see rot_x
- def rot_x=(v) DataTypeValidator.validate "#{self.class}.rot_x", [Integer, Fixnum], v, lambda {|arg| arg >= -90 && arg <= 90 }; @rot_x = v; end
+ # @see rot_x
+ def rot_x=(v)
+ RangeValidator.validate "View3D.rot_x", -90, 90, v
+ @rot_x = v
+ end
alias :rotX= :rot_x=
- # @see h_percent
- def h_percent=(v)
- RegexValidator.validate "#{self.class}.h_percent", H_PERCENT_REGEX, v
- @h_percent = v
- end
+ # @see h_percent
+ def h_percent=(v)
+ RegexValidator.validate "#{self.class}.h_percent", H_PERCENT_REGEX, v
+ @h_percent = v
+ end
alias :hPercent= :h_percent=
- # @see rot_y
- def rot_y=(v) DataTypeValidator.validate "#{self.class}.rot_y", [Integer, Fixnum], v, lambda {|arg| arg >= 0 && arg <= 360 }; @rot_y = v; end
+ # @see rot_y
+ def rot_y=(v)
+ RangeValidator.validate "View3D.rot_y", 0, 360, v
+ @rot_y = v
+ end
alias :rotY= :rot_y=
- # @see depth_percent
- def depth_percent=(v) RegexValidator.validate "#{self.class}.depth_percent", DEPTH_PERCENT_REGEX, v; @depth_percent = v; end
+ # @see depth_percent
+ def depth_percent=(v) RegexValidator.validate "#{self.class}.depth_percent", DEPTH_PERCENT_REGEX, v; @depth_percent = v; end
alias :depthPercent= :depth_percent=
- # @see r_ang_ax
- def r_ang_ax=(v) Axlsx::validate_boolean(v); @r_ang_ax = v; end
+ # @see r_ang_ax
+ def r_ang_ax=(v) Axlsx::validate_boolean(v); @r_ang_ax = v; end
alias :rAngAx= :r_ang_ax=
- # @see perspective
- def perspective=(v) DataTypeValidator.validate "#{self.class}.perspective", [Integer, Fixnum], v, lambda {|arg| arg >= 0 && arg <= 240 }; @perspective = v; end
+ # @see perspective
+ def perspective=(v)
+ RangeValidator.validate "View3D.perspective", 0, 240, v
+ @perspective = v
+ end
+
+ # DataTypeValidator.validate "#{self.class}.perspective", [Integer, Fixnum], v, lambda {|arg| arg >= 0 && arg <= 240 }; @perspective = v; end
# Serializes the object
# @param [String] str
# @return [String]
def to_xml_string(str = '')
str << '<c:view3D>'
- str << '<c:rotX val="' << @rot_x.to_s << '"/>' unless @rot_x.nil?
- str << '<c:hPercent val="' << @h_percent.to_s << '"/>' unless @h_percent.nil?
- str << '<c:rotY val="' << @rot_y.to_s << '"/>' unless @rot_y.nil?
- str << '<c:depthPercent val="' << @depth_percent.to_s << '"/>' unless @depth_percent.nil?
- str << '<c:rAngAx val="' << @r_ang_ax.to_s << '"/>' unless @r_ang_ax.nil?
- str << '<c:perspective val="' << @perspective.to_s << '"/>' unless @perspective.nil?
+ %w(rot_x h_percent rot_y depth_percent r_ang_ax perspective).each do |key|
+ str << element_for_attribute(key, 'c')
+ end
str << '</c:view3D>'
end
+
+ private
+ # Note: move this to Axlsx module if we find the smae pattern elsewhere.
+ def element_for_attribute(name, namespace='')
+ val = instance_values[name]
+ return "" if val == nil
+ "<%s:%s val='%s'/>" % [namespace, Axlsx::camel(name, false), val]
+ end
end
end
diff --git a/lib/axlsx/package.rb b/lib/axlsx/package.rb
index 829eb199..e3981d62 100644
--- a/lib/axlsx/package.rb
+++ b/lib/axlsx/package.rb
@@ -173,7 +173,7 @@ module Axlsx
# @return [Array] An array of hashes that define the entry, document and schema for each part of the package.
# @private
def parts
- @parts = [
+ parts = [
{:entry => RELS_PN, :doc => relationships.to_xml_string, :schema => RELS_XSD},
{:entry => "xl/#{STYLES_PN}", :doc => workbook.styles.to_xml_string, :schema => SML_XSD},
{:entry => CORE_PN, :doc => @core.to_xml_string, :schema => CORE_XSD},
@@ -184,39 +184,39 @@ module Axlsx
]
workbook.drawings.each do |drawing|
- @parts << {:entry => "xl/#{drawing.rels_pn}", :doc => drawing.relationships.to_xml_string, :schema => RELS_XSD}
- @parts << {:entry => "xl/#{drawing.pn}", :doc => drawing.to_xml_string, :schema => DRAWING_XSD}
+ parts << {:entry => "xl/#{drawing.rels_pn}", :doc => drawing.relationships.to_xml_string, :schema => RELS_XSD}
+ parts << {:entry => "xl/#{drawing.pn}", :doc => drawing.to_xml_string, :schema => DRAWING_XSD}
end
workbook.tables.each do |table|
- @parts << {:entry => "xl/#{table.pn}", :doc => table.to_xml_string, :schema => SML_XSD}
+ parts << {:entry => "xl/#{table.pn}", :doc => table.to_xml_string, :schema => SML_XSD}
end
workbook.comments.each do|comment|
if comment.size > 0
- @parts << { :entry => "xl/#{comment.pn}", :doc => comment.to_xml_string, :schema => SML_XSD }
- @parts << { :entry => "xl/#{comment.vml_drawing.pn}", :doc => comment.vml_drawing.to_xml_string, :schema => nil }
+ parts << { :entry => "xl/#{comment.pn}", :doc => comment.to_xml_string, :schema => SML_XSD }
+ parts << { :entry => "xl/#{comment.vml_drawing.pn}", :doc => comment.vml_drawing.to_xml_string, :schema => nil }
end
end
workbook.charts.each do |chart|
- @parts << {:entry => "xl/#{chart.pn}", :doc => chart.to_xml_string, :schema => DRAWING_XSD}
+ parts << {:entry => "xl/#{chart.pn}", :doc => chart.to_xml_string, :schema => DRAWING_XSD}
end
workbook.images.each do |image|
- @parts << {:entry => "xl/#{image.pn}", :path => image.image_src}
+ parts << {:entry => "xl/#{image.pn}", :path => image.image_src}
end
if use_shared_strings
- @parts << {:entry => "xl/#{SHARED_STRINGS_PN}", :doc => workbook.shared_strings.to_xml_string, :schema => SML_XSD}
+ parts << {:entry => "xl/#{SHARED_STRINGS_PN}", :doc => workbook.shared_strings.to_xml_string, :schema => SML_XSD}
end
workbook.worksheets.each do |sheet|
- @parts << {:entry => "xl/#{sheet.rels_pn}", :doc => sheet.relationships.to_xml_string, :schema => RELS_XSD}
- @parts << {:entry => "xl/#{sheet.pn}", :doc => sheet.to_xml_string, :schema => SML_XSD}
+ parts << {:entry => "xl/#{sheet.rels_pn}", :doc => sheet.relationships.to_xml_string, :schema => RELS_XSD}
+ parts << {:entry => "xl/#{sheet.pn}", :doc => sheet.to_xml_string, :schema => SML_XSD}
end
- @parts
+ parts
end
# Performs xsd validation for a signle document
diff --git a/lib/axlsx/rels/relationship.rb b/lib/axlsx/rels/relationship.rb
index 99c8e112..04911904 100644
--- a/lib/axlsx/rels/relationship.rb
+++ b/lib/axlsx/rels/relationship.rb
@@ -55,7 +55,7 @@ module Axlsx
h = self.instance_values
h[:Id] = 'rId' << rId.to_s
str << '<Relationship '
- str << h.map { |key, value| '' << key.to_s << '="' << value.to_s << '"'}.join(' ')
+ str << h.map { |key, value| '' << key.to_s << '="' << Axlsx::coder.encode(value.to_s) << '"'}.join(' ')
str << '/>'
end
diff --git a/lib/axlsx/stylesheet/color.rb b/lib/axlsx/stylesheet/color.rb
index b5537ac1..744e63d5 100644
--- a/lib/axlsx/stylesheet/color.rb
+++ b/lib/axlsx/stylesheet/color.rb
@@ -69,8 +69,8 @@ module Axlsx
# Serializes the object
# @param [String] str
# @return [String]
- def to_xml_string(str = '')
- str << "<color "
+ def to_xml_string(str = '', tag_name = 'color')
+ str << "<" << tag_name << " "
serialized_attributes str
str << "/>"
end
diff --git a/lib/axlsx/stylesheet/gradient_fill.rb b/lib/axlsx/stylesheet/gradient_fill.rb
index cfd51e64..b077d497 100644
--- a/lib/axlsx/stylesheet/gradient_fill.rb
+++ b/lib/axlsx/stylesheet/gradient_fill.rb
@@ -84,6 +84,7 @@ module Axlsx
@bottom = v
end
+ # validates that the value provided is between 0.0 and 1.0
def validate_format_percentage(name, value)
DataTypeValidator.validate name, Float, value, lambda { |arg| arg >= 0.0 && arg <= 1.0}
end
diff --git a/lib/axlsx/stylesheet/pattern_fill.rb b/lib/axlsx/stylesheet/pattern_fill.rb
index c06c7f16..504624e6 100644
--- a/lib/axlsx/stylesheet/pattern_fill.rb
+++ b/lib/axlsx/stylesheet/pattern_fill.rb
@@ -6,7 +6,6 @@ module Axlsx
class PatternFill
include Axlsx::OptionsParser
-
# Creates a new PatternFill Object
# @option options [Symbol] patternType
# @option options [Color] fgColor
@@ -62,19 +61,11 @@ module Axlsx
def to_xml_string(str = '')
str << '<patternFill patternType="' << patternType.to_s << '">'
if fgColor.is_a?(Color)
- str << "<fgColor "
- fgColor.instance_values.each do |key, value|
- str << key.to_s << '="' << value.to_s << '" '
- end
- str << "/>"
+ fgColor.to_xml_string str, "fgColor"
end
if bgColor.is_a?(Color)
- str << "<bgColor "
- bgColor.instance_values.each do |key, value|
- str << key.to_s << '="' << value.to_s << '" '
- end
- str << "/>"
+ bgColor.to_xml_string str, "bgColor"
end
str << '</patternFill>'
end
diff --git a/lib/axlsx/util/accessors.rb b/lib/axlsx/util/accessors.rb
index 3096d9c7..f578be26 100644
--- a/lib/axlsx/util/accessors.rb
+++ b/lib/axlsx/util/accessors.rb
@@ -1,19 +1,42 @@
module Axlsx
+ # This module defines some of the more common validating attribute
+ # accessors that we use in Axlsx
+ #
+ # When this module is included in your class you can simply call
+ #
+ # string_attr_access :foo
+ #
+ # To generate a new, validating set of accessors for foo.
module Accessors
def self.included(base)
base.send :extend, ClassMethods
end
+ # Defines the class level xxx_attr_accessor methods
module ClassMethods
+
+ # Creates one or more string validated attr_accessors
+ # @param [Array] symbols An array of symbols representing the
+ # names of the attributes you will add to your class.
def string_attr_accessor(*symbols)
validated_attr_accessor(symbols, 'validate_string')
end
+ # Creates on or more boolean validated attr_accessors
+ # @param [Array] symbols An array of symbols representing the
+ # names of the attributes you will add to your class.
def boolean_attr_accessor(*symbols)
validated_attr_accessor(symbols, 'validate_boolean')
end
+ # Template for defining validated write accessors
SETTER = "def %s=(value) Axlsx::%s(value); @%s = value; end"
+
+ # Creates the reader and writer access methods
+ # @param [Array] symbols The names of the attributes to create
+ # @param [String] validator The axlsx validation method to use when
+ # validating assignation.
+ # @see lib/axlsx/util/validators.rb
def validated_attr_accessor(symbols, validator)
symbols.each do |symbol|
attr_reader symbol
diff --git a/lib/axlsx/util/options_parser.rb b/lib/axlsx/util/options_parser.rb
index b6332275..07dd128b 100644
--- a/lib/axlsx/util/options_parser.rb
+++ b/lib/axlsx/util/options_parser.rb
@@ -1,5 +1,11 @@
module Axlsx
+ # This module defines a single method for parsing options in class
+ # initializers.
module OptionsParser
+
+ # Parses an options hash by calling any defined method by the same
+ # name of the key postfixed with an '='
+ # @param [Hash] options Options to parse.
def parse_options(options={})
options.each do |key, value|
self.send("#{key}=", value) if self.respond_to?("#{key}=") && value != nil
diff --git a/lib/axlsx/util/serialized_attributes.rb b/lib/axlsx/util/serialized_attributes.rb
index 59efbc9f..5519f843 100644
--- a/lib/axlsx/util/serialized_attributes.rb
+++ b/lib/axlsx/util/serialized_attributes.rb
@@ -1,20 +1,44 @@
module Axlsx
+ # This module allows us to define a list of symbols defining which
+ # attributes will be serialized for a class.
module SerializedAttributes
+ # Extend with class methods
def self.included(base)
base.send :extend, ClassMethods
end
+ # class methods applied to all includers
module ClassMethods
+ # This is the method to be used in inheriting classes to specify
+ # which of the instance values are serializable
def serializable_attributes(*symbols)
@xml_attributes = symbols
end
+
+ # a reader for those attributes
def xml_attributes
@xml_attributes
end
+
+ # This helper registers the attributes that will be formatted as elements.
+ def serializable_element_attributes(*symbols)
+ @xml_element_attributes = symbols
+ end
+
+ # attr reader for element attributes
+ def xml_element_attributes
+ @xml_element_attributes
+ end
end
+ # serializes the instance values of the defining object based on the
+ # list of serializable attributes.
+ # @param [String] str The string instance to append this
+ # serialization to.
+ # @param [Hash] additional_attributes An option key value hash for
+ # defining values that are not serializable attributes list.
def serialized_attributes(str = '', additional_attributes = {})
key_value_pairs = instance_values
key_value_pairs.each do |key, value|
@@ -22,9 +46,30 @@ module Axlsx
key_value_pairs.delete(key) unless self.class.xml_attributes.include?(key.to_sym)
end
key_value_pairs.merge! additional_attributes
-
key_value_pairs.each do |key, value|
- str << "#{Axlsx.camel(key, false)}='#{value}' "
+ str << "#{Axlsx.camel(key, false)}=\"#{value}\" "
+ end
+ str
+ end
+
+
+ # serialized instance values at text nodes on a camelized element of the
+ # attribute name. You may pass in a block for evaluation against non nil
+ # values. We use an array for element attributes becuase misordering will
+ # break the xml and 1.8.7 does not support ordered hashes.
+ # @param [String] str The string instance to which serialized data is appended
+ # @param [Array] additional_attributes An array of additional attribute names.
+ # @param [Proc] block A which will be called with the value for each element.
+ # @return [String] The serialized output.
+ def serialized_element_attributes(str='', additional_attributes=[], &block)
+ attrs = self.class.xml_element_attributes + additional_attributes
+ values = instance_values
+ attrs.each do |attribute_name|
+ value = values[attribute_name.to_s]
+ next if value.nil?
+ value = yield value if block_given?
+ element_name = Axlsx.camel(attribute_name, false)
+ str << "<#{element_name}>#{value}</#{element_name}>"
end
str
end
diff --git a/lib/axlsx/util/simple_typed_list.rb b/lib/axlsx/util/simple_typed_list.rb
index a6c11a5d..4d188ffd 100644
--- a/lib/axlsx/util/simple_typed_list.rb
+++ b/lib/axlsx/util/simple_typed_list.rb
@@ -43,16 +43,16 @@ module Axlsx
def to_ary
@list
end
-
+
alias :to_a :to_ary
-
+
# Unlock the list
# @return [self]
def unlock
@locked_at = nil
self
end
-
+
# join operator
# @param [Array] v the array to join
# @raise [ArgumentError] if any of the values being joined are not
@@ -62,7 +62,7 @@ module Axlsx
v.each do |item|
DataTypeValidator.validate "SimpleTypedList.+", @allowed_types, item
@list << item
- end
+ end
end
# Concat operator
@@ -107,6 +107,18 @@ module Axlsx
v
end
+ # inserts an item at the index specfied
+ # @param [Integer] index
+ # @param [Any] v
+ # @raise [ArgumentError] if the index is protected by locking
+ # @raise [ArgumentError] if the index is not one of the allowed types
+ def insert(index, v)
+ DataTypeValidator.validate "SimpleTypedList.<<", @allowed_types, v
+ raise ArgumentError, "Item is protected and cannot be changed" if protected? index
+ @list.insert(index, v)
+ v
+ end
+
# determines if the index is protected
# @param [Integer] index
def protected? index
diff --git a/lib/axlsx/util/validators.rb b/lib/axlsx/util/validators.rb
index 9c1ec741..cc8f0a92 100644
--- a/lib/axlsx/util/validators.rb
+++ b/lib/axlsx/util/validators.rb
@@ -140,7 +140,15 @@ module Axlsx
def self.validate_page_orientation(v)
RestrictionValidator.validate "page_orientation", [:default, :landscape, :portrait], v
end
+ # Requires that the value is one of :none, :single, :double, :singleAccounting, :doubleAccounting
+ def self.validate_cell_u(v)
+ RestrictionValidator.validate "cell run style u", [:none, :single, :double, :singleAccounting, :doubleAccounting], v
+ end
+ # validates cell style family which must be between 1 and 5
+ def self.validate_family(v)
+ RestrictionValidator.validate "cell run style family", 1..5, v
+ end
# Requires that the value is valid pattern type.
# valid pattern types must be one of :none, :solid, :mediumGray, :darkGray, :lightGray, :darkHorizontal, :darkVertical, :darkDown,
# :darkUp, :darkGrid, :darkTrellis, :lightHorizontal, :lightVertical, :lightDown, :lightUp, :lightGrid, :lightTrellis, :gray125, or :gray0625.
diff --git a/lib/axlsx/version.rb b/lib/axlsx/version.rb
index 9a40f3f1..f3f0c5f6 100644
--- a/lib/axlsx/version.rb
+++ b/lib/axlsx/version.rb
@@ -1,5 +1,5 @@
module Axlsx
# The current version
- VERSION = "1.3.1"
+ VERSION = "1.3.4"
end
diff --git a/lib/axlsx/workbook/defined_name.rb b/lib/axlsx/workbook/defined_name.rb
index 833093fd..b55856de 100644
--- a/lib/axlsx/workbook/defined_name.rb
+++ b/lib/axlsx/workbook/defined_name.rb
@@ -55,9 +55,9 @@ module Axlsx
# creates a new DefinedName.
# @param [String] formula - the formula the defined name references
# @param [Hash] options - A hash of key/value pairs that will be mapped to this instances attributes.
- #
+ #
# @option [String] name - Specifies the name that appears in the user interface for the defined name.
- # This attribute is required.
+ # This attribute is required.
# The following built-in names are defined in this SpreadsheetML specification:
# Print
# _xlnm.Print_Area: this defined name specifies the workbook's print area.
@@ -111,25 +111,13 @@ module Axlsx
@local_sheet_id = value
end
- string_attr_accessor :short_cut_key, :status_bar, :help, :description, :custom_menu, :comment
+ string_attr_accessor :short_cut_key, :status_bar, :help, :description, :custom_menu, :comment, :name, :formula
- # boolean attributes that will be added when this class is evaluated
boolean_attr_accessor :workbook_parameter, :publish_to_server, :xlm, :vb_proceedure, :function, :hidden
serializable_attributes :short_cut_key, :status_bar, :help, :description, :custom_menu, :comment,
:workbook_parameter, :publish_to_server, :xlm, :vb_proceedure, :function, :hidden, :name, :local_sheet_id
-
- attr_reader :name
- # The name of this defined name. Please refer to the class documentation for more information
- def name=(value)
- Axlsx::RestrictionValidator.validate 'DefinedName.name', %w(_xlnm.Print_Area _xlnm.Print_Titles _xlnm.Criteria _xlnm._FilterDatabase _xlnm.Extract _xlnm.Consolidate_Area _xlnm.Database _xlnm.Sheet_Title), value
- @name = value
- end
-
- # The formula this defined name references
- attr_reader :formula
-
def to_xml_string(str='')
raise ArgumentError, 'you must specify the name for this defined name. Please read the documentation for Axlsx::DefinedName for more details' unless name
str << '<definedName '
diff --git a/lib/axlsx/workbook/workbook.rb b/lib/axlsx/workbook/workbook.rb
index a1964883..6c99d6de 100644
--- a/lib/axlsx/workbook/workbook.rb
+++ b/lib/axlsx/workbook/workbook.rb
@@ -9,8 +9,10 @@ require 'axlsx/workbook/worksheet/cell.rb'
require 'axlsx/workbook/worksheet/page_margins.rb'
require 'axlsx/workbook/worksheet/page_set_up_pr.rb'
require 'axlsx/workbook/worksheet/page_setup.rb'
+require 'axlsx/workbook/worksheet/header_footer.rb'
require 'axlsx/workbook/worksheet/print_options.rb'
require 'axlsx/workbook/worksheet/cfvo.rb'
+require 'axlsx/workbook/worksheet/cfvos.rb'
require 'axlsx/workbook/worksheet/color_scale.rb'
require 'axlsx/workbook/worksheet/data_bar.rb'
require 'axlsx/workbook/worksheet/icon_set.rb'
@@ -214,6 +216,23 @@ require 'axlsx/workbook/worksheet/selection.rb'
# see @use_autowidth
def use_autowidth=(v=true) Axlsx::validate_boolean v; @use_autowidth = v; end
+ # inserts a worksheet into this workbook at the position specified.
+ # It the index specified is out of range, the worksheet will be added to the end of the
+ # worksheets collection
+ # @return [Worksheet]
+ # @param index The zero based position to insert the newly created worksheet
+ # @param [Hash] options Options to pass into the worksheed during initialization.
+ # @option options [String] name The name of the worksheet
+ # @option options [Hash] page_margins The page margins for the worksheet
+ def insert_worksheet(index=0, options={})
+ worksheet = Worksheet.new(self, options)
+ @worksheets.delete_at(@worksheets.size - 1)
+ @worksheets.insert(index, worksheet)
+ yield worksheet if block_given?
+ worksheet
+ end
+
+ #
# Adds a worksheet to this workbook
# @return [Worksheet]
# @option options [String] name The name of the worksheet.
diff --git a/lib/axlsx/workbook/worksheet/cell.rb b/lib/axlsx/workbook/worksheet/cell.rb
index 86e61d9d..cfcb6118 100644
--- a/lib/axlsx/workbook/worksheet/cell.rb
+++ b/lib/axlsx/workbook/worksheet/cell.rb
@@ -112,16 +112,43 @@ module Axlsx
def font_name=(v) set_run_style :validate_string, :font_name, v; end
# The inline charset property for the cell
+ # As far as I can tell, this is pretty much ignored. However, based on the spec it should be one of the following:
+ # 0  ANSI_CHARSET
+ # 1 DEFAULT_CHARSET
+ # 2 SYMBOL_CHARSET
+ # 77 MAC_CHARSET
+ # 128 SHIFTJIS_CHARSET
+ # 129  HANGUL_CHARSET
+ # 130  JOHAB_CHARSET
+ # 134  GB2312_CHARSET
+ # 136  CHINESEBIG5_CHARSET
+ # 161  GREEK_CHARSET
+ # 162  TURKISH_CHARSET
+ # 163  VIETNAMESE_CHARSET
+ # 177  HEBREW_CHARSET
+ # 178  ARABIC_CHARSET
+ # 186  BALTIC_CHARSET
+ # 204  RUSSIAN_CHARSET
+ # 222  THAI_CHARSET
+ # 238  EASTEUROPE_CHARSET
+ # 255  OEM_CHARSET
# @return [String]
attr_reader :charset
# @see charset
def charset=(v) set_run_style :validate_unsigned_int, :charset, v; end
# The inline family property for the cell
- # @return [String]
+ # @return [Integer]
+ # 1 Roman
+ # 2 Swiss
+ # 3 Modern
+ # 4 Script
+ # 5 Decorative
attr_reader :family
# @see family
- def family=(v) set_run_style :validate_string, :family, v; end
+ def family=(v)
+ set_run_style :validate_family, :family, v.to_i
+ end
# The inline bold property for the cell
# @return [Boolean]
@@ -165,11 +192,17 @@ module Axlsx
# @see extend
def extend=(v) set_run_style :validate_boolean, :extend, v; end
- # The inline underline property for the cell
+ # The inline underline property for the cell.
+ # It must be one of :none, :single, :double, :singleAccounting, :doubleAccounting, true
# @return [Boolean]
+ # @return [String]
+ # @note true is for backwards compatability and is reassigned to :single
attr_reader :u
# @see u
- def u=(v) set_run_style :validate_boolean, :u, v; end
+ def u=(v)
+ v = :single if (v == true || v == 1 || v == :true || v == 'true')
+ set_run_style :validate_cell_u, :u, v
+ end
# The inline color property for the cell
# @return [Color]
@@ -365,8 +398,8 @@ module Axlsx
end
# assigns the owning row for this cell.
- def row=(v) DataTypeValidator.validate "Cell.row", Row, v; @row=v end
-
+ def row=(v) @row=v end
+
# Determines the cell type based on the cell value.
# @note This is only used when a cell is created but no :type option is specified, the following rules apply:
# 1. If the value is an instance of Date, the type is set to :date
@@ -411,6 +444,9 @@ module Axlsx
v ? 1 : 0
else
@type = :string
+ v.to_s
+ # TODO find a better way to do this as it accounts for 30% of
+ # processing time in benchmarking...
::CGI.escapeHTML(v.to_s)
end
end
diff --git a/lib/axlsx/workbook/worksheet/cfvos.rb b/lib/axlsx/workbook/worksheet/cfvos.rb
new file mode 100644
index 00000000..d642bfc6
--- /dev/null
+++ b/lib/axlsx/workbook/worksheet/cfvos.rb
@@ -0,0 +1,15 @@
+module Axlsx
+
+ #A collection of Cfvo objects that initializes with the required
+ #first two items
+ class Cfvos < SimpleTypedList
+
+ def initialize
+ super(Cfvo)
+ end
+
+ def to_xml_string(str='')
+ @list.each { |cfvo| cfvo.to_xml_string(str) }
+ end
+ end
+end
diff --git a/lib/axlsx/workbook/worksheet/col.rb b/lib/axlsx/workbook/worksheet/col.rb
index 596531ab..a2658724 100644
--- a/lib/axlsx/workbook/worksheet/col.rb
+++ b/lib/axlsx/workbook/worksheet/col.rb
@@ -23,7 +23,7 @@ module Axlsx
parse_options options
end
- serializable_attributes :collapsed, :hidden, :outline_level, :phonetic, :style, :width, :min, :max
+ serializable_attributes :collapsed, :hidden, :outline_level, :phonetic, :style, :width, :min, :max, :best_fit, :custom_width
# First column affected by this 'column info' record.
# @return [Integer]
@@ -38,7 +38,8 @@ module Axlsx
# 'Best fit' means that when numbers are typed into a cell contained in a 'best fit' column, the column width should
# automatically resize to display the number. [Note: In best fit cases, column width must not be made smaller, only larger. end note]
# @return [Boolean]
- attr_reader :bestFit
+ attr_reader :best_fit
+ alias :bestFit :best_fit
# Flag indicating if the outlining of the affected column(s) is in the collapsed state.
# @return [Boolean]
@@ -66,7 +67,8 @@ module Axlsx
attr_reader :width
# @return [Boolean]
- attr_reader :customWidth
+ attr_reader :custom_width
+ alias :customWidth :custom_width
# @see Col#collapsed
def collapsed=(v)
@@ -103,7 +105,7 @@ module Axlsx
# @see Col#width
def width=(v)
Axlsx.validate_unsigned_numeric(v) unless v == nil
- @customWidth = @bestFit = v != nil
+ @custom_width = @best_fit = v != nil
@width = v
end
diff --git a/lib/axlsx/workbook/worksheet/color_scale.rb b/lib/axlsx/workbook/worksheet/color_scale.rb
index 11f97e21..287e6869 100644
--- a/lib/axlsx/workbook/worksheet/color_scale.rb
+++ b/lib/axlsx/workbook/worksheet/color_scale.rb
@@ -7,34 +7,70 @@ module Axlsx
# @see ConditionalFormattingRule#initialize
class ColorScale
+ class << self
+
+ # These are the default conditional formatting value objects
+ # that define a two tone color gradient.
+ def default_cfvos
+ [{:type => :min, :val => 0, :color => 'FFFF7128'},
+ {:type => :max, :val => 0, :color => 'FFFFEF9C'}]
+ end
+
+ # A builder for two tone color gradient
+ # @example
+ # # this creates a two tone color scale
+ # color_scale = Axlsx::ColorScale.two_tone
+ # @see examples/example.rb conditional formatting examples.
+ def two_tone
+ self.new
+ end
+
+ # A builder for three tone color gradient
+ # @example
+ # #this creates a three tone color scale
+ # color_scale = Axlsx::ColorScale.three_tone
+ # @see examples/example.rb conditional formatting examples.
+ def three_tone
+ self.new({:type => :min, :val => 0, :color => 'FFF8696B'},
+ {:type => :percent, :val => '50', :color => 'FFFFEB84'},
+ {:type => :max, :val => 0, :color => 'FF63BE7B'})
+ end
+ end
# A simple typed list of cfvos
# @return [SimpleTypedList]
# @see Cfvo
- attr_reader :value_objects
+ def value_objects
+ @value_objects ||= Cfvos.new
+ end
# A simple types list of colors
# @return [SimpleTypedList]
# @see Color
- attr_reader :colors
+ def colors
+ @colors ||= SimpleTypedList.new Color
+ end
# creates a new ColorScale object.
- # This method will yield it self so you can alter the properites of the defauls conditional formating value object (cfvo and colors
- # Two value objects and two colors are created on initialization and cannot be deleted.
# @see Cfvo
# @see Color
- def initialize
- initialize_value_objects
- initialize_colors
+ # @example
+ # color_scale = Axlsx::ColorScale.new({:type => :num, :val => 0.55, :color => 'fff7696c'})
+ def initialize(*cfvos)
+ initialize_default_cfvos(cfvos)
yield self if block_given?
end
# adds a new cfvo / color pair to the color scale and returns a hash containing
# a reference to the newly created cfvo and color objects so you can alter the default properties.
# @return [Hash] a hash with :cfvo and :color keys referencing the newly added objects.
+ # @param [Hash] options options for the new cfvo and color objects
+ # @option [Symbol] type The type of cfvo you to add
+ # @option [Any] val The value of the cfvo to add
+ # @option [String] The rgb color for the cfvo
def add(options={})
- @value_objects << Cfvo.new(:type => options[:type] || :min, :val => options[:val] || 0)
- @colors << Color.new(:rgb => options[:color] || "FF000000")
- {:cfvo => @value_objects.last, :color => @colors.last}
+ value_objects << Cfvo.new(:type => options[:type] || :min, :val => options[:val] || 0)
+ colors << Color.new(:rgb => options[:color] || "FF000000")
+ {:cfvo => value_objects.last, :color => colors.last}
end
@@ -42,8 +78,8 @@ module Axlsx
# @param [Integer] index The index of the cfvo and color object to delete
# @note you cannot remove the first two cfvo and color pairs
def delete_at(index=2)
- @value_objects.delete_at index
- @colors.delete_at index
+ value_objects.delete_at index
+ colors.delete_at index
end
# Serialize this color_scale object data to an xml string
@@ -51,26 +87,24 @@ module Axlsx
# @return [String]
def to_xml_string(str = '')
str << '<colorScale>'
- @value_objects.each { |cfvo| cfvo.to_xml_string(str) }
- @colors.each { |color| color.to_xml_string(str) }
+ value_objects.to_xml_string(str)
+ colors.each { |color| color.to_xml_string(str) }
str << '</colorScale>'
end
private
-
- # creates the initial cfvo objects
- def initialize_value_objects
- @value_objects = SimpleTypedList.new Cfvo
- @value_objects.concat [Cfvo.new(:type => :min, :val => 0), Cfvo.new(:type => :max, :val => 0)]
- @value_objects.lock
+ # There has got to be cleaner way of merging these arrays.
+ def initialize_default_cfvos(user_cfvos)
+ defaults = self.class.default_cfvos
+ user_cfvos.each_with_index do |cfvo, index|
+ if index < defaults.size
+ cfvo = defaults[index].merge(cfvo)
+ end
+ add cfvo
+ end
+ while colors.size < defaults.size
+ add defaults[colors.size - 1]
+ end
end
-
- # creates the initial color objects
- def initialize_colors
- @colors = SimpleTypedList.new Color
- @colors.concat [Color.new(:rgb => "FFFF0000"), Color.new(:rgb => "FF0000FF")]
- @colors.lock
- end
-
end
end
diff --git a/lib/axlsx/workbook/worksheet/data_bar.rb b/lib/axlsx/workbook/worksheet/data_bar.rb
index bca24bf7..e67f76a4 100644
--- a/lib/axlsx/workbook/worksheet/data_bar.rb
+++ b/lib/axlsx/workbook/worksheet/data_bar.rb
@@ -10,21 +10,31 @@ module Axlsx
include Axlsx::OptionsParser
include Axlsx::SerializedAttributes
+ class << self
+ # This differs from ColorScale. There must be exactly two cfvos one color
+ def default_cfvos
+ [{:type => :min, :val => "0"},
+ {:type => :max, :val => "0"}]
+ end
+ end
+
# Creates a new data bar conditional formatting object
+ # @param [Hash] options
# @option options [Integer] minLength
# @option options [Integer] maxLength
# @option options [Boolean] showValue
# @option options [String] color - the rbg value used to color the bars
- def initialize(options = {})
- @minLength = 10
- @maxLength = 90
- @showValue = true
- initialize_value_objects
+ # @param [Array] cfvos hashes defining the gradient interpolation points for this formatting.
+ def initialize(options = {}, *cfvos)
+ @min_length = 10
+ @max_length = 90
+ @show_value = true
parse_options options
+ initialize_cfvos(cfvos)
yield self if block_given?
end
- serializable_attributes :minLength, :maxLength, :showValue
+ serializable_attributes :min_length, :max_length, :show_value
# instance values that must be serialized as their own elements - e.g. not attributes.
CHILD_ELEMENTS = [:value_objects, :color]
@@ -33,24 +43,29 @@ module Axlsx
# The minimum length of the data bar, as a percentage of the cell width.
# The default value is 10
# @return [Integer]
- attr_reader :minLength
+ attr_reader :min_length
+ alias :minLength :min_length
# maxLength attribute
# The maximum length of the data bar, as a percentage of the cell width.
# The default value is 90
# @return [Integer]
- attr_reader :maxLength
+ attr_reader :max_length
+ alias :maxLength :max_length
# maxLength attribute
# Indicates whether to show the values of the cells on which this data bar is applied.
# The default value is true
# @return [Boolean]
- attr_reader :showValue
+ attr_reader :show_value
+ alias :showValue :show_value
# A simple typed list of cfvos
# @return [SimpleTypedList]
# @see Cfvo
- attr_reader :value_objects
+ def value_objects
+ @value_objects ||= Cfvos.new
+ end
# color
# the color object used in the data bar formatting
@@ -60,20 +75,33 @@ module Axlsx
end
# @see minLength
- def minLength=(v); Axlsx.validate_unsigned_int(v); @minLength = v end
- # @see maxLength
- def maxLength=(v); Axlsx.validate_unsigned_int(v); @maxLength = v end
-
- # @see showValue
- def showValue=(v); Axlsx.validate_boolean(v); @showValue = v end
-
- # Sets the color for the data bars.
- # @param [Color|String] v The color object, or rgb string value to apply
- def color=(v)
- @color = v if v.is_a? Color
- self.color.rgb = v if v.is_a? String
- @color
+ def min_length=(v)
+ Axlsx.validate_unsigned_int(v)
+ @min_length = v
end
+ alias :minLength= :min_length=
+
+ # @see maxLength
+ def max_length=(v)
+ Axlsx.validate_unsigned_int(v)
+ @max_length = v
+ end
+ alias :maxLength= :max_length=
+
+ # @see showValue
+ def show_value=(v)
+ Axlsx.validate_boolean(v)
+ @show_value = v
+ end
+ alias :showValue= :show_value=
+
+ # Sets the color for the data bars.
+ # @param [Color|String] v The color object, or rgb string value to apply
+ def color=(v)
+ @color = v if v.is_a? Color
+ self.color.rgb = v if v.is_a? String
+ @color
+ end
# Serialize this object to an xml string
# @param [String] str
@@ -82,19 +110,22 @@ module Axlsx
str << '<dataBar '
serialized_attributes str
str << '>'
- @value_objects.each { |cfvo| cfvo.to_xml_string(str) }
+ value_objects.to_xml_string(str)
self.color.to_xml_string(str)
str << '</dataBar>'
end
private
- # Initalize the simple typed list of value objects
- # I am keeping this private for now as I am not sure what impact changes to the required two cfvo objects will do.
- def initialize_value_objects
- @value_objects = SimpleTypedList.new Cfvo
- @value_objects.concat [Cfvo.new(:type => :min, :val => 0), Cfvo.new(:type => :max, :val => 0)]
- @value_objects.lock
+ def initialize_cfvos(cfvos)
+ self.class.default_cfvos.each_with_index.map do |default, index|
+ if index < cfvos.size
+ value_objects << Cfvo.new(default.merge(cfvos[index]))
+ else
+ value_objects << Cfvo.new(default)
+ end
+ end
end
+
end
end
diff --git a/lib/axlsx/workbook/worksheet/header_footer.rb b/lib/axlsx/workbook/worksheet/header_footer.rb
new file mode 100644
index 00000000..a40ad853
--- /dev/null
+++ b/lib/axlsx/workbook/worksheet/header_footer.rb
@@ -0,0 +1,54 @@
+module Axlsx
+ # Header/Footer options for printing a worksheet. All settings are optional.
+ #
+ # Headers and footers are generated using a string which is a combination
+ # of plain text and control characters. A fairly comprehensive list of control
+ # characters can be found here:
+ # https://github.com/randym/axlsx/blob/master/notes_on_header_footer.md
+ #     
+ # @note The recommended way of managing header/footers is via Worksheet#header_footer
+ # @see Worksheet#initialize
+ class HeaderFooter
+
+ include Axlsx::OptionsParser
+ include Axlsx::SerializedAttributes
+ include Axlsx::Accessors
+
+ # Creates a new HeaderFooter object
+ # @option options [String] odd_header The content for headers on odd numbered pages.
+ # @option options [String] odd_footer The content for footers on odd numbered pages.
+ # @option options [String] even_header The content for headers on even numbered pages.
+ # @option options [String] even_footer The content for footers on even numbered pages.
+ # @option options [String] first_header The content for headers on even numbered pages.
+ # @option options [String] first_footer The content for footers on even numbered pages.
+ # @option options [Boolean] different_odd_even Setting this to true will show different headers/footers on odd and even pages. When false, the odd headers/footers are used on each page. (Default: false)
+ # @option options [Boolean] different_first If true, will use the first header/footer on page 1. Otherwise, the odd header/footer is used.
+ def initialize(options = {})
+ parse_options options
+ end
+
+ serializable_attributes :different_odd_even, :different_first
+ serializable_element_attributes :odd_header, :odd_footer, :even_header, :even_footer, :first_header, :first_footer
+ string_attr_accessor :odd_header, :odd_footer, :even_header, :even_footer, :first_header, :first_footer
+ boolean_attr_accessor :different_odd_even, :different_first
+
+ # Set some or all header/footers at once.
+ # @param [Hash] options The header/footer options to set (possible keys are :odd_header, :odd_footer, :even_header, :even_footer, :first_header, :first_footer, :different_odd_even, and :different_first).
+ def set(options)
+ parse_options options
+ end
+
+ # Serializes the header/footer object.
+ # @param [String] str
+ # @return [String]
+ def to_xml_string(str = '')
+ str << "<headerFooter "
+ serialized_attributes str
+ str << ">"
+ serialized_element_attributes(str) do |value|
+ value = ::CGI.escapeHTML(value)
+ end
+ str << "</headerFooter>"
+ end
+ end
+end
diff --git a/lib/axlsx/workbook/worksheet/pane.rb b/lib/axlsx/workbook/worksheet/pane.rb
index 6ac87f13..a34b3140 100644
--- a/lib/axlsx/workbook/worksheet/pane.rb
+++ b/lib/axlsx/workbook/worksheet/pane.rb
@@ -1,4 +1,3 @@
-# encoding: UTF-8
module Axlsx
# Pane options for a worksheet.
#
@@ -132,7 +131,7 @@ module Axlsx
private
def finalize
- if @state == 'frozen' && @top_left_cell.nil?
+ if @state == 'frozen' && @top_left_cell.nil?
row = @y_split || 0
column = @x_split || 0
@top_left_cell = "#{('A'..'ZZ').to_a[column]}#{row+1}"
diff --git a/lib/axlsx/workbook/worksheet/protected_range.rb b/lib/axlsx/workbook/worksheet/protected_range.rb
index c58b895d..15904292 100644
--- a/lib/axlsx/workbook/worksheet/protected_range.rb
+++ b/lib/axlsx/workbook/worksheet/protected_range.rb
@@ -41,7 +41,6 @@ module Axlsx
# our output to that object. Use this - it helps limit the number of
# objects created during serialization
def to_xml_string(str="")
- attrs = self.instance_values.reject{ |key, value| value == nil }
str << '<protectedRange '
serialized_attributes str
str << '/>'
diff --git a/lib/axlsx/workbook/worksheet/row.rb b/lib/axlsx/workbook/worksheet/row.rb
index b10d8403..1b64b412 100644
--- a/lib/axlsx/workbook/worksheet/row.rb
+++ b/lib/axlsx/workbook/worksheet/row.rb
@@ -5,59 +5,14 @@ module Axlsx
# @see Worksheet#add_row
class Row
+ include SerializedAttributes
+ include Accessors
# No support is provided for the following attributes
# spans
# thickTop
# thickBottom
-
- # A list of serilizable attributes.
- # @note height(ht) and customHeight are manages separately for now. Have a look at Row#height
- SERIALIZABLE_ATTRIBUTES = [:hidden, :outlineLevel, :collapsed, :s, :customFormat, :ph]
-
- # The worksheet this row belongs to
- # @return [Worksheet]
- attr_reader :worksheet
-
- # The cells this row holds
- # @return [SimpleTypedList]
- attr_reader :cells
-
- # Row height measured in point size. There is no margin padding on row height.
- # @return [Float]
- attr_reader :height
-
- # Flag indicating if the outlining of row.
- # @return [Boolean]
- attr_reader :collapsed
-
- # Flag indicating if the the row is hidden.
- # @return [Boolean]
- attr_reader :hidden
-
- # Outlining level of the row, when outlining is on
- # @return [Integer]
- attr_reader :outlineLevel
-
- # The style applied ot the row. This affects the entire row.
- # @return [Integer]
- attr_reader :s
-
- # indicates that a style has been applied directly to the row via Row#s
- # @return [Boolean]
- attr_reader :customFormat
-
- # indicates if the row should show phonetic
- # @return [Boolean]
- attr_reader :ph
-
- # NOTE removing this from the api as it is actually incorrect.
- # having a method to style a row's cells is fine, but it is not an attribute on the row.
- # The proper attribute is ':s'
- # attr_reader style
- #
-
- # Creates a new row. New Cell objects are created based on the values, types and style options.
+ # Creates a new row. New Cell objects are created based on the values, types and style options.
# A new cell is created for each item in the values array. style and types options are applied as follows:
# If the types option is defined and is a symbol it is applied to all the cells created.
# If the types option is an array, cell types are applied by index for each cell
@@ -73,7 +28,7 @@ module Axlsx
# @see Row#array_to_cells
# @see Cell
def initialize(worksheet, values=[], options={})
- @height = nil
+ @ht = nil
self.worksheet = worksheet
@cells = SimpleTypedList.new Cell
@worksheet.rows << self
@@ -81,29 +36,48 @@ module Axlsx
array_to_cells(values, options)
end
- # @see Row#collapsed
- def collapsed=(v)
- Axlsx.validate_boolean(v)
- @collapsed = v
- end
+ # A list of serializable attributes.
+ serializable_attributes :hidden, :outline_level, :collapsed, :custom_format, :s, :ph, :custom_height, :ht
+
+ # Boolean row attribute accessors
+ boolean_attr_accessor :hidden, :collapsed, :custom_format, :ph, :custom_height
- # @see Row#hidden
- def hidden=(v)
- Axlsx.validate_boolean(v)
- @hidden = v
+ # The worksheet this row belongs to
+ # @return [Worksheet]
+ attr_reader :worksheet
+
+ # The cells this row holds
+ # @return [SimpleTypedList]
+ attr_reader :cells
+
+ # Row height measured in point size. There is no margin padding on row height.
+ # @return [Float]
+ def height
+ @ht
end
-
- # @see Row#ph
- def ph=(v) Axlsx.validate_boolean(v); @ph = v end
+
+ # Outlining level of the row, when outlining is on
+ # @return [Integer]
+ attr_reader :outline_level
+ alias :outlineLevel :outline_level
+
+ # The style applied ot the row. This affects the entire row.
+ # @return [Integer]
+ attr_reader :s
# @see Row#s
- def s=(v) Axlsx.validate_unsigned_numeric(v); @s = v; @customFormat = true end
+ def s=(v)
+ Axlsx.validate_unsigned_numeric(v)
+ @custom_format = true
+ @s = v
+ end
# @see Row#outline
- def outlineLevel=(v)
+ def outline_level=(v)
Axlsx.validate_unsigned_numeric(v)
- @outlineLevel = v
+ @outline_level = v
end
+ alias :outlineLevel= :outline_level=
# The index of this row in the worksheet
# @return [Integer]
@@ -116,18 +90,11 @@ module Axlsx
# @param [String] str The string this rows xml will be appended to.
# @return [String]
def to_xml_string(r_index, str = '')
- str << '<row r="' << (r_index + 1 ).to_s << '" '
- instance_values.select { |key, value| SERIALIZABLE_ATTRIBUTES.include? key.to_sym }.each do |key, value|
- str << key << '="' << value.to_s << '" '
- end
- if custom_height?
- str << 'customHeight="1" ht="' << height.to_s << '">'
- else
- str << '>'
- end
+ str << '<row '
+ serialized_attributes(str, { :r => r_index + 1 })
+ str << '>'
@cells.each_with_index { |cell, c_index| cell.to_xml_string(r_index, c_index, str) }
str << '</row>'
- str
end
# Adds a singel sell to the row based on the data provided and updates the worksheet's autofit data.
@@ -154,13 +121,13 @@ module Axlsx
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
+ def height=(v)
+ Axlsx::validate_unsigned_numeric(v)
+ unless v.nil?
+ @ht = v
+ @custom_height = true
+ end
+ @ht
end
private
diff --git a/lib/axlsx/workbook/worksheet/sheet_protection.rb b/lib/axlsx/workbook/worksheet/sheet_protection.rb
index a472ec55..5ff888ea 100644
--- a/lib/axlsx/workbook/worksheet/sheet_protection.rb
+++ b/lib/axlsx/workbook/worksheet/sheet_protection.rb
@@ -45,12 +45,6 @@ module Axlsx
# @return [String]
attr_reader :salt_value
- # If 1 or true then sorting should not be allowed when the sheet is protected.
- # If 0 or false then sorting should be allowed when the sheet is protected.
- # @return [Boolean]
- # default true
- attr_reader :sort
-
# Password hash
# @return [String]
# default nil
diff --git a/lib/axlsx/workbook/worksheet/worksheet.rb b/lib/axlsx/workbook/worksheet/worksheet.rb
index 6a32e881..8a595b2d 100644
--- a/lib/axlsx/workbook/worksheet/worksheet.rb
+++ b/lib/axlsx/workbook/worksheet/worksheet.rb
@@ -9,7 +9,8 @@ module Axlsx
# This is used for autowidth calculations
# @return [String]
def self.thin_chars
- @thin_chars ||= "^.acefijklrstxyzFIJL()-"
+ # removed 'e' and 'y' from this list - as a GUESS
+ @thin_chars ||= "^.acfijklrstxzFIJL()-"
end
# Creates a new worksheet.
@@ -18,6 +19,7 @@ module Axlsx
# @option options [String] name The name of this worksheet.
# @option options [Hash] page_margins A hash containing page margins for this worksheet. @see PageMargins
# @option options [Hash] print_options A hash containing print options for this worksheet. @see PrintOptions
+ # @option options [Hash] header_footer A hash containing header/footer options for this worksheet. @see HeaderFooter
# @option options [Boolean] show_gridlines indicates if gridlines should be shown for this sheet.
def initialize(wb, options={})
self.workbook = wb
@@ -34,6 +36,7 @@ module Axlsx
@page_margins = PageMargins.new options[:page_margins] if options[:page_margins]
@page_setup = PageSetup.new options[:page_setup] if options[:page_setup]
@print_options = PrintOptions.new options[:print_options] if options[:print_options]
+ @header_footer = HeaderFooter.new options[:header_footer] if options[:header_footer]
end
# The name of the worksheet
@@ -41,7 +44,7 @@ module Axlsx
def name
@name ||= "Sheet" + (index+1).to_s
end
-
+
# The sheet calculation properties
# @return [SheetCalcPr]
def sheet_calc_pr
@@ -104,7 +107,7 @@ module Axlsx
# An range that excel will apply an autfilter to "A1:B3"
# This will turn filtering on for the cells in the range.
# The first row is considered the header, while subsequent rows are considerd to be data.
- # @return String
+ # @return String
def auto_filter
@auto_filter ||= AutoFilter.new self
end
@@ -193,6 +196,21 @@ module Axlsx
@print_options
end
+ # Options for headers and footers.
+ # @example
+ # wb = Axlsx::Package.new.workbook
+ # # would generate something like: "file.xlsx : sheet_name 2 of 7 date with timestamp"
+ # header = {:different_odd_ => false, :odd_header => "&L&F : &A&C&Pof%N%R%D %T"}
+ # ws = wb.add_worksheet :header_footer => header
+ #
+ # @see HeaderFooter#initialize
+ # @return [HeaderFooter]
+ def header_footer
+ @header_footer ||= HeaderFooter.new
+ yield @header_footer if block_given?
+ @header_footer
+ end
+
# convinience method to access all cells in this worksheet
# @return [Array] cells
def cells
@@ -237,7 +255,7 @@ module Axlsx
# Indicates if gridlines should be shown in the sheet.
# This is true by default.
# @return [Boolean]
- # @deprecated Use {SheetView#show_grid_lines=} instead.
+ # @deprecated Use SheetView#show_grid_lines= instead.
def show_gridlines=(v)
warn('axlsx::DEPRECIATED: Worksheet#show_gridlines= has been depreciated. This value can be set over SheetView#show_grid_lines=.')
Axlsx::validate_boolean v
@@ -246,7 +264,7 @@ module Axlsx
# @see selected
# @return [Boolean]
- # @deprecated Use {SheetView#tab_selected=} instead.
+ # @deprecated Use SheetView#tab_selected= instead.
def selected=(v)
warn('axlsx::DEPRECIATED: Worksheet#selected= has been depreciated. This value can be set over SheetView#tab_selected=.')
Axlsx::validate_boolean v
@@ -255,7 +273,7 @@ module Axlsx
# Indicates if the worksheet should show gridlines or not
# @return Boolean
- # @deprecated Use {SheetView#show_grid_lines} instead.
+ # @deprecated Use SheetView#show_grid_lines instead.
def show_gridlines
warn('axlsx::DEPRECIATED: Worksheet#show_gridlines has been depreciated. This value can get over SheetView#show_grid_lines.')
sheet_view.show_grid_lines
@@ -265,7 +283,7 @@ module Axlsx
# It is possible to have more than one worksheet selected, however it might cause issues
# in some older versions of excel when using copy and paste.
# @return Boolean
- # @deprecated Use {SheetView#tab_selected} instead.
+ # @deprecated Use SheetView#tab_selected instead.
def selected
warn('axlsx::DEPRECIATED: Worksheet#selected has been depreciated. This value can get over SheetView#tab_selected.')
sheet_view.tab_selected
@@ -280,7 +298,7 @@ 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] name
+ # @param [String] name
def name=(name)
validate_sheet_name name
@name=Axlsx::coder.encode(name)
@@ -388,7 +406,7 @@ module Axlsx
cf = ConditionalFormatting.new( :sqref => cells )
cf.add_rules rules
conditional_formattings << cf
- conditional_formattings
+ conditional_formattings
end
# Add data validation to this worksheet.
@@ -513,7 +531,7 @@ module Axlsx
def sanitize(str)
str.gsub(CONTROL_CHAR_REGEX, '')
end
-
+
# The worksheet relationships. This is managed automatically by the worksheet
# @return [Relationships]
def relationships
@@ -570,12 +588,12 @@ module Axlsx
private
-
+
def validate_sheet_name(name)
DataTypeValidator.validate "Worksheet.name", String, name
raise ArgumentError, (ERR_SHEET_NAME_TOO_LONG % name) if name.size > 31
raise ArgumentError, (ERR_SHEET_NAME_COLON_FORBIDDEN % name) if name.include? ':'
- name = Axlsx::coder.encode(name)
+ name = Axlsx::coder.encode(name)
sheet_names = @workbook.worksheets.map { |s| s.name }
raise ArgumentError, (ERR_DUPLICATE_SHEET_NAME % name) if sheet_names.include?(name)
end
@@ -586,7 +604,7 @@ module Axlsx
sheet_data, sheet_calc_pr, @sheet_protection, protected_ranges,
auto_filter, merged_cells, conditional_formattings,
data_validations, hyperlinks, print_options, page_margins,
- page_setup, worksheet_drawing, worksheet_comments,
+ page_setup, header_footer, worksheet_drawing, worksheet_comments,
tables]
end
@@ -606,7 +624,7 @@ module Axlsx
# @see Worksheet#protect_range
# @return [SimpleTypedList] The protected ranges for this worksheet
def protected_ranges
- @protected_ranges ||= ProtectedRanges.new self
+ @protected_ranges ||= ProtectedRanges.new self
# SimpleTypedList.new ProtectedRange
end
@@ -619,7 +637,7 @@ module Axlsx
# data validations array
# @return [Array]
def data_validations
- @data_validations ||= DataValidations.new self
+ @data_validations ||= DataValidations.new self
end
# merged cells array
diff --git a/lib/axlsx/workbook/worksheet/worksheet_hyperlink.rb b/lib/axlsx/workbook/worksheet/worksheet_hyperlink.rb
index 830698cc..d352ec90 100644
--- a/lib/axlsx/workbook/worksheet/worksheet_hyperlink.rb
+++ b/lib/axlsx/workbook/worksheet/worksheet_hyperlink.rb
@@ -73,7 +73,7 @@ module Axlsx
# r:id should only be specified for external targets.
# @return [Hash]
def location_or_id
- @target == :external ? { :"r:id" => id } : { :"location" => location }
+ @target == :external ? { :"r:id" => id } : { :location => Axlsx::coder.encode(location) }
end
end
end
diff --git a/test/benchmark.rb b/test/benchmark.rb
index d61aa7b2..33bf7d2c 100644
--- a/test/benchmark.rb
+++ b/test/benchmark.rb
@@ -4,11 +4,10 @@ $:.unshift "#{File.dirname(__FILE__)}/../lib"
require 'axlsx'
require 'csv'
require 'benchmark'
-
row = []
input = (32..126).to_a.pack('U*').chars.to_a
20.times { row << input.shuffle.join}
-times = 2000
+times = 3000
Benchmark.bmbm(30) do |x|
x.report('axlsx_noautowidth') {
diff --git a/test/content_type/tc_default.rb b/test/content_type/tc_default.rb
index 2fe0d965..d765a904 100644
--- a/test/content_type/tc_default.rb
+++ b/test/content_type/tc_default.rb
@@ -3,14 +3,6 @@ require 'tc_helper.rb'
class TestDefault < Test::Unit::TestCase
- def test_initialization_requires_Extension_and_ContentType
- assert_raise(ArgumentError, "raises argument error if Extension and/or ContentType are not specified") { Axlsx::Default.new }
- assert_raise(ArgumentError, "raises argument error if Extension and/or ContentType are not specified") { Axlsx::Default.new :Extension=>"xml" }
- assert_raise(ArgumentError, "raises argument error if Extension and/or ContentType are not specified") { Axlsx::Default.new :ContentType=>"asdf" }
-
- assert_nothing_raised {Axlsx::Default.new :Extension=>"foo", :ContentType=>Axlsx::XML_CT}
-
- end
def test_content_type_restriction
assert_raise(ArgumentError, "raises argument error if invlalid ContentType is") { Axlsx::Default.new :ContentType=>"asdf" }
end
@@ -20,8 +12,5 @@ class TestDefault < Test::Unit::TestCase
doc = Nokogiri::XML(type.to_xml_string)
assert_equal(doc.xpath("Default[@ContentType='#{Axlsx::XML_CT}']").size, 1)
assert_equal(doc.xpath("Default[@Extension='xml']").size, 1)
-
end
-
-
end
diff --git a/test/content_type/tc_override.rb b/test/content_type/tc_override.rb
index 920f1667..d9bec90c 100644
--- a/test/content_type/tc_override.rb
+++ b/test/content_type/tc_override.rb
@@ -1,16 +1,6 @@
-# -*- coding: utf-8 -*-
require 'tc_helper.rb'
-
class TestOverride < Test::Unit::TestCase
- def test_initialization_requires_Extension_and_ContentType
- err = "requires PartName and ContentType options"
- assert_raise(ArgumentError, err) { Axlsx::Override.new }
- assert_raise(ArgumentError, err) { Axlsx::Override.new :PartName=>"xml" }
- assert_raise(ArgumentError, err) { Axlsx::Override.new :ContentType=>"asdf" }
- assert_nothing_raised {Axlsx::Override.new :PartName=>"foo", :ContentType=>Axlsx::CHART_CT}
- end
-
def test_content_type_restriction
assert_raise(ArgumentError, "requires known content type") { Axlsx::Override.new :ContentType=>"asdf" }
end
@@ -20,8 +10,5 @@ class TestOverride < Test::Unit::TestCase
doc = Nokogiri::XML(type.to_xml_string)
assert_equal(doc.xpath("Override[@ContentType='#{Axlsx::CHART_CT}']").size, 1)
assert_equal(doc.xpath("Override[@PartName='somechart.xml']").size, 1)
-
end
-
-
end
diff --git a/test/profile.rb b/test/profile.rb
index fa81577b..0190dc16 100644
--- a/test/profile.rb
+++ b/test/profile.rb
@@ -1,31 +1,22 @@
#!/usr/bin/env ruby -s
-# -*- coding: utf-8 -*-
# Usage:
# > ruby test/profile.rb
-# > pprof.rb --gif /tmp/axlsx_noautowidth > /tmp/axlsx_noautowidth.gif
+# > pprof.rb --gif /tmp/axlsx > /tmp/axlsx.gif
# > open /tmp/axlsx_noautowidth.gif
$:.unshift "#{File.dirname(__FILE__)}/../lib"
require 'axlsx'
-require 'csv'
-
-# require 'benchmark'
require 'perftools'
row = []
+# Taking worst case scenario of all string data
input = (32..126).to_a.pack('U*').chars.to_a
20.times { row << input.shuffle.join}
times = 3000
-PerfTools::CpuProfiler.start("/tmp/axlsx_noautowidth") do
+PerfTools::CpuProfiler.start("/tmp/axlsx") do
p = Axlsx::Package.new
- p.use_autowidth = false
- p.use_shared_strings = true
- wb = p.workbook
-
- #A Simple Workbook
-
- wb.add_worksheet do |sheet|
+ p.workbook.add_worksheet do |sheet|
times.times do
sheet << row
end
diff --git a/test/rels/tc_relationship.rb b/test/rels/tc_relationship.rb
index ef995449..32b9e4a1 100644
--- a/test/rels/tc_relationship.rb
+++ b/test/rels/tc_relationship.rb
@@ -18,4 +18,9 @@ class TestRelationships < Test::Unit::TestCase
assert_nothing_raised { Axlsx::Relationship.new( Axlsx::WORKSHEET_R, 'target', :target_mode => :External) }
end
+ def test_ampersand_escaping_in_target
+ r = Axlsx::Relationship.new(Axlsx::HYPERLINK_R, "http://example.com?foo=1&bar=2", :target_mod => :External)
+ doc = Nokogiri::XML(r.to_xml_string(1))
+ assert_equal(doc.xpath("//Relationship[@Target='http://example.com?foo=1&bar=2']").size, 1)
+ end
end
diff --git a/test/tc_helper.rb b/test/tc_helper.rb
index 84e834c4..34f7f22d 100644
--- a/test/tc_helper.rb
+++ b/test/tc_helper.rb
@@ -1,4 +1,8 @@
$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib"
-require 'cover_me' unless RUBY_VERSION == '1.8.7'
+require 'simplecov'
+SimpleCov.start do
+ add_filter "/test/"
+end
+
require 'test/unit'
require "axlsx.rb"
diff --git a/test/util/tc_validators.rb b/test/util/tc_validators.rb
index 1c3e173c..de896f3d 100644
--- a/test/util/tc_validators.rb
+++ b/test/util/tc_validators.rb
@@ -159,6 +159,20 @@ class TestValidators < Test::Unit::TestCase
assert_raise(ArgumentError) { Axlsx.validate_split_state_type 0 }
end
+ def test_validate_family
+ assert_raise(ArgumentError) { Axlsx.validate_family 0 }
+ (1..5).each do |item|
+ assert_nothing_raised { Axlsx.validate_family item }
+ end
+ end
+
+ def test_validate_u
+ assert_raise(ArgumentError) { Axlsx.validate_cell_u :hoge }
+ [:none, :single, :double, :singleAccounting, :doubleAccounting].each do |sym|
+ assert_nothing_raised { Axlsx.validate_cell_u sym }
+ end
+ end
+
def test_range_validation
# exclusive
assert_raise(ArgumentError) { Axlsx::RangeValidator.validate('foo', 1, 10, 10, false) }
diff --git a/test/workbook/tc_workbook.rb b/test/workbook/tc_workbook.rb
index f10ad24a..1a9b9669 100644
--- a/test/workbook/tc_workbook.rb
+++ b/test/workbook/tc_workbook.rb
@@ -49,6 +49,14 @@ class TestWorkbook < Test::Unit::TestCase
assert_equal(@wb.worksheets.first, ws, "the worksheet returned is the worksheet added")
assert_equal(ws.name, "bob", "name option gets passed to worksheet")
end
+
+ def test_insert_worksheet
+ @wb.add_worksheet(:name => 'A')
+ @wb.add_worksheet(:name => 'B')
+ ws3 = @wb.insert_worksheet(0, :name => 'C')
+ assert_equal(ws3.name, @wb.worksheets.first.name)
+ end
+
def test_relationships
#current relationship size is 1 due to style relation
assert(@wb.relationships.size == 1)
diff --git a/test/workbook/worksheet/tc_cell.rb b/test/workbook/worksheet/tc_cell.rb
index 0b332d86..b237077c 100644
--- a/test/workbook/worksheet/tc_cell.rb
+++ b/test/workbook/worksheet/tc_cell.rb
@@ -162,9 +162,12 @@ class TestCell < Test::Unit::TestCase
end
def test_u
+ @c.type = :string
assert_raise(ArgumentError) { @c.u = -1.1 }
- assert_nothing_raised { @c.u = false }
- assert_equal(@c.u, false)
+ assert_nothing_raised { @c.u = :single }
+ assert_equal(@c.u, :single)
+ doc = Nokogiri::XML(@c.to_xml_string(1,1))
+ assert(doc.xpath('//u[@val="single"]'))
end
def test_i
@@ -187,8 +190,8 @@ class TestCell < Test::Unit::TestCase
def test_family
assert_raise(ArgumentError) { @c.family = -1.1 }
- assert_nothing_raised { @c.family = "Who knows!" }
- assert_equal(@c.family, "Who knows!")
+ assert_nothing_raised { @c.family = 5 }
+ assert_equal(@c.family, 5)
end
def test_b
@@ -251,6 +254,8 @@ class TestCell < Test::Unit::TestCase
end
def test_to_xml_string_with_run
+ # Actually quite a number of similar run styles
+ # but the processing should be the same
@c.b = true
@c.type = :string
@c.value = "a"
@@ -259,6 +264,7 @@ class TestCell < Test::Unit::TestCase
c_xml = Nokogiri::XML(@c.to_xml_string(1,1))
assert(c_xml.xpath("//b"))
end
+
def test_to_xml_string_formula
p = Axlsx::Package.new
ws = p.workbook.add_worksheet do |sheet|
@@ -285,6 +291,7 @@ class TestCell < Test::Unit::TestCase
sz = @c.send(:font_size)
assert_equal(sz, 52)
end
+
def test_cell_with_sz
@c.sz = 25
@@ -293,6 +300,7 @@ class TestCell < Test::Unit::TestCase
def test_to_xml
# TODO This could use some much more stringent testing related to the xml content generated!
@ws.add_row [Time.now, Date.today, true, 1, 1.0, "text", "=sum(A1:A2)"]
+ @ws.rows.last.cells[5].u = true
schema = Nokogiri::XML::Schema(File.open(Axlsx::SML_XSD))
doc = Nokogiri::XML(@ws.to_xml_string)
errors = []
diff --git a/test/workbook/worksheet/tc_col.rb b/test/workbook/worksheet/tc_col.rb
index 9621eb14..c0c5e64b 100644
--- a/test/workbook/worksheet/tc_col.rb
+++ b/test/workbook/worksheet/tc_col.rb
@@ -58,6 +58,16 @@ class TestCol < Test::Unit::TestCase
assert_nothing_raised(ArgumentError, 'phonetic must be boolean(ish)') { @col.phonetic = true }
end
+ def test_to_xml_string
+ @col.width = 100
+ doc = Nokogiri::XML(@col.to_xml_string)
+ assert_equal(1, doc.xpath("//col [@bestFit='#{@col.best_fit}']").size)
+ assert_equal(1, doc.xpath("//col [@max=#{@col.max}]").size)
+ assert_equal(1, doc.xpath("//col [@min=#{@col.min}]").size)
+ assert_equal(1, doc.xpath("//col [@width=#{@col.width}]").size)
+ assert_equal(1, doc.xpath("//col [@customWidth='#{@col.custom_width}']").size)
+ end
+
def test_style
assert_equal(@col.style, nil)
@col.style = 1
diff --git a/test/workbook/worksheet/tc_color_scale.rb b/test/workbook/worksheet/tc_color_scale.rb
index d7e66fcf..a0d75fab 100644
--- a/test/workbook/worksheet/tc_color_scale.rb
+++ b/test/workbook/worksheet/tc_color_scale.rb
@@ -5,6 +5,37 @@ class TestColorScale < Test::Unit::TestCase
@color_scale = Axlsx::ColorScale.new
end
+ def test_three_tone
+ color_scale = Axlsx::ColorScale.three_tone
+ assert_equal 3, color_scale.value_objects.size
+ assert_equal 3, color_scale.colors.size
+ end
+
+ def test_two_tone
+ color_scale = Axlsx::ColorScale.two_tone
+ assert_equal 2, color_scale.value_objects.size
+ assert_equal 2, color_scale.colors.size
+ end
+ def test_default_cfvo
+ first = Axlsx::ColorScale.default_cfvos.first
+ second = Axlsx::ColorScale.default_cfvos.last
+ assert_equal 'FFFF7128', first[:color]
+ assert_equal :min,first[:type]
+ assert_equal 0, first[:val]
+
+ assert_equal 'FFFFEF9C', second[:color]
+ assert_equal :max, second[:type]
+ assert_equal 0, second[:val]
+ end
+
+ def test_partial_default_cfvo_override
+ first_def = {:type => :percent, :val => "10.0", :color => 'FF00FF00'}
+ color_scale = Axlsx::ColorScale.new(first_def)
+ assert_equal color_scale.value_objects.first.val, first_def[:val]
+ assert_equal color_scale.value_objects.first.type, first_def[:type]
+ assert_equal color_scale.colors.first.rgb, first_def[:color]
+ end
+
def test_add
@color_scale.add :type => :max, :val => 5, :color => "FFDEDEDE"
assert_equal(@color_scale.value_objects.size,3)
@@ -12,8 +43,6 @@ class TestColorScale < Test::Unit::TestCase
end
def test_delete_at
- assert_raise(ArgumentError, "minimum two are protected") { @color_scale.delete_at 0 }
- assert_raise(ArgumentError, "minimum two are protected") { @color_scale.delete_at 1 }
@color_scale.add :type => :max, :val => 5, :color => "FFDEDEDE"
assert_nothing_raised {@color_scale.delete_at 2}
assert_equal(@color_scale.value_objects.size,2)
diff --git a/test/workbook/worksheet/tc_data_bar.rb b/test/workbook/worksheet/tc_data_bar.rb
index af803f23..a6194de9 100644
--- a/test/workbook/worksheet/tc_data_bar.rb
+++ b/test/workbook/worksheet/tc_data_bar.rb
@@ -11,6 +11,13 @@ class TestDataBar < Test::Unit::TestCase
assert_equal @data_bar.showValue, true
end
+ def test_override_default_cfvos
+ data_bar = Axlsx::DataBar.new({:color => 'FF00FF00'}, {:type => :min, :val => "20"})
+ assert_equal("20", data_bar.value_objects.first.val)
+ assert_equal("0", data_bar.value_objects.last.val)
+ end
+
+
def test_minLength
assert_raise(ArgumentError) { @data_bar.minLength = :invalid_type }
assert_nothing_raised { @data_bar.minLength = 0}
diff --git a/test/workbook/worksheet/tc_header_footer.rb b/test/workbook/worksheet/tc_header_footer.rb
new file mode 100644
index 00000000..4d78aa9d
--- /dev/null
+++ b/test/workbook/worksheet/tc_header_footer.rb
@@ -0,0 +1,151 @@
+require 'tc_helper'
+
+class TestHeaderFooter < Test::Unit::TestCase
+
+ def setup
+ @p = Axlsx::Package.new
+ ws = @p.workbook.add_worksheet :name => 'test'
+ @hf = ws.header_footer
+ end
+
+ def test_initialize
+ assert_equal(nil, @hf.odd_header)
+ assert_equal(nil, @hf.odd_footer)
+
+ assert_equal(nil, @hf.even_header)
+ assert_equal(nil, @hf.even_footer)
+
+ assert_equal(nil, @hf.first_header)
+ assert_equal(nil, @hf.first_footer)
+
+ assert_equal(nil, @hf.different_first)
+ assert_equal(nil, @hf.different_odd_even)
+ end
+
+ def test_initialize_with_options
+ header_footer = {
+ :odd_header => 'oh',
+ :odd_footer => 'of',
+
+ :even_header => 'eh',
+ :even_footer => 'ef',
+
+ :first_header => 'fh',
+ :first_footer => 'ff',
+
+ :different_first => true,
+ :different_odd_even => true
+ }
+ optioned = @p.workbook.add_worksheet(:name => 'optioned', :header_footer => header_footer).header_footer
+
+ assert_equal('oh', optioned.odd_header)
+ assert_equal('of', optioned.odd_footer)
+
+ assert_equal('eh', optioned.even_header)
+ assert_equal('ef', optioned.even_footer)
+
+ assert_equal('fh', optioned.first_header)
+ assert_equal('ff', optioned.first_footer)
+
+ assert_equal(true, optioned.different_first)
+ assert_equal(true, optioned.different_odd_even)
+ end
+
+ def test_string_attributes
+ %w(odd_header odd_footer even_header even_footer first_header first_footer).each do |attr|
+ assert_raise(ArgumentError, 'only strings allowed in string attributes') { @hf.send("#{attr}=", 1) }
+ assert_nothing_raised { @hf.send("#{attr}=", 'test_string') }
+ end
+ end
+
+ def test_boolean_attributes
+ %w(different_first different_odd_even).each do |attr|
+ assert_raise(ArgumentError, 'only booleanish allowed in string attributes') { @hf.send("#{attr}=", 'foo') }
+ assert_nothing_raised { @hf.send("#{attr}=", 1) }
+ end
+ end
+
+ def test_set_all_values
+ @hf.set(
+ :odd_header => 'oh',
+ :odd_footer => 'of',
+
+ :even_header => 'eh',
+ :even_footer => 'ef',
+
+ :first_header => 'fh',
+ :first_footer => 'ff',
+
+ :different_first => true,
+ :different_odd_even => true
+ )
+
+ assert_equal('oh', @hf.odd_header)
+ assert_equal('of', @hf.odd_footer)
+
+ assert_equal('eh', @hf.even_header)
+ assert_equal('ef', @hf.even_footer)
+
+ assert_equal('fh', @hf.first_header)
+ assert_equal('ff', @hf.first_footer)
+
+ assert_equal(true, @hf.different_first)
+ assert_equal(true, @hf.different_odd_even)
+ end
+
+ def test_to_xml_all_values
+ @hf.set(
+ :odd_header => 'oh',
+ :odd_footer => 'of',
+
+ :even_header => 'eh',
+ :even_footer => 'ef',
+
+ :first_header => 'fh',
+ :first_footer => 'ff',
+
+ :different_first => true,
+ :different_odd_even => true
+ )
+
+ doc = Nokogiri::XML.parse(@hf.to_xml_string)
+ assert_equal(1, doc.xpath(".//headerFooter[@differentFirst='true'][@differentOddEven='true']").size)
+
+ assert_equal(1, doc.xpath(".//headerFooter/oddHeader").size)
+ assert_equal('oh', doc.xpath(".//headerFooter/oddHeader").text)
+ assert_equal(1, doc.xpath(".//headerFooter/oddFooter").size)
+ assert_equal('of', doc.xpath(".//headerFooter/oddFooter").text)
+
+ assert_equal(1, doc.xpath(".//headerFooter/evenHeader").size)
+ assert_equal('eh', doc.xpath(".//headerFooter/evenHeader").text)
+ assert_equal(1, doc.xpath(".//headerFooter/evenFooter").size)
+ assert_equal('ef', doc.xpath(".//headerFooter/evenFooter").text)
+
+ assert_equal(1, doc.xpath(".//headerFooter/firstHeader").size)
+ assert_equal('fh', doc.xpath(".//headerFooter/firstHeader").text)
+ assert_equal(1, doc.xpath(".//headerFooter/firstFooter").size)
+ assert_equal('ff', doc.xpath(".//headerFooter/firstFooter").text)
+ end
+
+ def test_to_xml_some_values
+ @hf.set(
+ :odd_header => 'oh',
+ :different_odd_even => false
+ )
+
+ doc = Nokogiri::XML.parse(@hf.to_xml_string)
+ assert_equal(1, doc.xpath(".//headerFooter[@differentOddEven='false']").size)
+ assert_equal(0, doc.xpath(".//headerFooter[@differentFirst]").size)
+
+ assert_equal(1, doc.xpath(".//headerFooter/oddHeader").size)
+ assert_equal('oh', doc.xpath(".//headerFooter/oddHeader").text)
+ assert_equal(0, doc.xpath(".//headerFooter/oddFooter").size)
+
+ assert_equal(0, doc.xpath(".//headerFooter/evenHeader").size)
+ assert_equal(0, doc.xpath(".//headerFooter/evenFooter").size)
+
+ assert_equal(0, doc.xpath(".//headerFooter/firstHeader").size)
+ assert_equal(0, doc.xpath(".//headerFooter/firstFooter").size)
+ end
+end
+
diff --git a/test/workbook/worksheet/tc_row.rb b/test/workbook/worksheet/tc_row.rb
index b126845a..d847d475 100644
--- a/test/workbook/worksheet/tc_row.rb
+++ b/test/workbook/worksheet/tc_row.rb
@@ -12,13 +12,13 @@ class TestRow < Test::Unit::TestCase
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([email protected]_height?, "no custom height by default")
+ assert([email protected]_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?)
+ assert(row.custom_height)
end
def test_style
@@ -57,7 +57,7 @@ class TestRow < Test::Unit::TestCase
def test_custom_height
@row.height = 20
- assert(@row.custom_height?)
+ assert(@row.custom_height)
end
def test_height
@@ -111,7 +111,7 @@ class TestRow < Test::Unit::TestCase
@row.add_cell 1
@row.height = 20
r_s_xml = Nokogiri::XML(@row.to_xml_string(0, ''))
- assert_equal(r_s_xml.xpath(".//row[@r=1][@ht=20][@customHeight=1]").size, 1)
+ assert_equal(r_s_xml.xpath(".//row[@r=1][@ht=20][@customHeight='true']").size, 1)
end
end
diff --git a/test/workbook/worksheet/tc_worksheet.rb b/test/workbook/worksheet/tc_worksheet.rb
index 4c8f2822..da90ffa0 100644
--- a/test/workbook/worksheet/tc_worksheet.rb
+++ b/test/workbook/worksheet/tc_worksheet.rb
@@ -55,6 +55,17 @@ class TestWorksheet < Test::Unit::TestCase
end
end
+ def test_header_footer
+ assert(@ws.header_footer.is_a? Axlsx::HeaderFooter)
+ end
+
+ def test_header_footer_yield
+ @ws.header_footer do |hf|
+ assert(hf.is_a? Axlsx::HeaderFooter)
+ assert(@ws.header_footer == hf)
+ end
+ end
+
def test_no_autowidth
@ws.workbook.use_autowidth = false
@ws.add_row [1,2,3,4]
@@ -65,7 +76,8 @@ class TestWorksheet < Test::Unit::TestCase
page_margins = {:left => 2, :right => 2, :bottom => 2, :top => 2, :header => 2, :footer => 2}
page_setup = {:fit_to_height => 1, :fit_to_width => 1, :orientation => :landscape, :paper_width => "210mm", :paper_height => "297mm", :scale => 80}
print_options = {:grid_lines => true, :headings => true, :horizontal_centered => true, :vertical_centered => true}
- optioned = @ws.workbook.add_worksheet(:name => 'bob', :page_margins => page_margins, :page_setup => page_setup, :print_options => print_options, :selected => true, :show_gridlines => false)
+ header_footer = {:different_first => false, :different_odd_even => false, :odd_header => 'Header'}
+ optioned = @ws.workbook.add_worksheet(:name => 'bob', :page_margins => page_margins, :page_setup => page_setup, :print_options => print_options, :header_footer => header_footer, :selected => true, :show_gridlines => false)
page_margins.keys.each do |key|
assert_equal(page_margins[key], optioned.page_margins.send(key))
end
@@ -75,6 +87,9 @@ class TestWorksheet < Test::Unit::TestCase
print_options.keys.each do |key|
assert_equal(print_options[key], optioned.print_options.send(key))
end
+ header_footer.keys.each do |key|
+ assert_equal(header_footer[key], optioned.header_footer.send(key))
+ end
assert_equal(optioned.name, 'bob')
assert_equal(optioned.selected, true)
assert_equal(optioned.show_gridlines, false)
@@ -293,6 +308,16 @@ class TestWorksheet < Test::Unit::TestCase
assert_equal(doc.xpath('//xmlns:worksheet/xmlns:printOptions[@gridLines="true"][@horizontalCentered="true"]').size, 1)
end
+ def test_to_xml_string_header_footer
+ @ws.header_footer do |hf|
+ hf.different_first = false
+ hf.different_odd_even = false
+ hf.odd_header = 'Test Header'
+ end
+ doc = Nokogiri::XML(@ws.to_xml_string)
+ assert_equal(doc.xpath('//xmlns:worksheet/xmlns:headerFooter[@differentFirst="false"][@differentOddEven="false"]').size, 1)
+ end
+
def test_to_xml_string_drawing
@ws.add_chart Axlsx::Pie3DChart
doc = Nokogiri::XML(@ws.to_xml_string)
@@ -317,7 +342,7 @@ class TestWorksheet < Test::Unit::TestCase
def test_styles
assert(@ws.styles.is_a?(Axlsx::Styles), 'worksheet provides access to styles')
end
-
+
def test_to_xml_string_with_illegal_chars
nasties = "\v\u2028\u0001\u0002\u0003\u0004\u0005\u0006\u0007\u0008\u001f"
@ws.add_row [nasties]
@@ -400,7 +425,7 @@ class TestWorksheet < Test::Unit::TestCase
@ws.add_row [1, 2, 3]
assert_nothing_raised {@ws.protect_range(@ws.rows.first.cells) }
assert_equal('A1:C1', @ws.send(:protected_ranges).last.sqref)
-
+
end
def test_merge_cells
@ws.add_row [1,2,3]
@@ -412,7 +437,7 @@ class TestWorksheet < Test::Unit::TestCase
assert_equal(@ws.send(:merged_cells).size, 3)
assert_equal(@ws.send(:merged_cells).last, "A3:B3")
end
-
+
def test_merge_cells_sorts_correctly_by_row_when_given_array
10.times do |i|
@ws.add_row [i]
@@ -420,7 +445,7 @@ class TestWorksheet < Test::Unit::TestCase
@ws.merge_cells [@ws.rows[8].cells.first, @ws.rows[9].cells.first]
assert_equal "A9:A10", @ws.send(:merged_cells).first
end
-
+
def test_auto_filter
assert(@ws.auto_filter.range.nil?)
assert_raise(ArgumentError) { @ws.auto_filter = 123 }
@@ -432,6 +457,6 @@ class TestWorksheet < Test::Unit::TestCase
@ws.auto_filter.range = 'A1:D9'
@ws.auto_filter.add_column 0, :filters, :filter_items => [1]
doc = Nokogiri::XML(@ws.to_xml_string)
- assert(doc.xpath('//sheetPr[@filterMode="true"]'))
+ assert(doc.xpath('//sheetPr[@filterMode="true"]'))
end
end
diff --git a/test/workbook/worksheet/tc_worksheet_hyperlink.rb b/test/workbook/worksheet/tc_worksheet_hyperlink.rb
index ad993e62..278c5add 100644
--- a/test/workbook/worksheet/tc_worksheet_hyperlink.rb
+++ b/test/workbook/worksheet/tc_worksheet_hyperlink.rb
@@ -5,7 +5,7 @@ class TestWorksheetHyperlink < Test::Unit::TestCase
p = Axlsx::Package.new
wb = p.workbook
@ws = wb.add_worksheet
- @options = { :location => 'https://github.com/randym/axlsx', :tooltip => 'axlsx', :ref => 'A1', :display => 'AXSLX', :target => :internal }
+ @options = { :location => 'https://github.com/randym/axlsx?foo=1&bar=2', :tooltip => 'axlsx', :ref => 'A1', :display => 'AXSLX', :target => :internal }
@a = @ws.add_hyperlink @options
end